Forum: Ruby on Rails Automatted Getter/Setter

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Ray M. (Guest)
on 2006-06-02 01:07
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
Josh S. (Guest)
on 2006-06-02 01:42
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
This topic is locked and can not be replied to.