0

The problem is that I get this error:

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: amenity_id

when I run this code:

task import_amenities: :environment do

  agent = Mechanize.new

  Kindergarten.find_all_by_public(false).each do |k| 
    p = agent.get(k.uri)
    amenities = p.search("td td tr:nth-child(11) td:nth-child(2)").text.split(/(;|,) */)
    amenities.each do |a|
      am = Amenity.find_or_create_by_name!("#{a}")
      k.update_attributes(amenity_id: am.id)
    end
  end
end

Kindergartens and Amenities are linked through a HABTM relation and are are defined as below:

kindergarten.rb

class Kindergarten < ActiveRecord::Base
  attr_accessible :location, :name, :public, :uri, :address, :contact, 
                  :phone, :url, :email, :description, 
                  :password, :password_confirmation, :amenity_ids
  has_and_belongs_to_many :amenities
end

amenity.rb

class Amenity < ActiveRecord::Base
  attr_accessible :name, :kindergarten_ids
  has_and_belongs_to_many :kindergartens
end

and here's the migration for the join table:

class CreateKindergartensAmenitiesJoinTable < ActiveRecord::Migration
  def up

    create_table :kindergartens_amenities, :id => false do |t|
      t.integer :kindergarten_id
      t.integer :amenity_id
    end
  end
end

The error is caused by this line in the rake task:

k.update_attributes(amenity_id: am.id)

Everything seems to work great in the console until I reach the mass assignment. And I think i am really messing something up here since I've never used before HABTM.

Any thoughts?

Robin Winton
  • 591
  • 10
  • 23

1 Answers1

1

I couldn't sleep last night because of this bug but I finally found the solution.

there are a few issues in the code and the first one i noticed once i started digging and adding data in the db manually is that the join table is wrongfully named. Fix for that:

class RenameKindergartensAmenitiesTable < ActiveRecord::Migration
  def up
    rename_table :kindergartens_amenities, :amenities_kindergartens
  end
end

apparently the habtm association is has to have stuff put alphabetically in title. source

Second problem is that I assumed that

k.amenity_id = am.id

would add an amenity_id / kindergarten_id for each amenity existing. In fact k.amenity_id does not mean anything (especially in the case of many ids). The solution that worked is this:

amenities.each do |a|
  am = Amenity.find_or_create_by_name!("#{a}")
  k.update_attributes(amenity_ids: k.amenity_ids.push(am.id))
end

I haven't modified the attr_accessible anywhere

Robin Winton
  • 591
  • 10
  • 23