1

I have am creating a twitter style following relationship between users in my Rails 3.2.2 application. I have User and Relationship models.

class Relationship < ActiveRecord::Base
  belongs_to :user
  belongs_to :follower, :class_name => 'User'

  attr_accessible :follower, :follower_id, :status
end

class User < ActiveRecord::Base
  has_many :authentications, class_name: 'UserAuthentication'
  has_many :relationships
  has_many :followers, :through => :relationships
  has_many :following, :through => :relationships, :foreign_key => 'follower_id', :source => :follower

  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :omniauthable, :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me
end

I decided to leave the devise and omniauth stuff in there incase it happened to be part of the issue, though I doubt it.

In the command line I am working with two users u1 and u2.

I run the command

u1.followers.build(:follower_id=>u2.id)

and receive this error

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: follower_id
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activemodel-3.2.2/lib/active_model/mass_assignment_security.rb:228:in `sanitize_for_mass_assignment'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/base.rb:495:in `initialize'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/reflection.rb:183:in `new'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/reflection.rb:183:in `build_association'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/association.rb:233:in `build_record'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/has_many_through_association.rb:91:in `build_record'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/collection_association.rb:112:in `build'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-3.2.2/lib/active_record/associations/collection_proxy.rb:46:in `build'
    from (irb):29
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands/console.rb:47:in `start'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands/console.rb:8:in `start'
    from /Users/bradleyp/.rvm/gems/ruby-1.9.2-p290/gems/railties-3.2.2/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'

It's the first time I have used the build method on an association but it seems quite convenient if I can get it to work. If you need any more information please ask. Thanks for your help!

wuliwong
  • 4,238
  • 9
  • 41
  • 69
  • 1
    **attr_accessible** is not a very good way of protecting attributes. **strong_parameters** is now the recommended method. – ronalchn May 25 '13 at 01:06

1 Answers1

0

The follower_id is a field on Relationship. When you call u1.followers.build you are building a User which doesn't have a follower_id column. Since you are using attr_accessible, rails doesn't let you know that column doesn't exist, it just tells you you don't have access to it. (Which is good form a security perspective.)

Regardless, looks like you want to do:

u1.relationships.build(:follower_id => u2.id)

or maybe

u1.followers << u2

(With the code you showed I'm not 100% sure the second case will work off the type of my head -- you might need to further tweak your attr_accessible to get this second method to work. First one will definitely work, though.)

John Hinnegan
  • 5,864
  • 2
  • 48
  • 64