我需要帮助正确形成这个 ActiveRecord 关联 [英] I need help properly forming this ActiveRecord association

查看:14
本文介绍了我需要帮助正确形成这个 ActiveRecord 关联的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

基本上,用户可以作为(或可能同时作为)供应商和活动教职员工参加一个或多个活动.

Basically, a User can participate in one or more events as either (or potentially both) a vendor and as a member of the event's faculty.

默认情况下,用户既不归类为供应商也不归类为教职员工,而是在事件上下文中获得任一(或两者)状态(例如,用户已被允许参加事件作为其教职员工).

A user is, by default, categorized as neither a vendor nor a faculty member but rather attains either (or both) status(es) within the context of an event (e.g., the user has been admitted to an event as a member of its faculty).

似乎我想说的是,用户通过供应商或教师链接表(或两者)有许多事件,但我不确定我是否会在我的 Rails 模型中表示这一点.这是我迄今为止尝试过的:

It seems like what I want to say is that the user has many events through either (or both) the vendors or the faculty linking tables, but I'm not sure I'd go about representing this in my Rails model. Here's what I've tried so far:

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

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

Here's a sample of a query that I think I'd need to make:

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

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

Could someone provide some direction as to how to properly form this ActiveRecord association?

更新:

因此,我已尝试使用单表继承来解决该问题,但最终得到了一个仅包含单个用户类型记录的用户表.在仍然使用单表继承的同时,如何让我的用户拥有多种类型?(我知道这本质上是一种多对多的关系;我只是不确定如何使用 STI 来实现这一点.)

So, I've tried using single-table inheritance to solve the issue, and I've ended up with a user table which records containing only a single user type. While still using single-table inheritance, how do I get my users to have multiple types? (I know this is essentially a many-to-many relationship; I'm just not sure of how to accomplish this using 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

推荐答案

单表继承可能正是您所需要的.简而言之:它允许将具有相同类型数据的多个类放入一个表中.唯一的要求是该表有一个 type 列,一个 string.

Single-table inheritance might be what you need. In a nutshell: it allows several classes with the same kind of data to be put into one table. The only requirement is that that table has a type column, a string.

基本上,这是关于常识.比方说,用户可以拥有参加活动的通行证:供应商通行证和教职员工通行证.他可能两者兼而有之.让我们创建一个 Pass 模型,记住我们需要不同种类的它.但是我们稍后会使用它.现在让我们坚持使用 has_many through:

Basically, it's about common sense. Let's say, a user can have passes to an event: a vendor's pass and a faculty member's pass. He might have both. Let's create a Pass model, bearing in mind that we'll need different kinds of it. But we'll use it later. For now let's just stick to has_many through:

rails g model Pass type:string user:references event:references

迁移这个,我们就不需要再修改我们的数据库了.我们只会修改 Ruby.我们应该有一个Pass类,我们需要在关联中标记它的角色:

Migrate this and we won't need to modify our database anymore. We'll only modify Ruby. We should have got a class Pass, we'll need to mark its role in association:

class Pass < ActiveRecord::Base
  belongs_to :user
  belongs_to :event
end

好吧.然后我们会有这样的 UserEvent:

All right. Then we'll have this sort of User and 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 魔法的由来.让我们再创建两个类.

Here's where the STI magic comes. Let's create two more classes.

rails g model VendorPass --no-migration --parent=Pass
rails g model FacultyPass --no-migration --parent=Pass

我们生成了一些没有数据库表的类(我们不需要它们).它们是空的,我们不会改变它:它们继承了一个 Pass 而这就是我们所需要的.但是我们需要在我们的 UserEvent 和新通行证之间创建一些额外的关联.最后,我发现这行得通:

We've generated some classes without database tables (we don't need them). They are empty and we won't change it: they inherit a Pass and that's all we need. But we'll need to create some extra associations between our User, Event and the new passes. In the end, I've found this working:

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,其 typeVendorPass", 与 FacultyPass 相同.

Rails maintains its own understanding of VendorPass which is "it's a Pass, whose type is VendorPass", same with FacultyPass.

好的部分:

  • 容易想象:数据结构看起来合理且合乎逻辑
  • 我们可以自由添加更多类型的Passes而无需更改数据库
  • Easy to imagine: data structure seems sane and logical
  • We're free to add more types of Passes without changing the database

不好的部分:

  • 无法仅向 Pass 的特定子类添加额外字段:它们都在同一个表中
  • 关联看起来有点重复和繁琐
  • Rails 只允许 typestring,而不是最快的比较类型
  • No way to add extra fields to only specific subclasses of Pass: they're all in the same table
  • Associations look a bit repetitive and cumbersome
  • Rails only allows type to be a string, not the fastest type to compare

这篇关于我需要帮助正确形成这个 ActiveRecord 关联的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