Ruby on Rails/ActiveRecord/Associations
关联是连接两个模型的方法。对象操作变得非常简单。关联描述了模型之间关系的作用。ActiveRecord 关联可以用来描述模型之间的一对一 (1:1)、一对多 (1:n) 和多对多 (n:m) 关系。有几种类型的关联
- belongs_to 和
- has_one 形成一对一关系
- has_one :through 是一种创建一对一关系的不同方法
- has_many 和
- belongs_to 形成一对多关系
- has_and_belongs_to_many 或另一种方法
- has_many :through 创建多对多关系
对于所有以下示例,我们假设以下 4 个模型
class Product < ActiveRecord::Base
end
class Category < ActiveRecord::Base
end
class Rating < ActiveRecord::Base
end
class Tag < ActiveRecord::Base
end
也查看以下模型的 ER 图
该belongs_to关联建立与其他模型的一对一 (1:1) 或一对多 (1:n) 关系。
在我们的示例中,一个 Rating 属于一个 Product,因此我们需要设置一个belongs_to关联。
class Product < ActiveRecord::Base
belongs_to :rating
end
产品存储 Rating 的 ID,它们之间有一对一关系。这意味着:一个产品属于一个类别,一个产品属于一个 Rating。
该has_one关联也是一对一关系。它声明 Product 模型中的每个产品实例都只有一个 rating_id。
class Rating< ActiveRecord::Base
has_one :product
end
由于 Rating 和 Product 之间存在一对一关系,因此我们可以选择将引用放在哪里。因为我们将引用 (rating_id) 放入 Product (查看 Product 模型中的 belongs_to :rating),因此 Rating 的关联必须是 has_one:product。Has_one和belongs_to始终一起形成关系。
这是与其他模型的一对多连接。在这种情况下,一个类别有多个产品。注意拼写,如果您使用has_many。您要引用的模型需要用复数形式。
class Category< ActiveRecord::Base
has_many :products #note the plural here!
end
class Product< ActiveRecord::Base
belongs_to :category
end
类别和产品形成一对多关系。由于一个类别有多个产品,因此我们将has_many关联放在类别中。注意产品还需要包含对类别的引用。一个产品只属于一个类别,因此我们将belongs_to :category放在 Product 模型中。
也称为:HABTM。
Has_and_belongs_to_many是最复杂的关联。您需要牢记一些事项:由于关系型数据库的工作方式,您无法设置直接关系。您需要创建连接表。这可以通过迁移轻松完成。如果我们想为产品和标签创建 HABTM 关联,则连接表的关联可能如下所示
class CreateProductTagJoinTable < ActiveRecord::Migration
def self.up
create_table :products_tags, :id => false do |t| #we DO NOT need the id here!
t.integer :product_id #alternatively, we can write t.references :product
t.integer :tag_id
end
end
def self.down
drop_table :products_tags
end
end
因为我们不需要在连接表中使用主键,所以我们使用:id => false来阻止自动创建主键列。表名必须按字母顺序排列。字母 "P" 在 "T" 之前,因此表名必须是 products_tags(注意:复数)。
class Product< ActiveRecord::Base
has_and_belongs_to_many :tags
end
class Tag< ActiveRecord::Base
has_and_belongs_to_many :products
end
此关联是形成多对多关系的另一种方法。请考虑以下 ER 图来显示关系。
class Product < ActiveRecord::Base
belongs_to :category
belongs_to :supplier
end
class Supplier < ActiveRecord::Base
has_many :products
has_many :categories, :through => :products
end
class Category< ActiveRecord::Base
has_many :products
has_many :suppliers, :through => :products
end
我们不使用连接表,而是使用另一个模型来建立关系。如果我们想找出哪个供应商负责某个特定类别,我们需要使用产品将模型连接在一起。这样,我们就可以在充当连接模型的真实模型中存储更多数据。每当您需要存储也属于关联的额外数据(例如创建日期)时,您可能希望使用这种类型的关联。
与has_many :through, has_one :through关联使用一个“额外”模型来形成关系。
请考虑这种视觉关系
class Network < ActiveRecord::Base
has_one :group
has_one :user, :through =>:group
end
class Group < ActiveRecord::Base
belongs_to :network
has_one :user
end
class User< ActiveRecord::Base
belongs_to :group
end
注意:此示例假设组内的成员资格对每个用户都是排他的。