2012-01-26 92 views
4

考慮這個簡單的has_many關係:ActiveRecord的:治療的has_many列表作爲一個簡單的數組

class Basket < ActiveRecord::Base 
    has_many :apples 
    ... 
end 

class Apple < ActiveRecord::Base 
    belongs_to :basket 
end 

現在,我在籃下類中的方法,其中,我要創建「蘋果」數組的臨時副本並操縱臨時副本。對於初學者來說,我想一個新的元素添加到臨時副本如下:

class Basket < ActiveRecord::Base 
    has_many :apples 

    def do_something 
     #create a temporary working copy of the apples array 
     temp_array = self.apples 

     #create a new Apple object to insert in the temporary array 
     temp_apple = Apple.new 

     #add to my temporary array only 
     temp_array << temp_apple 

     #Problem! temp_apple.validate gets called but I don't want it to. 
    end 
end 

當我這樣做,我發現,驗證程序被調用的臨時蘋果對象上,當我嘗試將其添加到我的臨時陣列。我創建臨時數組的所有原因是爲了避免主數組帶來的所有行爲,例如驗證,數據庫插入等...

這就是說,我確實找到了一種蠻力方式避免這個問題的產生在時間temp_array一個對象的for循環如下所示。這有效,但它很醜。我想知道是否有一個更優雅的方式來實現這一點。

class Basket < ActiveRecord::Base 
    has_many :apples 

    def do_something 
     #create a temporary working copy of the apples array 
     temp_array = [] 
     for x in self.apples 
      temp_array << x 
     end 

     #create a new Apple object to insert in the temporary array 
     temp_apple = Apple.new 

     #add to my temporary array only 
     temp_array << temp_apple 

     #Yippee! the temp_apple.validate routine doesn't get called this time!. 
    end 
end 

如果有人比我聽到的更好的解決方案,我很樂意聽到它。

謝謝!

回答

9

問題是,self.apples實際上並不是一個數組 - 它是一個關係,一旦你應用Array/Enumerable方法就可以解決這個問題。所以,在此之後:temp_array = self.apples甚至SQL查詢沒有被解僱。

簡單的解決方案來強制獲取數據,並擺脫一切關係的行爲,只是使用方法all

#create a temporary working copy of the apples array 
temp_array = self.apples.all 
+0

這做到了。非常感謝! – Denis

2
temp_array = self.apples # => This results in an instance of ActiveRecord::Relation, not an Array 

你可以嘗試明確評估的關係

temp_array = self.apples.all # => This will give you an Array 
1

我覺得使用更合乎邏輯self.apples.to_a(= to_array):

基本上,ActiveRecord::Relation是一個擴展Array本身的對象,這意味着它具有所有Array技能但更多。

如果需要減少ActiveRecord::Relation的技能,將其轉換成一個數組,你是好。

+0

正是我需要的,謝謝! –