批量分配异常未找到解释(Rails 3.2.1)

发布于 2025-01-05 09:07:51 字数 6369 浏览 2 评论 0原文

另请参阅这篇文章

注意: 当前的 rake 任务在设置帖子对象时会保存 User 和 Topic 对象,但不会保存帖子或标签。

问题:在我的 rake 任务(如下所示)中描述这种关系的正确方法是什么,以便它不会引发无法批量分配属性异常?

以下是我的步骤:

第 1 步:创建模型

class Post < ActiveRecord::Base
  belongs_to :topic, inverse_of: :posts
  has_and_belongs_to_many :tags
  attr_accessible :title, :description, :content, :tags_attributes
  accepts_nested_attributes_for :tags, allow_destroy: true, reject_if: lambda {|attrs| attrs.all? {|key, value| value.blank?}}
end

class Tag < ActiveRecord::Base
 has_and_belongs_to_many :posts
 attr_accessible :tag_name #UPDATE
end

class Topic < ActiveRecord::Base
  has_many :posts, inverse_of: :topic
  attr_accessible :topic_name, :posts_attributes
  accepts_nested_attributes_for :posts, allow_destroy: true, reject_if: lambda {|attrs| attrs.all? {|key, value| value.blank?}}
end

因此,我的 Post 模型是 Topic 的子模型,并且 Post 与 具有 HABTM 关系>标签。

第 2 步:创建 rake 任务

namespace :db do
desc "Fill database with sample data"
task :posts => :environment do
 Rake::Task['db:reset'].invoke
 make_users
 make_topics
 make_posts
 end
end

def make_users
 puts "making users" + "..."
 5.times do |n|
  name  = Faker::Name.name
  password = "foo"
  email = "example-#{n+1}@example.com"
    user = User.create!(
                codename: name,
                email: email,
                password: password,
                password_confirmation: password)
 end
end

def make_topics
  puts "making topics"+"..."
  3.times do
  t = Faker::Lorem.words(1)
  topic = Topic.create!(topic_name: t)
 end
end

def make_posts
 puts "making posts" + "..."
 User.all(limit: 3).each do |user|
  Topic.all.each do |topic|

    10.times do
      content = Faker::Lorem.paragraphs(3)
      description = Faker::Lorem.words(10)
      title = Faker::Lorem.words(4)
      tag_1 = Faker::Lorem.words(1)
      tag_2 = Faker::Lorem.words(1)
      tag_3 = Faker::Lorem.words(1)
      post = user.posts.create!(title: title, 
                                posts_attributes: [{topic_name: @topic}], 
                                description: description, 
                                content: content, 
                                tags_attributes: [{tag_name: tag_1}, {tag_name: tag_2}, {tag_name: tag_3}])
    end
  end
 end

end

第 3 步:现在运行 rake 任务

...
making users...
making posts...
rake aborted!
Can't mass-assign protected attributes: posts_attributes
...
...
/lib/tasks/make_posts.rake:45:in `block (3 levels) in make_posts'
/lib/tasks/make_posts.rake:38:in `times'
/lib/tasks/make_posts.rake:38:in `block (2 levels) in make_posts'
/lib/tasks/make_posts.rake:36:in `each'
/lib/tasks/make_posts.rake:36:in `block in make_posts'
/lib/tasks/make_posts.rake:35:in `each'
/lib/tasks/make_posts.rake:35:in `make_posts'
/lib/tasks/make_posts.rake:7:in `block (2 levels) in <top (required)>'

...
...

现在,由于我无法启动 rake 任务,所以我进入了控制台,下面是错误:

Topic Load (1.5ms)  SELECT "topics".* FROM "topics" LIMIT 1
=> #<Topic id: 1, topic_name: "---\n- aut\n", created_at: "2012-02-14 21:06:41", updated_at: "2012-02-14 21:06:41">
irb(main):007:0> topic.posts_attributes = {"1"=>{tag_name:"hammer time"}}
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: tag_name
 from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security.rb:228:in `sanitize_for_mass_assignment'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/base.rb:495:in `initialize'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/reflection.rb:183:in `new'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/reflection.rb:183:in `build_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/associations/association.rb:233:in `build_record'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/associations/collection_association.rb:112:in `build'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:405:in `block in assign_nested_attributes_for_collection_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:400:in `each'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:400:in `assign_nested_attributes_for_collection_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:288:in `posts_attributes='
   from (irb):7
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'
from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'irb(main):008:0>

Please see this post as well.

Note: The current rake task saves User and Topic objects, but not posts or tags when setting a post object.

Question: What is a proper way to describe this relationship in my rake task (shown below) so that it does not throw a can't mass assign attributes exception?

