1

我对 Rails 将嵌套表单存储在数据库中的方式有​​疑问。我正在设计一个食谱网站(爱好),为此我创建了三个模型食谱、成分和成分食谱(代码如下)。成分可通过 has_many 和 Recipe 访问。所以菜谱可以有很多成分,成分可以属于很多菜谱。此外,IngredientRecipe 模型保存了每种配方和成分组合所独有的数量。

我的问题不是创建用于输入数据的嵌套表单,而是它存储在数据库中的方式。使用我当前的代码,每个新条目都会在 IngredienRecipe 模型中生成两行,一行用于配方和数量的组合,另一行用于配方成分关系。但是,我试图以一种方式对其进行设置,即每个条目在成分食谱表中恰好生成一行,将配方、成分和数量的独特组合链接在一起。

任何提示或代码片段都非常感谢,因为我已经被这个问题困扰了几天了:-(

这是我目前的模型:

class Recipe < ActiveRecord::Base
      attr_accessible :description, :name
      attr_accessible :ingredients_attributes, :ingredient_recipes_attributes

      has_many :ingredient_recipes
      has_many :ingredients, :through => :ingredient_recipes

      accepts_nested_attributes_for :ingredients
      accepts_nested_attributes_for :ingredient_recipes
  end

class Ingredient < ActiveRecord::Base
      attr_accessible :name, :unit

      has_many :ingredient_recipes
      has_many :recipes, :through => :ingredient_recipes
     end

class IngredientRecipe < ActiveRecord::Base
      attr_accessible :quantity

      belongs_to :recipe
      belongs_to :ingredient
end

修改后的配方控制器:

   #Modified controller function
    def new
        @recipe = Recipe.new
        @ingredients = @recipe.ingredients.build
        @ingredient_recipes = @recipe.ingredient_recipes.build

        respond_to do |format|
          format.html # new.html.erb
          format.json { render json: @recipe }
        end
      end

和 form_for 视图文件

<%= form_for @recipe do |f| %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <div class="field">
    <%= f.label :description %><br />
    <%= f.text_area :description %>
  </div>

<%=f.fields_for :ingredients do |ff|%>
   <div class="field">
    <%= ff.label :name %><br />
    <%= ff.text_field :name %>
  </div>

     <%= f.fields_for :ingredient_recipes do |fff| %>
         <div class="field">
           <%= fff.label :quantity%><br />
           <%= fff.text_field :quantity %>
         </div>
  <% end -%>   

  <div class="field">
    <%= ff.label :unit %><br />
    <%= ff.text_field :unit %>
  </div>
  <% end -%>

  <div class="actions">
   <%= f.submit %>
  </div>
   <% end %>

好的,在多次检查我的代码之后,我终于想出了一个更好的解决我的问题的方法。诀窍在于通过Recipe --> Ingredient --> JOIN table将模型相互嵌套。我当前的解决方案还没有动态添加 fields_for,但是这个版本不需要对 recipes_controller 进行任何更改。如果其他人也在为此苦苦挣扎,这是我的代码:

    class Recipe < ActiveRecord::Base
  attr_accessible :description, :name, :ingredients_attributes

  has_many :unique_recipes
  has_many :ingredients, :through => :unique_recipes

  accepts_nested_attributes_for :ingredients

end

class UniqueRecipe < ActiveRecord::Base
  attr_accessible :quantity, :recipe_id, :ingredient_id

    belongs_to :recipe
    belongs_to :ingredient

end


class Ingredient < ActiveRecord::Base
  attr_accessible :name, :unit, :unique_recipes_attributes

  has_many :unique_recipes
  has_many :recipes, :through => :unique_recipes

  accepts_nested_attributes_for :unique_recipes, allow_destroy: true

end


<%= form_for @recipe, :html => { :class => 'form-horizontal' } do |f| %>
    <%= f.label :name, :class => %>
      <%= f.text_field :name, :class => 'text_field' %>
    <%= f.label :description, :class => 'control-label' %>
      <%= f.text_area :description, :class => 'text_area' %>

<%= f.fields_for :ingredients do |ff| %>
    <%= ff.label :name, :class => %>
      <%= ff.text_field :name, :class => 'text_field' %>
    <%= ff.label :unit, :class => %>
      <%= ff.text_field :unit, :class => 'text_field' %>
  <%= ff.fields_for :unique_recipes do |fff| %>
    <%= fff.label :quantity, :class => %>
      <%= fff.text_field :quantity, :class => 'text_field' %>
<% end -%>

  <div class="form-actions">
    <%= f.submit nil, :class => 'btn btn-primary' %>
    <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
                recipes_path, :class => 'btn' %>
<% end %>
4

1 回答 1

2

这是我当前的工作解决方案,用于嵌套表单字段,通过关联具有 has_many 和动态添加字段的茧宝石。我仍在为这个特定场景进行一些茧调整,但模型和关联确实有效。

型号:

class Recipe < ActiveRecord::Base
  attr_accessible :description, :name, :ingredients_attributes

  has_many :unique_recipes
  has_many :ingredients, :through => :unique_recipes

  accepts_nested_attributes_for :ingredients

end

class UniqueRecipe < ActiveRecord::Base
  attr_accessible :quantity, :recipe_id, :ingredient_id

    belongs_to :recipe
    belongs_to :ingredient

end


class Ingredient < ActiveRecord::Base
  attr_accessible :name, :unit, :unique_recipes_attributes

  has_many :unique_recipes
  has_many :recipes, :through => :unique_recipes

  accepts_nested_attributes_for :unique_recipes, allow_destroy: true

end

Twitter引导程序中混合了一些表单字段:

    <%= form_for @recipe, :html => { :class => 'form-horizontal' } do |f| %>
  <div class="control-group">
    <%= f.label :name, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_field :name, :class => 'text_field' %>
    </div>
  </div>
  <div class="control-group">
    <%= f.label :description, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_area :description, :class => 'text_area' %>
    </div>
  </div>

<%= f.fields_for :ingredients do |ff| %>
<%= render 'ingredient_fields', f: ff %>

<% end -%>

  <div class="form-actions">
    <%= link_to_add_association 'Add an Ingredient', f, :ingredients, :class => 'btn btn-  primary'%>
    <%= f.submit nil, :class => 'btn btn-primary' %>
    <%= link_to t('.cancel', :default => t("helpers.links.cancel")),
                recipes_path, :class => 'btn' %>
  </div>
<% end %>

和匹配的部分 _ingredient_fields.html.erb

   <div class="control-group">
    <%= f.label :name, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_field :name, :class => 'text_field' %>
    </div>
  </div>
  <div class="control-group">
    <%= f.label :unit, :class => 'control-label' %>
    <div class="controls">
      <%= f.text_field :unit, :class => 'text_field' %>
    </div>
  </div>
  <%=link_to_remove_association "Remove Ingredient", f%>

  <%= render 'quantity_fields', f: ff %>
<% end -%>

recipes_controller 没有变化。如果您希望能够动态添加和删除嵌套表单元素,我强烈推荐 cocoon gem (http://github.com/nathanvda/cocoon)。

干杯!

于 2012-10-25T20:10:12.283 回答