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.
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.
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
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
Sure -- 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
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
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.