2011-12-12 91 views
0

我有這樣的模式:紅寶石EVAL重構

Class User 
    has_many :comments 
    # have field 'name' in DB 
end 

Class Comment 
    belongs_to :user 
end 

,我已經非常複雜,非常困難的理解管理員後臺,它可以獲取所有車型,並允許從管理界面控制它。它獲取所有關聯並用evals處理它。

而這樣的eval正常工作:

eval("comment." + o[0][:object]) 

其中o [0] [:對象] = 「user.name」

但我想要做它沒有EVAL。這種方法的工作原理,但它不是很普遍:

comment.send("user").send("name") 

而在實際的代碼看起來很醜陋:

(o[0][:object].split(".").count < 2) ? h(object.send(o[0][:object])) : h(object.send(o[0][:object].split(".")[0]).send(o[0][:object].split(".")[1])) 

那麼,什麼是讓EVAL的univesality這樣contructions最好的方式,如果我想顯示更多嵌套呼叫,如:

comment.user.first_friend.haters.count 

???

+0

命名作用域在創建複雜的查找器時非常流行。至於重構eval,看起來你可能可以用單表繼承來完成它。 – CambridgeMike

+1

它看起來很醜,因爲你在內聯 - 在現實生活中,你會編寫一個方法,遞歸或迭代,調用當前對象的下一個方法,設置當前對象,並繼續執行直到完成或發生錯誤。除此之外,你的目的並不清楚 - 你是否試圖避免爲每個模型寫一個管理頁面? –

回答

2

我不確定爲什麼你不想在這種情況下使用eval。有時候這是最好的解決方案。

在這裏,您可以簡單地這樣做:

o[0][:object].split('.').reduce(object){|method, obj| obj.send method } 
+0

這裏是_shortest_解決方案(絕對不是最好的),但即使這是因爲他有另一種代碼味道:o [0] [:object]'的內容。那是怎麼做的(方法名稱以點分隔)到達那裏? 'eval'似乎是這裏最少的問題。 –

+0

@MladenJablanović當然,這個問題是缺少的上下文。我不想在這裏猜測OP。 –

+0

順便說一句,它似乎也可以工作:'o [0] [:object] .split('。')。reduce(object,:send)' –

0
這個

什麼?

class Object # or just ActiveRecord::Base 
    def multiple_send(methods) 
    first_method, remaining_methods = methods.split(".", 2) 
    ret = __send__(first_method) # I use __send__ to prevent from classes overwriting send() method 

    remaining_methods.nil? ? ret : ret.multiple_send(remaining_methods) 
    end 
end 

然後你可以寫一些像comment.multiple_send("user.name")