我需要帮助正确形成这个ActiveRecord关联
基本上,用户可以作为(或可能是两者)供应商和作为活动教员的成员参与一个或多个事件。
默认情况下,用户既不是供应商也不是教师,而是在事件的上下文中获得(或两者)状态(例如,用户已作为其成员被接纳为事件)学院)。
看起来我想说的是用户通过供应商或教师链接表中的任何一个(或两个)都有很多事件,但我不确定我是否会在我的Rails模型中表示这一点。 这是我到目前为止所尝试的内容:
class User vendors has_many :events through => faculty end
这是我认为我需要进行的查询示例:
Select * from vendors where user_id = 1; Select * from faculty where user_id = 1;
有人可以提供一些指导如何正确形成这个ActiveRecord关联?
更新:
所以,我已经尝试使用单表inheritance来解决这个问题,而我最终得到的用户表记录只包含一个用户类型。 虽然仍然使用单表inheritance,但如何让我的用户拥有多种类型? (我知道这实际上是一个多对多的关系;我只是不确定如何使用STI实现这一点。)
id | first_name | last_name | birth_date | city | zip_code | email | type | created_at | updated_at ----+------------+-----------+------------+------+----------+-------+---------+----------------------------+---------------------------- 1 | Akira | Yamaoka | | | | | Vendor | 2014-08-30 14:58:26.917333 | 2014-08-30 14:58:26.917333 2 | Pyramid | Head | | | | | Faculty | 2014-08-30 15:02:04.70209 | 2014-08-30 15:02:04.70209
单表inheritance可能就是您所需要的。 简而言之:它允许将具有相同类型数据的多个类放入一个表中。 唯一的要求是该表有一个type
列,一个string
。
基本上,这是常识。 比方说,用户可以获得一个事件的通行证:供应商的通行证和教员通行证。 他可能都有。 让我们创建一个Pass
模型,记住我们需要不同类型的模型。 但我们稍后会用它。 现在让我们坚持使用has_many through
:
rails g model Pass type:string user:references event:references
迁移它,我们不再需要修改我们的数据库了。 我们只修改Ruby。 我们应该有一个类Pass
,我们需要在关联中标记它的作用:
class Pass < ActiveRecord::Base belongs_to :user belongs_to :event end
行。 然后我们将有这种User
和Event
:
class Event < ActiveRecord::Base has_many :passes has_many :users, through: :passes end class User < ActiveRecord::Base has_many :passes has_many :events, through: :passes end
这是STI魔术的来源。 让我们再创建两个类。
rails g model VendorPass --no-migration --parent=Pass rails g model FacultyPass --no-migration --parent=Pass
我们已经生成了一些没有数据库表的类(我们不需要它们)。 它们是空的,我们不会改变它:它们inheritance了Pass
,这就是我们所需要的。 但是我们需要在User
, Event
和new pass之间创建一些额外的关联。 最后,我发现这个工作:
class Event < ActiveRecord::Base # We already had this has_many :passes has_many :users, through: :passes # New stuff! has_many :vendor_passes has_many :vendors, through: :vendor_passes, source: :user has_many :faculty_passes has_many :faculty_members, through: :faculty_passes, source: :user end class User < ActiveRecord::Base # We already had this has_many :passes has_many :events, through: :passes # New stuff! has_many :vendor_passes has_many :vendor_events, through: :vendor_passes, source: :event has_many :faculty_passes has_many :faculty_events, through: :faculty_passes, source: :event end
Rails维护自己对VendorPass
的理解,这是“它是一个Pass
,其type
是VendorPass
”,与FacultyPass
相同。
好的部分:
- 容易想象:数据结构看起来很健全且合乎逻辑
- 我们可以自由添加更多类型的
Pass
es而无需更改数据库
坏的部分:
- 无法将额外的字段仅添加到
Pass
特定子类:它们都在同一个表中 - 协会看起来有点重复和繁琐
- Rails只允许
type
为string
,而不是要比较的最快类型
假设每个活动都有一张个人独有的门票,一个活动,并说明该人是否被录取为教职员工或供应商。
class User < ActiveRecord::Base has_many :tickets has_many :events, through: :tickets end class Event < ActiveRecord::Base has_many :tickets has_many :users, through: :tickets end class Ticket < ActiveRecord::Base belongs_to :event belongs_to :user belongs_to :vendor belongs_to :faculty end class Faculty < ActiveRecord::Base has_many :tickets end class Vendor < ActiveRecord::Base has_many :tickets end