ネストされた属性の許可されていないパラメーター


127

私が持っているBill多くの持っているオブジェクト、Dueオブジェクトを。Dueオブジェクトはまたに属しますPersonBillとその子をDuesすべて1ページで作成できるフォームが必要です。このRailscastの属性と同様に、ネストされた属性を使用してフォームを作成しようとしています。

関連するコードを以下に示します。

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

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

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

bills_controller.rbへのUPDATE これは機能します!

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

適切なフィールドがページに表示され(Personまだドロップダウンはありません)、送信は成功します。ただし、子会費はデータベースに保存されず、サーバーログにエラーがスローされます。

Unpermitted parameters: dues_attributes

エラーの直前に、ログはこれを表示します:

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"}

Rails 4に変更はありますか?


5
フォーマットの修正:params.require(:bill).permit(:company、:month、:year、:dues_attributes => [:amount、:person_id])
Andy Copley

回答:


187

以前のオプションのgem strong_parametersがRailsコアの一部になったため、属性保護の処理に変更があり、コントローラーのパラメーターを(モデルのattr_accessibleではなく)ホワイトリストに登録する必要があるようです。

これは次のようになります。

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またはここで詳細を見つけることができます


1
BillControllerを次のように変更し def bill_params params.require(:bill).permit(:company, :month, :year, :dues_attributes[:amount, :person_id]) end ました:このエラーが発生しました: SymbolからIntegerへの暗黙の変換はありません
jcanipar

2
まあ、それはコロンを正しい場所に置くのに役立ちます...これはまさに実行する必要があったものです。ありがとう@ thorsten-muller!
jcanipar 2013

88
IDをお忘れなく!!!! pets_attributes: [:id, :name, :category]そうしないと、編集時に各ペットが再度作成されます。
Arcolye 2013年

8
あなたがする必要があるかPerson.create(person_params)、それはメソッドを呼び出さないでしょう。代わりにを取得しActiveModel::ForbiddenAttributesErrorます。
アンドロフ2013

16
また、フォームからアイテムを破棄する場合は、非表示の:_destroyパラメーターをホワイトリストに登録する必要もあります。iepets_attributes: [:id, :name, :category, :_destroy]
病原体2014

21

ドキュメントから

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

params.require(:log_entry).permit!

ネストされた属性はハッシュの形式です。私のアプリでは、Answer.rbモデルのネストされた属性を受け入れるQuestion.rbモデルがあります(ユーザーが作成した質問の回答選択肢を作成します)。questions_controllerで、私はこれを行います

  def question_params

      params.require(:question).permit!

  end

ネストされた回答属性を含め、質問ハッシュのすべてが許可されます。これは、ネストされた属性が配列の形式である場合にも機能します。

とは言っても、厳密に何を指定せずにハッシュ内にあるものをすべて許可するため、このアプローチにはセキュリティ上の懸念があるのではないかと思います。これは強力なパラメーターの目的に反するようです。


すばらしい、範囲パラメーターを明示的に許可することはできません。これにより、数時間節約できます。
Bartek Skwira 2013

3
ええ、.permitを使用しています!通常、潜在的なセキュリティ上の問題と見なされます。あなたが本当にそれを使いたいのは、ユーザーが管理者である場合だけですが、それでも私はその使用に警戒しています。
8bithero、2013

6
ネストされた属性も配列にあります。ある.permit!唯一のオプションは?配列が詰まっているため、許可されているすべてのモデルの属性を使用しても機能しません。
Clifton Labrum 2013


12

実際には、ネストされたすべてのパラメータをホワイトリストに登録する方法があります。

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

この方法は、他のソリューションよりも優れています。深くネストされたパラメーターを許可することができます。

他の解決策は次のとおりです。

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

しないでください。


ソース:

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


3

今日、私はこれと同じ問題に遭遇しましたが、レール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

すべての作品!


こんにちはありがとう@KingsleyIjomah-子供の特定の属性をホワイトリストに登録したい場合はどうなりますか?
BKSpurgeon

1

JSONBフィールドを使用する場合は、.to_json(ROR)を使用してフィールドをJSONに変換する必要があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.