我正在为我的rails应用程序构建食谱书。我有成分嵌套在食谱下。我可以创建一个配方并添加成分。但是,当我去编辑食谱时,它会复制表格中的所有成分。然后它将显示视图页面中重复的所有成分,当我删除其中一个重复的成分项目只有一个时,它会删除这两个项目。我们也不允许对这个项目使用accepts_nested_forms_for,因此为什么我有自定义编写器
食谱模型
class Recipe < ApplicationRecord
belongs_to :user, required: false
has_many :recipe_ingredients
has_many :ingredients, through: :recipe_ingredients
validates :name, presence: true
validates :instructions, length: {minimum: 5}
validates :cooktime, presence: true
def self.alphabetical
self.order(name: :asc)
end
def ingredients_attributes=(ingredients_attributes)
ingredients_attributes.values.each do |ingredients_attribute|
if !ingredients_attribute.empty? &&
new_ingredient =
Ingredient.find_or_create_by(ingredients_attribute)
self.ingredients << new_ingredient
end
end
end
end
成分模型
class Ingredient < ApplicationRecord
has_many :recipe_ingredients
has_many :recipes, through: :recipe_ingredients
def self.alphabetical
self.order(name: :asc)
end
end
Recipe_Ingredient Model
class RecipeIngredient < ApplicationRecord
belongs_to :recipe, required: false
belongs_to :ingredient, required: false
end
配方控制器
class RecipesController < ApplicationController
before_action :authenticate_user!
def new
@recipe = Recipe.new
3.times do
ingredient = @recipe.ingredients.build
end
end
def index
@recipes = current_user.recipes.alphabetical
end
def create
@recipe = current_user.recipes.new(recipe_params)
if @recipe.save
redirect_to recipe_path(@recipe)
else
render :new
end
end
def show
@recipe = Recipe.find(params[:id])
@ingredients = @recipe.ingredients.alphabetical
end
def edit
@recipe = Recipe.find(params[:id])
end
def update
@recipe = Recipe.find(params[:id])
if @recipe.update(recipe_params)
redirect_to @recipe
else
render :edit
end
end
def destroy
@recipe = Recipe.find(params[:id])
@recipe.delete
redirect_to recipes_path
end
private
def recipe_params
params.require(:recipe).permit(:name, :instructions, :cooktime,
:ingredient_ids => [], ingredients_attributes: [:recipe_id, :name])
end
end
食谱展示页
<h1> Recipe for <%=@recipe.name%></h1>
<h4>Recipe Instructions: <%=@recipe.instructions%></h4>
<h4>Cook Time: <%=@recipe.cooktime%></h4>
</ul>
<h4> Ingredients: </h4>
<% @ingredients.each do |ingredient|%>
<li><%=ingredient.name %></li>
<%end%>
</ul>
<%=link_to "Ingredients", recipe_ingredients_path(@recipe,
@ingredients)%>
<br>
<%=link_to "Delete Recipe", recipe_path(@recipe), :method => "delete"
%>
<br>
<%=link_to "Edit Recipe", edit_recipe_path(@recipe) %>
<br>
<%=link_to "All Recipes", recipes_path %>
<br>
以下是编辑和新表单
<%= form_for @recipe do |f| %>
<%=f.label :name, "Name" %>
<%=f.text_field :name %>
<br>
<%=f.label :instructions, "Instructions" %>
<%=f.text_area :instructions, :rows => 3 %>
<br>
<%=f.label :cooktime, "Cook Time" %>
<%=f.text_field :cooktime %>
<br>
<%#= f.collection_check_boxes :ingredient_ids, Ingredient.all, :id,
:name %>
<%= f.fields_for :ingredients, @ingredient do |ingredient_fields| %>
<br>
<div class = >
<%= ingredient_fields.label :name, "Ingredient" %>
<%= ingredient_fields.text_field :name %>
<% end %>
<%=f.submit%>
非常感谢任何帮助。
答案 0 :(得分:0)
此代码将表单上的所有成分添加到配方的ingredients
关系中。
def ingredients_attributes=(ingredients_attributes)
ingredients_attributes.values.each do |ingredients_attribute|
if !ingredients_attribute.empty? &&
new_ingredient =
Ingredient.find_or_create_by(ingredients_attribute)
self.ingredients << new_ingredient
end
end
end
在开始推送返回的属性之前,您应该清除成分关系
def ingredients_attributes=(ingredients_attributes)
self.ingredients.destroy_all # <- this will clear down ingredients
ingredients_attributes.values.each do |ingredients_attribute|
if !ingredients_attribute.empty? &&
new_ingredient =
Ingredient.find_or_create_by(ingredients_attribute)
self.ingredients << new_ingredient
end
end
end
答案 1 :(得分:0)
您唯一需要做的就是在重新添加之前检查配方的嵌入物中是否已包含new_ingredient
。
你可以这样做:
#recipe.rb
def ingredients_attributes=(ingredients_attributes)
ingredients_attributes.values.each do |ingredients_attribute|
if !ingredients_attribute.empty? &&
new_ingredient =
Ingredient.find_or_create_by(ingredients_attribute)
self.ingredients << new_ingredient if !self.ingredients.include?(new_ingredient)
end
end
end