Hi, all,
I need to DRY up some code in a few models. My first inclination,
having come from the Java world, was to go with an abstract class.
After a bit of reading, I then decided to follow the mixin route
instead. Now I’m running into trouble, most likely from a few basic
misunderstandings.
There are three models I will be using to average and count rating
data by executing a scheduled job. Basically, I want to get averages
and counts for the last week, the last month, and all time, and dump
the data into isolated tables to allow for quick reads. The logic is
pretty much identical for each instance. I just have a variance of
dates and a different table for each set of summary data. So I
defined a module (messy, I know):
module RatingTotals::StoryRatingTotals
def refresh_story_totals(date = Date.new(2007, 1, 1))
# Removed most the code.
ratings = Rating.find(:all,
:select => 'rateable_id, AVG(rating) as
average_rating, COUNT(id) as count ',
:conditions => ["rateable_type = ‘story’ AND
created_at >= ? ", date],
:group => 'rateable_id ')
totals = []
ratings.each do |rating|
totals << self.new(:story_id => rating.rateable_id,
:rating => rating.average_rating,
:count => rating.count)
end
self.transaction do
self.delete_all
totals.each do |total|
total.save
end
end
end
end
Then my models are pretty simple. I’d like to get a better aliasing
technique in place, but this at least executes:
class AllTimeStoryRatingTotal < ActiveRecord::Base
belongs_to :story
extend StoryRatingTotals
def self.refresh_totals
self.refresh_story_totals
end
end
class WeeklyStoryRatingTotal < ActiveRecord::Base
belongs_to :story
extend StoryRatingTotals
def self.refresh_totals
self.refresh_story_totals(1.week.ago)
end
end
class MonthlyStoryRatingTotal < ActiveRecord::Base
belongs_to :story
extend StoryRatingTotals
def self.refresh_totals
self.refresh_story_totals(1.month.ago)
end
end
When testing through the console, I can only execute a single one of
the class methods ( e.g. MonthlyStoryRatingTotal.refresh_totals).
Whichever class method I invoke first can be executed ad naseum, but
if I try to execute one of the other class refresh_totals methods they
are blocked out with the most classic of error messages:
ArgumentError: RatingTotals is not missing constant StoryRatingTotals!
What I suspect is that I’m confused on my ability to use ‘self’ within
modules. Another thought is that the way scoping works under the
console may not be true to real life. Though I also attempted to pass
in the class type as a parameter and I received the same errors.
Any thoughts on the most elegant way to abstract these class methods
successfully?
Thanks,