如何重构ruby代码?

时间:2013-01-04 22:38:42

标签: ruby refactoring

嗨,我有一个我想重构的代码

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

3 个答案:

答案 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