2013-01-04 67 views
2

嗨,我有一個代碼,我想重構如何重構ruby代碼?

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還是定義方法?我已經嘗試過這一點,但也有一些錯誤,我不能發現尚未:

%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 
+2

代碼審查/重構現在在http://codereview.stackexchange.com –

回答

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 
+0

+1不錯!每當我們認爲我們需要元編程時,我們應該首先考慮如果我們可以通過傳遞符號的通用方法來實現它。即使在Rails上的find_by_ *方法也改變爲這種方法。 –

+0

謝謝。它非常乾淨! – Danil

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的範圍內?方法被調用。但哦,它仍然是一個很好的例子,我覺得:)

-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