Posts Tagged ‘rails’

14
10/09
2

jQuery Weighs Less

Well, that may not be 100% accurate. Unobtrusive JavaScript is likely to weigh less in a Rails application, but that doesn’t get fan boys riled up enough.

In a standard Rails application, Prototype is included by default as the JavaScript library and several of the html helper methods used in the views will generate Prototype code for you. A great example of this is link_to_remote which generates a link that will make an AJAX request to the desired url.

This Rails view snippet was found in my forum app:

<%= link_to_remote "delete", :update => nil,
  :url => post_path(post), :method => :delete,
  :confirm => "Are you sure you want to delete this post?" %>

And it generates this html mixed with some very obtrusive JavaScript:

<a onclick="if (confirm('Are you sure you want to delete this post?')) {
    new Ajax.Request('/posts/1', {asynchronous:true, evalScripts:true,
      method:'delete', parameters:'authenticity_token=' +
      encodeURIComponent('abcde')
    });
  }; return false;" href="#">delete</a>

There is nothing really wrong with this code. It works fine and did the job while it was in production. The problem is this one link is found in every single post on a thread page. This means the giant link can be repeated on the page hundreds of times.

After I made the switch to unobtrusive jQuery, I wanted to see exactly what kind of a difference it made in page sizes. I looked at three different thread pages, one with 1 post, one with 94 posts, and one with 306. Here are the page sizes (in bytes) and they show a pretty remarkable difference.

# of Posts jQuery Page Size Prototype Page Size % Difference
1 5,450 6,568 20.5
94 103,671 129,641 25.1
306 270,736 350,170 29.3

The difference ended up being quite a bit bigger than I was expecting and really helps sell me on jQuery. Unobtrusive Prototype could no doubt have dropped the page size just as much, but I’ll be sticking with jQuery from now on.

16
8/09
0

Implementing Who's Online with Rails and Memcached

I have wanted to add a “Who’s Online” feature to my forum site for quite some time. Users are more likely to stay and post if they know someone else is there to read what they write. In the first implementation of the site, back in the Rails 1.2 days, sessions were most easily stored in the database with the ActiveRecord SessionStore. This made fetching who is currently using the site easy as all of the necessary information was stored in the database.

Once Rails 2.0 came out, the default session store was using browser cookies. Now it was not so trivial to determine who is on the site. One option was to add a new column to the User model and update it every time the user accessed a page. While this would work, it would mean an extra SQL read and update for every page accessed. The server would have no trouble handling the extra load, but I decided to wait for a better option.

Having not seen a better option in the latest releases of Rails, I implemented my own solution and got my first experience with memcached along the way.

First things first, get memcached installed and running in verbose mode for development:

sudo port install memcached
memcached -vv

Next, set the Rails development environment (in development.rb) to use caching and memcached as the cache store:

config.action_controller.perform_caching = true
config.cache_store = :mem_cache_store

The real work is done by a method in application_controller.rb

before_filter :set_online_users

def set_online_users
  return unless logged_in?

  current_user.last_seen = Time.now
  users = Rails.cache.fetch("online_users") { [current_user] }
  @online_users = users.collect do |user|
    user if user.last_seen > 5.minutes.ago
  end.compact
  unless @online_users.include?(current_user)
    @online_users << current_user
  end
  Rails.cache.write("online_users", @online_users)
end

The final solution is a fast (not verified by benchmarking) solution with zero extra database access. Some readers might notice this is not a thread-safe solution. All lines between the fetch and the write call should be wrapped with a mutex of some sort, but I will leave that for another time.

If you the looking for extra reading, especially about memcached, Railslab: Epsiode 8 is an excellent resource for getting started with memcached and Rails.

Tagged:  
14
4/09
3

Evaluating Frameworks

When working in a community that is constantly changing with new features coming out every week, there are a lot of different plugins, mini-frameowrks, and other packages that are worth using in your projects. One can spend more time researching new tools to use than doing actual work. One always hopes the time spent finding tools and frameworks to make development faster will make up for the time lost from not developing.

My latest research involved the testing frameworks for Rails. Although there are plenty of them out there, I focused on RSpec and Shoulda. Besides Test::Unit, they are the two biggest players in the Rails testing world. I could have spent weeks trying to figure out which best fit my needs, but I enforced some time-boxing on myself and refused to spend more than four hours on this. With so few hours to determine which framework is for me, I really focused on the parts that are most important to me. Within those few hours, I finally decided on Shoulda. RSpec may or may not have more momentum behind it, but Shoulda fits the way I think and is (hopefully) the best solution right now.

When evaluating frameworks or plugins for yourself, always remember to time-box. Choosing the right one is certainly important, but spending the right amount of time choosing is just as important. You have to have time before you can start saving it.