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.