CJ *_*J F 5 ruby activerecord ruby-on-rails
我认为我的问题最好被描述为一个例子.假设我有一个名为"Thing"的简单模型,它有一些简单数据类型的属性.就像是...
Thing
- foo:string
- goo:string
- bar:int
Run Code Online (Sandbox Code Playgroud)
这并不难.db表将包含三个具有这三个属性的列,我可以使用@ thing.foo或@ thing.bar等访问它们.
但是我试图解决的问题是当"foo"或"goo"不再包含在简单数据类型中时会发生什么?假设foo和goo代表相同类型的对象.也就是说,它们都只是具有不同数据的"Whazit"实例.所以现在Thing可能看起来像这样......
Thing
- bar:int
Run Code Online (Sandbox Code Playgroud)
但现在有一个名为"Whazit"的新模型看起来像这样......
Whazit
- content:string
- value:int
- thing_id:int
Run Code Online (Sandbox Code Playgroud)
到目前为止,这一切都很好.现在这里是我被困住的地方.如果我有@thing,我怎么设置它来引用我的2个Whazit实例的名称(为了记录,"业务规则"是任何Thing总是有2个Whazits)?也就是说,我需要知道我的Whazit是否基本上是foo或goo.显然,我不能在当前的设置中做@ thing.foo,但我认为这是理想的.
我最初的想法是给Whazit添加一个"name"属性,这样我就可以得到与我的@thing相关的Whatzits,然后通过这种方式选择我想要的Whazit.这看起来很难看.
有没有更好的办法?
有几种方法可以做到这一点.首先,您可以设置两个belongs_to/ has_one关系:
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
Run Code Online (Sandbox Code Playgroud)
另一种选择是更简洁,但在处理插件时也更痛苦,是单表继承.在这种情况下,你有两个类,Foo和Goo,但它们都保存在whazits表中,并带有区分它们的类型列.
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
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,你都可以做@thing.foo和@thing.goo.使用第一种方法,您需要执行以下操作:
@thing.foo = Whazit.new
Run Code Online (Sandbox Code Playgroud)
而使用第二种方法,您可以执行以下操作:
@thing.foo = Foo.new
Run Code Online (Sandbox Code Playgroud)
但是,STI有其自身的一系列问题,特别是如果您使用较旧的插件和宝石.通常,@object.class当他们真正想要的是代码调用时,这是一个问题@object.base_class.必要时可以轻松修补.
| 归档时间: |
|
| 查看次数: |
1816 次 |
| 最近记录: |