机械化HABTM连接表的质量分配错误

时间:2012-09-16 18:36:13

标签: ruby-on-rails mechanize has-and-belongs-to-many

问题是我收到了这个错误:

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

当我运行此代码时:

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

幼儿园和设施通过HABTM关系相互关联,定义如下:

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

这是联接表的迁移:

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

错误是由rake任务中的这一行引起的:

k.update_attributes(amenity_id: am.id)

在我完成大规模任务之前,一切似乎都在控制台中运行良好。因为我从来没有在HABTM之前使用过,所以我觉得我真的搞乱了。

有什么想法吗?

1 个答案:

答案 0 :(得分:1)

由于这个错误我昨晚无法入睡,但我终于找到了解决办法。

代码中存在一些问题,我注意到的第一个问题是我开始在数据库中手动挖掘和添加数据时,连接表被错误命名。解决了这个问题:

class RenameKindergartensAmenitiesTable < ActiveRecord::Migration
  def up
    rename_table :kindergartens_amenities, :amenities_kindergartens
  end
end
显然,habtm协会必须按字母顺序排列标题。 source

第二个问题是我认为

k.amenity_id = am.id

会为现有的每个设施添加amenity_id / kindergarten_id。事实上,k.amenity_id并不意味着什么(特别是在许多ID的情况下)。有效的解决方案是:

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

我没有修改attr_accessible任何地方