I work for a lead generation company. Part of the application I’m working required us to know how many people viewed a particular item in the system. So, my co-worker and I created an Impression model that tracked each appearance of the associated object. We created a polymorphic association to allow impressions to be gathered on several different models.
The trick was that we found ourselves writing the same functionality on each of the models that needed impressions gathered. So, we took that functionality as well as the has_many polymorphic association and moved them into a module. Here’s what the module looks like:
module ImpressionableMixin def self.included(base) base.instance_eval("has_many :impressions, :as => :impressionable") end def add_impression(visitor) Impression.create(:visitor => visitor, :impressionable => self) end end
This bit of code does two things for us. First, it creates the has many association on the model with the ImpressionableMixin module is included. Second, it adds the functionality related to the association to the model, which allows us to keep our code DRY. In other words, our models look like this:
class SomeModel < ActiveRecord::Base # associations ... include ImpressionableMixin # methods ... end
I’ve left the module’s file in /app/models as it gets loaded when the models are loaded. This allows Rails to load it up when it loads all of the models.
I really like the encapsulation it provides for the functionality and the clean interface it provides.