2014-05-23 28 views
0

我有這樣的代碼。未定義的方法`find_each'for []:Array

@deliveries = User.find_uniq_deliveries(...) 
. 
. 
. 
(many conditions added using 'named_scope') 
@deliveries.sort do |a,b| 
. 
. 
end 

的主要問題是,這是獲取大量結果,並給予甲骨文例外,超過1000個元素中不允許「在」語句。 所以我試圖用find_each分批

deliveries_list = [] 
@deliveries.find_each(:batch_size=999) do |delivery| 
    deliveries_list.push(delivery) 
end 
@deliveries = deliveries_list 

獲取但這給人的例外

未定義的方法`find_each」爲[]數組

正如你所看到的感到相當新的鐵路(來自java)和鐵路完全沒有意義。我能做些什麼來防止的Oracle SQL錯誤,但獲取數據

編輯:

def find_uniq_deliveries(category,date,view) 
    dels = [] 
    sent_deliveries.send("for_#{category}s").send("with_#{category}_status", view).for_date_range(date).collect(&:workflow_item).uniq.each do |m| 
     dels << m.deliveries.first unless m.deliveries.empty? 
    end 
    dels.compact 
    end 
+0

完整的回溯應該列出出現錯誤的文件名和行號。你的for_each在find_uniq_deliveries裏面嗎?我懷疑Ruby或Rails中存在for_each。 –

+0

這是我的錯誤,對不起!它的find_each。 – Skeptor

+0

錯誤位於使用排序的行中。 – Skeptor

回答

0

很多後研究一週並通過檢查其源代碼來了解named_scopes。我明白了問題所在。 @deliveries是類ActiveRecord::NamedScope::Scope的一個對象。這個類沒有find_each方法。所以我寫了限制新named_scope和遵循Delivery模型文件偏移:

named_scope :limit_and_offset, lambda { |lim,off| { :limit => lim, :offset=>off } } 

在此之後,我在一個循環中通過偏移和限制,爲前稱它。第一個循環的offset = 0,limit = 999,第二個循環的offset = 999,limit = 999。我將把所有結果添加到emptry數組中。該循環繼續進行,直到結果大小小於極限值。這是按照我想要的方式,批量工作。

set = 1 
total_deliveries = [] 
set_limit=999 
original_condition = @deliveries 
loop do 
    offset = (set-1) * set_limit 
    temp_condition = original_condition.limit_and_offset(set_limit,offset) 
    temp_deliveries = temp_condition.find(:all) 
    total_deliveries+= temp_deliveries 
    set += 1 
    break if temp_deliveries.size < set_limit 
end 
@deliveries = total_deliveries.sort do |a, b| 
2

find_each必須調用上的活動記錄查詢結果。

您正從find_uniq_deliveries返回一個數組,因此find_each不受支持。

您需要重寫查詢以將find_each調用放在.collect(&:workflow_item)之前。

又見活動記錄的查詢接口是可鏈接的方法:

http://guides.rubyonrails.org/active_record_querying.html

的.collect方法將導致值的數組所以你不能以後把find_each。

編輯:這裏是如何重構代碼以使用find_each一個簡單的例子

的基本配方是:

  1. 建立一個活動記錄查詢調用任何非查詢方法之前,如收集。

  2. 作爲該查詢的一部分,您將使用find_each遍歷結果集,以動態方式從數據庫中提取批結果。

  3. 保存非活動記錄調用,如最後一次收集。您可以返回結果數組,但只需知道您將無法使用此數組調用任何其他AR方法(如命名範圍)。

下面是一個使用find_each,它以一個查詢爲例find_uniq_deliveries:

def find_uniq_deliveries(query,category,date,view) 
    dels = [] 
    query.send("for_#{category}s").send("with_#{category}_status", view).for_date_range(date).find_each do |delivery| 
    # do something with your delivery object and save result 
    result = process_delivery(delivery) 
    dels << result 
    end 
    dels.compact 
end 

而且你可以用任何交付查詢,像這樣稱呼它:

query = Delivery.some_named_scope.some_other_scope 
find_uniq_deliveries(query,category,date,view) 
+0

這是一個現有的代碼所以只是爲了啓用批處理,不知道是否需要做所有這些更改,並且是一名Java開發人員,所以堅持使用這個rails魔術。 – Skeptor

+0

@Skeptor - find_each要求您使用.each迭代器來處理結果。您目前的方法與此不兼容。這將需要對您的技術進行相當大的改變才能使用find_each。或者,您可以將您的ID分爲1000個ID組,以解決您的原始問題:) – TomDavies

+0

感謝您的洞察力Tom Davies。你能否詳細說明你的替代解決方案?我沒有權限直接修改SQL權限,除非我完全寫出不同的代碼。 – Skeptor

相關問題