Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Pass ar_relation to should_require_tenant? for improved control #349

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,18 @@ ActsAsTenant.configure do |config|
end
```

The lambda can also optionally receive the ar_relation currently being evaulated as an argument. This is useful for finer control over tenant requirements.

For example, if you wanted to require the tenant for every model except `User`, you could do the following:

```ruby
ActsAsTenant.configure do |config|
config.require_tenant = lambda do |relation|
relation.klass.name != "User"
end
end
```

`ActsAsTenant.should_require_tenant?` is used to determine if a tenant is required in the current context, either by evaluating the lambda provided, or by returning the boolean value assigned to `config.require_tenant`.

When using `config.require_tenant` alongside the `rails console`, a nice quality of life tweak is to set the tenant in the console session in your initializer script. For example in `config/initializers/acts_as_tenant.rb`:
Expand Down
11 changes: 5 additions & 6 deletions lib/acts_as_tenant.rb
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,11 @@ def self.with_mutable_tenant(&block)
ActsAsTenant.mutable_tenant!(false)
end

def self.should_require_tenant?
if configuration.require_tenant.respond_to?(:call)
!!configuration.require_tenant.call
else
!!configuration.require_tenant
end
def self.should_require_tenant?(context = nil)
config = configuration.require_tenant
return !!config unless config.respond_to?(:call)

config.arity.zero? ? !!config.call : !!config.call(context)
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/acts_as_tenant/model_extensions.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def acts_as_tenant(tenant = :account, scope = nil, **options)
belongs_to tenant, scope, **valid_options

default_scope lambda {
if ActsAsTenant.should_require_tenant? && ActsAsTenant.current_tenant.nil? && !ActsAsTenant.unscoped?
if ActsAsTenant.should_require_tenant?(self) && ActsAsTenant.current_tenant.nil? && !ActsAsTenant.unscoped?
raise ActsAsTenant::Errors::NoTenantSet
end

Expand Down
15 changes: 15 additions & 0 deletions spec/acts_as_tenant/configuration_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,21 @@
expect(ActsAsTenant.should_require_tenant?).to eq(false)
end

it "evaluates lambda with context" do
account = accounts(:foo)
test_context = nil

ActsAsTenant.configure do |config|
config.require_tenant = ->(context) {
test_context = context
context.klass.name == "Project"
}
end

expect { account.projects.create!(name: "foobar") }.to raise_error(ActsAsTenant::Errors::NoTenantSet)
expect(test_context.klass.name).to eq("Project")
end

it "evaluates boolean" do
ActsAsTenant.configure do |config|
config.require_tenant = true
Expand Down