I have an interesting problem. I'm using Ruby 1.9.2 and Rails 3.1.3.
I have 2 models, for simplification let's say customers and stores. Stores have many customers, and a customer belongs to a store. I'm trying to collect all customers for a store, and create a place for a few more that I can populate with values later. Instead, customer.save is called when I don't expect it.
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
For some reason when the customer is pushed into the array, customer.save is called. It doesn't happen if you push to an array is a plain array and not a relation.
I found a workaround, but I'm still wondering why that happens. The workaround:
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
Another way around this would be to change your second line (of your original code) to:
customers_array = store.customers.to_a
That casts the active record association to a real array object, so the <<
method will be the normal Array#push method.
<<
is an alias for push
which in the ActiveRecord::Associations::CollectionProxy
calls concat
which calls concat_records
where you can see the insert taking place.
So, with an existing record (persisted into the database), running <<
or .push
will insert records into the collection, persisting them to the database if necessary. Calling <<
on an Array, not the record collection, as you're doing in
random_array << customer
calls Ruby's <<
Array method, not the AR equivalent (as you found, no save takes place in this case).
Edit: To be clear, the workaround you found is more or less how I typically handle the situation you're dealing with; my answer focuses more on why <<
has this behavior.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With