I'm using postgres schemas in my Rails app so there's no clear way to query across all companies (for our own analytics). I'd like to implement each method that iterates over all the companies and switches the postgres schema appropriately.
I'd like to be able to call:
Company.each do |company|
  # do something in the context of each company
end
but I'd also like to get some of the other Enumerable methods like collect in this example of getting all managers across all companies: 
Company.collect do |company|
  Users.managers
end
Currently I have this which works well
class Company < ActiveRecord::Base
  # ...
  def self.each(&block)
    Company.all.each do |company|
      if Schemas.include? company.subdomain
        # this changes to that company's schema so all queries are scoped
        Apartment::Database.switch company.subdomain
        yield company if block_given?
      end
    end
  end
but how do I get the Enumerable mixin at the class-level not the instance level.
i.e., when include Enumerable is in the class, Enumerable methods get called like 
company = Company.new
# which might iterate over the contents (users?) in a company
company.collect {|u| u} 
but I want to call
# iterate over all companies and collect the managers
Company.collect {|c| User.managers} 
and have it use
 Company.each
I feel like the answer is obvious but my meta-programming foo is weak this morning.
You can use include from within class << self:
class Foo
  class << self
    include Enumerable
  end
  def self.each
    yield 1
    yield 2
    yield 3
  end
end
Foo.map { |x| x * 2 } # => [2, 4, 6]
This pattern is used in Ruby's Prime class. Writing include to include a module looks cleaner to me, but you can probably use extend as well (see Uri Agassi's answer).
There would be a difference if the included module relied on the included callback (Enumerable doesn't):
module M
  def self.included(other)
    puts "included in #{other}"
  end
end
class Foo
  class << self
    include M
  end
end
#=> "included in #<Class:Foo>"
class Bar
  extend M
end
#=> nothing
As noted by Зелёный you could define each right within the block: (and without using self)
class Foo
  class << self
    include Enumerable
    def each
      # ...
    end
  end
end
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With