ruby-on-rails - rails - strong params permit




como permitir um array com parâmetros fortes (4)

Deveria ser como

params.permit(:id => [])

Além disso, desde a versão 4+ dos trilhos, você pode usar:

params.permit(id: [])

Eu tenho um aplicativo funcional do Rails 3 que usa o has_many: através de associações que não são, já que eu o refiz como um aplicativo do Rails 4, permitindo salvar ids do modelo associado na versão do Rails 4.

Estes são os três modelos relevantes são os mesmos para as duas versões.

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

Em ambos os aplicativos, os IDs de categoria são transmitidos para a ação de criação, como esta

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

No aplicativo Rails 3, quando eu crio uma nova pergunta, ela é inserida na tabela de perguntas e depois na tabela de categorizações

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

No aplicativo rails 4, depois de processar os parâmetros em QuestionController # create, estou recebendo este erro nos logs do servidor

Unpermitted parameters: category_ids

e a questão só está sendo inserida na tabela de perguntas

 (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

Embora eu não esteja armazenando category_ids no modelo de Perguntas, defino category_ids como um parâmetro permitido no questions_controller

   def question_params

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

Alguém pode explicar como eu devo salvar as category_ids? Observe que não há nenhuma ação de criação no categories_controller.rb de qualquer aplicativo.

Estas são as três tabelas que são as mesmas em ambos os aplicativos

 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

Atualizar

Esta é a ação de criação do aplicativo Rails 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

Esta é a ação de criação do aplicativo 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

Este é o método question_params

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

Este https://github.com/rails/strong_parameters parece ser a seção relevante dos documentos:

Os tipos escalares permitidos são: String, Símbolo, NilClass, Numérico, TrueClass, FalseClass, Data, Hora, DateTime, StringIO, IO, ActionDispatch :: Http :: UploadedFile e Rack :: Test :: UploadedFile.

Para declarar que o valor em params deve ser uma matriz de valores escalares permitidos, mapeie a chave para uma matriz vazia:

params.permit(:id => [])

No meu aplicativo, as category_ids são passadas para a ação de criação em uma matriz

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

Portanto, ao declarar parâmetros fortes, eu defini explicitamente category_ids para ser um array

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

Funciona perfeitamente agora!


Se você quiser permitir uma matriz de hashes (ou an array of objects da perspectiva do JSON)

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

2 pontos para notar aqui:

  1. array deve ser o último argumento do método de permit .
  2. você deve especificar chaves do hash na matriz, caso contrário, você receberá um erro Unpermitted parameter: array , que é muito difícil de depurar neste caso.

Se você tem uma estrutura hash como esta:

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

Então é assim que eu consegui trabalhar:

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




strong-parameters