views:

374

answers:

3

I have a 'name' attribute on a Person model

and every time I access the name attribute, I want name.capitalize to be returned.

Doing the following inside the model won't work,

def name name.capitalize end

so what is the alternative?

A: 

Try this:

def name
  self[:name].capitalize
end
Mr. Matt
+9  A: 

I suggest you to create a secondary method with your custom formatters.

class Person

  def formatted_name
    name.capitalize
  end

end

This is a better solution compared with overwriting the default implementation because setter and getters might called when updating/writing/saving the record to the database. I remember once when I overwrote the default implementation of an attribute and each time a record was saved, the attribute was updated with the formatted value.

If you want to follow this way you can use alias_method_chain or take advantage of inheritance including an external module.

class Person

  def name_with_formatter
    name_without_formatter.capitalize
  end
  alias_method_chain :name, :formatter

end

Also you can overwrite name and call read_attribute(:name) from within your custom method.

def name
  read_attribute(:name).capitalize
end

def name
  self[:name].capitalize
end

Again, don't do this. Go ahead and create a custom method.

Simone Carletti
Why don't you recommend your last suggestion?def name self[:name].capitalizeendLooks elegant, it is just a attribute reader. What's the problem?
Mostly because some plugins relies on name, some other calls self[:name]. You might end up with inconsistent values.
Simone Carletti
+1  A: 

But happens when name is null?

capitalize will throw an undefined method for nil::Class if self[:name] returns nil.

The following covers that:

def name
  self[:name] ? self[:name].capitalize : nil
end

But I agree that you should create the formatted method and leave the name method as is. Never know when you might need the raw data.

FYI: the reason why your method didn't work was because it was causing, what I like to call, a self referring loop. You are redefining the method but calling the method in the new method. So you have to use self[:name] or read_attribute to get to the internal model data.

Tony Fontenot