Pierre
Pierre

Reputation: 176

Ruby ActiveRecord fundamentals : appending an object to an array with << might update its attributes?

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

Answers (1)

user229044
user229044

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

Related Questions