Sonntag, 3. August 2014

Stringify your ActiveRecord model objects!

The view in a Ruby on Rails project very often is about string representations of the stored ActiveRecord model objects. For example:
class Food < ActiveRecord::Base
  validates :name, presence: true
  belongs_to :category
end

class Category < ActiveRecord::Base
  validates :name, presence: true
  attr_accessible: name
end
and in the view the objects (food and its category) are represented by their name attribute:
Food name: <%= @food.name %>
Food category: <%= @food.category.name unless @food.category.nil? %>
That works actually and the generated HTML could look like:
Food name: Apple Cider Cookie
Food category: Sweets
The ERB templating in Ruby on Rails sends the to_s message to the embedded result anyway. So something like that:
Food name: <%= @food %>
Food category: <%= @food.category %>
would not throw an exception, if the category was nil (since nil.to_s returns a blank string) and send the ActiveRecord::Base#to_s to the objects. Please note, not only the methods name are left out, but also the unless condition can be omitted, which looks much nicer in the view. At that point the result looks like:
Food name: #<Food:0x000000070c5010>
Food category: #<Category:0x0000000153b708>
It is the natural string representation of ActiveRecord model objects but does not serve any purpose. Overwriting ActiveRecord::Base#to_s in particular models is absolutely reasonable:
class Food < ActiveRecord::Base
  validates :name, presence: true
  belongs_to :category
  def to_s
    name
  end
end

class Category < ActiveRecord::Base
  validates :name, presence: true
  attr_accessible: name
  def to_s
    name
  end
end
and in the ERB template:
Food name: <%= @food %>
Food category: <%= @food.category %>
results in:
Food name: Apple Cider Cookie
Food category: Sweets
The big plus for overwriting ActiveRecord::Base#to_s is that the typical string representation for the model objects can be defined and especially in the case of more complex string representations it is absolutely reasonable.

Supported by Ruby 2.1.1 and Ruby on Rails 3.2.17