J'ai une application Rails 3 fonctionnelle qui utilise has_many: via des associations qui ne sont pas, comme je la refais comme une application Rails 4, me permettant d'enregistrer les identifiants du modèle associé dans la version Rails 4.
Ce sont les trois modèles pertinents qui sont les mêmes pour les deux versions.
Catégorisation.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
Dans les deux applications, les identifiants de catégorie sont transmis à l'action de création comme celle-ci
"question"=>{"question_content"=>"How do you spell car?", "question_details"=>"blah ", "category_ids"=>["", "2"],
Dans l'application Rails 3, lorsque je crée une nouvelle question, elle s'insère dans le tableau des questions, puis dans le tableau des catégorisations
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]]
Dans l'application Rails 4, après avoir traité les paramètres dans QuestionController # create, je reçois cette erreur dans les journaux du serveur
Unpermitted parameters: category_ids
et la question est seulement insérée dans le tableau des questions
(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
Bien que je ne stocke pas les category_ids sur le modèle Questions, j'ai défini category_ids comme paramètre autorisé dans le questions_controller
def question_params
params.require(:question).permit(:question_details, :question_content, :user_id, :accepted_answer_id, :province_id, :city, :category_ids)
end
Quelqu'un peut-il expliquer comment je suis censé enregistrer les category_ids? Remarque, il n'y a pas d'action de création dans categories_controller.rb de l'une ou l'autre des applications.
Ce sont les trois tableaux qui sont les mêmes dans les deux applications
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
Mettre à jour
Ceci est l'action de création de l'application 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
Ceci est l'action de création de l'application 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
Ceci est la méthode 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
Réponses:
Ce https://github.com/rails/strong_parameters ressemble à la section pertinente de la documentation:
Dans mon application, les category_ids sont passés à l'action de création dans un tableau
Par conséquent, lors de la déclaration de paramètres forts, j'ai explicitement défini category_ids pour être un tableau
Fonctionne parfaitement maintenant!
( IMPORTANT: comme le note @Lenart dans les commentaires, les déclarations de tableau doivent se trouver à la fin de la liste des attributs, sinon vous obtiendrez une erreur de syntaxe.)
la source
syntax error, unexpected ')', expecting =>
category_ids
n'est pas un tableau (par exemple, une chaîne a été envoyée), alors rails devient complètement dingue et soulèveERROR TypeError: expected Array (got String) for param `category_ids'
un problème. Edit: oui c'est: github.com/rails/rails/issues/11502params.permit(:foo, { bar: [] }, :zoo)
.Si vous souhaitez autoriser un tableau de hachages (ou
an array of objects
du point de vue de JSON)2 points à noter ici:
array
devrait être le dernier argument de lapermit
méthode.Unpermitted parameter: array
, qui est très difficile à déboguer dans ce cas.la source
array
n'a pas besoin d'être à la fin, mais vous devez vous assurer que vous avez un Ruby valide.params.permit(:foo, array: [:key1, :key2], :bar)
ne serait pas un rubis valide car l'interpréteur attend des clés de hachage: paires de valeurs après le premier ensemble. Pour avoir un Ruby valide dont vous avez besoinparams.permit(:foo, {array: [:key1, :key2]}, :bar)
Ça devrait être comme
Depuis la version 4+ des rails, vous pouvez également utiliser:
la source
Si vous avez une structure de hachage comme celle-ci:
Alors voici comment je l'ai fait fonctionner:
la source
Je ne peux pas encore commenter, mais en suivant la solution Fellow Stranger, vous pouvez également continuer à imbriquer au cas où vous auriez des clés dont les valeurs sont un tableau. Comme ça:
Cela marche:
la source