2010-01-14 64 views
1

在我的應用程序中,我試圖根據loss_report的兩個屬性僅顯示activerecord對象(loss_reports)數組的唯一元素。根據對象的屬性獲取activerecord對象數組的唯一元素的最佳方式是什麼?

架構

class Agent < ActiveRecord::Base 
    has_many :loss_reports, :through => policy 
end 

class LossReport < ActiveRecord::Base 
    belongs_to :agent 
end 

我第一次嘗試重寫EQL?和LossReport的哈希方法,這樣我可以做類似的東西:

選項1:

class LossReport ... 
    def eql? other 
    self.policy_id == other.policy_id && loss_occurred_on.hash == self.loss_occurred_on 
    end 

    def hash 
    policy_id + loss_occurred_on.hash 
    end 
end 

class Agent ... 
    def unique_losses 
    loss_reports.to_set 
    end 
end 

,但很快刪除,因爲ActiveRecord的的代碼已經覆蓋的方法和我不是肯定的反響。

選項2:

class Agent ... 
    def unique_losses 
    loss_reports.sort{|l1,l2| l2.created_at <=> l1.created_at}.group_by{|l| (l.policy_id + l.loss_occurred_on.hash)}.collect{|hl| hl[-1].first} 
    end 
end 

選項3:

class Agent 
    def unique_losses 
    hsh_array = [] 
    unique = [] 
    loss_reports.sort{|l1,l2| l2.created_at <=> l1.created_at}.each do |l| 
     unique << l unless hsh_array.include?(l.hsh) 
     hsh_array << l.hsh 
    end 
    unique   
    end 
end 

基準測試結果:

Benchmark.bmbm do |bm| 
    bm.report("option 2") do 
    losses.sort{|l1,l2| l2.created_at <=> l1.created_at}.group_by{|l| (l.policy_id + l.loss_occurred_on.hash)}.collect{|hl| hl[-1].first} 
    end 
    bm.report("option 3") do 
    hsh_array,unique = [],[] 
    losses.sort{|l1,l2| l2.created_at <=> l1.created_at}.each do |l| 
     unique << l unless hsh_array.include?(l.policy_id+l.loss_occurred_on.hash) 
     hsh_array << l.policy_id + l.loss_occurred_on.hash 
    end 
    end 
end 
Rehearsal -------------------------------------------- 
option 2 0.400000 0.000000 0.400000 ( 0.407615) 
option 3 0.250000 0.000000 0.250000 ( 0.254399) 
----------------------------------- total: 0.650000sec 

       user  system  total  real 
option 2 0.400000 0.000000 0.400000 ( 0.403535) 
option 3 0.250000 0.000000 0.250000 ( 0.262578) 

既不方式FE埃爾斯權利,但都工作。哪個是最好的選擇還是有更好的方法?

+0

不知道爲什麼,但agent.loss_reports(:order =>'created_at desc')沒有排序結果 – russellkt 2010-01-14 00:47:30

+0

agent.loss_reports(:order =>'created_at desc')沒有排序結果,因爲agent.loss_reports沒有采用與ActiveRecord :: Base.find相同的參數。 (它只需要一個布爾參數:reload(重新運行數據庫查詢)如果爲true)。使用agent.loss_reports.find(:all,:order =>'created_at desc')來執行此操作。 – 2010-01-14 00:54:49

回答

1

我不知道基準的想法,但似乎inject將是最簡單的方法:

loss_reports.inject([]) do |arr, report| 
    arr << report unless arr.detect{|r| ... } 
end 

,或者甚至更好的方式是通過定義一個自定義的SQL組named_scope ...

+0

偉大的建議 - 在http://stackoverflow.com/questions/2061389找到一個類似的問題,用一個使用named_scope的例子。 – russellkt 2010-01-15 13:26:01

相關問題