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