2012-06-15 10 views
11

Ich habe ein interessantes Problem. Ich benutze Ruby 1.9.2 und Rails 3.1.3.Schienen schieben in Array speichert Objekt

Ich habe 2 Modelle, zur Vereinfachung sagen wir Kunden und speichert. Stores haben viele Kunden, und ein Kunde gehört zu einem Geschäft. Ich versuche, alle Kunden für ein Geschäft zu sammeln, und erstellen Sie einen Platz für ein paar mehr, die ich später mit Werten füllen kann. Stattdessen wird customer.save aufgerufen, wenn ich es nicht erwarte.

store = Store.find(1) 
customers_array = store.customers 
random_array = Array.new 
customers_count = customers_array.count + 1 

(customers_count..2).each do |i| 
    customer = Customer.new 
    c.id = "#{i}000000000000" 
    random_array << customer # this line doesn't call customer.save 
    customers_array << customer # this line calls customer.save when store has customers 
end 

Aus irgendeinem Grund, wenn der Kunde in das Array geschoben wird, wird customer.save aufgerufen. Es passiert nicht, wenn Sie auf ein Array drücken, ist ein einfaches Array und keine Beziehung.

Ich habe einen Workaround gefunden, aber ich frage mich immer noch, warum das passiert. Die Abhilfe:

store = Store.find(1) 
initial_customers_array = store.customers 
additional_customers_array = Array.new 
customers_count = initial_customers_array.count + 1 

(customers_count..2).each do |i| 
    customer = Customer.new 
    c.id = "#{i}000000000000" 
    additional_customers_array << customer 
end 
customers_array = initial_customers_array + additional_customers_array 
+1

Für diejenigen, die nach einer Lösung und nicht nach dem Warum suchen: Verwenden Sie '' 'build''' für die Sammlung, um ein Modell zu erstellen, ohne es zu speichern: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods .html # module-ActiveRecord :: Assoziationen :: ClassMethods-label-Collections – blu

+0

Ich hatte das gegenteilige Problem. Wenn Sie 'build' in den Modellspezifikationen verwenden, funktioniert das Hinzufügen von Elementen zu einer Sammlung mit << nicht. Die Antworten auf diese Frage erklären warum nicht. – CJBrew

Antwort

21

<< ist ein Alias ​​für push

die in den ActiveRecord::Associations::CollectionProxy Anrufe concat

die Anrufe concat_records

, wo Sie der Einsatz stattfindet, sehen kann.

Also, mit einem vorhandenen Datensatz (beharrte in die Datenbank), läuft << oder .push werden Datensätze in die Sammlung einfügen, sie in die Datenbank bei Bedarf persistierenden. Der Aufruf << auf einem Array, nicht die Plattensammlung, wie Sie in

random_array << customer 

ruft Ruby << Array-Methode, nicht die AR Äquivalent tun (wie Sie, ohne Speichern erfolgt in diesem Fall).

Bearbeiten: Um klar zu sein, die Problemumgehung, die Sie gefunden haben, ist mehr oder weniger, wie ich in der Regel die Situation behandeln, die Sie beschäftigen; Meine Antwort konzentriert sich mehr auf , warum<< dieses Verhalten hat.

3

Ein anderer Weg, um dies wäre Ihre zweite Linie zu ändern (von Ihrem ursprünglichen Code):

customers_array = store.customers.to_a 

, dass die aktive Datensatz Assoziation zu einem echten Array-Objekt wirft, so dass die << Methode wird die normal sein Array # Push-Methode.

Verwandte Themen