从Rails中的has_many到select中选择单个关联

时间:2012-06-25 16:54:02

标签: sql ruby-on-rails ruby-on-rails-3 associations has-many-through

使用has_many通过关联时是否有任何(干净)方式来访问单个关联?

例如,要获得食谱的所有成分,我可以写:

@ingredients = @recipe.ingredients

但是,如果我已经选择了一种成分,并且我想将数据添加到配方/成分的连接表中,我无法找出添加数据的简洁方法。

我无法使用

访问单一成分协会的金额
ingredient = Ingredient.find(an_id)  

amount = @recipe.ingredient.amount

选择存储在连接表中的单一成分信息的方法是什么?

4 个答案:

答案 0 :(得分:1)

在这种情况下,选项:select非常有用。例如

class Recipe
  has_many :ingredients, through: ingredients_recipes, select: "ingredinets.*, ingredients_recipes.some_additional_column as some_additional_column"
  ....

然后致电

Recipe.first.ingredients.first.some_additional_column # => profit!

您也可以在范围内使用它。

答案 1 :(得分:0)

你可以@ingredient = @recipe.ingredients.first(如果它真的是唯一的,不确定你怎么知道这一点。)

假设您已经选择了成分,就像在变量中一样,您可以像任何其他ActiveRecord对象一样设置它们。

@ingredient = @recipe.ingredients.first
@ingredient.amount = 15 #or @ingredient.amount = params[:amount] (if you get the new value from POST)
@ingredient.unit = "Ounces"
@ingredient.save

如果您只想检索配方的每种成分的属性并对它们执行某些操作,例如在视图中的某些html标记中显示它们,您可以尝试这样做。

@ingredients = @recipe.ingredients
   @ingredients.each do |ingr|
    info = %w[amount, brand, id, recipe_id , unit].map do |attr|
      ingr.send(attr)
    end

在每个内循环的末尾,数组'info'将是一个成分的所有属性。(假设你将它们包含在info数组中)

这是您可能用于存储关联的表的示例,它应该使用rails :through => :recipe_ingedient方法:

CREATE TABLE `recipe_ingredient` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `recipe_id` int(11) NOT NULL,
  `ingedient_id` int(11) NOT NULL,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=59 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci$$

答案 2 :(得分:0)

联接表对您很重要,因此它应该有一个名称。 您可以将其称为recipe_ingredient,但真实姓名有助于避免在精神上混淆事物。 (它帮助我们讨论问题)

给定连接表,例如slot

class Recipe
  has_many :slots
  has_many :ingredients, :through => :slots
  ..
class Slot
  belongs_to :recipe
  belongs_to :ingredient
  ...

通过调用

获得定义的插槽
@slot = @recipe.slots.where(:ingredients_id => @ingredient).first 
@slot.amount = 20

为了提高效率并确保每个组合只存在一次,您可以为recipe_id和ingredient_id

定义一个唯一的复合索引。

答案 3 :(得分:-1)

我不知道这样的事情是如何存在的。如果您有许多关联对象,则需要指定您想要的。这并不是Rails的限制,而是限制......我不知道,设定理论?逻辑? 您可以使用.firstingredient = @recipe.ingredients.first)获取其中一个关联对象,但除非您还指定了订单,否则无法确定它将是哪一个。