I''ve clearly go a lot of repetition in the following methods:
def name=(value)
write_attribute(:name, if [0,"0","","
"].include? value then nil
else value end)
end
def address=(value)
write_attribute(:address, if [0,"0","","
"].include? value then nil
else value end)
end
def city=(value)
write_attribute(:city, if [0,"0","","
"].include? value then nil
else value end)
end
Can someone tell me the convention to DRY this code? I''m wondering if
I
use a lambda but am not quite sure that''s the right path or how to do
that.
Thanks,
Bill
--
Posted via http://www.ruby-forum.com/.
Hi -- On Sat, 17 Oct 2009, Bill Devaul wrote:> > I''ve clearly go a lot of repetition in the following methods: > > def name=(value) > write_attribute(:name, if [0,"0",""," "].include? value then nil > else value end) > end > def address=(value) > write_attribute(:address, if [0,"0",""," "].include? value then nil > else value end) > end > def city=(value) > write_attribute(:city, if [0,"0",""," "].include? value then nil > else value end) > end > > Can someone tell me the convention to DRY this code? I''m wondering if I > use a lambda but am not quite sure that''s the right path or how to do > that.One idea is simply to parameterize the process: def generic_writer(attr, value) @blanks ||= [0, "0", "", " "] write_attribute(attr, @blanks.include?(value) ? nil : value) end def name=(value) generic_writer(:name, value) end etc. If you want, you can automate the creation of the methods instead: %w{ name address city }.each do |attr| define_method("#{attr}=") do |value| @blanks ||= [0, "0", "", " "] write_attribute(attr, @blanks.include?(value) ? nil : value) end end David -- The Ruby training with D. Black, G. Brown, J.McAnally Compleat Jan 22-23, 2010, Tampa, FL Rubyist http://www.thecompleatrubyist.com David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)
Thanks for the help. I used the latter to come up with:
@fields_to_normalize = %w{ address city country_id email_general fax
name phone phone_local state_id vacation_end_on vacation_notice
vacation_start_on zip_code }
@fields_to_normalize.each do |attr|
define_method("#{attr}=") do |value|
@blanks ||= [0, "0", "", " "]
write_attribute(attr, @blanks.include?(value) ? nil : value)
end
end
Is it possible to do something more Rails-ish so it reads:
normalize_fields :address, :city, :country_id
This additional re-factoring would allow re-use across models.
Bill
--
Posted via http://www.ruby-forum.com/.
Hi -- On Sat, 17 Oct 2009, Bill Devaul wrote:> > Thanks for the help. I used the latter to come up with: > > @fields_to_normalize = %w{ address city country_id email_general fax > name phone phone_local state_id vacation_end_on vacation_notice > vacation_start_on zip_code } > > @fields_to_normalize.each do |attr| > define_method("#{attr}=") do |value| > @blanks ||= [0, "0", "", " "] > write_attribute(attr, @blanks.include?(value) ? nil : value) > end > end > > Is it possible to do something more Rails-ish so it reads: > > normalize_fields :address, :city, :country_idSure -- just write the method :-) I would consider putting the blanks in a constant. class Whatever BLANKS = [0, "0", "", " "] def self.normalize_fields(*syms) syms.each do |attr| define_method("#{attr}=") do |value| write_attribute(attr, BLANKS.include?(value) ? nil : value) end end end normalize_fields :address, :city, :country_id end David -- The Ruby training with D. Black, G. Brown, J.McAnally Compleat Jan 22-23, 2010, Tampa, FL Rubyist http://www.thecompleatrubyist.com David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)
Thanks to your help David I now have:
# lib/normalizer.rb
module Normalizer
BLANKS = [0, "0", "", " "]
def self.included(base)
base.class_eval do
def self.normalize(*syms)
syms.each do |attr|
define_method("#{attr}=") do |value|
write_attribute(attr, BLANKS.include?(value) ? nil : value)
end
end
end
end
end
end
(I struggled with the above until I read that class_eval is needed to
make the inclusion happen. I wonder if a change to class_eval to yield
the included module would feel more natural.)
and
# models/model.rb
include Normalizer
normalize :name, :address, :city, :country_id
Looks great and tests pass!
Thanks,
Bill
--
Posted via http://www.ruby-forum.com/.
Hi -- On Sun, 18 Oct 2009, Bill Devaul wrote:> > Thanks to your help David I now have: > > # lib/normalizer.rb > module Normalizer > > BLANKS = [0, "0", "", " "] > > def self.included(base) > base.class_eval do > def self.normalize(*syms) > syms.each do |attr| > define_method("#{attr}=") do |value| > write_attribute(attr, BLANKS.include?(value) ? nil : value) > end > end > end > end > end >end> > (I struggled with the above until I read that class_eval is needed to > make the inclusion happen. I wonder if a change to class_eval to yield > the included module would feel more natural.)You should be able to do: def self.included(base) def base.normalize(*syms) ... end end I might be inclined to do: module Normalizer def normalize(*syms) ... end end class Whatever extend Normalizer ... end i.e., extend the class object directly rather than grabbing it indirectly and operating on it. It seems a little more streamlined. David -- The Ruby training with D. Black, G. Brown, J.McAnally Compleat Jan 22-23, 2010, Tampa, FL Rubyist http://www.thecompleatrubyist.com David A. Black/Ruby Power and Light, LLC (http://www.rubypal.com)