Flowdock
to_param() public

Returns a String, which Action Pack uses for constructing an URL to this object. The default implementation returns this record’s id as a String, or nil if this record’s unsaved.

For example, suppose that you have a User model, and that you have a resources :users route. Normally, user_path will construct a path with the user object’s ‘id’ in it:

  user = User.find_by_name('Phusion')
  user_path(user)  # => "/users/1"

You can override to_param in your model to make user_path construct a path using the user’s name instead of the user’s id:

  class User < ActiveRecord::Base
    def to_param  # overridden
      name
    end
  end

  user = User.find_by_name('Phusion')
  user_path(user)  # => "/users/Phusion"
Show source
Register or log in to add new notes.
April 28, 2009
3 thanks

Tip: Define from_param(...) as Opposite

Often when defining a to_param method, it’s handy to introduce an opposite method for decoding them. For example:

class User < ActiveRecord::Base
  def self.from_param(param)
    find_by_name!(param)
  end

  def to_param
    name
  end
end

While you can just as easily redefine the find() method, this may be confusing since the expectation is that find() works with numerical IDs, or whatever the key column is defined as.

April 24, 2009
2 thanks

have your to_param begin with the object's id

If you overwrite the to_param method in your model class such that it does not begin with its id, you can be in for a nasty surprise:

Example

class User
  def to_param
    self.login
  end
  ...
end

Let’s say you have a user called “bob”, than you might think this works:

>> bob = User.find(3)
=> #<User id: 3, login: "bob", ...>
>> User.find(bob.to_param)
ActiveRecord::RecordNotFound: Couldn't find User with ID=bob

But it’s not the reason being that Rails find method looks for a beginning number (d+) and uses that to look up the record (and ignores everything that comes after the last digit). So the solution is to have your to_param return something that begins with the object’s id, like so:

Example

class User
  def to_param
    "#{self.id}-#{self.login}"
  end
  ...
end

>> bob = User.find(3)
=> #<User id: 3, login: "bob", ...>

>> User.find(bob.to_param)

> # id: 3, login: “bob”, …>

>> bob.to_param

> “3-bob”

March 5, 2009
1 thank

Mistake

It’s not:

user = User.find_by_name('Phusion')
user_path(path)  

It’s:

user = User.find_by_name('Phusion')
user_path(user)  
May 30, 2013
0 thanks

Avoiding to_param method when using URL helper methods

I recently found myself in the situation where I needed to generate URLs which included the ID instead of the value returned from the model’s to_param method (since someone had overridden the to_param method). It turned out to be easier than I thought. You can simply pass an ID to the helper method and it will construct the URL correctly:

edit_admin_foobar_path(@foobar.id)
# /admin/foobars/123/edit