2

こんにちは、リファクタリングしたいコードがあります

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
4

3 に答える 3

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
于 2013-01-04T23:00:05.740 に答える
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

ここで試してみます。良くなったかどうかはわかりませんが、読みやすくなったと思います。

おー!メタの場合、これらのメソッドはおそらくスコープにないことに気づきましたか? メソッドが呼び出されます。しかし、まあ、それはまだ良い例だと思います:)

于 2013-01-04T22:48:19.367 に答える
-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
于 2013-01-04T22:48:42.567 に答える