Answers:
假设您有两个模型: User
和Group
。
如果您希望用户属于组,则可以执行以下操作:
class Group < ActiveRecord::Base
has_many :users
end
class User < ActiveRecord::Base
belongs_to :group
end
如果您想跟踪关联周围的其他元数据怎么办?例如,当用户加入组时,或者用户在组中的角色是什么?
这是使关联成为一流对象的地方:
class GroupMembership < ActiveRecord::Base
belongs_to :user
belongs_to :group
# has attributes for date_joined and role
end
这将引入一个新表,并group_id
从用户表中删除该列。
此代码的问题在于,您必须在使用用户类的其他所有位置进行更新并进行更改:
user.groups.first.name
# becomes
user.group_memberships.first.group.name
这种类型的代码很烂,并且使引入这样的更改变得很痛苦。
has_many :through
让您两全其美:
class User < ActiveRecord::Base
has_many :groups, :through => :group_memberships # Edit :needs to be plural same as the has_many relationship
has_many :group_memberships
end
现在,您可以像对待普通对象一样对待它has_many
,但是在需要时可以从关联模型中受益。
请注意,您也可以使用has_one
。
编辑:轻松添加用户到组
def add_group(group, role = "member")
self.group_associations.build(:group => group, :role => role)
end
user.groups << group
吗?还是一切都由该协会处理?
假设您有以下模型:
Car
Engine
Piston
汽车has_one :engine
引擎belongs_to :car
引擎has_many :pistons
活塞belongs_to :engine
汽车has_many :pistons, through: :engine
活塞has_one :car, through: :engine
本质上,您是将一个模型关系委派给另一个模型,因此不必调用car.engine.pistons
,您只需执行car.pistons
has_many :through
和has_and_belongs_to_many
关系通过函数连接表,这是一个表示其它表之间的关系的中间表。与JOIN查询不同,数据实际上存储在表中。
使用has_and_belongs_to_many
,您不需要主键,并且可以通过ActiveRecord关系而不是通过ActiveRecord模型访问记录。当您要链接具有多对多关系的两个模型时,通常使用HABTM。
has_many :through
当您想作为Rails模型与联接表进行交互时,可以使用一种关系,并具有主键以及将自定义列添加到联接数据的功能。后者对于与连接的行相关但不真正属于相关模型的数据特别重要-例如,存储从连接的行中的字段派生的计算值。
在“活动记录关联指南”中,建议如下:
最简单的经验法则是,如果需要将关系模型作为独立实体使用,则应设置has_many:through关系。如果您不需要对关系模型做任何事情,则设置has_and_belongs_to_many关系可能更简单(尽管您需要记住要在数据库中创建联接表)。
如果需要在连接模型上进行验证,回调或其他属性,则应使用has_many:through。
user
模型上添加方法以添加组的地方。就像我刚才所做的编辑一样。希望这可以帮助。