This project is archived and is in readonly mode.
Array of records from ActiveRecord Association does not behave as expected
Reported by Kent T | January 7th, 2010 @ 05:37 PM
From my limited experience and knowledge of Ruby on Rails, it
appears that an Array can perform just like an association array
when it is created from an array of associated records.
Take the following example. (Though this is simple, it illustrates
the point.)
Project has_and_belongs_to_many Contracts
Contract has_and_belongs_to_many Projects
@record = Project.first
all_contracts = @record.contracts
@cts = Contracts.find(:all, :limit=>5)
@cts.each do |c|
all_contracts << c
end
Every record that is added to the all_contracts array is
actually added to the @record.contracts association. It performs
like I had called @record.contracts << c
In the console I can even see the records being inserted into the
database.
My solution was like this:
@record = Project.first
all_contracts = Array.new()
all_contracts = all_contracts | @record.contracts
@cts = Contracts.find(:all, :limit=>5)
@cts.each do |c|
all_contracts << c
end
My solution does not create any join records.
Is this a feature or a bug? Did I miss some documentation some where to this effect?
Comments and changes to this ticket
-
Matt Jones January 7th, 2010 @ 07:04 PM
- State changed from new to wontfix
This behavior is by design - @record.contracts doesn't actually return an Array, but an instance of AssociationCollection that mostly pretends to be an array. This lets you do things like:
@record.contracts.exists?(@some_contract)
which does a specific SQL query if
@record.contracts
isn't loaded yet, avoiding that database overhead. It also permits you to chain named scopes onto an association (@record.contracts.some_scope
) and build/create associated records (with@record.contracts.build
, etc.).If you really want to remove all the magic,
@record.contracts.to_a
will do what you're looking for. -
Kent T January 7th, 2010 @ 07:31 PM
I don't wish to remove any of the magic of @record.contracts.
However, when I instantiate an array from @record.contracts, should the array be an Array or an instance of AssociationCollection?Example
all_contracts = @record.contracts
all_contracts would be an array
@record.contracts would be an instance of AssociationCollection
Interestingly enough, when I printed the class of all_contracts it shows as an array, but it behaves like AssociationCollection. This is what I don't understand.
-
Matt Jones January 7th, 2010 @ 09:32 PM
This is a common gotcha in Ruby - objects are pretty much passed around as references. An example:
a = [1,2,3] b = a a << 4 b # => [1,2,3,4]
So in your example, all_contracts is still an instance of AssociationCollection (although it fibs in the .class method and claims to be an Array). There are some ways to tell the two apart, though - all_contracts.respond_to?(:proxy_reflection) will return true, not that one typically needs to figure out that difference in standard Rails code.
Anyway, if you have further questions, feel free to ask on the rails-talk list to avoid cluttering up Lighthouse.
-
Rohit Arondekar October 7th, 2010 @ 05:21 AM
- Tag changed from activerecord associations, habtm to activerecord, associations, habtm
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>