कैसे मजबूत मापदंडों के साथ एक सरणी अनुमति देने के लिए


269

मेरे पास एक कामकाजी रेल 3 ऐप है जो has_many का उपयोग करता है: संघों के माध्यम से, जो कि नहीं है, जैसा कि मैंने इसे एक रेल 4 ऐप के रूप में रीमेक किया है, जिससे मुझे संबंधित मॉडल से रेल 4 संस्करण में आईडी बचाने की सुविधा मिलती है।

ये तीन प्रासंगिक मॉडल हैं जो दो संस्करणों के लिए समान हैं।

Categorization.rb

class Categorization < ActiveRecord::Base

  belongs_to :question
  belongs_to :category
end

Question.rb

has_many :categorizations
has_many :categories, through: :categorizations

Category.rb

has_many :categorizations
has_many :questions, through: :categorizations

दोनों ऐप में, श्रेणी आईडी को इस तरह बनाने की कार्रवाई में पारित किया जा रहा है

  "question"=>{"question_content"=>"How do you spell car?", "question_details"=>"blah ", "category_ids"=>["", "2"],

रेल 3 ऐप में, जब मैं एक नया प्रश्न बनाता हूं, तो यह प्रश्न तालिका में और फिर श्रेणीकरण तालिका में सम्मिलित हो जाता है

 SQL (82.1ms)  INSERT INTO "questions" ("accepted_answer_id", "city", "created_at", "details", "province", "province_id", "question", "updated_at", "user_id") VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)  [["accepted_answer_id", nil], ["city", "dd"], ["created_at", Tue, 14 May 2013 17:10:25 UTC +00:00], ["details", "greyound?"], ["province", nil], ["province_id", 2], ["question", "Whos' the biggest dog in the world"], ["updated_at", Tue, 14 May 2013 17:10:25 UTC +00:00], ["user_id", 53]]
  SQL (0.4ms)  INSERT INTO "categorizations" ("category_id", "created_at", "question_id", "updated_at") VALUES (?, ?, ?, ?)  [["category_id", 2], ["created_at", Tue, 14 May 2013 17:10:25 UTC +00:00], ["question_id", 66], ["updated_at", Tue, 14 May 2013 17:10:25 UTC +00:00]]

रेल्स 4 ऐप में, यह क्वेश्चनकंट्रोलर # क्रिएट में पैरामीटर प्रोसेस करने के बाद, मुझे सर्वर लॉग्स में यह त्रुटि मिल रही है

Unpermitted parameters: category_ids

और प्रश्न केवल प्रश्न तालिका में डाला जा रहा है

 (0.2ms)  BEGIN
  SQL (67.6ms)  INSERT INTO "questions" ("city", "created_at", "province_id", "question_content", "question_details", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["city", "dd"], ["created_at", Tue, 14 May 2013 17:17:53 UTC +00:00], ["province_id", 3], ["question_content", "How's your car?"], ["question_details", "is it runnign"], ["updated_at", Tue, 14 May 2013 17:17:53 UTC +00:00], ["user_id", 12]]
   (31.9ms)  COMMIT

हालाँकि मैं प्रश्न मॉडल पर category_ids को संग्रहीत नहीं कर रहा हूँ, फिर भी मैंने answer_controller में एक अनुमत पैरामीटर के रूप में category_ids सेट किया है

   def question_params

      params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids)
    end

क्या कोई समझा सकता है कि मैं किस तरह से श्रेणी_ सेव करने वाला हूं? ध्यान दें, किसी भी ऐप की श्रेणियाँ_कंट्रोलर.बीआर में कोई क्रिएट एक्शन नहीं है।

ये तीन टेबल हैं जो दोनों ऐप में समान हैं

 create_table "questions", force: true do |t|
    t.text     "question_details"
    t.string   "question_content"
    t.integer  "user_id"
    t.integer  "accepted_answer_id"
    t.datetime "created_at"
    t.datetime "updated_at"
    t.integer  "province_id"
    t.string   "city"
  end

 create_table "categories", force: true do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "categorizations", force: true do |t|
    t.integer  "category_id"
    t.integer  "question_id"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

अपडेट करें

यह रेल 3 ऐप से क्रिएट एक्शन है

  def create
      @question = Question.new(params[:question])
      respond_to do |format|
      if @question.save
        format.html { redirect_to @question, notice: 'Question was successfully created.' }
        format.json { render json: @question, status: :created, location: @question }
      else
        format.html { render action: "new" }
        format.json { render json: @question.errors, status: :unprocessable_entity }
      end
    end
end

यह Rails 4 ऐप से क्रिएट एक्शन है

   def create
      @question = Question.new(question_params)

       respond_to do |format|
      if @question.save
        format.html { redirect_to @question, notice: 'Question was successfully created.' }
        format.json { render json: @question, status: :created, location: @question }
      else
        format.html { render action: "new" }
        format.json { render json: @question.errors, status: :unprocessable_entity }
      end
    end
    end

यह सवाल_परम पद्धति है

 private
    def question_params 
      params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids)
    end

दोनों ऐप्स में बनाने की क्रिया क्या दिखती है?
bennick

@bennick मैंने दो क्रियाओं को जोड़ा। धन्यवाद
Leahcim

जवाबों:


527

यह https://github.com/rails/strong_parameters डॉक्स के संबंधित खंड की तरह लगता है:

अनुमत स्केलर प्रकार स्ट्रिंग, प्रतीक, NilClass, न्यूमेरिक, TrueClass, FalseClass, दिनांक, समय, दिनांक समय, स्ट्रिंग, IO, ActionDispatch :: Http :: UploadedFile और रैक :: टेस्ट :: UploadedFile हैं।

