Automatted Getter/Setter


#1

Hey…

So I have a model that has a lot of number fields. Each of these go
through a process when read in and read out to add/remove commas
(between every three numbers) to make them more readable.

The getter I currently have is like this:

def sale_price
Listing.insert_commas(read_attribte (:sale_price))
end

and the setter is:

def sale_price=(price)
write_attribute(:saleprice, Listing.remove_commas(price))
end

The trouble is there is at least 5 other fields that need the same thing
done for them (and most likely more will be added in time). I was
wondering if there is some way I could do this more automatted like:

:attr_reader :sale_price, …, …, …

Any help would be great… anything to make the code more readbale and
manageable would likewise be much appreciated!

-Ray


#2

Ray M. wrote:

Hey…

So I have a model that has a lot of number fields. Each of these go
through a process when read in and read out to add/remove commas
(between every three numbers) to make them more readable.

The getter I currently have is like this:

def sale_price
Listing.insert_commas(read_attribte (:sale_price))
end

and the setter is:

def sale_price=(price)
write_attribute(:saleprice, Listing.remove_commas(price))
end

The trouble is there is at least 5 other fields that need the same thing
done for them (and most likely more will be added in time). I was
wondering if there is some way I could do this more automatted like:

:attr_reader :sale_price, …, …, …

Any help would be great… anything to make the code more readbale and
manageable would likewise be much appreciated!

There are two main ways you can do this. One is to use a before/after
filter to reformat the number in-place in the same attribute that gets
saved in the db. The other is to create a second attribute that is a
format transformation of the db representation. I’d go with the second
option, myself.

You can get arbitrarily tricky making your comma transformed attributes
DRY. One way to do it is to use metaprogramming and create a class
method that defines your formatted accessors.

def self.number_with_commas(attr_name)

use whatever name system you want here

comma_attr_name = attr_name.to_s + “_with_commas”
class_eval <<-END_EVAL
def #{comma_attr_name}
@#{comma_attr_name} ||= format_with_commas(#{attr_name})
end
def #{comma_attr_name}=(number_with_commas)
@#{comma_attr_name} = number_with_commas
#{attr_name} = strip_commas(number)
end
END_EVAL
end

Whip up some format_with_commas and strip_commas methods to do the grunt
work and that should do it. Note: this is written in email and
untested, so there’s bound to be a bug somewhere. Also, caching the
value of the number might cause problems if you are forcing the object
to reload from the db. But this should get you started.


Josh S.
http://blog.hasmanythrough.com