influitive / apartment

Database multi-tenancy for Rack (and Rails) applications
2.66k stars 464 forks source link

Feature request: callbacks on switch #595

Closed griswoldbar closed 5 years ago

griswoldbar commented 5 years ago

I am currently caching some per-tenant configuration in the current thread (using the RequestStore gem), which is safe given that I only ever connect to one tenant in any web request, and RequestStore middleware takes care of clearing this configuration between requests.

However there are contexts (such as rake tasks and scheduled jobs) where I iterate through various tenants. In order to ensure each tenant uses its own config in this situation, I need to clear RequestStore on each tenant switch, which I currently achieve with this:

module Apartment::Tenant
  def self.switch!(*args)
    RequestStore.clear!
    super
  end
end

It occurred to me it might be nice to have some kind of callback mechanism in Apartment, e.g.:

Apartment.configure do |config|
  config.after_switch { RequestStore.clear! }
  config.before_switch ...
end

Is something like this of any use to anybody? I'd be happy to have a stab at implementing if so.

lcjury commented 5 years ago

Adapters have callbacks on create and switch methods, so you can do this:

require 'apartment/adapters/abstract_adapter'

module Apartment
  module Adapters
    class AbstractAdapter
      set_callback :switch, :after do |object|
        RequestStore.clear! 
      end
      set_callback :switch, :before do |object|
        ...
      end
    end
  end
end

At startup, loaded parts of the gem don't require abstract_adapter, so, you need to require it by yourself or you're going to have a nice "set_callback not found". I don't understand Ruby Gem loader behavior.

griswoldbar commented 5 years ago

@lcjury thanks for this - closing this issue :)