The addition of RESTful routing and the #to_param
method in Rails has undoubtedly improved both the ease and usefulness of URL generation in Rails apps. However, there has come to be a rather insidious tendency to have an auto-generated id as the true reference for a given item. This may make sense for some or even many apps, but by and large records should be referred to by their content, not their ids, in URLs if at all possible. With this goal in mind, I have released from_param
, a simple addition to ActiveRecord that makes it dead simple to use better URL finders.
Example
First of all, from_param
is meant to simply be the complement of to_param
, that is, you should be able to pass Model.from_param(some_parameter)
the same way you would pass Model.from_xml(some_xml)
. Let’s examine how this works in practice:
class User < ActiveRecord::Base def to_param "#{id}-#{login.downcase}" end end class UsersController < ApplicationController # GET /users/1-mbleigh def show @user = User.from_param(params[:id]) # => <User id=1 login="mbleigh"> end end
Simple enough, and it should look very familiar except that instead of a User.find
or User.find_by_id
, we have User.from_param
. In fact, that’s exactly what this code does: from_param by default will call find_by_id
since that is how the default to_param
is configured.
Now let’s take something a little more complicated: a blog post title. I definitely don’t want an id in the URL if it’s a permalink, so how can I make an arbitrary parameter found as easily as the id? Simple, just add a param
column to your table! Take a look:
class Post < ActiveRecord::Base def to_param "#{created_at.strftime("%Y-%m-%d")}-#{title.gsub(" ","-").downcase.gsub(/[^a-z0-9-]/,"")}" end end class PostsController < ApplicationController # GET /posts/2008-04-26-from-param-plugin-released @post = Post.from_param(params[:id]) # => <Post title="From Param: Plugin Released" created_at="2008-04-26"> end
From Param will auto-magically save the to_param of your model to the specified parameter column (defaults to “param” but you can set it by calling set_param_column
) and then automatically know to find by that column if it exists when from_param
is called. This way, all you have to do is define a to_param
that will be unique to your record and everything else is handled for you!
This plugin is really quite simple, but it establishes a convention that I feel has been missing from Rails for some time: a standard method to call to retrieve a record based on its URL parameter.
Installation
To install the plugin on Edge Rails or Rails 2.1 and greater:
script/plugin install git://github.com/mbleigh/from_param.git
On earlier versions of Rails:
git clone git://github.com/mbleigh/from_param.git vendor/plugins/from_param
Resources
If you have any suggestions for expanding the usefulness of the plugin or run into any problems, please report them on the From Param Lighthouse Project.