eddorre

Connecting a Wii using WPA2 and a Complex Password

January 10, 2009 — 2 Comments

I recently upgraded my 802.11n wireless bridge/access point to a D-Link 802.11n so that I could have better download speeds when streaming video content to my Xbox or PS3. The concept of this device is simple, connect all of your devices to it via Ethernet and the bridge connects to the wireless network.

Unfortunately, the D-Link bridge doesn’t like to connect to Access Points/routers that are not broadcasting their SSIDs. This was a problem for me because I had set my Apple Airport Extreme (I still hate that name – Extreme? Really? I thought we got over that in the 90s) not to broadcast my SSID.

I’ve known for a while that not broadcasting your SSID isn’t really a security measure as it only discourages wireless network snooping. Anyone that really wants to hack into your wireless network, will know how to bypass that. In order to have real wireless network security your Access point should be using WPA or WPA2 with AES encryption and a very strong password. I should note that your SSID should never be something real world. Never your physical address, social security number, family last name, etc.

With this in mind, I allowed my Access Point to broadcast the SSID and then changed my wireless password to be 63 characters long.

After the change, the D-Link bridge was up and running but my Nintendo Wii decided to have a fit and not connect anymore. Fortunately, there is a fix.

Apparently the Wii has a problem connecting to Access Points using WPA/WPA2 when using a really large password.

I found this out by attempting to type the 63 character password (TIP: use a USB keyboard do to this as entering it with the Wii remote is likely to drive people insane) and having it fail. Then I tried a simple password of testtest (changed on both my wireless Access Point and my Wii). When I changed it to use a simple password, I was able to connect.

That set me Googling in the right direction. Where I found the information on WiiChat.com and then buried on Nintendo’s own tech support forums.

Basically, the problem is this: Passwords that are 63 characters are supposed to be hashed down to a 64 hex digit key and then sent off the Access Point for authentication. Unfortunately, the Wii fails to do this as it’s a broken implementation of how keys are transmitted to an Access Point.

What Zorach found out was that you can fake out the Wii by entering in the hex key yourself instead of the password. In order to generate the hex key, he used Joris van Rantwijk’s site an entered in his password and SSID to generate the key.

Now if entering a password and SSID into a random page on the Internet is sounding alarm bells in your head, well good, you’re getting as paranoid as I am. However, I’ve looked at the Javascript code and there there is nothing funky going on. If you want to be really paranoid, save the source of the HTML file locally, disconnect from the Internet and then run it in the browser.

Type in the hex key that is generated into your Wii and it should work. I should note, that in my situation, I did have to do one more thing; I set the IP information on the Wii statically as it would not download the information via DHCP.

A shout out goes to the user Zorach for linking the information, Messowires for linking to Zorach’s post and Joris van Rantwijk making it easy for people to generate a hex key from a password.

Standardizing Next and Previous Tab Commands in OS X

January 25, 2009 — 0 Comments

