activerecord relations rails confusion

时间:2015-06-11 09:56:25

标签: ruby-on-rails ruby activerecord

我想创建一个饮料数据库。

每种饮料都含有许多成分,成分含量很多。

因此,一种成分属于剂量,剂量属于鸡尾酒。

但是,一旦我删除饮料,我想删除相关的剂量,但不是因为可以在其他饮料中使用。

目前我正在考虑像这样构建我的数据库。

rails g model drink name:string dose_id:references
rails g model dose cl:string ingredient_id:references
rails g model ingredient name:string

问题:

1)这是否符合我的需要,还是我错过了什么?

2)我是否需要鸡尾酒和配料之间的关系,还是通过剂量来完成?如果是/否,为什么?

3)这个:引用除了将FK链接到PK之外还做什么吗?

4)命名对于引用是否重要,它如何检测要链接的表?

2 个答案:

答案 0 :(得分:2)

我假设您使用MySQL和Ruby 2.我建议您可以像这样构建模型:

class Drink < ActiveRecord::Base
  has_many :doses, dependent: :destroy
  has_many :ingredients, through: :doses
end

class Dose < ActiveRecord::Base
  belongs_to :drink
  belongs_to :ingredient
end

class Ingredient < ActiveRecord::Base
  has_many :doses, dependent: :restrict
  has_many :drinks, through: :doses
end

Rails中的关系遵循一些约定:

  • 表名称为复数形式
  • 模型名称为单数形式
  • 外键名为:othertable_id
  • 包含belongs_to关系的模型还包含外键(在您的情况下,这将是:drink_id:ingredient_id)。
  • :through语句为您在SQL中生成连接语句,因此您可以说my_drink.ingredientsmy_ingredient.drinks
  • dependent: :destroy会在删除饮品时销毁:doses,但不会与ingredients相关联。
  • dependent: :restrict将拒绝删除一种仍然被一剂或多剂量使用的成分

我总是在连接表中使用额外的模型(你可以跳过它,并且rails会为你带来魔力)。但最大的好处是,您可以将额外的属性存储到该模型中,例如金额,单位......在您的红宝石代码中也很清楚,关系来自哪里。

这些模型尚未经过测试,如果:through语法正确,我不能100%确定。但你应该明白这一点。

答案 1 :(得分:2)

您可以在rails指南上阅读有关参考和迁移的更多信息,但这里有一些想法。

  1. 你似乎错过了一些东西。您希望drink有多个ingredients。为drink添加dose的引用意味着drink只属于一个dose,因为它一次只能存储一个dose_id

  2. 您可能希望drinkingredients之间存在多对多关系。 drink可以包含多个ingredients。一种成分可以是许多drink的一部分。 dose实际上可以更成功地解决此问题。

     rails g model drink name:string 
     rails g model dose cl:string ingredient:references drink:references
     rails g model ingredient name:string
    
  3. 它的行为应该与SQL中的典型REFERENCES约束相同。下面是一些很好的读取,但在Rails中它还会在列上添加btree索引。

    一个。 http://www.postgresql.org/docs/9.4/static/ddl-constraints.html#DDL-CONSTRAINTS-FK

    How to use the keyword 'references' in MySQL?

  4. 生成迁移时,它会使引用关系中的模型名称复数化。

    rails g model dose ingredient:references变得类似于架构中的以下内容:

       ...
         add_index "doses", ["ingredient_id"], name: "index_doses_on_ingredient_id", using: :btree
         add_foreign_key "doses", "ingredients"