Here were my steps:

Step 1: Create models

class Post < ActiveRecord::Base
  belongs_to :topic, inverse_of: :posts
  has_and_belongs_to_many :tags
  attr_accessible :title, :description, :content, :tags_attributes
  accepts_nested_attributes_for :tags, allow_destroy: true, reject_if: lambda {|attrs| attrs.all? {|key, value| value.blank?}}
end

class Tag < ActiveRecord::Base
 has_and_belongs_to_many :posts
 attr_accessible :tag_name #UPDATE
end

class Topic < ActiveRecord::Base
  has_many :posts, inverse_of: :topic
  attr_accessible :topic_name, :posts_attributes
  accepts_nested_attributes_for :posts, allow_destroy: true, reject_if: lambda {|attrs| attrs.all? {|key, value| value.blank?}}
end

Therefore, my Post model is a child of Topic and Post has a HABTM relationship with Tags.

Step 2: Create a rake task

namespace :db do
desc "Fill database with sample data"
task :posts => :environment do
 Rake::Task['db:reset'].invoke
 make_users
 make_topics
 make_posts
 end
end

def make_users
 puts "making users" + "..."
 5.times do |n|
  name  = Faker::Name.name
  password = "foo"
  email = "example-#{n+1}@example.com"
    user = User.create!(
                codename: name,
                email: email,
                password: password,
                password_confirmation: password)
 end
end

def make_topics
  puts "making topics"+"..."
  3.times do
  t = Faker::Lorem.words(1)
  topic = Topic.create!(topic_name: t)
 end
end

def make_posts
 puts "making posts" + "..."
 User.all(limit: 3).each do |user|
  Topic.all.each do |topic|

    10.times do
      content = Faker::Lorem.paragraphs(3)
      description = Faker::Lorem.words(10)
      title = Faker::Lorem.words(4)
      tag_1 = Faker::Lorem.words(1)
      tag_2 = Faker::Lorem.words(1)
      tag_3 = Faker::Lorem.words(1)
      post = user.posts.create!(title: title, 
                                posts_attributes: [{topic_name: @topic}], 
                                description: description, 
                                content: content, 
                                tags_attributes: [{tag_name: tag_1}, {tag_name: tag_2}, {tag_name: tag_3}])
    end
  end
 end

end

Step 3: Now run the rake task

...
making users...
making posts...
rake aborted!
Can't mass-assign protected attributes: posts_attributes
...
...
/lib/tasks/make_posts.rake:45:in `block (3 levels) in make_posts'
/lib/tasks/make_posts.rake:38:in `times'
/lib/tasks/make_posts.rake:38:in `block (2 levels) in make_posts'
/lib/tasks/make_posts.rake:36:in `each'
/lib/tasks/make_posts.rake:36:in `block in make_posts'
/lib/tasks/make_posts.rake:35:in `each'
/lib/tasks/make_posts.rake:35:in `make_posts'
/lib/tasks/make_posts.rake:7:in `block (2 levels) in <top (required)>'

...
...

Now since I could not get my rake task going, I went into the console and here is the error:

Topic Load (1.5ms)  SELECT "topics".* FROM "topics" LIMIT 1
=> #<Topic id: 1, topic_name: "---\n- aut\n", created_at: "2012-02-14 21:06:41", updated_at: "2012-02-14 21:06:41">
irb(main):007:0> topic.posts_attributes = {"1"=>{tag_name:"hammer time"}}
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: tag_name
 from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
  from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activemodel-3.2.1/lib/active_model/mass_assignment_security.rb:228:in `sanitize_for_mass_assignment'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/base.rb:495:in `initialize'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/reflection.rb:183:in `new'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/reflection.rb:183:in `build_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/associations/association.rb:233:in `build_record'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/associations/collection_association.rb:112:in `build'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:405:in `block in assign_nested_attributes_for_collection_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:400:in `each'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:400:in `assign_nested_attributes_for_collection_association'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/activerecord-3.2.1/lib/active_record/nested_attributes.rb:288:in `posts_attributes='
   from (irb):7
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'
   from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'
from /home/rhodee/.rbenv/versions/1.9.3-p0/lib/ruby/gems/1.9.1/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'irb(main):008:0>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

北城半夏 2025-01-12 09:07:51

为什么要将 posts_attributes 传递给 user.posts.create?在我看来,您想要创建一个包含许多帖子的主题,在这种情况下,您应该执行user.topics.create

Why are you passing posts_attributes to user.posts.create? It looks to me like you're wanting to create a topic that has many posts, in which case you should be doing user.topics.create instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文