mar*_*ada 37 polymorphism activerecord ruby-on-rails
我想做这样的事情:
Category
--------
- id
- name
Tag
--------
- id
- tag
Campaign
--------
- id
- name
- target (either a tag *or* a category)
Run Code Online (Sandbox Code Playgroud)
这是一个多态关联的答案吗?我似乎无法弄清楚如何使用has_one:target,:as =>:targetable.
基本上,我希望Campaign.target设置为Tag或Category(或将来可能是另一个模型).
Kri*_* PD 78
我不相信你在has_one
这里需要一个协会,belongs_to
应该是你正在寻找的.
在这种情况下,您需要在Campaign表上添加一个target_id
和target_type
列,您可以通过t.references :target
调用在rake中创建这些列(其中t
是table
变量).
class Campaign < ActiveRecord::Base
belongs_to :target, :polymorphic => true
end
Run Code Online (Sandbox Code Playgroud)
现在,运动可以关联到任何一个Tag
或Category
并且@campaign.target
将返回相应的一个.
has_one
如果目标表上的外键指向您的外键,则将使用该关联Campaign
.
例如,你的表会有
Tag: id, tag, campaign_id
Category: id, category, campaign_id
并且会对belongs_to :campaign
两者都有关联.在这种情况下,您必须使用has_one :tag
和has_one :category
,但此时您无法使用通用target
.
那更有意义吗?
编辑
由于target_id
并且target_type
实际上是另一个表的外键,因此您Campaign
属于其中一个表.我可以看到你对措辞的困惑,因为逻辑上它Campaign
是容器.我猜你可以把它想象成Campaign
一个目标,那是一个Tag
或一个Container
,因此它属于一个Tag
或者Container
.
这has_one
是说在目标类上定义关系的方式.例如,a Tag
将通过has_one
关系与广告系列相关联,因为标记类上没有任何标识关联的内容.在这种情况下,你有
class Tag < ActiveRecord::Base
has_one :campaign, :as => :target
end
Run Code Online (Sandbox Code Playgroud)
同样的Category
.在这里,:as
关键字告诉rails哪个关联与此有关Tag
.Rails不知道怎么算出来的前期,因为有这个名字没有关联tag
的Campaign
.
可提供进一步的混乱另外两个选项是source
和source_type
选项.这些仅用于:through
您实际加入through
另一个表的关系的关系中.文档可能更好地描述它,但是source
定义关联名称,并且source_type
在关联是多态的地方使用.它们只需要在目标关联(在:through
类上)具有不明显的名称时使用 - 就像上面的target and
Tag一样 - 我们需要告诉rails使用哪一个.
这些问题的答案很棒,但我只是想提一下另一种方法来实现同样的目标.你可以做的是创建两个关系,例如:
class Campaign < ActiveRecord::Base
belongs_to :tag
belongs_to :category
validate :tag_and_category_mutually_exclusive
def target=(tag_or_category)
case
when tag_or_category.kind_of?(Tag)
self.tag = tag_or_category
self.category = nil
when tag_or_category.kind_of?(Category)
self.category = tag_or_category
self.tag = nil
else
raise ArgumentError, "Expected Tag or Category"
end
end
def target(tag_or_category)
tag || category
end
private
def tag_and_category_mutually_exclusive
if tag && category
errors.add "Can't have both a tag and a category"
end
end
end
Run Code Online (Sandbox Code Playgroud)
验证确保您不会意外地最终设置两个字段,并且target
帮助程序允许对标记/类别进行多态访问.
这样做的好处是,您可以获得更正确的数据库模式,您可以在其中为id列定义正确的外键约束.这也将在数据库级别上导致更好,更有效的SQL查询.
归档时间: |
|
查看次数: |
25962 次 |
最近记录: |