Reputation: 176
I just noticed that one of the attributes of an object was being updated when this object was appended to an array. This behavior looks very surprising to me and I thought I might be missing something fundamental about ActiveRecord.
In my app, every idea has a father (through its father_id attribute). This association is set in models/idea.rb with the following :
class Idea < ActiveRecord::Base
belongs_to :father, :class_name => "Idea" # , :foreign_key => "idea_id"
has_many :children, :class_name => "Idea", :foreign_key => "father_id", :dependent => :destroy
[...]
Here is what happens in rails console :
I first select a given idea :
irb(main):003:0> n = Idea.find(1492)
Idea Load (1.1ms) SELECT "ideas".* FROM "ideas" WHERE "ideas"."id" = $1 LIMIT 1 [["id", 1492]]
=> #<Idea id: 1492, father_id: 1407, [...]>
I then retrieve its children through the associations :
irb(main):004:0> c = n.children
Idea Load (0.5ms) SELECT "ideas".* FROM "ideas" WHERE "ideas"."father_id" = 1492
=> []
It doesn't have any, which is ok. I then want to append the idea itself to the 'c' variable but this triggers an unwanted UPDATE action in the database :
irb(main):005:0> c << n
(0.1ms) BEGIN
(0.9ms) UPDATE "ideas" SET "father_id" = 1492, "updated_at" = '2013-12-06 12:57:25.982619' WHERE "ideas"."id" = 1492
(0.4ms) COMMIT
=> [#<Idea id: 1492, father_id: 1492, [...]>]
The father_id attribute, which had the value 1407 now has the value 1492, i.e. the idea's id.
Can anyone explain me why this happens and how I can create an array that includes an object's children and the object itself without altering the object's attributes ?
NB : I'm using ruby 1.9.3p448 (2013-06-27 revision 41675) [x86_64-darwin13.0.0]
Upvotes: 0
Views: 128
Reputation: 239311
This is expected behavior. You're adding a new idea to the set of ideas belonging to a specific father. This happens because it's not an array you're appending to, it's an ActiveRecord association. In your console, try n.children.class
.
If you want a flat array which won't modify objects appended to it, you want:
c = n.children.to_a
c << n
Upvotes: 1