嵌套受保护模型的“无法批量分配受保护属性”

Posted

技术标签:

【中文标题】嵌套受保护模型的“无法批量分配受保护属性”【英文标题】:"Can't mass-assign protected attributes" with nested protected models 【发布时间】:2012-09-05 00:51:29 【问题描述】:

我正在努力让这个嵌套模型工作。我已经尝试了各种复数/单数形式,完全删除了 attr_accessible,谁知道还有什么。

餐厅.rb:

# == RESTAURANT MODEL
#
# Table name: restaurants
#
#  id         :integer          not null, primary key
#  name       :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null
#

class Restaurant < ActiveRecord::Base
  attr_accessible :name, :job_attributes

  has_many    :jobs
  has_many    :users, :through => :jobs
  has_many    :positions

  accepts_nested_attributes_for :jobs, :allow_destroy => true

  validates :name, presence: true

end

job.rb:

# == JOB MODEL
#
# Table name: jobs
#
#  id            :integer          not null, primary key
#  restaurant_id :integer
#  shortname     :string(255)
#  user_id       :integer
#  created_at    :datetime         not null
#  updated_at    :datetime         not null
#

class Job < ActiveRecord::Base
  attr_accessible :restaurant_id, :shortname, :user_id

  belongs_to    :user
  belongs_to    :restaurant
  has_many      :shifts


  validates :name, presence: false

end

restaurants_controller.rb:

class RestaurantsController < ApplicationController

  before_filter :logged_in, only:  [:new_restaurant]

  def new
    @restaurant = Restaurant.new
    @user = current_user
  end

  def create
    @restaurant = Restaurant.new(params[:restaurant])
    if @restaurant.save
      flash[:success] = "Restaurant created."  
      redirect_to welcome_path
    end
  end

end

new.html.erb:

<% provide(:title, 'Restaurant') %>

  <%= form_for @restaurant do |f| %>
        <%= render 'shared/error_messages' %>

        <%= f.label "Restaurant Name" %>
        <%= f.text_field :name %>

        <%= f.fields_for :job do |child_f| %>

              <%= child_f.label "Nickname" %>
              <%= child_f.text_field :shortname %>

        <% end %>

        <%= f.submit "Done", class: "btn btn-large btn-primary" %>

  <% end %>

输出参数:

"utf8"=>"✓",
 "authenticity_token"=>"DjYvwkJeUhO06ds7bqshHsctS1M/Dth08rLlP2yQ7O0=",
 "restaurant"=>"name"=>"The Pink Door",
 "job"=>"shortname"=>"PD",
 "commit"=>"Done"

我收到的错误是:

ActiveModel::MassAssignmentSecurity::Error in RestaurantsController#create

Cant mass-assign protected attributes: job
Rails.root: /home/johnnyfive/Dropbox/Projects/sa

Application Trace | Framework Trace | Full Trace
app/controllers/restaurants_controller.rb:11:in `new'
app/controllers/restaurants_controller.rb:11:in `create'

任何人都有 ANY 线索如何让它工作?谢谢!

【问题讨论】:

与您的问题无关 - 我注意到每个类顶部的 cmets 定义了数据库结构。保持更新是一件很痛苦的事,而且很容易变得陈旧。 Rails 在运行迁移时自动更新 schema.rb 做得很好,并且可能是您根据模型记录数据库的更好方法。 @MichaelShimmins 我不这样做,它是由 gem 'annotate' 完成的。 【参考方案1】:

在餐厅.rb:

应该是 attr_accessible :name, :jobs_attributes 代替 attr_accessible :name, :job_attributes

【讨论】:

谢谢你(不太确定),但是我在当前的迭代中有这个,我仍然收到同样的错误。 餐厅模特有很多工作,所以我想你应该把&lt;%= f.fields_for :jobs do |child_f| %&gt;而不是:job @Kishie,我同意你的观点,并且也尝试过,但是当我这样做时,在浏览器中查看时,“短名称”字段会完全消失。我敢肯定这很简单,但我这辈子都想不通。 @JohnnyFive @kishie 所说的一切都是正确的。我认为您的问题是没有将任何工作记录添加到您的 @restraunt 对象的结果。如果您遵循@kishie 的建议3.times @restaurant.jobs.build 添加到RestaurantsController#new 操作的末尾会发生什么。 @JohnnyFive 这是因为f.fields_for 试图遍历与@restaurant 对象关联的所有作业。但是,因为@restaurant 是一个新对象,您需要手动添加一些默认作业。有关嵌套表单如何工作的更多信息,请观看 railscasts.com/episodes/196-nested-model-form-part-1 上的视频,这是我学习如何使用嵌套表单的地方。【参考方案2】:

关于您的最后评论: 您可以在工作表中提交 user_id,这应该将 user_id 提交给模型

【讨论】:

以上是关于嵌套受保护模型的“无法批量分配受保护属性”的主要内容,如果未能解决你的问题,请参考以下文章

如何删除引用到对象的所有嵌套对象?

Twig 访问受保护/私有模型变量

在 Laravel 中创建模型时使用受保护的 $table 变量

如何在没有 Laravel 尝试将其保存到数据库的情况下在 Eloquent 模型中使用受保护的属性

无法批量分配受保护的属性:配置文件,

“警告:无法批量分配受保护的属性”