cómo permitir una matriz con parámetros fuertes


Tengo una aplicación Rails 3 en funcionamiento que usa has_many :a través de asociaciones que no lo es, ya que la rehizo como una aplicación Rails 4, lo que me permite guardar ID del modelo asociado en la versión Rails 4.

Estos son los tres modelos relevantes son los mismos para las dos versiones.

Categorización.rb

class Categorization < ActiveRecord::Base

  belongs_to :question
  belongs_to :category
end

Pregunta.rb

has_many :categorizations
has_many :categories, through: :categorizations

Categoría.rb

has_many :categorizations
has_many :questions, through: :categorizations

En ambas aplicaciones, los id de categoría se pasan a la acción create como esto

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

En la aplicación Rails 3, cuando creo una pregunta nueva, se inserta en la tabla de preguntas y luego en la tabla de categorizaciones

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

En la aplicación rails 4, después de procesar los parámetros en QuestionController # create, recibo este error en los registros del servidor

Unpermitted parameters: category_ids

Y la pregunta solo se inserta en la tabla de preguntas

 (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

Aunque no soy almacenar el id de categoría en las Preguntas modelo, me puse como un id de categoría parámetro permitido en questions_controller

   def question_params

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

¿Puede alguien explicar cómo se supone que debo guardar los category_ids? Nota, no hay ninguna acción create en categories_controller.rb de cualquiera de las aplicaciones.

Estas son las tres tablas que son iguales en ambas aplicaciones

 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

Actualizar

Esta es la acción create desde la aplicación 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 es la acción create desde la aplicación 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 es el question_params método

 private
    def question_params 
      params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids)
    end
Author: mu is too short, 2013-05-14

5 answers

Esto https://github.com/rails/strong_parameters parece que la sección relevante de los documentos:

Los tipos escalares permitidos son String, Symbol, NilClass, Numeric, TrueClass, FalseClass, Date, Time, DateTime, StringIO, IO, ActionDispatch::Http::UploadedFile and Rack::Test:: UploadedFile.

Para declarar que el valor en parámetros debe ser una matriz de valores escalares permitidos mapear la clave a una matriz vacía:

params.permit(:id => [])

En mi aplicación, el category_id se pasan a la acción de crear en una matriz

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

Por lo tanto, cuando declaro parámetros fuertes, establezco explícitamente category_ids como un array

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

Funciona perfectamente ahora!

 474
Author: Leahcim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-07-26 16:05:43

Si desea permitir una matriz de hashes (o an array of objects desde la perspectiva de JSON)

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

2 puntos a tener en cuenta aquí:

  1. array debe ser el último argumento del método permit.
  2. debe especificar las claves del hash en la matriz, de lo contrario obtendrá un error Unpermitted parameter: array, que es muy difícil de depurar en este caso.
 80
Author: Brian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-05-17 09:53:42

Debería ser como

params.permit(:id => [])

También desde rails versión 4 + puedes usar:

params.permit(id: [])
 12
Author: Matias Seguel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-18 16:05:21

Si tienes una estructura hash como esta:

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

Entonces así es como conseguí que funcionara:

params.require(:link).permit(:title, time_span: [[:start, :end]])
 7
Author: Fellow Stranger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-03 15:49:28

Todavía no puedo comentar, pero siguiendo la solución de Compañeros extraños también puede seguir anidando en caso de que tenga claves cuyos valores son una matriz. Así:

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

Esto funciona:

params.require(:model).permit(filters: [[:name, values: []]])
 1
Author: Daniel Duque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-10-12 16:19:33