我希望有一个新食谱的表单,在提交时会创建一个新配方及其相关成分和每种成分的数量。
我已经进行了相当广泛的搜索,并花了几天时间试图解决这个问题。任何帮助将非常感激。
我有这些相关的模型:
class Recipe < ApplicationRecord
belongs_to :user
has_many :items
has_many :ingredients, through: :items
accepts_nested_attributes_for :ingredients, reject_if: :all_blank,
allow_destroy: true
validates :name, presence: true
end
class Ingredient < ApplicationRecord
has_many :items
has_many :recipes, through: :items
has_many :quantities
accepts_nested_attributes_for :quantities, reject_if: :all_blank,
allow_destroy: true
end
class Quantity < ApplicationRecord
belongs_to :ingredient
end
以下是观点:
recipes / _form
<%= form_for(@recipe) do |f| %>
<% if @recipe.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@recipe.errors.count, "error") %> prohibited this recipe from being saved:
</h2>
<ul>
<% @recipe.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="form-group">
<%= f.label :name %>
<%= f.text_field :name, class: "form-control" %></div>
<div class="form-group">
<%= f.label :instructions %>
<%= f.text_field :instructions, class: "form-control" %></div>
<h3>Ingredients</h3>
<div id='ingredients'>
<%= f.fields_for @ingredient do |ingredient| %>
<%= render 'ingredient_fields', :f => ingredient %>
<% end %>
<br>
<div class='links'>
<br><%= link_to_add_association 'add ingredient', f, :ingredients, class: "btn btn-default add_button" %>
</div>
</div>
<br>
<div class="actions">
<%= f.submit class: "btn btn-primary" %>
</div>
<% end %>
配方/ _ingredient_fields
<div class='nested-fields'>
<%= f.label :name %>
<%= f.text_field :name, class: "form-input form-control" %>
<%= f.fields_for @ingredient.quantities.build do |quantity| %>
<%= render 'quantity_fields', :f => quantity %>
<% end %>
<%= link_to_remove_association "remove ingredient", f, class: "form-button btn btn-default" %>
<br>
</div>
配方/ _quantity_fields
<div class="nested-fields">
<%= f.label :amount %>
<%= f.text_field :amount, class: "form-input form-control" %>
</div>
recipes_controller
class RecipesController < ApplicationController
before_action :set_recipe, only: [:show, :edit, :update, :destroy]
before_action :require_logged_in, except: [:index]
def index
if params[:user_id]
@recipes = User.find(params[:user_id]).recipes
else
@recipes = Recipe.all
end
end
def new
@recipe = Recipe.new
@ingredient = Ingredient.new
@ingredient.quantities.build
end
def create
byebug
@recipe = Recipe.new(recipe_params)
@recipe.user = current_user
respond_to do |format|
if @recipe.save
format.html { redirect_to recipe_path(@recipe), notice: 'Recipe was successfully created.' }
else
format.html { render :new }
end
end
end
def show
end
def edit
end
def update
respond_to do |format|
if @recipe.update(recipe_params.reject{|k,v| v.blank?})
format.html { redirect_to @recipe, notice: 'User was successfully updated.' }
else
format.html { render :edit, notice: 'Update unsuccessful' }
end
end
end
def destroy
@recipe.destroy
redirect_to recipes_path, notice: "Recipe deleted."
end
private
def set_recipe
@recipe = Recipe.find(params[:id])
end
def recipe_params
params.require(:recipe).permit(
:name,
:instructions,
ingredients_attributes: [:id, :name, :_destroy, quantities: [:id, :amount]]
#items_attributes: [:quantity]
)
end
end
我尝试过这么多不同的方式。这正是我目前的代码所在。我大多尝试使用这种语法
<%= f.fields_for :ingredients %>
如果我能说得更清楚,或者更好地回答任何问题,我很乐意帮忙。提前致谢。