Question

I have two classes Ads and Zones which both inherit from a class called Tracked which in turn contains several Events. The idea is that Ads as well as Zones can be associated with various events (i.e. 'View', 'Click', 'Conversion'). Those events must be tracked.

How would I go about and model that using ActiveRecords? What would the migration code look like?

This is what I got so far:

Event:

class Event < ActiveRecord :: Base

  attribute :event_date
  belongs_to :trackable, polymorphic: true
[...]
end

Tracked:

class Tracked < ActiveRecord :: Base

  self.abstract_class = true
  has_many :views, class_name: "Event"
  has_many :clicks, class_name: "Event"
  has_many :conversions, class_name: "Event"

  belongs_to :trackable, polymorphic: true
[...]
end

Ad:

class Ad < Tracked

  attribute :size, :content
  attr_accessor :width, :height
  belongs_to :advertisers
  has_and_belongs_to_many :campaigns
[...]
end

Campaign:

require 'date'

class Campaign < ActiveRecord :: Base

  attribute :name, :target_url,
            :expiration_date,:categories,
            :billing_type, :budget, :budget_type,
            :cp_click, :cp_view, :cp_conversion

  belongs_to :advertiser
  has_and_belongs_to_many :ads
  has_many :zones
[...]
end

At first I thought that I may want to use the through association but since it is paramount for me to distinguish between those three events (View, Click, Conversion) I think that I can' apply that pattern. Therefore I think I got to use Polymorphic Associations.

Please note that the code I pasted contains all the necessary information to create the model i.e. there are no attributes or associations that I left out. Also I know how to write migration code for all the attributes/associations that don't belong to the problem described above.

Was it helpful?

Solution

Polymorphic Association

To implement a polymorphic associations here, Ads and Zones should both use:

has_one :tracked, as: :trackable

You wouldn't need this line in Events: belongs_to :trackable, polymorphic: true since you already have it in Tracked.

You then need to run some migrations to set up Tracked to handle the trackable association (this explains that better than I could).

I think you would need to also remove self.abstract_class = true in Tracked since it will now be represented in the db.

There is perhaps a better way to approach this:

Perhaps you would be better off creating the 'views', 'clicks' and 'conversion' associations directly on Ads and Zones and then including any shared logic with a module.

You could take the logic of Tracked, move it into a 'trackable' module and including that module in Ads and Zones (if you're using Rails 4 you can wrap this up in a 'trackable' concern).

You would also move the following associations into Ads and Zones:

  has_many :views, class_name: "Event"
  has_many :clicks, class_name: "Event"
  has_many :conversions, class_name: "Event"

You then wouldn't need the Tracked class any more.

This approach would mean you could call Ad.first.views as opposed to Ad.first.tracked.views which would be the case if you used a polymorphic association.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top