I am learning rails and will be very grateful for an advice about creating a form object with multiple input fields with the same name. I am having errors with unpermitted params. I've been searching information for several days, have tried a lot without any result. This is my first question, sorry if it is not easy to understand.
I am using rails 6.0.0, and having 3 models: Recipe, Ingredient, RecipeIngredientRelation. I want to make multiple input fields for Ingredient and RecipesIngredient. Errors:
Parameters: {"authenticity_token"=>"G6vwDdptMBgl2SPvLfS4BoiCjoRnf+FGYuKW0Ykt3Aodt5HfBEx5KHWBEpl4r52ANCv9QWz13rDyAP42qCyESg==", "recipes_ingredient"=>{"name"=>"Recipe", "portions"=>"1", "time_count_id"=>"3", "calories"=>"", "ingredients"=>{"i_name"=>"water"}, "recipe_ingredient_relations"=>{"quantity"=>["100"], "measurement_id"=>"3"}, "recipe"=>"some text", "tips"=>"", "is_public"=>"0"}, "commit"=>"レシピを投稿する"}
Unpermitted parameters: :ingredients, :recipe_ingredient_relations
binding.pry gets me @recipes_ingredient.errors:
@details={:i_name=>[{:error=>:blank}]},
@messages={:i_name=>["can't be blank"]}>
my models are: Recipe
has_many :recipe_ingredient_relations
has_many :ingredients, through: :recipe_ingredient_relations
accepts_nested_attributes_for :ingredients, :recipe_ingredient_relations, allow_destroy: true
Ingredient
has_many :recipe_ingredient_relations
has_many :recipes, through: :recipe_ingredient_relations
RecipeIngredientRelation
belongs_to :recipe
belongs_to :ingredient
Form Object
class RecipesIngredient
include ActiveModel::Model
attr_accessor :ingredients, :i_name, :recipe_ingredient_relations, :quantity, :measurement_id, :name, :image, :portions, :time_count_id, :recipe, :tips, :calories, :is_public, :user_id
with_options presence: true do
validates :i_name #, uniqueness: true
validates :quantity, length:{maximum: 10}, allow_blank: true
validates :measurement_id, allow_blank: true
validates :name
validates :portions
validates :time_count_id, numericality: {other_than: 1}
validates :recipe
validates :tips, allow_blank: true
validates :calories, allow_blank: true
validates :is_public
end
def save
recipe = Recipe.create(user_id: user_id, name: name, image: image, portions: portions, time_count_id: time_count_id, recipe: recipe, tips: tips, calories: calories, is_public: is_public)
ingredient = Ingredient.create(i_name: i_name)
recipe_ingredient_relation = RecipeIngredientRelation.create(recipe_id: recipe.id, ingredient_id: ingredient.id, quantity: quantity, measurement_id: measurement_id)
end
end
part of input form view:
%= form_with(model: @recipes_ingredient, url:recipes_path, local: true) do |form| %>
<...>
<%= form.fields_for :ingredients do |f| %>
<%= f.text_field :i_name, placeholder: "例)レタス", class: "form-el ingredient-input required" %>
<% end %>
<%= form.fields_for :recipe_ingredient_relations do |f| %>
<div class="quantity">
<%= f.text_field :quantity, multiple: true, placeholder: "例)100", class: "form-el quantity-input required" %>
<%= f.collection_select(:measurement_id, Measurement.all, :id, :name, {}, {class:"after-input-required"}) %>
<p class="after-input after-input-btn-required">+</p>
</div>
</div>
<% end %>
and, finally, the Recipes controller:
class RecipesController < ApplicationController
def index
@recipe = Recipe.all
end
def new
@recipes_ingredient = RecipesIngredient.new
end
def create
@recipes_ingredient = RecipesIngredient.new(recipe_params)
binding.pry
# if @recipe.valid?
# @recipe.save
# redirect_to root_path
# else
# render action: :new
# end
end
private
def recipe_params
params.require(:recipes_ingredient).permit(:name, :image, :portions, :time_count_id, :recipe, :tips, :calories, :is_public, ingredients_attributes: [:id, :i_name], recipe_ingredient_relations_attributes: [:id, :quantity, :measurement_id] ).merge(user_id: current_user.id)
end
end