Ruby-on-rails 嵌套属性不允许参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15919761/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 21:48:01  来源:igfitidea点击:

Nested attributes unpermitted parameters

ruby-on-railsruby-on-rails-4

提问by jcanipar

I have a Billobject, which has many Dueobjects. The Dueobject also belongs to a Person. I want a form that can create the Billand its children Duesall in one page. I am trying to create a form using nested attributes, similar to ones in this Railscast.

我有一个Bill对象,它有很多Due对象。该Due对象也属于Person. 我想要一个可以在一页中创建Bill及其子项的表单Dues。我正在尝试使用嵌套属性创建一个表单,类似于这个 Railscast 中的那些。

Relevant code is listed below:

相关代码如下:

due.rb

到期.rb

class Due < ActiveRecord::Base
    belongs_to :person
    belongs_to :bill
end

bill.rb

账单文件

class Bill < ActiveRecord::Base
    has_many :dues, :dependent => :destroy 
    accepts_nested_attributes_for :dues, :allow_destroy => true
end

bills_controller.rb

bills_controller.rb

  # GET /bills/new
  def new
      @bill = Bill.new
      3.times { @bill.dues.build }
  end

bills/_form.html.erb

bills/_form.html.erb

  <%= form_for(@bill) do |f| %>
    <div class="field">
        <%= f.label :company %><br />
        <%= f.text_field :company %>
    </div>
    <div class="field">
        <%= f.label :month %><br />
        <%= f.text_field :month %>
    </div>
    <div class="field">
        <%= f.label :year %><br />
        <%= f.number_field :year %>
    </div>
    <div class="actions">
        <%= f.submit %>
    </div>
    <%= f.fields_for :dues do |builder| %>
        <%= render 'due_fields', :f => builder %>
    <% end %>
  <% end %>

bills/_due_fields.html.erb

bills/_due_fields.html.erb

<div>
    <%= f.label :amount, "Amount" %>        
    <%= f.text_field :amount %>
    <br>
    <%= f.label :person_id, "Renter" %>
    <%= f.text_field :person_id %>
</div>

UPDATE to bills_controller.rbThis works!

更新到 bills_controller.rb这有效!

def bill_params 
  params
  .require(:bill)
  .permit(:company, :month, :year, dues_attributes: [:amount, :person_id]) 
end

The proper fields are rendered on the page (albeit without a dropdown for Personyet) and submit is successful. However, none of the children dues are saved to the database, and an error is thrown in the server log:

页面上呈现了正确的字段(尽管还没有下拉列表Person)并且提交成功。但是,没有任何孩子的会费保存到数据库中,并且在服务器日志中抛出错误:

Unpermitted parameters: dues_attributes

Just before the error, the log displays this:

就在错误之前,日志显示:

Started POST "/bills" for 127.0.0.1 at 2013-04-10 00:16:37 -0700
Processing by BillsController#create as HTML<br>
Parameters: {"utf8"=>"?", 
"authenticity_token"=>"ipxBOLOjx68fwvfmsMG3FecV/q/hPqUHsluBCPN2BeU=",
 "bill"=>{"company"=>"Comcast", "month"=>"April ", 
"year"=>"2013", "dues_attributes"=>{
"0"=>{"amount"=>"30", "person_id"=>"1"}, 
"1"=>{"amount"=>"30", "person_id"=>"2"},
 "2"=>{"amount"=>"30", "person_id"=>"3"}}}, "commit"=>"Create Bill"}

Has there been some change in Rails 4?

Rails 4 有什么变化吗?

回答by thorsten müller

Seems there is a change in handling of attribute protection and now you must whitelist params in the controller (instead of attr_accessible in the model) because the former optional gem strong_parameters became part of the Rails Core.

似乎在处理属性保护方面发生了变化,现在您必须将控制器中的参数列入白名单(而不是模型中的 attr_accessible),因为以前的可选 gem strong_parameters 成为 Rails Core 的一部分。

This should look something like this:

这应该是这样的:

class PeopleController < ActionController::Base
  def create
    Person.create(person_params)
  end

private
  def person_params
    params.require(:person).permit(:name, :age)
  end
end

So params.require(:model).permit(:fields)would be used

所以params.require(:model).permit(:fields)会被使用

and for nested attributes something like

和嵌套属性类似

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])

Some more details can be found in the Ruby edge API docsand strong_parameters on githubor here

更多细节可以在Ruby 边缘 API 文档github 上的 strong_parameters这里找到

回答by Leahcim

From the docs

从文档

To whitelist an entire hash of parameters, the permit! method can be used

params.require(:log_entry).permit!

Nested attributes are in the form of a hash. In my app, I have a Question.rb model accept nested attributes for an Answer.rb model (where the user creates answer choices for a question he creates). In the questions_controller, I do this

嵌套属性采用散列形式。在我的应用程序中,我有一个 Question.rb 模型接受 Answer.rb 模型的嵌套属性(用户为他创建的问题创建答案选项)。在questions_controller中,我这样做

  def question_params

      params.require(:question).permit!

  end

Everything in the question hash is permitted, including the nested answer attributes. This also works if the nested attributes are in the form of an array.

问题哈希中的所有内容都是允许的,包括嵌套的答案属性。如果嵌套属性采用数组形式,这也适用。

Having said that, I wonder if there's a security concern with this approach because it basically permits anything that's inside the hash without specifying exactly what it is, which seems contrary to the purpose of strong parameters.

话虽如此,我想知道这种方法是否存在安全问题,因为它基本上允许散列中的任何内容,而没有具体说明它是什么,这似乎与强参数的目的背道而驰。

回答by Amit Agarwal

or you can simply use

或者你可以简单地使用

def question_params

  params.require(:question).permit(team_ids: [])

end

回答by nothing-special-here

Actually there is a way to just white-list all nested parameters.

实际上有一种方法可以将所有嵌套参数列入白名单。

params.require(:widget).permit(:name, :description).tap do |whitelisted|
  whitelisted[:position] = params[:widget][:position]
  whitelisted[:properties] = params[:widget][:properties]
end

This method has advantage over other solutions. It allows to permit deep-nested parameters.

这种方法优于其他解决方案。它允许允许深度嵌套的参数。

While other solutions like:

而其他解决方案如:

params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])

Don't.

别。



Source:

来源:

https://github.com/rails/rails/issues/9454#issuecomment-14167664

https://github.com/rails/rails/issues/9454#issuecomment-14167664

回答by Kingsley Ijomah

Today I came across this same issue, whilst working on rails 4, I was able to get it working by structuring my fields_for as:

今天我遇到了同样的问题,在使用 rails 4 时,我能够通过将 fields_for 结构化为:

<%= f.select :tag_ids, Tag.all.collect {|t| [t.name, t.id]}, {}, :multiple => true %>

Then in my controller I have my strong params as:

然后在我的控制器中,我有我的强大参数:

private
def post_params
    params.require(:post).permit(:id, :title, :content, :publish, tag_ids: [])
end

All works!

所有作品!

回答by Wouter Schoofs

If you use a JSONB field, you must convert it to JSON with .to_json (ROR)

如果您使用 JSONB 字段,则必须使用 .to_json (ROR) 将其转换为 JSON