Forum: Ruby on Rails mixin behavior

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
bjhess (Guest)
on 2007-04-13 06:43
(Received via mailing list)
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,
This topic is locked and can not be replied to.