2012-06-15 23 views
11

Tengo un problema interesante. Estoy usando Ruby 1.9.2 y Rails 3.1.3.Rails push into array guarda el objeto

Tengo 2 modelos, para simplificación, digamos clientes y tiendas. Las tiendas tienen muchos clientes y un cliente pertenece a una tienda. Estoy tratando de reunir a todos los clientes de una tienda y crear un lugar para algunos más que pueda completar con valores posteriores. En cambio, se llama a customer.save cuando no lo espero.

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 

Por alguna razón, cuando se introduce al cliente en la matriz, se llama a customer.save. No sucede si presionas una matriz es una matriz simple y no una relación.

Encontré una solución, pero todavía me pregunto por qué sucede eso. La solución:

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

Para aquellos que buscan una solución y no el por qué: use '' 'build''' en la colección para crear un modelo sin guardarlo: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods .html # module-ActiveRecord :: Associations :: ClassMethods-label-Collections – blu

+0

Tuve el problema opuesto. Usar 'build' en las especificaciones del modelo, luego agregar elementos a una colección usando << no funcionó. Las respuestas a esta pregunta explican por qué no. – CJBrew

Respuesta

21

<< es un alias para push

que a las llamadas ActiveRecord::Associations::CollectionProxyconcat

que llama a concat_records

donde se puede ver el inserto que tiene lugar.

lo tanto, con un registro existente (persistido en la base de datos), correr o <<.push va a insertar registros en la colección, que persiste a la base de datos si es necesario. Llamando << en una matriz, y no la colección de discos, como se está haciendo en

random_array << customer 

llama al método << matriz de Ruby, no el AR equivalente (como lo encontró, sin salvación tiene lugar en este caso).

Edit: Para ser claros, la solución que ha encontrado es más o menos cómo manejo la situación que está tratando; mi respuesta se centra más en por qué<< tiene este comportamiento.

3

Otra forma de evitar esto sería cambiar su segunda línea (de su código original) para:

customers_array = store.customers.to_a 

que proyecta la asociación registro activo a un objeto de matriz real, así que el método << será la normal, Array # push method.

Cuestiones relacionadas