我需要帮助正确形成这个ActiveRecord关联

时间:2014-08-29 19:08:36

标签: ruby-on-rails database activerecord rails-activerecord

基本上,用户可以作为(或可能是两者)供应商和作为活动教员的成员参与一个或多个活动。

默认情况下,用户既不是供应商也不是教师,而是在事件的上下文中获得(或两者)状态(例如,用户已被录取为事件)教职员工。)

似乎我想说的是用户通过供应商或教师链接表中的任何一个(或两者)有很多事件,但我不确定我是否会在我的Rails模型中表示这一点。这是我到目前为止所尝试的内容:

class User < ActiveRecord::Base
  has_many :events through => vendors
  has_many :events through => faculty
end

以下是我认为需要进行的查询示例:

Select * from vendors where user_id = 1;
Select * from faculty where user_id = 1;

有人可以就如何正确形成此ActiveRecord关联提供一些指导吗?

更新

所以,我尝试使用单表继承来解决这个问题,最后我得到了一个记录只包含一个用户类型的用户表。虽然仍然使用单表继承,但如何让我的用户拥有多种类型? (我知道这基本上是一个多对多关系;我只是不确定如何使用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

2 个答案:

答案 0 :(得分:2)

单表继承可能就是您所需要的。简而言之:它允许将具有相同类型数据的多个类放入一个表中。唯一的要求是该表格具有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

好的。然后我们会有UserEvent

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

我们已经生成了一些没有数据库表的类(我们不需要它们)。它们是空的,我们不会改变它:它们继承了Pass,这就是我们所需要的。但我们需要在UserEvent和新传递之间创建一些额外的关联。最后,我发现这有效:

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的理解,这是&#34;它是Pass,其typeVendorPass&#34;,与FacultyPass

好的部分:

  • 容易想象:数据结构看起来很健全
  • 我们可以自由添加更多类型的Pass es而无需更改数据库

不良部分:

  • 无法将额外字段仅添加到Pass的特定子类中:它们全部在同一个表中
  • 协会看起来有点重复和繁琐
  • Rails只允许type成为string,而不是最快的比较类型

答案 1 :(得分:0)

让我们说每个活动都有一张个人独有的门票,一个活动,并说明该人是否被录取为教职员工或供应商。

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