Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Rails 3 has_many through forces developer to make *_id attributes unprotected

#6552

In the classic Group <-> Membership <-> User scenario:

class Group
  has_many :memberships
  has_many :users, :through => :memberships
end

class Membership
  belongs_to :user
  belongs_to :group
end

class User
  has_many :memberships
end

If Membership has:

attr_protected :user_id, :group_id

Then executing:

group = Group.create!
user = User.create!

group.users << user
group.users.include? user # => true
group.users.reload.include? user # => false

Causes membership creation to fail.

From my research, it appears this is due to new way of creating "through" models in Rails 3.
Through models are now created using mass-assignment.

The problem lies in ActiveRecord::Associations::HasManyThroughAssociation#insert_record method defined in lib/active_record/associations/has_many_through_association.rb file.

Here is a quick monkey patch which resolves the issue (put it in config/initializers/fix_has_many.rb):

class ActiveRecord::Associations::HasManyThroughAssociation
  protected

  def insert_record(record, force = true, validate = true)
    if record.new_record?
      if force
        record.save!
      else
        return false unless record.save(:validate => validate)
      end
    end

    through_association = @owner.send(@reflection.through_reflection.name)

    through_association.create! do |r|
      construct_join_attributes(record).each { |k, v| r.send "#{k}=", v }
    end
  end
end

Reported by Pawel · March 9th, 2011 @ 09:15 PM

State: resolved
Milestone: none
Assigned to: Dan Pickett Dan Pickett
Importance: Low

Activity

  1. Dan Pickett
    Dan Pickett
    • Tag changed from activerecord rails3 has_many through mass-assignment security attr_accessible to attr_accessible, has_many_through_association, rails3
    • State changed from new to open
    • Assigned user set to Dan Pickett
    • Importance changed from to Low

    based on my reading of the code on edge in has_many_through association it is performing a direct assignment on both ends of the relationship and the assignment should be unaffected by attr security.

    Can you provide a failing test case for this, Pawel?

    March 12th, 2011 @ 05:41 PM

  2. Pawel
    Pawel

    I was testing this only on 3.0.5.
    From reading the edge source code it appears to be fixed, so the bug could be closed now.

    March 15th, 2011 @ 12:53 PM

  3. Dan Pickett
    Dan Pickett
    • State changed from open to resolved

    March 15th, 2011 @ 12:57 PM

  4. dmitry zhelnin
    dmitry zhelnin

    The issue is still unresolved in 3.0.6

    April 6th, 2011 @ 09:17 AM

  5. Dan Pickett
    Dan Pickett

    Dmitry,

    Could you provide a failing test case? I'd be happy to look into it.

    Thanks,
    Dan

    April 6th, 2011 @ 11:16 AM

  6. dmitry zhelnin