Closed jurgens closed 5 years ago
Could you open a new rails console, copy and paste the following and paste the full cli session here?
User.first
Apartment::Tenant.switch('tenant1') { User.first }
Apartment::Tenant.switch!('tenant1')
User.first
If both queries went to the public schema, you shouldn't have different "names".
2.4.4 :001 > User.first
User Load (0.4ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<User id: 1, name: "user public 1", created_at: "2019-06-03 12:17:16", updated_at: "2019-06-03 12:17:16", status: 0>
2.4.4 :002 > Apartment::Tenant.switch('tenant1') { User.first }
User Load (1.2ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<User id: 1, name: "user tenant1 user1", created_at: "2019-06-03 12:18:33", updated_at: "2019-06-03 12:18:33", status: 0>
2.4.4 :003 > Apartment::Tenant.switch!('tenant1')
=> nil
2.4.4 :004 > User.first
User Load (0.5ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<User id: 1, name: "user tenant1 user1", created_at: "2019-06-03 12:18:33", updated_at: "2019-06-03 12:18:33", status: 0>
in addition here's another trick
2.4.4 :008 > Apartment::Tenant.switch('tenant1') { User.all }
User Load (0.2ms) SELECT "users".* FROM "users"
=> #<ActiveRecord::Relation [#<User id: 1, name: "user public 1", created_at: "2019-06-03 12:17:16", updated_at: "2019-06-03 12:17:16", status: 0>]>
2.4.4 :009 > Apartment::Tenant.switch('tenant1') { User.first }
User Load (0.3ms) SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT $1 [["LIMIT", 1]]
=> #<User id: 1, name: "user tenant1 user1", created_at: "2019-06-03 12:18:33", updated_at: "2019-06-03 12:18:33", status: 0>`
I'm not able to reproduce your problem nor I have an idea of why it doesn't work. switch
and switch!
works correctly when using User.first
, but they don't with User.all
Is possible that you have something inside your User model that may be overriding the schema?
the project I'm running it in is an empty rails playground application created specifically for this purpose, but first we ran into this problem in another production rails app. here I'm just confirming this problem
class User < ApplicationRecord
has_many :topic_users, class_name: 'TopicUser'
has_many :topics, through: :topic_users
end
here's the repo https://github.com/jurgens/apartment-playground
I see the problem now. From what I remember, this is expected behavior, and any part of the documentation says something different.
The problem is with rails not loading the resources until it's necesary
if you do the following: User.all;
rails execute something like this: User.all.inspect
(that's why rails shows the result on the console)
But, if you execute the following:
users = User.all;1 #rails is going to inspect the integer instead of the User.all result
users.loaded #so, this is going to return false. This resource might not be used, so it's not loaded until we need it.
users.load #now users is loaded.
When you do:
users = Apartment::Tenant.switch('tenant1') { User.all };1 #this return the relationship
users.loaded? #but it's not loaded.
users.load #as we are out of the switch, if we load users. It's going to query using the schema_path
So, now we that we are out of 'tenant1' if we try to load u
, it's going to execute the query with the search_path
set to public (as we're out of the switch)
u.load #should return `"<User name: 'user public 1'>"`
if you force the loading inside the block, it works has you expect:
u = Apartment::Tenant.switch('tenant1') { User.all.load }
u[0] #should return `"<User name: 'user tenant 1'>"`
Hope this explanation helps, and sorry if I'm overexplaining things :)
yep. you're not executing the query in the block :).
thanks, guys!
feeling stupid, I should have figured it out myself. thanks again.
Steps to reproduce
This is weird since I believe this is quite major feature and it should be working well
When using switch with block it does not switch to desired tenant but pulls data from public schema instead, here's code from console
Note that in both cases it returns users with same ID=1 but names are different (named after tenant)
Expected behavior
I would expect both switching methods to work in a similar way as documented.
Actual behavior
switch method with block does not switch tenant
System configuration
Database: postgres 9.6
Apartment version: 2.2.0
Apartment config
use_schemas
:true
Rails (or ActiveRecord) version: 5.0.7.2 and 5.2.1
Ruby version: 2.4.4