has_many tricky replace method

Today I discovered a small bug / feature of rails 3.1.3.

Having the following structure:

class Item < ActiveRecord::Base
  has_many :tags
end

class Tag < ActiveRecord::Base
  # Tag has a boolean flag 'enabled'
  belongs_to :item
end

It's possible to completely replace the has_many collection
with a new collection. Make this collection:

item = Item.find(1)
tags = [ 
  item.tags.create( :enabled => true, :name => "tag1" )
]

All fine for the moment. As expected the enabled flag of the first item is set:

tags[0].name      # => "tag1"
tags[0].enabled?  # => true

Now replacing the existing tags:

item.tags.replace( tags )
item.tags[0].name        # => "tag1"
item.tags[0].enabled?    # => false 

What?? It just forgot the enabled flag!!

The way to replace the items is by assigning:

item.tags = tags
item.tags[0].name        # => "tag1"
item.tags[0].enabled?    # => true

So remember when replacing collections of has_many do not replace them but assign them....