Ruby on rails Rails:访问一对多关联中的其他对象

Ruby on rails Rails:访问一对多关联中的其他对象,ruby-on-rails,ruby-on-rails-5,Ruby On Rails,Ruby On Rails 5,这是我的代码: class Recipe < ActiveRecord::Base has_many :neededingredients end 因此,一份食谱有多种必需成分。一个NeededIngredient有一个对成分的引用,有一个数量和一个单位(例如克)。我希望能够像a\u配方。needededingredients这样查找给定配方的所有所需成分,或者a\u needingred\u配料。recipe这样查找给定所需成分的配方。由于某种原因,我找不到一个方法来做这件事。

这是我的代码:

class Recipe < ActiveRecord::Base
    has_many :neededingredients
end

因此,一份食谱有多种必需成分。一个NeededIngredient有一个对成分的引用,有一个数量和一个单位(例如克)。我希望能够像
a\u配方。needededingredients
这样查找给定配方的所有所需成分,或者
a\u needingred\u配料。recipe
这样查找给定所需成分的配方。由于某种原因,我找不到一个方法来做这件事。我的迁移或模型中有什么错误吗?谢谢你的帮助

您使用复数而不是单数(在迁移和模型中),并且您应该使用

更改以下内容:

class Recipe < ApplicationRecord
  has_many :neededingredients
  has_many :ingredients, through: :neededingredients
end

class Neededingredient < ApplicationRecord
    belongs_to :ingredient
    belongs_to :recipe
end

class Ingredient < ApplicationRecord
    has_many :neededingredients
    has_many :recipes, through: :neededingredients
end

create_table :neededingredients do |neededingredients|
    neededingredients.integer :quantity, null: false
    neededingredients.string :unit
    neededingredients.references :ingredient, foreign_key: true
    neededingredients.references :recipe, foreign_key: true
end
类配方

现在您可以调用(例如):
Recipe.first.components
Recipe.first.neededingredients
component.first.recipes

您使用复数而不是单数(在迁移和模型中),您应该使用

更改以下内容:

class Recipe < ApplicationRecord
  has_many :neededingredients
  has_many :ingredients, through: :neededingredients
end

class Neededingredient < ApplicationRecord
    belongs_to :ingredient
    belongs_to :recipe
end

class Ingredient < ApplicationRecord
    has_many :neededingredients
    has_many :recipes, through: :neededingredients
end

create_table :neededingredients do |neededingredients|
    neededingredients.integer :quantity, null: false
    neededingredients.string :unit
    neededingredients.references :ingredient, foreign_key: true
    neededingredients.references :recipe, foreign_key: true
end
类配方

现在您可以调用(例如):
Recipe.first.components
Recipe.first.neededingredients
component.first.recipes
,这里的关键问题是命名/多元化非常糟糕。我强烈建议您根据重新命名,以避免混淆和将来的bug

类名应为CamelCase-
NeededIngredient
。把复合词分开

属性、表名、实例变量、路由、方法名和其他所有内容都应该是snake\u case-
needed\u components
needed\u components
,具体取决于上下文

这比使用小写字母更容易阅读和理解

将三个不同的表定义塞进一个迁移中(如果您正在这样做的话)是一个坏主意。尤其是因为通过模型生成器生成迁移非常简单。通过单独的迁移,您可以按顺序运行它们,并单独回滚它们以使其正确

class CreateNeededIngredients < ActiveRecord::Migration[6.0]
  def change
    # there is no need to use super long block argument names
    create_table :needed_ingredients do |t|
      t.decimal :quantity, null: false # yeah decimal
      t.string :unit
      t.references :ingredient, foreign_key: true # this should be singular!
      t.references :recipe, foreign_key: true # this should be singular!
      t.timestamps
    end
    # consider adding a unique index to avoid duplicates
    # add_index: :needed_ingredients, [:ingredient_id, :recipe_id], unique: true
  end
end
这不是一对多的联想。它是多对多的。如果你需要显示配方的成分,你应该注意,你应该循环通过所需的_成分协会,而不是成分

class NeededIngredient
  belongs_to :recipe # belongs_to is always singular!
  belongs_to :ingredient # belongs_to is always singular!

  # use delegation/proxing to avoid Law of Demeter violations
  def name
    ingredient.ingredient # why isn't this column just called name?
  end
end
类RecipiesController
#app/views/recipies/show.html.erb
名称
量

这里的关键问题是非常糟糕的命名/多元化。我强烈建议您根据重新命名,以避免混淆和将来的bug

类名应为CamelCase-
NeededIngredient
。把复合词分开

属性、表名、实例变量、路由、方法名和其他所有内容都应该是snake\u case-
needed\u components
needed\u components
,具体取决于上下文

这比使用小写字母更容易阅读和理解

将三个不同的表定义塞进一个迁移中(如果您正在这样做的话)是一个坏主意。尤其是因为通过模型生成器生成迁移非常简单。通过单独的迁移,您可以按顺序运行它们,并单独回滚它们以使其正确

class CreateNeededIngredients < ActiveRecord::Migration[6.0]
  def change
    # there is no need to use super long block argument names
    create_table :needed_ingredients do |t|
      t.decimal :quantity, null: false # yeah decimal
      t.string :unit
      t.references :ingredient, foreign_key: true # this should be singular!
      t.references :recipe, foreign_key: true # this should be singular!
      t.timestamps
    end
    # consider adding a unique index to avoid duplicates
    # add_index: :needed_ingredients, [:ingredient_id, :recipe_id], unique: true
  end
end
这不是一对多的联想。它是多对多的。如果你需要显示配方的成分,你应该注意,你应该循环通过所需的_成分协会,而不是成分

class NeededIngredient
  belongs_to :recipe # belongs_to is always singular!
  belongs_to :ingredient # belongs_to is always singular!

  # use delegation/proxing to avoid Law of Demeter violations
  def name
    ingredient.ingredient # why isn't this column just called name?
  end
end
类RecipiesController
#app/views/recipies/show.html.erb
名称
量

您是否尝试了
有很多:通过关联
您是否尝试了
有很多:通过关联
class NeededIngredient
  belongs_to :recipe # belongs_to is always singular!
  belongs_to :ingredient # belongs_to is always singular!

  # use delegation/proxing to avoid Law of Demeter violations
  def name
    ingredient.ingredient # why isn't this column just called name?
  end
end
class RecipiesController < ApplicationController
  def show
    @recipe = Recipe.include(:ingedients).find(params[:id])
  end 
end
# app/views/recipies/show.html.erb
<h1><%= @recipe.name %></h1>

<table>
  <thead>
    <tr>
      <th>Name</th>
      <th>Quantity</th> 
    </tr>
  </thead>
  <tbody>
  <% @recipe.needed_ingredients.each do |i|%>
    <tr>
      <td><%= i.name %></td>
      <td><%= i.quantity %> <%= i.unit %></td>  
    </tr>
  <% end %>
  </tbody>
</table>