代码之家  ›  专栏  ›  技术社区  ›  bax

Rails:需要帮助理解连接表、嵌套表单、关联吗

  •  -1
  • bax  · 技术社区  · 7 年前

    我是一个学习Rails的学生,我的项目是制作一个食谱应用程序。我的食谱应用程序有模型 Recipe , Ingredient 一定是餐桌上唯一的配料。一行就是一个id和名称。桌子上只能有一个“米”,所以任何一个都可以 配方 以大米为原料,使用同一行。这样我就可以过滤了 配方 s由 s。

    在创建/编辑表单时,我必须使用嵌套表单 ,因此用户可以在一个屏幕中填写配方信息和配料,包括添加新的 Ingredients 配料 配方 .

    我知道我需要一个连接表(食谱\配料??如果是的话,这个模型叫什么, RecipesIngredient ?

    我真的不明白这种嵌套形式是如何工作的。我要创造一个 fields_for 对所有人 什么?如何解除关联并创建?

    我也尝试过使用简单的形式和茧,但我觉得这只是困惑我更。

    对这个问题的任何解释都是惊人的。非常感谢。

    2 回复  |  直到 7 年前
        1
  •  2
  •   max Mike Williams    7 年前

    enter image description here

    这里我们有一个规范化的表,名为 ingredients 作为配料和 recipe_ingredients 它与 recipe 桌子。

    在Rails中,我们将此设置为 has_many through: 协会:

    class Recipe < ApplicationRecord
      has_many :recipe_ingredients
      has_many :ingredients, through: :recipe_ingredients
    end
    
    class Ingredient < ApplicationRecord
      has_many :recipe_ingredients
      has_many :recipes, through: :recipe_ingredients
    end
    
    class RecipeIngredient < ApplicationRecord
      belongs_to :recipe
      belongs_to :ingredient
    end
    

    你想用的理由 has_many through: has_and_belongs_to_many 后者是“无头的”,因为没有模型。这似乎是个好主意,直到您意识到无法访问其他列(例如数量)。

    命名的联接表时 通过以下方式获得了很多: [thing in singular]_[thing in plural] 由于Rails从表名解析类名的方式。使用 recipes_ingredients 例如,当Rails尝试加载时,会导致丢失常量错误 Recipes::Ingredient . 联接模型本身应该命名为 SingularSingular .

    当然,您也可以命名符合域的连接表。

    nested attributes fields_for :recipe_ingredients :

    <%= form_for(@recipe) do |f| %>
      <div class="field">
        <%= f.label :name %>
        <%= f.text_field :name %>
      </div>
    
      <fieldset>
        <legend>Ingredients</legend>
        <%= fields_for :recipe_ingredients do |ri| %>
        <div class="nested_fields">
           <div class="field">
             <%= ri.label :ingredient %>
             <%= ri.collection_select(:ingredient_id, Ingredient.all, :id, :name) %>
           </div>
           <div class="field">
             <%= ri.number_field :quantity %>
           </div>
        </div>
        <% end %>
      </fieldset>
    <% end %>
    

    但是,嵌套字段在许多方面都是一种允许同时创建/修改多个模型的工具。将所有东西组合在一起的用户体验和应用程序流程很难达到理想的效果。

    /recipies/:recipe_id/ingredients

    请参见:

        2
  •  1
  •   Nick D    7 年前

    用简单的词来描述多对多的关联。

    所以首先看一下指南 https://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

    你需要3个模型。配方模型、配料模型和配方配料模型。

    rails generate migration create_recipe_ingredients   
    

    db/migrate/***create_recipe_ingredients.rb 创建连接表

    def change
     create_table :recipe_ingredients do |t|
       t.integer :ingredient_id, :recipe_id
     end
    end
    

    所以你们的模型:

    class Recipe < ApplicationRecord
      has_many:recipe_ingredients
      has_many:ingredients, through: :recipe_ingredients 
    end
    
    class RecipeIngredient < ApplicationRecord
      belongs_to :recipe
      belongs_to :ingredient
    end
    
    class Ingredient < ApplicationRecord
      has_many:recipe_ingredients
      has_many:recipes, through: :recipe_ingredients
    end
    

    irb:> recipe=Recipe.first
    irb:> ingre=Ingredient.first
    irb:> ingre.recipes << recipe
    irb:> ingre.recipes #Recipes with this ingredient
    irb:> recipe.ingredients #The ingredients of this specific recipe.
    irb:> Ingredient.all #List all your ingredients.
    irb:> Recipe.all #List all your recipes.
    
    推荐文章