I'd like to do something like this:
Category
--------
- id
- name
Tag
--------
- id
- tag
Campaign
--------
- id
- name
- target (either a tag *or* a category)
Is a polymorphic association the answer here? I can't seem to figure out how to use it with has_one :target, :as => :targetable.
Basically, I want Campaign.target to be set to a Tag or a Category (or potentially another model in the future).
I don't believe you're in need of a has_one
association here, the belongs_to
should be what you're looking for.
In this case, you'd want a target_id
and target_type
column on your Campaign table, you can create these in a rake with a t.references :target
call (where t
is the table
variable).
class Campaign < ActiveRecord::Base
belongs_to :target, :polymorphic => true
end
Now campaign can be associated to either a Tag
or Category
and @campaign.target
would return the appropriate one.
The has_one
association would be used if you have a foreign key on the target table pointing back to your Campaign
.
For example, your tables would have
Tag: id, tag, campaign_id
Category: id, category, campaign_id
and would have a belongs_to :campaign
association on both of them. In this case, you'd have to use has_one :tag
and has_one :category
, but you couldn't use a generic target
at this point.
Does that make more sense?
EDIT
Since target_id
and target_type
are effectively foreign keys to another table, your Campaign
belongs to one of them. I can see your confusion with the wording because logically the Campaign
is the container. I guess you can think of it as Campaign
has a single target, and that's a Tag
or a Container
, therefore it belongs in a Tag
or Container
.
The has_one
is the way of saying the relationship is defined on the target class. For example, a Tag
would have be associated to the campaign through a has_one
relationship since there's nothing on the tag class that identifies the association. In this case, you'd have
class Tag < ActiveRecord::Base
has_one :campaign, :as => :target
end
and likewise for a Category
. Here, the :as
keyword is telling rails which association relates back to this Tag
. Rails doesn't know how to figure this out upfront because there's no association with the name tag
on the Campaign
.
The other two options that may provide further confusion are the source
and source_type
options. These are only used in :through
relationships, where you're actually joining the association through
another table. The docs probably describe it better, but the source
defines the association name, and source_type
is used where that association is polymorphic. They only need to be used when the target association (on the :through
class) has a name that isn't obvious -- like the case above with target and
Tag -- and we need to tell rails which one to use.