Common Rails Beginner Issues

» 27 Jun 2009

I’ve recently become somewhat addicted to Stack Overflow, and I have noticed some areas of confusion with using Ruby on Rails. Convention over configuration and awesome magick are pretty foreign concepts in most of CS, so the confusion is quite understandable. The Rails community also seems to have a love for demonstrating simple applications being created simply (Blog in 5 minutes, extreme!) and complex corner cases solved through advance techniques. There isn’t much in the way of middle ground.

If you are planning on doing a lot of Rails and are okay with buying dead tree books, you should go buy The Rails Way by Obie Fernandez at your soonest convenience. It is worth its (considerable) weight in gold1

The following are what I’ve observed to be among the hardest issues for people moving from idealized Rails applications to the realities of actual websites. I will try to mostly avoid the issues of separation between the levels of MVC and any of the philosophical opinions of DRY.

Dependencies: How to make Rails find your classes.

Starting out, Rails is amazing at automagically including everything you need to make the code run without any need for require or load lines. Things get a little more confusing when you write your own code and find that it is not being included where you expect. The key here is that Rails uses naming conventions to handle code loading.

The naming convention is that class names are in CamelCase and the file containing them are named using underscores.

#filename: foo.rb
  class Foo
  end
  
  #filename: foo_bar.rb
  class FooBar
  end
  
  #filename: admin/foo_bar.rb
  class Admin::FooBar
  end

Classes that serve as models, views, controllers, or sweepers should go in their properly named folders under app/. Other classes should either be placed in lib/ or factored out into plugins.

It is worth noting that files are only loaded when the class name is referenced in the code. Whenever an unknown class name (or any constant) is used in code, Rails attempts to find a file that might define it (according to file name) and then loads it.

Routing

config/routes.rb is kind of a mess. This is what you need to know.

Connect a url to a controller action

This makes http://foo.com/foo/42 go to FooController#bar with params[:id] = 42

map.connect '/foo/:id', :controller => 'foo', :action => 'bar'

This does the same, but only for GET requests

map.connect '/foo/:id', :controller => 'foo', :action => 'bar', 
      :conditions => {:method => :get}

This validates that params[:id] is a number (/foo/42 will match, /foo/baz will not)

map.connect '/foo/:id', :controller => 'foo', :action => 'bar', 
      :id => /\d+/

Named routes

Linking to controllers through link_to "click here", :controller => 'foo', :action => 'bar', :id => 42 is cumbersome. Named routes allow you to reference this same path with foo_path(42)

map.foo '/foo/:id', :controller => 'foo', :action => 'bar'

All previously discussed options work the same for named routes.

RESTful resources

If you use REST (and you should), routes get a whole new load of magick.

map.resources :products

</notextile

generates

/products products_path GET ProductsController#index
/products products_path POST ProductsController#create
/products/:id product_path(id) GET ProductsController#show
/products/:id product_path(id) PUT ProductsController#update
/products/:id product_path(id) DELETE ProductsController#destroy
/products/new new_product_path GET ProductsController#new
/products/:id/edit edit_product_path(id) GET ProductsController#edit

as well as versions of each of these that take a format parameter in the form of formatted_product_path(id, :xml)

Route precedence

High priority routes come first in the file. Routes specified first will override routes specified further down in the file.

Forgery protection

If you have POST or PUT actions that need to be called from other websites or programs, you need to skip the authentication token check. Put this line in the relevant controller.

skip_before_filter :verify_authenticity_token, 
      :only => :action_name

That’s it for now. The API (http://railsapi.com) is a great reference for other issues that might come up.

1 Ron Paul has proposed using copies of The Rails Way as the basis for US Currency.