Tengo una aplicación Rails 3 en funcionamiento que utiliza has_many: a través de asociaciones que no lo son, ya que la rehago como una aplicación Rails 4, lo que me permite guardar identificadores del modelo asociado en la versión Rails 4.
Estos son los tres modelos relevantes que son iguales para las dos versiones.
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
En ambas aplicaciones, los identificadores de categoría se pasan a la acción de creación como esta
"question"=>{"question_content"=>"How do you spell car?", "question_details"=>"blah ", "category_ids"=>["", "2"],
En la aplicación Rails 3, cuando creo una nueva pregunta, 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 que procesa 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 estoy almacenando los category_ids en el modelo de Preguntas, configuro category_ids como un parámetro permitido en el question_controller
def question_params
params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids)
end
¿Alguien puede explicar cómo se supone que debo guardar los category_ids? Tenga en cuenta que no hay ninguna acción de creación en el category_controller.rb de ninguna 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 de crear 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 de crear 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 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
fuente
Respuestas:
Este https://github.com/rails/strong_parameters parece ser la sección relevante de los documentos:
En mi aplicación, los category_ids se pasan a la acción de crear en una matriz
Por lo tanto, al declarar parámetros fuertes, establezco explícitamente category_ids para ser una matriz
¡Funciona perfectamente ahora!
( IMPORTANTE: como @Lenart señala en los comentarios, las declaraciones de la matriz deben estar al final de la lista de atributos, de lo contrario obtendrá un error de sintaxis).
fuente
syntax error, unexpected ')', expecting =>
category_ids
no es una matriz (p. ej., se envió una cadena), los rieles se vuelven totalmente locos y generan unERROR TypeError: expected Array (got String) for param `category_ids'
¿Es un error en los rieles? Editar: sí, es: github.com/rails/rails/issues/11502params.permit(:foo, { bar: [] }, :zoo)
.Si desea permitir una matriz de hashes (o
an array of objects
desde la perspectiva de JSON)2 puntos para notar aquí:
array
debería ser el último argumento delpermit
método.Unpermitted parameter: array
, que es muy difícil de depurar en este caso.fuente
array
no necesita estar al final, pero debe asegurarse de tener un Ruby válido.params.permit(:foo, array: [:key1, :key2], :bar)
no sería válido ruby ya que el intérprete espera claves hash: pares de valores después del primer conjunto. Para tener Ruby válido necesitasparams.permit(:foo, {array: [:key1, :key2]}, :bar)
Debería ser como
También desde rails versión 4+ puedes usar:
fuente
Si tiene una estructura hash como esta:
Entonces así es como lo hice funcionar:
fuente
No puedo comentar todavía, pero siguiendo la solución Fellow Stranger también puede seguir anidando en caso de que tenga claves cuyos valores son una matriz. Me gusta esto:
Esto funciona:
fuente