नेस्टेड एट्रिब्यूटेड मापदंडों को नेस्टेड करता है


127

मेरे पास एक Billऑब्जेक्ट है, जिसमें कई Dueऑब्जेक्ट हैं। Dueवस्तु भी एक के अंतर्गत आता है Person। मुझे एक ऐसा फॉर्म चाहिए, जो एक पेज में Billऔर उसके बच्चों को बना सके Dues। मैं नेस्टेड विशेषताओं का उपयोग करके एक फॉर्म बनाने की कोशिश कर रहा हूं, जो इस रेलकास्ट में लोगों के समान है ।

प्रासंगिक कोड नीचे सूचीबद्ध है:

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>

यह काम करता है बिल_कंट्रोलर को अपडेट करें !

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

क्या रेल्स 4 में कुछ बदलाव हुआ है?


5
फ़ॉर्मेटिंग पर फ़िक्स करें: params.require (: बिल) .permit (: कंपनी,:, महीने, वर्ष:: dues_attributes => [: amount, person_id])
Andy Copley

जवाबों:


187

लगता है कि विशेषता संरक्षण से निपटने में बदलाव हुआ है और अब आपको नियंत्रक (मॉडल में attr_accessible) के बजाय नियंत्रक में श्वेतसूची पार्म्स होना चाहिए क्योंकि पूर्व वैकल्पिक रत्न strong_parameters रेल कोर का हिस्सा बन गए।

यह कुछ इस तरह दिखना चाहिए:

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])

कुछ और विवरण रूबी एज एपीआई डॉक्स और मजबूत_परमीटर पर जीथब या यहां मिल सकते हैं


1
मैंने इस तरह दिखने के लिए अपने बिलकंट्रोलर को बदल दिया है: def bill_params params.require(:bill).permit(:company, :month, :year, :dues_attributes[:amount, :person_id]) end मुझे अब यह त्रुटि मिल रही है: प्रतीक का कोई निहितार्थ पूर्णांक में परिवर्तित नहीं किया गया
jcanipar

2
खैर, यह बृहदान्त्र को सही जगह पर रखने में मदद करता है ... यह वही है जो करने की आवश्यकता है। धन्यवाद @ थोरस्टेन-मुलर!
जोंकिपार

88
पहचान नहीं है !!!! pets_attributes: [:id, :name, :category]अन्यथा, जब आप संपादित करते हैं, तो प्रत्येक पालतू जानवर फिर से बन जाएगा।
आर्कोलाई

8
आपको करने की आवश्यकता है Person.create(person_params)या यह विधि को कॉल नहीं करेगा। इसके बदले आपको मिलेगा ActiveModel::ForbiddenAttributesError
andorov

16
इसके अलावा, यदि आप प्रपत्र से आइटम को नष्ट करना चाहते हैं, तो आपको छिपे हुए :_destroyपैरामीटर को भी श्वेत सूची में लाने की आवश्यकता है । अर्थात्pets_attributes: [:id, :name, :category, :_destroy]
पाथोजन

21

डॉक्स से

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

params.require(:log_entry).permit!

नेस्टेड विशेषताएँ एक हैश के रूप में हैं। मेरे ऐप में, मेरे पास एक प्रश्न है। एक मॉडल उत्तर के लिए नेस्टेड विशेषताओं को स्वीकार करता है। एक मॉडल (जहां उपयोगकर्ता एक प्रश्न का उत्तर विकल्प बनाता है)। Questions_controller में, मैं यह करता हूं

  def question_params

      params.require(:question).permit!

  end

नेस्टेड उत्तर विशेषताओं सहित प्रश्न हैश में सब कुछ अनुमत है। यह भी काम करता है अगर नेस्टेड विशेषताएँ एक सरणी के रूप में हों।

यह कहने के बाद, मुझे आश्चर्य है कि अगर इस दृष्टिकोण के साथ एक सुरक्षा चिंता है क्योंकि यह मूल रूप से हैश के अंदर कुछ भी अनुमति देता है बिना यह निर्दिष्ट किए बिना कि यह क्या है, जो मजबूत मापदंडों के उद्देश्य के विपरीत लगता है।


बहुत बढ़िया, मुझे स्पष्ट रूप से एक सीमा पैरामीटर की अनुमति नहीं मिलती है, इससे मुझे कुछ घंटे बचते हैं।
बार्टेक स्कवीरा

3
हाँ, .permit का उपयोग कर! आमतौर पर एक संभावित सुरक्षा चिंता के रूप में देखा जाता है। यदि उपयोगकर्ता एक व्यवस्थापक है, तो आप केवल इसका उपयोग करना चाहते हैं, लेकिन तब भी मैं इसके उपयोग से सावधान रहूंगा।
8bithero

6
मेरी नेस्टेड विशेषताएँ एक सरणी में भी हैं। है .permit!ही एकमात्र विकल्प? मुझे इसकी अनुमति नहीं है कि यह सभी मॉडल की विशेषताओं के साथ भी काम कर सकता है क्योंकि यह सरणी पर चुटकी लेता है।
क्लिफ्टन लैब्रम


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 पर काम करते हुए, मैं इसे अपने खेतों को संरचित करके काम कर पाने में सक्षम था:

<%= 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

सभी काम करता है!


hi धन्यवाद @KingsleyIjomah - यदि आप बच्चों की विशिष्ट विशेषताओं को सफेद सूची में लाना चाहते हैं तो क्या होगा?
बीकेएसपार्किन जूल

1

यदि आप एक JSONB फ़ील्ड का उपयोग करते हैं, तो आपको इसे JSON के साथ .to_json (ROR) में बदलना होगा

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.