How to create a form object with multiple input fields with the same name

202 Views Asked by At

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
0

There are 0 best solutions below