I am having difficulty sending a JSON payload to an endpoint that contains a nested resource that I would like created with associations in-tact and persisted... no matter what I do I am presented in the console with Unpermitted parameter: :ingredients
.
models/meal.rb
class Meal < ApplicationRecord
has_many :ingredients
accepts_nested_attributes_for :ingredients
end
models/ingredient.rb
class Ingredient < ApplicationRecord
belongs_to :meal
end
controller/meals_controller.rb
class MealsController < ApplicationController
def create
@meal = Meal.new(meal_params)
puts meal_params.inspect
# just want to see the parameters in the log
# ...
end
private
def meal_params
params.require(:meal).permit(
:name,
ingredients_attributes: [:id, :text]
)
end
end
db/migrate/xxx_create_inredients.rb
class CreateIngredients < ActiveRecord::Migration[5.1]
def change
create_table :ingredients do |t|
t.belongs_to :meal, index: true
t.string :text
t.timestamps
end
end
end
request JSON payload
{
"meal": {
"name": "My Favorite Meal",
"ingredients": [
{ "text": "First ingredient" },
{ "text": "Second ingredient" }
]
}
}
I tried another approach from a SO article encountering a similar problem that seemed to recognize the ingredients parameter, but ultimately threw a 500:
params.require(:meal).permit(:name, { ingredients: [:id, :text] })
When doing that I receive the following:
ActiveRecord::AssociationTypeMismatch (Ingredient(#70235637684840) expected, got {"text"=>"First Ingredient"} which is an instance of ActiveSupport::HashWithIndifferentAccess(#70235636442880))
Any help in pointing out my flaw is much appreciated. And yes, I want the nested ingredients resource to be part of the payload going to this endpoint.
The only problem that you have here is that you have in your meal params ingredients_attributes
def meal_params
params.require(:meal).permit(
:name,
ingredients_attributes: [:id, :text]
)
end
so in your payload you need to have it with that key too
{
"meal": {
"name": "My Favorite Meal",
"ingredients_attributes": [
{ "text": "First ingredient" },
{ "text": "Second ingredient" }
]
}
}
they need to match.