Rails 4嵌套的属性不允许的参数
我是RoR的新手,但已经决定我可以在4学习。这可能或不是一个好主意。 我正在尝试创build一个使用嵌套属性的表单,我挣扎着。
我看了这个railscast http://railscasts.com/episodes/196-nested-model-form-part-1 ,我试图重新创build一个类似的情况我自己。
我有一个Bill对象,有许多Due对象。 Due对象也属于Person 。 我希望有一个表格可以在这儿创build条例草案及其子女在一个页面上收到全部费用 。
在页面上呈现适当的字段(尽pipe没有Person的下拉菜单),提交成功。 但是,没有一个孩子的会费保存到数据库,并在服务器日志中引发错误:
不允许的参数:dues_attributes
Rails 4中是否有过某种变化,或者我完全错过了某些东西。
在错误之前,日志显示这个:
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"}
相关代码列在下面
due.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
# GET /bills/new def new @bill = Bill.new 3.times { @bill.dues.build } end
票据/ _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 %>
票据/ _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>
更新到bills_controller.rb:这工作!
def bill_params params.require(:bill).permit(:company, :month, :year, dues_attributes: [:amount, :person_id]) end
似乎属性保护的处理发生了变化,现在您必须在控制器(而不是模型中的attr_accessible)中添加白名单,因为之前的可选gem strong_parameters成为了Rails Core的一部分。
这应该看起来像这样:
class PeopleController < ActionController::Base def create Person.create(person_params) end private def person_params params.require(:person).permit(:name, :age) end end
所以params.require(:model).permit(:fields)
将被使用
和嵌套属性的东西
params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])
一些更多的细节可以在Ruby边缘API文档和github或这里的 strong_parameters中 find
从文档
To whitelist an entire hash of parameters, the permit! method can be used params.require(:log_entry).permit!
嵌套属性是散列的forms。 在我的应用程序中,我有一个Question.rb模型接受Answer.rb模型的嵌套属性(其中用户为他创build的问题创build答案选项)。 在questions_controller中,我这样做
def question_params params.require(:question).permit! end
问题哈希中的所有内容都是允许的,包括嵌套的答案属性。 如果嵌套的属性是数组的forms,这也适用。
话虽如此,我不知道这种方法是否存在安全问题,因为它基本上允许在散列内部的任何内容,而不是明确地指定它是什么,这似乎与强参数的目的相反。
或者你可以简单地使用
def question_params params.require(:question).permit(team_ids: []) end
实际上有一种方法可以将所有嵌套的参数白名单。
params.require(:widget).permit(:name, :description).tap do |whitelisted| whitelisted[:position] = params[:widget][:position] whitelisted[:properties] = params[:widget][:properties] end
这种方法比其他解决scheme有优势。 它允许允许深嵌套的参数。
而其他解决scheme如:
params.require(:person).permit(:name, :age, pets_attributes: [:id, :name, :category])
别。
资源:
https://github.com/rails/rails/issues/9454#issuecomment-14167664
今天我遇到了同样的问题,同时在rails 4上工作时,通过将fields_for的结构设置为:
<%= f.select :tag_ids, Tag.all.collect {|t| [t.name, t.id]}, {}, :multiple => true %>
然后在我的控制器中,我有很强的参数:
private def post_params params.require(:post).permit(:id, :title, :content, :publish, tag_ids: []) end
所有的作品!
如果使用JSONB字段,则必须使用.to_json(ROR)将其转换为JSON。