【问题标题】:Mass-assign attributes fails in nested form. Silent error?批量分配属性以嵌套形式失败。静默错误?
【发布时间】:2012-01-11 18:48:21
【问题描述】:

这里有几个问题coverthisalready,我知道。我是编程和 Rails 的新手,所以请多多包涵。我的目标是收集n 标签对象并将它们显示在我的显示和索引操作中。

更新 感谢两位回答的人。每个建议都将我推向了正确的方向。我可以通过传入一个空数组来初始化 tags 对象,从而获得创建帖子的 rake 任务。但是仍然没有创建标签。经过进一步检查,我得到以下 SQL 异常:

irb(main):002:0> u.posts.build(title: "a new day", tags: "jump")
WARNING: Can't mass-assign protected attributes: tags
(1.7ms)  SELECT 1 FROM "posts" WHERE "posts"."title" = 'a new day' LIMIT 1
(0.5ms)  COMMIT
 => #<Post id: nil, title: "a new day", description: nil, content: nil, user_id: 1,    created_at: nil, updated_at: nil>

我的设置如下:

Tag模特

class Tag < ActiveRecord::Base

belongs_to :post

end

Post型号

class Post < ActiveRecord::Base

has_many :tags, autosave: true
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?}}
#add n number of form fields to capture tags in each article.
   def with_blank_tags(n = 3)
     n.times do
       tags.build
     end
     self
    end
end

'查看'代码

<%= form_for(@post.with_blank_tags) do |f| %>
<div class="field">
  <%= f.fields_for(:tags) do |tags| %>
   <%= unless tags.object.new_record? tags.check_box('_destroy') + tags.label('_destroy', 'Remove Tag') end%>
   <%= tags.label :tags, "Add a Tag"%>
   <%= tags.text_field :tags %>
  <%end%>   
</div>
<%end%>

“控制器”代码

def new
 @post = @user.posts.build
end

def create
 @post = @user.posts.build(params[:post])
  if @post.save?
   respond_to do |format|
     format.html { redirect_to @post, notice: 'Post was successfully created.' }
    else
     format.html { render action: :new }
    end
   end
end

我的耙子任务:

namespace :db do
desc "Fill database with sample data"
task :posts => :environment do
 Rake::Task['db:reset'].invoke
  make_users
  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_posts
 puts "making posts..."
User.all(:limit => 3).each do |user|
  10.times do
    content = Faker::Lorem.paragraphs(3)
    description = Faker::Lorem.words(10)
    title = Faker::Lorem.words(4)
    tag = []
    post = user.posts.create!(title: title, description: description, content: content, tags_attributes: tag)
  end
 end
end

【问题讨论】:

  • 如果这很重要,我会感到惊讶。但是到目前为止,我在网上看到的许多其他问题和示例在 attr_accessible 调用之前都有接受嵌套属性调用。是否需要在将 #{name}_attributes 列入白名单之前对其进行定义?
  • @agmcleod 我按照您建议的顺序拨打电话并收到了同样的异常。
  • @agmcleod 我在post 中遇到了一个建议重命名模型的解决方案。我想知道模型的名称标签是否不可接受?

标签: ruby-on-rails ruby-on-rails-3 model nested-attributes


【解决方案1】:

如果您在 rails 中的模型上将某些属性声明为 attr_accessible,则所有其他属性将自动设置为 attr_protected。在我看来,您的问题可能源于您正在尝试创建帖子并同时分配 tags 属性。尝试将:tags 添加到Post 模型中的attr_accessible 属性列表中,看看是否可以解决问题。

【讨论】:

  • 谢谢@Batkins。我进行了更改并在控制台中收到以下错误rake aborted! Tag(#38643420) expected, got String(#18449760)
  • 我不确定您是否可以通过用户关系构建帖子,并通过帖子关系在一行中创建标签。例如,@post = @user.posts.build(tags: Tag.new) 可能需要拆分为 @post = @user.posts.build,然后是 @post.tags.build 的新行。这只是一个猜测。
  • 好吧,无论如何,我的回答似乎解决了您遇到can't mass-assign protected attributes 问题的问题,这是您提出问题时遇到的问题,所以您是否接受我的回答是正确的?您可以将新错误作为一个单独的问题提出。
  • 我同意。如果您不介意,我会为我发布的问题分配适当的解决方案。
  • 我的意思是我对发布的原始问题给出了正确的解决方案。
【解决方案2】:

在您的控制器上的#create 中,您不想调用@post.save 吗?您也不需要第二个 .tags 方法。很简单:

def create
  @post = @user.posts.build(params[:post])
  if @post.save
    redirect_to @post, notice: 'Post was successfully created.' }
  else
    render action: :new
  end
end

【讨论】:

  • 这在我的代码库中是正确的,但在这篇文章中却不是。发生同样的错误。
  • 遵循您的建议并从 attr_accessible 调用中删除 tags 可以生成示例数据。谢谢。
  • 在我的控制台中检查post 对象后,标签对象似乎没有保存。有什么想法吗?
  • 还是空的。我添加了我的 rake 任务来完成图片。
  • 在 rake 任务中,您必须将其命名为“tags_attributes”
【解决方案3】:

我能够解决问题。在 rdocs here 之后,为了设置嵌套属性,您将散列数组传递给 *_attributes。这消除了我上面描述的错误并设置了对象 id tags_id

我所要做的就是删除这一行:

tag = []
post = user.posts.create!(title: title, description: description, content: content, tags_attributes: tag)

并在我的 rake 任务中用这个替换它:

tag = Faker::Lorem.words(1) # create a tag
post = user.posts.create!(tags_attributes: [tags: tags])

现在,当我从控制台执行Tag.all 之类的操作时,我看到:

[#<Tag id: 1, post_id: 1, tags: "---\n- adipisci\n", created_at: "2012-01-12 06:31:13", updated_at: "2012-01-12 06:31:13">,

【讨论】:

    猜你喜欢
    • 2013-04-18
    • 1970-01-01
    • 2014-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多