Troubleshooting AR Object Resets when Switching Tenants with Rails Apartment Gem

Introduction to Apartment Gem

The Apartment gem is a valuable tool for managing multiple tenants in a Rails application. It provides functionality to segregate data based on accounts or companies while allowing shared data to exist in a common tenant.

Issue: AR Objects Resetting During Tenant Switch

I encountered an unexpected behavior where Active Record objects stored in variables were being removed when switching from one tenant to another on the fly. This behavior could lead to confusing test failures without a clear understanding of why it was happening.

Here’s a simplified example illustrating the issue:

def switch(name)
  yield(name)
end

@customers = [1, 2, 3]
switch('shiva') do |name|
  puts name
  puts @customers
end

The output is as expected:

shiva
1
2
3

However, when attempting to switch tenants using the Apartment gem, unexpected results occur:

@roles = Role.all
@customers = org.branches
@list = [1, 2]

puts 'Role count' + @roles.count.to_s
puts 'Customer count' + @customers.count.to_s
puts 'list count' + @list.count.to_s

Apartment::Tenant.switch!(org.database_name)
puts '-------'
puts 'Role count' + @roles.count.to_s
puts 'Customer count' + @customers.count.to_s
puts 'list count' + @list.count.to_s

Output:

Role count: 2
Customer count: 2
List count: 2
-------
Role count: 0
Customer count: 0
List count: 2

Understanding the Reason

The root cause of this issue lies in the switch! method of the Apartment gem, specifically in the abstract_adapter.rb file.

# apartment-2.2.0/lib/apartment/adapters/abstract_adapter.rb
def switch!(tenant = nil)
  run_callbacks :switch do
    return reset if tenant.nil?

    connect_to_new(tenant).tap do
      Apartment.connection.clear_query_cache
    end
  end
end

This method is responsible for switching to a new tenant. If the tenant is nil, it triggers a reset. During a tenant switch, the Apartment gem connects to a new tenant and clears the query cache.

Conclusion

Understanding the intricacies of the Apartment gem, especially when dealing with tenant switches, is crucial for managing multi-tenancy effectively in a Rails application. The unexpected behavior of Active Record objects being reset during a tenant switch can be addressed by diving into the gem’s source code and applying appropriate modifications or workarounds.