ErwinM / acts_as_tenant

Easy multi-tenancy for Rails in a shared database setup.
MIT License
1.53k stars 263 forks source link

Has and belongs to many though option not scoping as expected #283

Open aarondufall opened 2 years ago

aarondufall commented 2 years ago

I followed the example of the Has and belongs to many. What I was expecting to happen is that when the following code is run, it would scope by the association.

account = Account.first
ActsAsTenant.current_tenant = account
User.where(email: "user@acount.com").first

The idea being the user could belong to many accounts but would only be found if the current_tenant was an account it was a member of.

When I run the above code the query it looks for an account_id on the User model. Producing an error when it can't find the foreign key.

PG::UndefinedColumn: ERROR:  column users.account_id does not exist (ActiveRecord::StatementInvalid)
LINE 1: SELECT "users".* FROM "users" WHERE "users"."account_id" = $...

This is what I expected as the normal behaviour for acts_as_tenant :account. I thought adding the through: option would then allow for the user to belong to many accounts, but only return the one that is the current tenant.

What exactly does the through: option allows for? Is there a common approach or best practice for a user belonging to many tenants?

Here is the code I used for the models

class User < ApplicationRecord
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  has_many :account_users
  acts_as_tenant :account, through: :account_users
end 
class AccountUser < ApplicationRecord
  belongs_to :user
  acts_as_tenant :account
end
class Account < ApplicationRecord
  has_many :account_users
  has_many :users, through: :account_users

  validates :name, presence: true, uniqueness: true
  validates :subdomain, presence: true, uniqueness: true
end
michaelnera commented 2 years ago

Got the same error.

I think it's probably because of this line:

belongs_to tenant, **valid_options

https://github.com/ErwinM/acts_as_tenant/blob/a05d9a2e07dc396fd56c857e7934bef67bd9dbc9/lib/acts_as_tenant/model_extensions.rb#L16

It doesn't have any has_many association, only belongs_to

yorsant commented 9 months ago

Any updates? Is #307 going to be approved any time soon?

giangdatoro commented 4 months ago

@aarondufall

actually you can do this way

# AccountUser.rb

def self.users
  user_ids = self.all.pluck(:user_id).uniq
  User.unscoped.where(id: user_ids)
end

# User

default_scope { AccountUser.users }

many to many relation ship and reuse the default scope of child model to do it. don't forget unscoped of the original model