3 つの主要なモデルを使用してレシピ キーパー アプリを構築しようとしています。
Recipe - 特定の料理のレシピ
Ingredient - 一意性が検証された材料のリスト
Quantity - 特定のレシピに必要な特定の材料の量も反映する Ingredient と Recipe の間の結合テーブル。
ネストされたフォーム (パート 1、パート 2 ) で素晴らしい Railscast を使用して作成したネストされたフォーム (以下を参照) を使用して、インスピレーションを得ています。(私のフォームは、この特定のスキーマの必要性により、いくつかの点でチュートリアルよりも複雑ですが、同様の方法で機能させることができました。)
ただし、フォームが送信されると、リストされているすべての材料が新たに作成されます。また、材料が DB に既に存在する場合は、一意性の検証に失敗し、レシピが作成されません。総抗力。
私の質問は次のとおりです。このフォームを送信して、成分名フィールドのいずれかに名前が一致する成分が存在する場合、同じ名前で新しい成分を作成するのではなく、既存の成分を参照する方法はありますか?
以下のコード仕様...
でRecipe.rb
:
class Recipe < ActiveRecord::Base
attr_accessible :name, :description, :directions, :quantities_attributes,
:ingredient_attributes
has_many :quantities, dependent: :destroy
has_many :ingredients, through: :quantities
accepts_nested_attributes_for :quantities, allow_destroy: true
でQuantity.rb
:
class Quantity < ActiveRecord::Base
attr_accessible :recipe_id, :ingredient_id, :amount, :ingredient_attributes
belongs_to :recipe
belongs_to :ingredient
accepts_nested_attributes_for :ingredient
そしてでIngredient.rb
:
class Ingredient < ActiveRecord::Base
attr_accessible :name
validates :name, :uniqueness => { :case_sensitive => false }
has_many :quantities
has_many :recipes, through: :quantities
に表示されるネストされたフォームは次のRecipe#new
とおりです。
<%= form_for @recipe do |f| %>
<%= render 'recipe_form_errors' %>
<%= f.label :name %><br>
<%= f.text_field :name %><br>
<h3>Ingredients</h3>
<div id='ingredients'>
<%= f.fields_for :quantities do |ff| %>
<div class='ingredient_fields'>
<%= ff.fields_for :ingredient_attributes do |fff| %>
<%= fff.label :name %>
<%= fff.text_field :name %>
<% end %>
<%= ff.label :amount %>
<%= ff.text_field :amount, size: "10" %>
<%= ff.hidden_field :_destroy %>
<%= link_to_function "remove", "remove_fields(this)" %><br>
</div>
<% end %>
<%= link_to 'Add ingredient', "new_ingredient_button", id: 'new_ingredient' %>
</div><br>
<%= f.label :description %><br>
<%= f.text_area :description, rows: 4, columns: 100 %><br>
<%= f.label :directions %><br>
<%= f.text_area :directions, rows: 4, columns: 100 %><br>
<%= f.submit %>
<% end %>
link_to
とは、そのlink_to_function
場で量/成分のペアを追加および削除できるようにするためにあり、前述の Railscast から採用されました。一部のリファクタリングを使用することもできますが、多かれ少なかれ正常に機能します。
更新: Leger の要求に従って、関連するコードをrecipes_controller.rb
. Recipes#new
ルートでは、3.times { @recipe.quantities.build }
特定のレシピに対して 3 つの空白の数量/材料のペアを設定します。これらは、上記の「材料を追加」および「削除」リンクを使用して、その場で削除または追加できます。
class RecipesController < ApplicationController
def new
@recipe = Recipe.new
3.times { @recipe.quantities.build }
@quantity = Quantity.new
end
def create
@recipe = Recipe.new(params[:recipe])
if @recipe.save
redirect_to @recipe
else
render :action => 'new'
end
end