Our Episodic Video Publishing Web Application is written in Ruby on Rails. I recently came across a situation where I had a model where I wanted to override it’s attribute accessors in some cases. Consider a model that looks like this.

create_table "podcasts", :force => true do |t|
t.string "name"
t.boolean "use_show_name", :default => true
t.integer "show_id"
end

As you can see above that each podcast belongs to a show. I also have a form for this model and in the name field I want to display the name of the podcast unless “use_show_name” is true then I want to display the name of the show that this podcast belongs to.

<%= text_field :podcast, :name, :class => "text", :disabled => @podcast.use_show_name %>

I don’t want to put this logic in the ERB template but instead I want to put it in the model so that anyone that calls Podcast.name will get the appropriate value depending on the “use_show_name”.

class Podcast < ActiveRecord::Base
belongs_to :show
 
def name
return self.use_show_name ? self.show.name : read_attribute(:name)
end
alias_method :name_before_type_cast, :name
end

So there a few things going on above.

  • We override the “name” method by simply implementing it. This works because ActiveRecord using method_missing to implement it’s “name” getter but since there is now a “name” method, method_missing will not be invoked.
  • In the method we check “use_show_name” to see what value to return.  If it is true we get the value from the show object.  Otherwise, we call read_attribute to get the value of the name attribute that stored in the DB.
  • Lastly, we alias the name method as “name_before_type_cast” since this is the method that is called by FormHelper.text_field.  ActiveRecord form helpers call the before_type_cast so that they can get the string value of the attribute but we want it to get the value from our “name” method.
Trackback

no comment untill now

Sorry, comments closed.