Rails中具有相同类的多个关联的最佳实践? [英] Best practices for multiple associations with the same class in Rails?

查看:72
本文介绍了Rails中具有相同类的多个关联的最佳实践?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为我的问题最好被描述为一个例子。假设我有一个名为事物的简单模型,它具有一些简单数据类型的属性。像...

I think my question is best described as an example. Let's say I have a simple model called "Thing" and it has a few attributes that are simple data types. Something like...

Thing
   - foo:string
   - goo:string
   - bar:int

这并不难。 db表将包含具有这三个属性的三列,我可以使用@ thing.foo或@ thing.bar之类的东西来访问它们。

That isn't hard. The db table will contain three columns with those three attributes and I can access them with something like @thing.foo or @thing.bar.

但是问题是试图解决的是,当 foo或 goo不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象。也就是说,它们都是带有不同数据的 Whazit实例。所以现在事情看起来像这样……

But the problem I'm trying to solve is what happens when "foo" or "goo" can no longer be contained in a simple data type? Assume that foo and goo represent the same type of object. That is, they are both instances of "Whazit" just with different data. So now Thing might look like this...

Thing
  - bar:int

但是现在有一个名为 Whazit的新模型,看起来像这样...

But now there is a new model called "Whazit" that looks like this...

Whazit
  - content:string
  - value:int
  - thing_id:int

到目前为止,一切都很好。现在这是我遇到的问题。如果我有@thing,该如何设置它以按名称引用我的2个Whazit实例(根据记录,业务规则是,任何Thing都将始终恰好具有2个Whazits)?也就是说,我需要知道我拥有的Whazit基本上是foo还是goo。显然,在当前设置中我无法执行@ thing.foo,但是我很理想。

So far this is all good. Now here is where I'm stuck. If I have @thing, how can I set it up to refer to my 2 instances of Whazit by name (For the record, the "business rule" is that any Thing will always have exactly 2 Whazits)? That is, I need to know if the Whazit I have is basically foo or goo. Obviously, I can't do @thing.foo in the current setup, but I'd that is ideal.

我最初的想法是添加名称属性到Whazit,以便我可以获取与我的@thing相关的Whatzits,然后以这种方式选择我想要的Whazit。

My initial thought is to add a "name" attribute to Whazit so I can get the Whatzits associated with my @thing and then choose the Whazit I want by name that way. That seems ugly though.

有更好的方法吗?

推荐答案

您可以通过以下两种方法进行操作。首先,您可以建立两个 belongs_to / has_one 关系:

There are a couple of ways you could do this. First, you could set up two belongs_to/has_one relationships:

things
  - bar:int
  - foo_id:int
  - goo_id:int

whazits
  - content:string
  - value:int

class Thing < ActiveRecord::Base
  belongs_to :foo, :class_name => "whazit"
  belongs_to :goo, :class_name => "whazit"
end

class Whazit < ActiveRecord::Base
  has_one :foo_owner, class_name => "thing", foreign_key => "foo_id"
  has_one :goo_owner, class_name => "thing", foreign_key => "goo_id"

  # Perhaps some before save logic to make sure that either foo_owner
  # or goo_owner are non-nil, but not both.
end

另一种选择是更清洁,但在交易时更痛苦与插件等,是单表继承。在这种情况下,您有Foo和Goo这两个类,但它们都保存在whazits表中,并带有区分它们的类型列。

Another option which is a little cleaner, but also more of a pain when dealing with plugins, etc., is single-table inheritance. In this case you have two classes, Foo and Goo, but they're both kept in the whazits table with a type column that distinguishes them.

things
  - bar:int

whazits
  - content:string
  - value:int
  - thing_id:int
  - type:string

class Thing < ActiveRecord::Base
  belongs_to :foo
  belongs_to :goo
end

class Whazit < ActiveRecord::Base
  # .. whatever methods they have in common ..
end

class Foo < Whazit
  has_one :thing
end

class Goo < Whazit
  has_one :thing
end

在两种情况下,您都可以做类似 @ thing.foo @ thing.goo 。使用第一种方法,您需要执行以下操作:

In both cases you can do things like @thing.foo and @thing.goo. With the first method, you'd need to do things like:

@thing.foo = Whazit.new

而使用第二种方法,您可以执行以下操作:

whereas with the second method you can do things like:

@thing.foo = Foo.new

STI具有但是,如果您使用的是旧版插件和gem,则可能会遇到一系列问题。通常,当他们真正想要的是 @ object.base_class 时,调用 @ object.class 的代码就会出现问题。必要时打补丁很容易。

STI has its own set of problems, though, especially if you're using older plugins and gems. Usually it's an issue with the code calling @object.class when what they really want is @object.base_class. It's easy enough to patch when necessary.

这篇关于Rails中具有相同类的多个关联的最佳实践?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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