यह घोषित करने के लिए कि परिमों में मूल्य अनुमत स्केलर सरणी का एक सरणी होना चाहिए, खाली सरणी के लिए कुंजी को मैप करें:

params.permit(:id => [])

मेरे ऐप में, श्रेणी_आईडी एक सरणी में एक्शन बनाने के लिए पास की गई हैं

"category_ids"=>["", "2"],

इसलिए, जब मजबूत मापदंडों की घोषणा करते हैं, तो मैं स्पष्ट रूप से एक सरणी होने के लिए category_ids सेट करता हूं

params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids => [])

अब पूरी तरह से काम करता है!

( महत्वपूर्ण: टिप्पणियों में @ नोटों के रूप में, सरणी घोषणाएं विशेषताओं की सूची के अंत में होनी चाहिए , अन्यथा आपको सिंटैक्स त्रुटि मिलेगी।)


105
मैंने यह भी देखा है कि ऐरे के लिए घोषणाएँ एट्रिब्यूट्स लिस्ट के अंत में होनी चाहिए। अन्यथा मुझे सिंटैक्स त्रुटि मिलती हैsyntax error, unexpected ')', expecting =>
लेनार्ट

45
कारण सरणी घोषणाएं (नेस्टेड परम) अंत में हैं कि ActionController :: Parameters.permit प्रत्येक तर्क को एक हैश या प्रतीक होने की उम्मीद करता है। रूबी मैजिक एक विधि कॉल के अंत में सभी प्रमुख मूल्य जोड़े को एक हैश में बदल देगा, लेकिन रूबी को यह नहीं पता होगा कि यदि आप अपनी विधि कॉल में कुंजी / मान जोड़े के साथ प्रतीकों को मिलाते हैं तो क्या करें।
उसी रात 20:05

7
अगर category_idsएक सरणी नहीं है (जैसे एक स्ट्रिंग भेजा गया था) तो रेल पूरी तरह से पागल हो जाती है और एक उठाती है ERROR TypeError: expected Array (got String) for param `category_ids'कि रेल में बग है? संपादित करें: हाँ यह है: github.com/rails/rails/issues/11502
डॉमिनिक गोल्टरमैन

4
@ धन्यवाद धन्यवाद, मुझे लगा कि मैं पागल हो रहा हूं। यह कम से कम strong_params README में दिखाई देना चाहिए
सेबस्टियलोनो

3
@ यदि आप सिंटैक्स त्रुटि से बचना चाहते हैं, तो आप इसे हैश के रूप में जोड़ सकते हैं। params.permit(:foo, { bar: [] }, :zoo)
फू बार ज़ू

99

यदि आप हैश की एक सरणी (या an array of objectsJSON के दृष्टिकोण से) की अनुमति देना चाहते हैं

params.permit(:foo, array: [:key1, :key2])

यहाँ नोटिस करने के लिए 2 अंक:

  1. arraypermitविधि का अंतिम तर्क होना चाहिए ।
  2. आपको सरणी में हैश की कुंजी निर्दिष्ट करनी चाहिए, अन्यथा आपको एक त्रुटि मिलेगी Unpermitted parameter: array, जिसे इस मामले में डीबग करना बहुत मुश्किल है।

और सरणियों के सारणी समर्थित नहीं हैं (अभी तक): github.com/rails/rails/issues/23640
सारणी

11
arrayअंत में होने की ज़रूरत नहीं है, लेकिन आपको यह सुनिश्चित करने की ज़रूरत है कि आपके पास वैध रूबी है। params.permit(:foo, array: [:key1, :key2], :bar)इंटरप्रेटर हैश कुंजी: पहले सेट के बाद मूल्य जोड़े के रूप में वैध रूबी मान्य नहीं होगा। रूबी को वैध बनाने के लिए आपको जरूरत हैparams.permit(:foo, {array: [:key1, :key2]}, :bar)
mastaBlasta

आप एक चैंपियन हैं!
लल्लीपॉप

22

यह जैसा होना चाहिए

params.permit(:id => [])

संस्करण 4+ के बाद से आप उपयोग कर सकते हैं:

params.permit(id: [])

12
कृपया नहीं कि यह सरणी परमिट विधि का अंतिम तर्क होना चाहिए
मतियास एलोरियागा

3
उस हैश सिंटैक्स जो आपने कहा था कि रेल v4 + के लिए लागू होता है, वास्तव में रूबी 1.9 और नए में एक सिंटैक्स उपलब्ध है, न कि रेल्स फ्रेमवर्क (हालाँकि रेल्स 4 के लिए रूबी 1.9.3 या नए की आवश्यकता होती है)
मेगाटैक्स

11

यदि आपके पास इस तरह से एक हैश संरचना है:

Parameters: {"link"=>{"title"=>"Something", "time_span"=>[{"start"=>"2017-05-06T16:00:00.000Z", "end"=>"2017-05-06T17:00:00.000Z"}]}}

फिर यह है कि मैं इसे काम करने के लिए कैसे मिला:

params.require(:link).permit(:title, time_span: [[:start, :end]])

6

मैं अभी तक कोई टिप्पणी नहीं कर सकता, लेकिन फेलो स्ट्रेंजर समाधान के बाद आप उन मामलों में नेस्टिंग भी रख सकते हैं जिनमें आपके पास कुंजी है, जो कि एक ऐरे हैं। ऐशे ही:

filters: [{ name: 'test name', values: ['test value 1', 'test value 2'] }]

यह काम:

params.require(:model).permit(filters: [[:name, values: []]])
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.