I use a lot of tabbed applications. OS X’s Terminal, Safari and Firefox come to mind. Each of these applications have a keyboard shortcut for moving between tabs; COMMAND+SHIFT+] to move forward and COMMAND+SHIFT+[ to move backwards.

There are some apps that don’t conform to this standard; Adium, Propane, and TextMate and it drives me nuts. Why can’t they all be standard? Well, actually they can using OS X to override the application specific command.

Below are some instructions and a screenshot of how to do this.

  • In order to do this first open up the System Preferences applet and click on Keyboard & Mouse.
  • Scroll down and select Application Keyboard Shortcuts
  • Click the + button
  • Select your application from the Application menu
  • Type in the menu title of the shortcut (for example, to move forward a tab in TextMate it’s Next File Tab
  • Type in the shortcut in the shortcut field and click Add

Mac OS X Keyboard System Preferences

Everyday Git from Refresh Portland

January 25, 2009 — 2 Comments

Refresh Portland LogoIn late December (2008) I floated an idea to the other Refresh Portland founders about doing a presentation on Git. As a newcomer and a recent convert to Git, I wanted to share my enthusiasm and learned knowledge with other people that might want to get the basics under their belt.

This past Thursday was the kick off for the Refresh Portland ’09 season and I gave my presentation, Everyday Git, to approximately 25-30 people with 16 viewing online.

If you missed it you can review the slides online or watch the entire presentation on UStream.

Thanks again to everyone that came out.

Manually Updating RubyGems

February 01, 2009 — 0 Comments

I just did a deployment of my blog and came across a nasty little problem. The deployment in question required that a database migration be run in order to create a new table. Unfortunately, when I tried to run the rake db:migrate command it complained that I was missing a gem. So I tried to install the gem using the command: sudo gem install [gem name].

Here is where the problem comes in. Since I was running RubyGems version 1.0.1, trying to install or update any gem (including updating itself!) would hammer my poor little web server. I think I waited at least 5-10 minutes before killing the process.

This happens because there is a bug in earlier versions of RubyGems. Updating to a newer version (at least 1.2.0) will take care of the issue. Unfortunately, since downloading the RubyGems update will kill the server using the gem update command, I had to install it manually.

First thing is first; download the gem manually using WGET (at the time of this writing the latest RubyGems is at 1.3.1.


wget http://rubyforge.org/frs/download.php/45904/rubygems-update-1.3.1.gem

Once it has been downloaded, install it:


sudo gem install rubygems-update-1.3.1.gem

Finally, update RubyGems:


sudo update_rubygems

If everything went OK, you should see 1.3.1 when running the command gem -v.

Once RubyGems was updated, downloading a single gem was almost instantaneous.

Released Tagging Feature for Site

February 01, 2009 — 0 Comments

I think the last new feature was Gravatar support way back in September of 2008. Now I’ve finally gotten enough free time to release a couple of new features. The first is linkable tags on post pages. I’ve had the ability to add tag for a while when creating a new post and they can be seen on the homepage and on post specific pages but they haven’t been linkable until now. Click on a tag and see what other posts have been marked with that tag.

Eventually I’ll add some sort of tag cloud so that one can see the most popular tags but that’s an update for another day.

Released Subscriptions Feature for Posts on Site

February 01, 2009 — 0 Comments

Having the ability to allow users to subscribe to a post (and therefore getting email updates when someone adds a follow-up comment) is something that I’ve been wanting to implement ever since I rolled out the first version with Ruby on Rails.

I think I first started the initial implementation of a subscription engine a few months back but it was extremely buggy and I was not satisfied with the underlying code. A couple of weeks ago, I dove in again and hacked a working version.

The implementation worked, but I was unhappy with the underlying code as it was based on code that I had written years ago. Now that my skill set has improved, I decided to rip out most of what was there and code up a cleaner version of the workable code.

After some rigorous testing, I’m finally happy with the implementation and the underlying code.

So how does it all work? Well, it’s simple really. If you want to be notified (by email) of follow-up comments to a post, click the Subscribe via email checkbox and post your comment. You’ll receive an email confirmation that let’s you know which post you’ve subscribed to. If someone posts a follow-up comment, you’ll get an email notification.

If you don’t want to be notified anymore, there is an opt-out/unsubscribe link on the emails that are sent out. Follow that link and the subscription to that specific post is terminated.

Object#type Errors with Single Table Inheritance

February 03, 2009 — 0 Comments

Everybody probably already know this but what the hell. I was working on some code recently using Single Table Inheritance and was getting errors in the console and log when comparing the type field.

Before I get into the error itself and what I’m doing to correct it, a little background on Single Table Inheritance. Suppose you have employees in your database and you have two employee types; managers and staff.

You might have the following model objects:


class Manager < ActiveRecord::Base
end

class Staff < ActiveRecord::Base
end

And in the database, you’d have two separate tables; one for managers and one for staff. This is fine if the Manager table and the Staff table differ greatly from one another, but if they are identical with the exception of the type (Manager or Staff) then they can be combined in one table and be referenced in Rails using Single Table Inheritance.

This is done by having one class that Manager and Staff inherit from:


class Employee < ActiveRecord::Base
end

class Manager < Employee
end

class Staff < Employee
end

Now you can have one table, Employee, with a type column that differentiates that two. For example:

id type full_name phone_number
1 Staff Joe Jukem 5035551212
2 Manager Joe Blow 7025551212

Now here is where the problem comes in. Apparently “type” shouldn’t be used in your code. So when you’re doing something like this:


x = Employee.find :first
if x.type == Manager
   do something here
end

You’ll get a message that reads: warning: Object#type is deprecated; use Object#class instead. Now, obviously, the fix is to use something like this:


x = Employee.find :first
if x.class == Manager
   do something here
end

That works, but I like the more readable version using the is_a? method. For example:


x = Employee.find :first
if x.is_a?(Manager)
   do something here
end

Buildin’ the Blog: Part 5 – Refactoring

February 15, 2009 — 0 Comments

It’s been a long time since I posted something in this series, almost 3 years to be exact, and it’s about due.

One of the things that developers do when they are new to the MVC paradigm/Rails is to litter their controllers with all sorts of business rules code. This isn’t a fault really. For beginners it’s a way to get your app and running quickly.

As a developer matures with the MVC paradigm, they begin to see that there is a better way to do things (think Fat Model/Skinny Controller). That certainly was the case with me.

For instance, the create action of my blog’s comment controller (the heaviest action by far) weighed in at a hefty 61 lines of code. After doing a bit of refactoring, my controller has dropped to 25 lines of code. Still not perfect, but all of the comment processing code has been moved into the model.

Let’s take a look at how and why I made the changes.

First thing is first. Since I’m using the Akismet web service to check for comment spam, I need to track the referrer, the IP address of the client, and the User Agent.

I used to have a line of code in the create action that got this information by calling a method in the Application Controller.


options = get_browser_info

That method was defined as:


def get_browser_info
  options = { :ip_address => request.env["REMOTE_ADDR"], 
                :user_agent => request.env["HTTP_USER_AGENT"], :referer => request.env["HTTP_REFERER"] }
end

This worked, but it lacked a little sophistication.

The new method in the Application Controller:


def fetch_browser_info
 @browser_info = { :ip_address => request.env["REMOTE_ADDR"], 
  :user_agent => request.env["HTTP_USER_AGENT"], :referer => request.env["HTTP_REFERER"] }
end

Now in the Comments controller, I can run a before filter on the actions that need this:


before_filter :fetch_browser_info, :only => :create

Unfortunately, the old Akismet plugin that I was using, ror_akismet, enforced the use of extra methods in the controller. I changed this up, by copying the akismet.rb file to my lib directory and removing its dependence on the controller. And yes, I know that ror_akismet is the old library file and rakismet is the replacement. At the time, I didn’t want to install and futz with the new plugin.

That allowed me to pull this entire code block:


if is_spam?(:comment_content => @comment.body, :comment_author => @comment.name, 
                :comment_author_email => @comment.email, :user_ip => @comment.ip_address, 
                :referrer => @comment.referer, :user_agent => @comment.user_agent)

That now goes into the model. With a code block that looks like this:


if is_spam?( { :comment_content => self.body, :comment_author => self.name, :comment_author_email => self.email, :user_ip => self.ip_address, :referrer => self.referer, :user_agent => self.user_agent }.merge(self.akismet_attributes))

That’s it for this edition of Buildin’ the Blog, but I’m not done rebuilding my Comments create action. In the next part of the series, I’ll cover how to access variables that aren’t part of your Model’s attributes (table columns) and a quick note about security.

Twonky Media Server 5.05 Up and Running

February 28, 2009 — 0 Comments

A year ago I posted an article on how I stream videos and music to my Xbox 360 using Linux and PacketVideo’s TwonkyMedia DLNA server.

In the year and a quarter since I posted the article a few things have changed. I picked up a PS3 which also allows me to stream music and videos to it and the new version of the TwonkyMedia server software was released. Unfortunately, the new version, version 5, broke my existing setup. So much so that I had to revert back to using 4.4.11.

After upgrading to the latest version, I setup the content directories that I wanted it to scan and it would never pick up anything and therefore no streaming. This afternoon, after poring through their forums (their actual support is terrible), I downloaded their beta release of 5 (version 5.055 to be exact) and tried to get it running again. No go.

I gave up, uninstalled version 5 and went back to version 4.4.11; at least for a couple of hours. Fortunately for me, my determination to solve problems is almost otherworldly.

In my instance, the problem was occurring because I had my media in the /var directory (/var/media/music and /var/media/video to be exact). For some reason, version 5 of the software refused to read any media from this location. Quite irritating.

The server was reading media from other locations and that was my clue that the server was working, just not reading from the /var directory. Moving all of my media from one location to another would be a pain in the ass, so using a tip from a forum poster I tried creating a symlink (aka alias) from my media directories to my home directory with the following commands:


ln -s /var/media/video /home/carlos/video

Once that was done, I put in the new content directories into Twonky (/home/carlos/video and /home/carlos/music) and then restarted the server. After restart I told it to re-scan the content directories and it finally recognized my media.

Now if only it could stream Hulu…

Buildin’ the Blog: Part 5 – Refactoring: Part 2

March 14, 2009 — 1 Comment

In my last Buildin’ the Blog article, I wrote about how I cleaned up my comments controller by moving all of the processing to the model. In this follow-up article, I’m going to write about how to access properties that aren’t part of your model object (aka table).

Take for example, a simple comments database table. It might look like this:

id full_name email_address url body

As you can see this is pretty straightforward, a single comment is comprised of a full_name, email_address, and the body. These attributes can easily be checked and processed in our comment model. Here comes the tricky part.

Take for instance my comment form below:

comment form photo

Name, email address, URL, and the body of the comment can all be mapped to database table fields. Unfortunately, Remember Me and Subscribe Via Email cannot and should not.

A beginner in Rails might write something like the following in their controller code:


if params[:subscribe]
#create a subscription record here
end

This code works but it leaves a lot of logic in the controller. The controller should be fairly lightweight, “I accept input from the user pass it to the model and then I pass it back to the browser/user.”

In order to get non-database bound fields to the model we use Ruby’s attr_accessor declaration (we could use attr_writer too to only write attributes and not read them).

For example:


class Comment < ActiveRecord::Base
  attr_accessor :subscribe
end

This allows me to create a form like the following:


  <% form_for @comment do |f| %>
  <%= f.text_field :full_name %>
  ...snip...
 <%= f.check_box :subscribe %>
 <%= f.submit %>

Once this is done, I can check what the value of the checkbox was set to in the model in a callback (let’s say either a before_save or an after_save):


  def before_save
    if self.subscribe == 1
      #create a subscription record here
    end
  end

It’s that simple. Now all of my logic can be done in the model.

With that out of the way, here is something to watch out for. Let’s say that you have a comments table that looks like this:

id full_name email_address url body is_admin

Obviously, the is_admin attribute should be set by the application and not by the user but unless you protect your model, the user can set any attribute he wants. Let’s say that you have a simple comments form with full_name, email_address, url, and body. The is_admin attribute is not displayed as a form field.

A malicious user could come by and change the form by adding the following or by submitting to the comment form using cURL. Here is an example:


  <input type="checkbox" name="comment[is_admin] checked="checked" />

By crafting this form and sending it, the user automatically becomes an admin!

One way to protect your application from this type of malicious activity is by protecting fields that should never be set by the user behind the attr_protected declaration. For example:


class Comment < ActiveRecord::Base
  attr_protected :is_admin
end

This will stop malicious users from trying to set attributes that should never be set by the user.

Canonical URLs

April 14, 2009 — 2 Comments

Canonical URLs are all the rage on the Internet nowadays. All one has to do is do a Twitter search for canonical to see the conversations going on.

The problem is this, micro-blogging services such as Twitter only allow a certain number of characters, so a URL like this http://eddorre.com/posts/buildin-the-blog-part-5-refactoring-part-2, is too long. This is where URL shorteners like tinyurl.com come in.

They take a long, but perfectly fine URL, and make it something like this: http://tinyurl.com/Hukjfd (this is an example – not a real link). This is much more useful on Twitter where character space is at a premium. However this has its own problems, one is trust. How can you trust tinyurl.com to actually be delivering you to a URL that you would even want to visit? Short answer, you don’t. Also, what happens if tinyurl.com goes away one day? Any search on Twitter that uses these links immediately becomes less valuable. It’s the opinion of some on the Internet, that a site should take care of its own short urls.

For example, the link http://eddorre.com/posts/buildin-the-blog-part-5-refactoring-part-2, could become http://eddorre.com/s/SQ2BAs. Notice that the domain remains the same and short url is under my control. If the link goes away it’s MY fault not someone else’s. I have a vested interest in making sure that the link doesn’t go away. It doesn’t solve the trust issue, but at least you know that it’s a link coming from eddorre.com instead of anywhere on the Internet.

Enter the debate about canonical URLs and rev=canonical. The theory behind rev=canonical is simple. When I include a link like this: http://eddorre.com/posts/buildin-the-blog-part-5-refactoring-part-2 in Twitter or a similar website, they will then load up the original link and look inside the HTML for markup that looks like this:


<link rev="canonical" href="http://eddorre.com/s/SQ2BAs" />

When Twitter or a similar service finds this tag, they should then replace the long link with the short one. It makes sense but this does have one drawback that will most likely kill its adoption. It’s expensive. Twitter, for every link that is posted, has to connect to the URL, parse the HTML and then return a new link if it supports canonical URLs.

With that in mind, there is a proposed new HTTP header for canonical URLs that a web server could return to a service like Twitter. Something like “X-Rev-Canonical: href=”http://eddorre.com/s/SQ2BAs". This way, Twitter or other services just have to do a GET request to the original URL and it would just return them the short URL. No downloading and parsing the HTML. Whether either of these methods becomes widely adopted remains to be seen.

This past Saturday, after reading comments in Twitter and blogs about short urls, I decided to try coding up my own system for my blog. Turns out it only took me about 15 minutes to code something in Ruby/Rails.

Here is how I did it.

  • I created a migration to my posts table to include a short_url column
  • Created a before_create callback method in my post model to create a short_url.
  • The creation of the short_url is done by randomly mixing 6 characters from the characters available in Base 62 encoding (meaning: 0-9, A-Z and a-z).
  • To create short_urls for all of my older blog posts, I just created a migration that looped through all of the blog posts and generated this random token string for all of those and saved them.

I create a named route similar to the following:


map.short_url "/s/:short_url", :controller => 'posts', :action => 'show'                                   

Next, in my controller I did something similar to this:


    if params[:short_url]
      @post = Post.find_by_short_url(params[:short_url])
      redirect_to post_path(@post), :status => :moved_permanently and return
    else
      @post = Post.find_by_permalink(params[:id])
    end

There you have it. Something quick and dirty in about 15 minutes. Now if I want to post links to my blog on Twitter, I can use my own short url instead of using a service like tinyurl.

I should note that this probably isn’t the best way of doing things and it’s most certainly not the only way, but for a quick hack project on a Saturday afternoon, it fit the bill.

I forgot to mention that the inspiration for this post was Duncan Davidson’s post Everybody Wants Short Links.

WebVisions Tentative Schedule

May 20, 2009 — 0 Comments

WebVisions, the web focused conference held in Portland, Oregon is upon us. This year, there was a special two-for-one conference pass with WebVisions and OS Bridge for 300 bucks. I couldn’t pass that offer up so I signed up.

Here is my tentative schedule for Thursday and Friday:

Thursday

  • 9:15 Cooking Up Gourmet User Experiences on a Fast-Food Budget – Jared Spool
  • 10:30 Design for Effective Knowledge Transfer: Don’t Repeat the Same ’Ol Same ’Ol – Todd Hudson
  • 1:15 Mental Models: Sparking Creativity Through Empathy – Indi Young
  • 2:45 Subject to Change: Creating Great Products and Services for an Uncertain World

Friday

  • 9:15 Makin’ Whuffie: Why You Should Raise Social Capital in Online Communities – Tara Hunt
  • 10:30 How to Win Projects and Influence Budgets – Daniel Schutzsmith
  • 1:15 Web Design: The Good, the Bad and the Future – JD Hoodge
  • 2:45 Process Meets Presentation: Visual Design – Jina Bolton
  • 4:15 Carpe Futurm: Building Communities Without the Blueprints

The Git Parabale – My Take

May 31, 2009 — 2 Comments

Tom Preston-Werner, one of the founders of GitHub, recently posted an article titled The Git Parable.

His assertion is that most people teach the functions of Git incorrectly, or in his words, Most people try to teach Git by demonstrating a few dozen commands and then yelling “tadaaaaa.” I believe this method is flawed. Such a treatment may leave you with the ability to use Git to perform simple tasks, but the Git commands will still feel like magical incantations.

He offers an alternative solution, which happens to be the rest of his article — all 4,126 words of it. There is nothing wrong with his article, but using it to teach Git? No way. If anything, it should be the 4th step in teaching Git; definitely not the first.

There seems to be a fundamental misunderstanding about how information is consumed and retained (retained being the most important piece) by people. Let me explain.

Let’s say that you’re being taught how to do something. For the sake of the argument, you’ll want to choose something that’s out of your comfort zone. So if you’re a programmer that doesn’t know anything about knitting, you’d choose that. If you’re a chef that doesn’t know anything about programming, you’d choose that, etc.

Rank the following in how you like to learn about this new skill.

  • I want to read about it
  • I want to talk to someone about it
  • I want to see someone do it
  • I want to be hands on and do it

How did you do?

Most people retain information using the following method:

  • I want to see someone do it
  • I want to be hands on and do it
  • I want to talk to someone about it
  • I want to read about it

Notice where reading is. Notice where seeing is. This is one of the reasons that screencasts, cooking TV shows, and pair programming are so popular amongst neophytes. See and then do. Reading is usually reserved for reference; “I know how to do the basics of this skill, but I want to expand upon it.”

Of course, this is predicated on the person’s learning style. If you chose “reading first” and then “doing” then Tom’s article, The Git Parable, would be right up your alley but it’s been my experience that most people simply do not learn in this fashion. In a very non-scientific and informal poll of people in the audience at Todd Hudson’s talk on Design for Effective Knowledge Transfer at WebVisions people overwhelmingly chose “seeing”, “doing”, “talking” and finally “reading”.

Interestingly enough, people also like the ability to be able to “switch” into the different learning modes as quickly as possible. Anything that prevents that this “learning switching” is going to detract from the end goal of information retention and knowledge transfer. An example of this? Let’s say that I’m watching a 20 minute screencast on how to get started with jQuery. I may watch the first 5 minutes of it, then immediately switch to trying to do it and then when I get stuck, I might want to go back to watching the rest of the screencast or I might try asking a co-worker or a friend. This is where most online learning goes wrong. It doesn’t allow the user to experience knowledge transfer in the way that they need to. Therefore retention of information goes down.

Based off of this information, the way to teach Git is not by reading a 4000 page article first. In fact, you’re most likely going to lose people and discourage them from learning the material in the first place.

Email Migration to GMail

July 03, 2009 — 0 Comments

Mailplane logoTwo years ago, I wrote a post called The Warhawk Flies that summarized my email server migration from Microsoft’s Exchange Server 2003 to the open source combination of Postfix and Cyrus IMAP. The move was both liberating and educational.

The experience with Debian, BIND DNS, MTAs and the IMAP protocol were well worth it and the server has been performing admirably ever since installation. Of course, hosting your own email server from your house isn’t without its drawbacks.

First is the actual server itself. Although the server is housed in a Mini-ATX case, it still takes up room and power. Then there is the noise. It’s much quieter than what I had before, by a measure of ten-fold, but it still gives off some noise. Most of the time I don’t care but sometimes I’d rather not have my home office sound like a mini server room.

Second is the maintenance. Backup routines, making sure that software and security updates are installed, and gawd forbid that there is an actual hardware failure. Most of these can be automated, but I’d rather spend my time doing something else.

Lastly, my notion of how email should work has changed. Although I was constantly squirreling away email in their own separate folders, I never actually found any old email by traversing the folder hierarchy; I simply searched for it. Google’s implementation of labels allow me to categorize and archive email without having to create a complex archival folder structure. At first I found this backwards, but the more that I used it at work the more I started to see the merits of adopting such a system.

With those drawbacks in mind, I started thinking about potentially moving my email and my email domain to GMail. After some deliberation and some clarification of what GMail’s service could and couldn’t do via our sysadmin (@demonbane) I decided to take the jump.

I signed up for the pro account ($50 a year per mailbox) so that I could use their IMAP4 import tools. You can cancel this after the free trial is over and I’ll probably do that because there is no compelling reason to keep my GMail account at the pro level.

Importing two mail boxes (my girlfriend’s and mine) took approximately 2 and a half hours. During that time, I changed all of my MX records to point to Google so that I would be up and running by the time the import was done.

Since I now have 3 GMail accounts that I’m checking (work, home and another domain that I manage), I decided to pick up a copy of Mailplane, which is basically an OS X application that wraps GMail, and allows you to switch accounts with a click of a button (probably the primary reason I chose to install Mailplane).

After the import was done, I tested inbound and outbound email and it worked flawlessly. No one on the outside could tell that my mail was now being routed and hosted at Google. Ultimately, I’m quite happy with hosting my email through Google.

Upgrade to iPhone 3GS

July 05, 2009 — 0 Comments

I bought my first generation iPhone 6 months after it had debuted in the market. It’s the first mobile device that I’ve actually bought myself. All of the previous mobile devices that I have had (including the terrible Windows Mobile Phone) have been owned by the company that I used to work for.

From the minute that I got it, I’ve loved it. Simplicity and elegance, Internet access from anywhere (where there was an EDGE connection), a full web browser and more.

As an Apple enthusiast, when the 3G iPhone version was released, I wanted to pick up the new model but there was little reason to upgrade (with the exception of the 3G speed boost). With very little motivation to upgrade, I stuck it out with my 1st generation iPhone.

A year after 3G model was released, I was completely frustrated with the speed of the EDGE connection. It reminded me of the old modem days. Anytime that I wanted information quickly the connection sputtered; traffic, email, weather, maps, directions, you name it. It reminded me of the old modem days and that’s something that I would rather forget.

When Apple released their new iPhone 3GS model, I knew that I was going to upgrade. In my mind, the main reason for upgrading was the 3G speed increase, everything else would be extra toppings.

I have to say that this is one of the best upgrades I’ve ever done (on any device; computer or electronic device). I came for the 3G connection, but everything about this new phone is better. Here is my list of reasons to upgrade from earlier versions of the iPhone:

  • 3G speed (Obviously the 1st gen 3G iPhone already had this)
  • GPS (The 1st gen 3G iPhone already had this)
  • Device specs upgrade (although Apple doesn’t publish the new specs the CPU increase and memory bump are noticeable)
  • Oleophobic screen (my 1st gen iPhone was a magnet for the oils that your skin secretes. This one has a new coating that keeps it to a minimum)
  • Better camera (new 3 mega pixel camera with auto focus)
  • All new video camera (VGA recording up to 30 fps with audio. Takes surprisingly good video for a phone (even in low light))
  • Better built in speakers (I believe the 1st gen 3G iPhone had the new speakers. I can finally hear my phone ring inside of my messenger bag)
  • Voice control (for voice calling and controlling iPod)

If you have a 1st gen iPhone and can afford it, I think that this upgrade is a no brainer. Even if you have a regular 3G iPhone, I think that this upgrade is still worth it (unless you rarely use the camera).

A System for Distributing Local and Regional News Data

July 10, 2009 — 2 Comments

I live in Vancouver, Washington but I commute to Portland for work every week day. For my commute, I usually take I-5 and therefore have to traverse Interstate Bridge to cross over into Oregon. The bridge allows for marine traffic on the Columbia River to pass underneath by lifting the spans and thus closing traffic off until it is clear. Naturally, because of the traffic implications, this is an event that occurs rather infrequently, but it still occurs nonetheless.

There have been times when I’ve been unfortunate enough to be stuck in traffic while a bridge lift was happening. Judging by the amount of other commuters and freight vehicles stuck beside me, I’m guessing that information about spans lifting isn’t being distributed efficiently.

The last time this happened, I tweeted the message: “Does anyone know if ODOT or WADOT make notifications (of any kind – web other otherwise) before they raise the I5 Interstate Bridge?” I was curious about this because I wanted to make a simple web app that tells you if the span is up or down.

A few days later, a response came from the OregonDOT’s twitter account, "Yes, we send traffic alert to Portland area traffic reporters before a bridge lift. @pdxcommute usually tweets about them. They shared a number for me to call for more information and while I have not yet called to get the details my mind started wondering how they would be able to distribute this information in a timely manner to multiple sources. I put the idea out of my head until I read Ilya Grigorik’s post titled HTTP PubSub: Webhooks & PubSubHubbub.

Using that as a springboard, I’ve come up with a conceptual system that addresses these questions.

Let’s say that you operate a web application that distributes traffic information to subscribers via IM, Email, SMS or Twitter. You’ll want to get that information from a reliable source and in Oregon that would be ODOT.

ODOT will surely have more than one service asking for traffic update data, so a polling mechanism on the client end is very inefficient for both the server and the client. Here, PubSubHubbub makes perfect sense. Images below are adapted from this Google Document (PubSubHubbub Subscription Flow Draft 0.1):

In step 1, you can see that my fictional web application (Subscriber) asks the ODOT Publisher to subscribe to traffic data. The Publisher sends information to the subscriber telling it where it can receive that data.

Step 1 in A System for Distributing Local and Regional News Data

In step 2, our web application subscribes to the data feed and tells the Hub to send updates to a specific URL.

Step 2 in A System for Distributing Local and Regional News Data

In step 3, there is some security checking from the Hub back to the Subscriber. The Hub sends the data to the URL that the Subscriber specified in step 2.

Step 3 in A System for Distributing Local and Regional News Data

In step 4, Someone at ODOT has posted a new traffic update and therefore the Publisher updates the specified Hub.

Step 4 in A System for Distributing Local and Regional News Data

In step 5, the Hub POSTs the update to the endpoint URL that the Subscriber specified in Step 2. Although the diagram below shows the interaction between the Hub and one Subscriber, in theory a Hub can update multiple Subscribers at once.

Step 5 in A System for Distributing Local and Regional News Data

In the final step, the Subscriber can then re-post the data via IM, Twitter, Email, or SMS or simply display it on their website. Once a Subscriber gets a hold of that data, then it’s up to them what they do with it.

Step 6 in A System for Distributing Local and Regional News Data

This conceptual method for delivering data is much more efficient. Besides the initial setup, the only data that’s being transferred is actual data and there is no useless polling going on. Although PubSubHubbub is one solution to the polling problem, it’s not the only one. Others are using the IM standard, XMPP, to also distribute information to Subscribers.

If you’re interested in PubSubHubbub, I strongly suggest that you read the documentation at Google’s Code page.

How I’m Managing the River of News

October 21, 2009 — 2 Comments

Keeping up with the flood of information these days almost seems like a monumental task. Between blogs and Twitter, I found myself constantly having about 30-70 tabs open in Safari just to keep track of the stuff that I wanted to read but hadn’t gotten around to yet.

I originally started trying to manage all of this information using Delicious but I found that it took too much cognitive load for rapid fire archival and retrieval especially when on my iPhone. Don’t get me wrong, I use Delicious for long term storage and reference but it’s not so good for stashing away, say, a tweet with a link.

Recently, I’ve been incorporating Instapaper into my workflow to stash away these links; a kind of GTD “Someday” bucket as it were.

The best thing about using Instapaper, is that people are starting to incorporate it into their apps. For example, my feed reader and my Twitter client on the iPhone (NetNewsWire and Tweetie 2 respectively) both support saving links off to Instapaper. Above and beyond that, you can also use the Read Later bookmarklet to automatically save links from your browser (mobile or otherwise).

Now if I come across an interesting link that I don’t have time to read that very second, I just save it off to Instapaper. When I have time, I’ll go through the links and read them. Some are one offs that I don’t care to save and the others get archived quite nicely into Delicious.

Using this method, I’m actually reading more instead of skimming and my Safari tabs have been tamed and now come in at around 5-10.

MacBook Pro Screen Flickering

October 27, 2009 — 3 Comments

I’ve had my MacBook Pro for almost a year now and I haven’t had a single problem with it, that is until recently. I’m guessing that the install of Snow Leopard has triggered a bug somewhere in the system that causes the screen to flicker. The only time I’ve noticed the flickering screen is when I have an external monitor connected to it.

For those wondering, this is what the flickering looks like.

Some people have been saying that you need to zap the PRAM but others dispute as not doing anything. I’ve found something that seems to work. This is obviously a bug somewhere and I hope that an update to Snow Leopard fixes this sooner rather than later (I’ve heard it’s supposed to be the next update).

Go into the Energy Saver Preference Pane and change the Graphics option from “Better battery life” to “Higher Performance”. After making this change, the screen no longer flickers. Obviously this is going to chew through your battery like there is no tomorrow, but it can be toggled back and forth (NOTE: To toggle this setting you need to logout of your user account and log back in).

Energy Saver Preference Pane

My Web Development Toolbox

November 01, 2009 — 3 Comments

I recently posted a guide to installing Ruby on Rails on a Mac that was adapted from my own installation notes. The article was specifically focused (and rightfully so) on just installing Ruby on Rails but I wanted to cover some of the apps that fill out my web development toolbox after a fresh install.

LaunchBar

LaunchBar

Not necessarily directly related to web development, but I find that I can’t live without a quick application launcher anymore. Instead of digging through the Applications directory for the app that I want to run or littering my dock with icons, I just hit CTRL + SPACE type in the first few letters of the application and hit ENTER when LaunchBar finds it.

LaunchBar isn’t free, but it’s what I’ve been using for a while.

Other alternatives: Quicksilver, Google’s Quick Search Box

TextMate

textmate

TextMate is where I spend a majority of my day. This text editor does it all. Ruby, Rails, Javascript, HTML, CSS, C, Objective-C and more. Beyond the huge number of languages that it supports (all with theme-able color coded syntax) it has a ton of bundles that provide keyboard shortcuts that dramatically speed up your development time.

Other alternatives: BBEdit, Coda

Safari’s Web Inspector and Firefox’s Firebug

Web Inspector

Firebug

One of the first things that I do when setting up a new Mac, is I turn on the Web Inspector in Safari and install Firebug in Firefox. I don’t think that I could develop on the web without these tools. Inspecting elements, the Javascript console, integrated resource tracking, Javascript profiling and a whole lot more.

Although I started out using Firebug exclusively, I’ve found that I actually prefer the Web Inspector now and it’s about to get even better. Joseph “BogoJoker” Pecoraro put up an excellent post titled Improving the Web Inspector with a ton of forthcoming improvements to the Web Inspector. If you’re impatient and want to play with these features now, you can download the WebKit Nightly builds.

Skitch

Skitch

An immensely valuable tool for collaboration. With it, you can take a snapshot of anything on your screen and then annotate it with text and shapes (of any color). You can then upload those images to Skitch’s web service and share among co-workers and clients. Did I mention that it’s free?

All of the image from this post were taken with Skitch.

Alternative: LittleSnapper

xScope

Screen Loupe

Iconfactory’s xScope is 7 tools in one. Dimensions, Rulers, Screens, Loupe, Guides, Frames, and Crosshair. Basically, xScope is a set of tools that are ideal for measuring , aligning and inspecting on screen graphics, elements, and layout. All of the tools float above windows and UI elements, so they don’t get in your way.

I find that the Loupe (pictured above) tool is my favorite and most used out of all of them. It magnifies anything that’s underneath it and gives you the X and Y coordinates as well as color information in hex, RGB, and HSB.

Color Picker

Color Picker

Speaking of color, OS X’s built in Color Picker the tool for building a color palette. Unfortunately, by default the Color Picker app is only available in applications where you can modify the color or fonts or graphics. Luckily, there is a way to make the Color Picker its own app by just one line of Applescript code. The instructions are easy:

  • Open the AppleScript Editor
  • Type the words: choose color
  • Save the file as an application giving it the title of Color Picker (this can be whatever you want but it makes sense to just call it Color Picker, no?)

You can replace the default script icon with an icon of your choice by doing the following:

  • Right click on the Color Picker application and selecting Show Package Contents
  • Open the Contents/Resources directory
  • Replace the applet.icns file with one of your choice

You can download the one that I use:

Color Picker Icon

Copy the newly created application to your Applications folder and now you can launch the Color Picker from anywhere.

If that wasn’t enough you can extend the Color Picker itself. Installing extensions is as easy as copying the extension file to ~/Library/ColorPickers or alternatively ~/Users/[username]/Library/ColorPickers if you only want the extensions to be available for a specific user.

I’m currently using 3 extensions to the Color Picker. The first one is the Developer Color Picker from Panic. This extension allows you to copy color is a variety of formats to the clipboard; NSColor, CGColorRef, UIColor, HTML (aka hex), and CSS (aka RGB).

The second extension, is the Hex Color Picker from Waffle Software. This is useful if you don’t want all of the options that Panic’s Developer Color Picker gives you. Just the hex, please.

The third extension that I have installed is Mondrainum 2 from the folks and Lithoglyph. Mondranium uses an API to talk to the Adobe Kuler web service. What is Adobe Kuler? It’s a site that allows one to create and share color themes.

Mondranium

Want a color theme for your site but you’re stuck or are low on inspiration? Choose from over 14,000 color palettes (as of this writing) all from the Color Picker itself.

Certainly these are not all of the tools that I use but these are the ones that I keep coming back to day after day and developing on the web wouldn’t be as much fun without these tools.

What tools do you use on a day to day basis?

Installing Ruby on Rails, PostgreSQL, MySQL on Snow Leopard

October 27, 2009 — 17 Comments

Snow Leopard, Apple’s latest release of their OS X Operating System, was released last month. I pre-ordered it from Amazon but it’s only now that I’ve gotten around to installing it on my machines. I first installed it on my Mac Mini as a fresh install and because of that, I wanted to document the process. I probably could have upgraded Leopard to Snow Leopard, but I didn’t want 32bit binaries floating around where I could have been using a 64bit binary.


Determining whether or not your Mac is 64bit or 32bit is based on the processor. Click on the Apple logo in the menu bar and choose About This Mac. Look at the processor type. If it’s a Core Duo, you have a 32bit Mac, if it’s a Core 2 Duo then you have a 64bit Mac. Keep that in mind when installing applications like RubyGems and database drivers.

One more thing, with this guide, I stuck with MacPorts for some application installs. I know that Homebrew is all the rage nowadays, but I’ve had little to no trouble using MacPorts, so that’s what I’ve stuck with.

Installing XCode

This whole process breaks down if you don’t install XCode, so go ahead an do that now. You could probably download it online but since the Snow Leopard DVD is only a month old (at the time of this writing), go ahead an install it from there.

Just in case you’ve never installed XCode, it’s located on the DVD in the Optional Installs directory. Just run the Xcode.mpkg installer. Choose the default settings for the installation.

Installing MacPorts

Head on over to the MacPorts site and download the dmg disk image for Snow Leopard. Once the download is complete, run the installer from the mounted disk image. I chose the defaults through the installation process.

The Snow Leopard version of MacPorts should modify your $PATH automatically so that you can run “port” commands from the Terminal without having to prefix it with the location path of the MacPort binaries. If you want to make sure, you can run this command from the Terminal:

cat ~/.profile

You should see something similar to this:

# MacPorts Installer addition on 2009-10-08_at_19:43:18: adding an appropriate PATH variable for use with MacPorts.
export PATH=/opt/local/bin:/opt/local/sbin:/usr/local/bin:$PATH
# Finished adapting your PATH environment variable for use with MacPorts.

If you don’t see this, you’ll want to edit your path to include /opt/local/bin and opt/local/sbin. You can do this by opening your .profile file with TextEdit and make the changes:

sudo '/Applications/TextEdit.app/Contents/MacOS/TextEdit' ~/.profile

Add the following lines before “$PATH”:

/opt/local/bin:/opt/local/sbin:/usr/local/bin:

Now you should be able to run the command

which port
and see the output
/opt/local/bin/port

MacPorts should correctly compile the correct version (32bit vs 64bit) of applications and libraries for you based on your CPU (confused about which Mac version you have?). If you’re feeling paranoid and want to force it to always use a certain mode, you can use your favorite text editor and edit the file at:

/opt/local/etc/macports/macports.conf
Example:
open -e /opt/local/etc/macports/macports.conf

Look in the file for the commented out “build_arch” declaration. If you want to force 64bit mode for example, you’d uncomment the line and change the value to x86_64.

Ruby, Rails, and Gems

Snow Leopard, like it’s predecessor comes bundled with a version of Ruby, Rails, and RubyGems. Since I’ve been using Rails professionally, I always like to install my own version of Ruby and RubyGems from MacPorts. I also like to download Rails from the gem source myself.

Before we can do that, we should hide the versions that come pre-bundled with Snow Leopard.

You can do that by running the following commands in the Terminal (inputting your password where requested):

sudo mv /usr/bin/ruby /usr/bin/ruby.orig
sudo mv /usr/bin/gem /usr/bin/gem.orig
sudo mv /usr/bin/rails /usr/bin/rails.orig

Finally we’re ready to install Ruby and RubyGems via MacPorts. Just run the following from the Terminal:

sudo port install ruby rb-rubygems

This will take a while, so you might want to take a break and stretch your legs while it’s doing its business. Once Ruby and RubyGems have been installed, you can go ahead and install Rails itself.

sudo gem install rails

Installing Your Database Servers

I use both PostgreSQL and MySQL but you don’t have to install them. In fact, since Rails uses SQLite for development (by default) you might not need to install either of them. With that being said, I highly recommend to install both database servers just in case you need to use them.

Installing both is quite trivial but make sure to pay attention to the output at the end of the commands as it has text that you’ll want to copy and paste into your Terminal. Run the following commands for PostgreSQL:

sudo port install postgresql84 postgresql84-server

Again, make sure you read the post install text as it’ll direct you to install a default database, create a default postgres user, and setup PostgreSQL to start automatically at start up. (recommended).

Once you’ve run the commands that it has suggestion, it’s a good time to add PostgreSQL to your path so that you can install the database driver. Again, open your .profile and edit your path and add the following right before “$PATH”.

/opt/local/lib/postgresql84/bin/:

Install the PostgreSQL Rails database driver by running the command:

sudo env ARCHFLAGS="-arch x86_64" gem install pg

If you want to install the 32bit driver, then you can just run:

sudo gem install pg

Installing MySQL is as simple as installing PostgreSQL. In the Terminal:

sudo port install mysql5 mysql5-server

Just like in the PostgreSQL install, make sure you read the post install text. It’ll have you setup a default database, and will give you a command so that MySQL can load at start up (recommended).

After MySQL has been installed you’ll want to install the MySQL database driver for Rails:

sudo env ARCHFLAGS="-arch x86_64" gem install mysql -- --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config

If you want the 32 version:

sudo env ARCHFLAGS="-arch i386" gem install mysql -- --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config

By default, MySQL likes to use UNIX sockets for communication and therefore it needs a .sock file. I usually like to store mine in /tmp/mysql.sock. It doesn’t exist by default, so you’ll have to create it:

sudo touch /tmp/mysql.sock

After that file has been created you’ll have to tell MySQL to use your newly created socket file:

sudo touch /opt/local/etc/mysql5/my.cnf
sudo '/Applications/TextEdit.app/Contents/MacOS/TextEdit' /opt/local/etc/mysql5/my.cnf

Add the following to the my.cnf file:

[mysqld_safe]
socket=/tmp/mysql.sock

[client]
socket=/tmp/mysql.sock

PostgreSQL and MySQL should now be installed but you’ll want to install the SQLite database driver gem. It’s dead simple:

sudo gem install sqlite3-ruby

Installing Your Web Server

I use Passenger for my development web server and I highly recommend you doing the same. It’s not necessary, so you can certainly skip the step if you’d like.

Before we start installing anything, let’s turn on Apache. Go to the Sharing Preference pane under System Preferences and check Web Sharing. This should activate Apache.

Let’s install the Passenger gem and the Apache 2 module:

sudo gem install passenger
sudo passenger-install-apache2-module

Make sure that you read the text after the Apache module has been installed. It will give you lines of text that you’ll need to copy into your Apache config file.

Here is a sample of mine:

# Passenger modules and configuration
LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so
PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6
PassengerRuby /opt/local/bin/ruby

I create a Passenger specific config file to hold this information:

sudo touch /etc/apache2/other/passenger.conf

Open the newly created file in TextEdit (you know the drill here sudo ‘/Applications/TextEdit.app/Contents/MacOS/TextEdit’ /etc/apache2/other/passenger.conf) and copy the lines from the post Apache 2 module install as well as some additional text. Here is a sample from my passenger.conf file:

# Passenger modules and configuration
LoadModule passenger_module /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6/ext/apache2/mod_passenger.so
PassengerRoot /opt/local/lib/ruby/gems/1.8/gems/passenger-2.0.6
PassengerRuby /opt/local/bin/ruby

# Set the default environment to development
RailsEnv development

# Which directory do you want Apache to be able to look into for projects?
<Directory "/Users/carlos/work">
    Order allow,deny
    Allow from all
</Directory>

You’ll obviously want to replace the path “/Users/carlos/work” with your own. This path doesn’t have to be specific as we’ll be using the Passenger Preference Pane to tell it where are projects are at.

Since the Passenger Preference Pane relies on Ruby Cocoa, we’ll need to install before we start to configure it.

NOTE: The Passenger Preference Pane is 32bit only so you’ll get a warning that the System Preferences has to relaunch in 32bit mode when you try to run it. It doesn’t negatively affect anything but it’s still a minor annoyance. Once MacRuby is stable enough it’ll be ported there and the warnings will go away.

Installing Ruby Cocoa is a simple port install:

sudo port install rb-cocoa

You might get errors setting up your projects using the Passenger Preference Pane because it expects to find the Snow Leopard bundled version of Ruby. Since we installed our own, I just trick it by running the command:

sudo ln -s /opt/local/bin/ruby /usr/bin/ruby

Next, download and install the latest Passenger Preference Pane (as of this writing it’s version 1.3). Adding projects to your Passenger Preference pane should be simple as it’s all GUI driven. When choosing a project path, just point it to the root directory of the project and it’ll figure out the rest.

Even though I prefer Passenger for development mode, it’s still handy to install Mongrel (and simple too).

sudo gem install mongrel

Parting Thoughts

At this point, you should have a working development environment for Ruby on Rails. I’ve tried to distill my notes into something readable just in case someone comes across this. If you have any problems with the steps above, feel free to ask a question in the comments.

Tutorial: Filtering results with jQuery UI Slider and Rails

November 05, 2009 — 16 Comments

At Planet Argon, we’re using the jQuery UI slider to filter results on one of our client projects. Since I had never implemented anything with jQuery UI slider, I decided to whip up a quick prototype just to see how it worked. It took me a little under an hour to get something put together. This post is the result of that prototype.

First of all, let’s visualize what we want to achieve. In my example, I have 20 dummy stocks that I want to filter down based on a high and low price. Here is a sample screen shot:

stocks

We’re going to start from scratch from a brand new Rails project. So we’ll have to create it:

NOTE: This tutorial uses Rails 2.3.4 but it can be easily adapted to work with recent earlier versions. The tutorial also uses jQuery 1.3.2 and jQuery UI 1.7.2 (the jQuery files can be downloaded from the Github repository.

rails jquery_slider_rails

Since we’re using jQuery instead of Prototype, we’ll want to install the jRails gem. While we’re installing gems, we’ll install a gem called Faker to create some dummy names as well as RSpec and RSpec Rails.

sudo gem install jrails
sudo gem install faker
sudo gem install rspec
sudo gem install rspec-rails

In order to use them, we’ll have to add config.gem statements to our environment.rb file.

  config.gem "faker"
  config.gem "jrails", :lib => false

Next thing we’ll have to do is go to the jQuery UI download page and we’ll download a custom build of jQuery UI. For this example, we’ll go lightweight and just select UI core and slider. I chose UI Lightness as the theme, but you can choose whatever you like; the theme won’t impact the results.

Once you download the files, place them in the following locations:

  • Images
    • /public/images/
  • jQuery and jQuery UI Javascript files
    • /public/javascripts/
  • CSS file
    • /public/stylesheets/

Now that we have all of the supporting files that we’ll need we’re ready to create our model that holds Stock information.

NOTE: Although I’m creating RSpec models and controller, I’m not writing any specs for this simple app. Perhaps that’s a post for another day.

script/generate rspec_model stock name:string price:integer

It’s probably a good idea to add an index on the price attribute since we’re going to be filtering on it.

Open up the db/migration directory and edit the only migration file to add the index. It should look like this when we’re done:

class CreateStocks < ActiveRecord::Migration
  def self.up
    create_table :stocks do |t|
      t.string :name
      t.integer :price
      t.timestamps
      
    end

      add_index :stocks, :price
  end

  def self.down
    drop_table :stocks
  end
end

Now that we have the migration, we’re ready to create our database and run said migration:

rake db:create:all
rake db:migrate

We should have a running database now (on SQLite) but now we need some data. We’ll mis(use) the seed file functionality that was added in Rails 2.3.4. You can find the seeds.rb file in the db directory.

We want 20 dummy stocks with fake names and fake prices. For fake random names, we’ll use the Faker gem. The Faker gem comes in really handy for writing specs/tests. A topic that I’ll probably cover soon. For random prices, we’ll just use Ruby’s rand method.

20.times do |x|
  Stock.create(:name => Faker::Lorem.words(1).to_s, :price => rand(5 * (100)))
end

Once we save the file, we can load up our data by running the following command:

rake db:seed

Once the sample data has been seeded we can start building our model. We know that we want to filter the data based on two points on the slider. This can easily by done by a named scope that takes two arguments.

named_scope :filter, lambda { |low, high| { :conditions => { :price => low..high } } }

We’ll also need to grab the highest and lowest prices to plug in as max and min values into the slider. For that we can create a class method that returns each price in an array.

  def self.high_low_prices
    [Stock.minimum(:price), Stock.maximum(:price)]
  end

Let’s move over to our controller. We know that we’ll need an index action but we’ll also need some sort of action to respond to slider ‘stop’ events. We can easily create a filter method/action in the controller, but as it turns out we can actually re-use the index action and remain fully RESTful.

Let’s focus on getting the correct data. We’ll be passing in the two points from the slider as parameters. If both of those exist, we’ll actually call our filter named scope. If not, we’ll just grab all of the stocks.

    unless params[:low] && params[:high]
      @stocks = Stock.all
    else
      @stocks = Stock.filter(params[:low], params[:high])
    end

We can probably grab the highest and lowest stock prices from the stocks instance variable, but let’s be explicit.

@price_range = Stock.high_low_prices

If the request is not an ajax request we’ll load the index view. If it’s an ajax request, let’s replace our stock list with the filtered list.

    respond_to do |format|
      format.html
      format.js do
        render :update do |page|
          page.replace_html 'x_stock_list', :partial => 'stocks/stock_list', :locals => { :stocks => @stocks }
        end
      end
    end
  end

We can use the replace_html method here because we’re using the jRails gem.

We’re now ready to tackle the views.

Create an index.html.erb view under /app/views/stocks/. While we’re at it we’ll create the partial that we alluded to in our controller. We’ll call this _stock_list.html.erb and it goes into the same directory as the index view.

Add the boilerplate stuff to the index.html.erb view; a DOCTYPE, html, head, and body tags. I also added an h1 tag wrapping the word Stocks.

Remember those jQuery files that we downloaded a while ago? We’ll link to them now.

  <head>
    <%= stylesheet_link_tag 'jquery-ui-1.7.2.custom.css' %>
    <%= javascript_include_tag 'jquery-1.3.2.min.js', 'jquery-ui-1.7.2.custom.min.js' %>
  </head>

Inside the body tag, we’ll create a div so that our slider can hook into it. NOTE: I use inline styles here because this is a quick and dirty example. Please keep all styles in CSS files in a real app.

I also have gotten in the habit of prepending all classes and IDs that are used by Javascript and ajax interactions with ‘x_’. This is a convention that we use at Planet Argon. Robby Russell originally blogged about this in the article Designers, Developers, and the x_ Factor

    <div id="x_slider" style="font-size:62.5%; width:350px;"></div>

I follow the slider div another div for the high and low prices.

     <div>
       <p>Showing all stocks between <span id="x_low_selected"><%= @price_range.first %></span> and <span id="x_high_selected"><%= @price_range.last %></span></p>
     </div>

The last HTML elements on the page is the stock list itself.

    <ul id="x_stock_list">
      <%= render 'stock_list', :stocks => @stocks %>
    </ul>

Before we get to the jQuery code, let’s jump over to our partial and flesh it out. The code necessary is minimal.

<% @stocks.each do |stock| %>
  <li>
      <p><%= stock.name %></p>
      <p><%= stock.price %></p>
  </li>
<% end  %>

The jQuery UI slider library takes care of most of the heavy lifting. Here is the final slider Javascript code with an explanation below it of all of the settings.

    <script type="text/javascript">
      $(function() {
        $("#x_slider").slider( { 
          range: true,
          step: 10,
          max: <%= @price_range.last %>,
          min: <%= @price_range.first %>,
          values: [<%= @price_range.first %>, <%= @price_range.last %> ],
          stop: function(event, ui) {
            var prices = $('#x_slider').slider('option', 'values');
            $('#x_low_selected').html(prices[0]);
            $('#x_high_selected').html(prices[1]);
            $.ajax({
              type: "GET",
              data: ({ low: prices[0], high: prices[1] }),
              url: 'http://0.0.0.0:3000/stocks',
              dataType: 'script'
            });
          }
        });
      });
    </script>

Before we bind the slider to our div, we’ll wrap everything in a convenience function to make sure that the DOM is loaded.

Next we bind the slider by simply writing:

$("x_slider").slider( { options here }

As you can see in the code above, the slider takes several options (see full documentation for all options):

  • Range
    • When this is set to true, you’ll get two or more points on the slider
    • Step
    • This is the value that the slider decrements or increments every time you move a point
  • Max
    • The maximum value of the slider
  • Min
    • The minimum value of the slider
  • Values
    • An array of low and high points on the slider
  • Stop
    • This is an event that is fired when a point on the slider stops moving

In the stop event there is a bunch of stuff going on. First, I set a price array to the set points on the slider so I can use them later for updating the user of the min and max values as well as passing those in as parameters to the ajax call.

This code snippet simply replaces the min and max values on the page:

$('#x_low_selected').html(prices[0]);
$('#x_high_selected').html(prices[1]);

The ajax function also has several options:

  • Type
    • This is the type of HTTP request. A simple GET request will do here
  • Data
    • These are the variables that we’ll be sending along
  • URL
    • This is the URL that we’ll be hitting – this assumes that you’ve started the web server using script/server or mongrel_rails
  • DataType
    • I originally set this to html thinking that is what I wanted, but that’s the wrong call. You’ll want to use script if you want to return fragments of HTML otherwise you’ll return the whole page in HTML form (layout and all).

That’s it. As I said before, to test it, you’ll want to start up a web server with either mongrel_rails, script/server or Passenger. In your web browser, you should be able to go to either http://0.0.0.0:3000/stocks or http://jquery_slider_rails.local/stocks if you’re using Passenger to see the results.

I’ve made all of the code available for this tutorial on GitHub.