2011-09-12 59 views
0

我一直在搞一個可排序的表模塊的東西。我知道有些可能存在,但想親自體驗一下。我有像這樣的想法:紅寶石發送方法與rails協會

SortedTable.new(ModelName, Hash_Of_Columns_And_Fields, ID) 

例如

SortedTable.new(Post, {"Title" => "title", "Body" => "body", "Last Comment" => "comment.last.title"}, params[:id]) 

我打算做這樣的事情:

def initialize(model, fields, id) 
    data = {} 
    model = model.capitalize.constantize 
    model.find(id) 
    fields.each do |column, field| 
    data[column] = model.send(field) 
    end 
end 

這工作正常標題和正文,但是當它它得到Last Commentcomment.last.title它出錯。我曾嘗試做Post.send("comments.last.title")但說NoMethodError: undefined method 'comments.last.title' for #<Post:0x0000010331d220>

我知道我可以做Post.send("comments").send("last").send("title")和作品,但我不能動態地採取領域和劈裂上想如何做到這一點。然後鏈接發送。任何人都可以給我建議如何做到這一點?如果我這樣做是完全錯誤的,那麼請說出或指向我的代碼方向,做類似的事情。我不是專家級的Ruby開發人員,但我在努力。

上述代碼可能無法正常工作,因爲我不在計算機上使用ruby/rails進行測試,但希望您能理解這一概念。

乾杯

回答

2

第一和最骯髒的解決方案是eval

fields.each do |column, field| 
    data[column] = eval("#{model}.#{field}") 
end 

下一個解決方案多一點功能

fields.each do |column, field| 
    data[column] = field.split(".").inject(model){|obj, met| obj.send(met)} 
end 

PS

而且你的設計是醜陋

EDIT

的注入可以更簡明地寫成field.split('.').inject(model, :send)。我強烈勸阻eval的方式 - 不必要的evals是你可以滑落並允許任意代碼執行的又一種情況,而且它們也很慢。 (另外,我敢肯定,這應該只是eval("model.#{field}") - 你不想插入字符串值model。又一個例子,它很容易滑倒eval表達式。) - @Chuck

+0

Hey , 感謝您的快速回復。我認爲我的方法會變得很難看:)還在學習。任何意見,將不勝感激。但是,感謝那些解決方案! – RailsSon

+0

注入可以更簡潔地寫成'field.split('。')。inject(model,:send)'。而且我強烈反對'eval'方式 - 不必要的'evals'是再次出現並允許任意代碼執行的情況,而且它們也很慢。 (另外,我很確定應該只是'eval(「model。#{field}」)' - 你不想插入'model'的字符串值。另一個例子很容易滑倒一個'eval'表達式。) – Chuck