嗨,我有一个我想重构的代码
def gear_type
@gear_type ||= self.class.gear_types.find{|gears| gears["id"]==source["gear_type_id"]}["text"] if source["gear_type_id"]
end
def brand
@brand ||= self.class.brands.find{|node| node["id"]==source["brand_id"].to_s}["text"] if source['brand_id']
end
最好的方法是什么?使用eval还是define方法?我试过这个但是有一些我还没发现的错误:
%w(gear_type brand).each do |meth|
define_method(meth){
instance_variable_get("@#{meth}") rescue
instance_variable_set("@#{meth}", self.class.send(meth.pluralize).find{|node| node["id"]==source["#{meth}_id"]}["text"]) if source["#{meth}_id"]
}
end
答案 0 :(得分:4)
我只想编写一个可以参数化的通用查找器方法:
def gear_type
@gear_type ||= generic_finder :gear_types, "gear_type_id"
end
def brand
@brand ||= generic_finder :brands, "brand_id"
end
def generic_finder(collection, primary_key)
self.class.send(collection).each do |object|
return object["text"] if object["id"] == source[primary_key]
end if source[primary_key]
nil
end
答案 1 :(得分:1)
instance_variable_get("@#{meth}")
不会引发错误,它将返回nil。所以你必须做的几乎和你做的一样:
%w(gear_type brand).each do |meth|
define_method(meth){
instance_variable_get("@#{meth}") || instance_variable_set("@#{meth}", self.class.send(meth.pluralize).find{|node| node["id"]==source["#{meth}_id"]}["text"]) if source["#{meth}_id"]
}
end
你也应该重构那条线。它有许多东西
%w(gear_type brand).each do |meth|
def source(meth)
@source ||= source["#{meth}_id"]
end
def class_meths(meth)
self.class.send(meth.pluralize)
end
def look_for(meth)
class_meths(meth).find{|node| node["id"] == source(meth)}["text"]
end
define_method(meth) do
value = instance_variable_get("@#{meth}")
instance_variable_set("@#{meth}", look_for(meth)) if !value && source(meth)
end
end
这是一个尝试。不确定它是否变得更好,但我认为它更容易阅读。
哦!我刚刚意识到那些方法可能不会在meta的范围内?方法被调用。但是哦,我认为它仍然是一个很好的例子:)
答案 2 :(得分:-1)
使用eval可能更简洁:
%w(gear_type brand).each do |meth|
eval <<-RUBY
def #{meth}
@#{meth} ||= self.class.#{meth.plural}.find{|item| item["id"]==source["#{meth}_id"]}["text"] if source["#{meth}_id"]
end
RUBY
end