Skip to content
Browse files

Moved require_tenant config option to an initializer.

  • Loading branch information...
1 parent d83d72d commit fbd28aaea4e4ec6441e183eee6bfddd215359b5a @ErwinM committed Feb 11, 2013
View
17 README.md
@@ -66,9 +66,9 @@ any code in this block will be scoped to the current tenant. All methods that se
**note:** If the current tenant is not set by one of these methods, Acts_as_tenant will be unable to apply the proper scope to your models. So make sure you use one of the two methods to tell acts_as_tenant about the current tenant.
-**Requiring tenant to be set**
+**Require tenant to be set always**
-If you want to require the tenant to be set at all times, include ```require_tenant``` in your ApplicationController. Acts_as_tenant will then raise an exeception if a query is made without a tenant available.
+If you want to require the tenant to be set at all times, you can configure acts_as_tenant to raise an error when a query is made without a tenant available. See below under configuarion options.
Scoping your models
-------------------
@@ -115,6 +115,19 @@ If you need to validate for uniqueness, chances are that you want to scope this
All options available to Rails' own `validates_uniqueness_of` are also available to this method.
+Configuration options
+---------------------
+An initializer can be created to control (currently one) option in ActsAsTenant. Defaults
+are shown below with sample overrides following. In `config/initializer/acts_as_tenant.rb`:
+
+```ruby
+ActsAsTenant.configure do |config|
+ config.require_tenant = false # true
+end
+```
+
+* `config.require_tenant` when set to true will raise an ActsAsTenant::NoTenant error whenever a query is made without a tenant set.
+
Note on testing
---------------
Whenever you set the `current_tenant` in your tests, either through integration tests or directly by calling `ActsAsTenant.current_tenant = some_tenant`, make sure to clean up the tenant after each test by calling `ActsAsTenant.current_tenant = nil`.
View
9 lib/acts_as_tenant.rb
@@ -8,9 +8,9 @@
require "acts_as_tenant"
require "acts_as_tenant/version"
-require "acts_as_tenant/exceptions"
-require "acts_as_tenant/controller_extensions.rb"
-require "acts_as_tenant/model_extensions.rb"
+require "acts_as_tenant/configuration"
+require "acts_as_tenant/controller_extensions"
+require "acts_as_tenant/model_extensions"
#$LOAD_PATH.shift
@@ -19,5 +19,6 @@
ActionController::Base.extend ActsAsTenant::ControllerExtensions
end
-
+module ActsAsTenant
+end
View
26 lib/acts_as_tenant/configuration.rb
@@ -0,0 +1,26 @@
+module ActsAsTenant
+ @@configuration = nil
+
+ def self.configure
+ @@configuration = Configuration.new
+
+ if block_given?
+ yield configuration
+ end
+
+ configuration
+ end
+
+ def self.configuration
+ @@configuration || configure
+ end
+
+ class Configuration
+ attr_accessor :require_tenant
+
+ def require_tenant
+ @require_tenant ||= false
+ end
+
+ end
+end
View
11 lib/acts_as_tenant/model_extensions.rb
@@ -32,14 +32,6 @@ def self.with_tenant(tenant, &block)
self.current_tenant= old_tenant
return value
end
-
- def self.tenant_required?
- Thread.current[:tenant_required]
- end
-
- def self.require_tenant
- Thread.current[:tenant_required] = true
- end
module ModelExtensions
def self.included(base)
@@ -52,7 +44,7 @@ def acts_as_tenant(association = :account)
ActsAsTenant.set_tenant_klass(association)
default_scope lambda {
- if ActsAsTenant.tenant_required? && ActsAsTenant.current_tenant.nil?
+ if ActsAsTenant.configuration.require_tenant && ActsAsTenant.current_tenant.nil?
raise "No tenant found, while tenant_required is set to true [ActsAsTenant]"
end
where({ActsAsTenant.fkey => ActsAsTenant.current_tenant.id}) if ActsAsTenant.current_tenant
@@ -103,6 +95,7 @@ def validates_uniqueness_to_tenant(fields, args ={})
else
args[:scope] = tenant_id
end
+
validates_uniqueness_of(fields, args)
end
end
View
28 spec/acts_as_tenant/configuration_spec.rb
@@ -0,0 +1,28 @@
+require 'spec_helper'
+
+describe ActsAsTenant::Configuration do
+ describe 'no configuration given' do
+ before do
+ ActsAsTenant.configure
+ end
+
+ it 'provides defaults' do
+ ActsAsTenant.configuration.require_tenant.should_not be_true
+ end
+ end
+
+ describe 'with config block' do
+ after do
+ ActsAsTenant.configure
+ end
+
+ it 'stores config' do
+ ActsAsTenant.configure do |config|
+ config.require_tenant = true
+ end
+
+ ActsAsTenant.configuration.require_tenant.should be_true
+ end
+
+ end
+end
View
108 spec/model_extensions_spec.rb → spec/acts_as_tenant/model_extensions_spec.rb
@@ -10,35 +10,35 @@
t.column :name, :string
t.column :account_id, :integer
end
-
+
create_table :managers, :force => true do |t|
t.column :name, :string
t.column :project_id, :integer
t.column :account_id, :integer
end
-
+
create_table :tasks, :force => true do |t|
t.column :name, :string
t.column :account_id, :integer
t.column :project_id, :integer
t.column :completed, :boolean
end
-
+
create_table :countries, :force => true do |t|
t.column :name, :string
end
-
+
create_table :cities, :force => true do |t|
t.column :name, :string
end
-
+
create_table :sub_tasks, :force => true do |t|
t.column :name, :string
t.column :attribute2, :string
t.column :something_else, :integer
t.column :account_id, :integer
end
-
+
end
# Setup the models
@@ -50,7 +50,7 @@ class Project < ActiveRecord::Base
has_one :manager
has_many :tasks
acts_as_tenant :account
-
+
validates_uniqueness_to_tenant :name
end
@@ -62,7 +62,7 @@ class Manager < ActiveRecord::Base
class Task < ActiveRecord::Base
belongs_to :project
default_scope :conditions => { :completed => nil }, :order => "name"
-
+
acts_as_tenant :account
validates_uniqueness_of :name
end
@@ -85,30 +85,23 @@ class SubTask < ActiveRecord::Base
before { ActsAsTenant.current_tenant = :foo }
it { ActsAsTenant.current_tenant == :foo }
end
-
+
describe 'is_scoped_as_tenant should return the correct value' do
it {Project.respond_to?(:scoped_by_tenant?).should == true}
end
-
- describe 'sets tenant_required' do
- before { ActsAsTenant.require_tenant }
- it { ActsAsTenant.tenant_required?.should be_true }
- after { Thread.current[:tenant_required] = nil }
- end
-
+
describe 'Project.all should be scoped to the current tenant if set' do
before do
@account1 = Account.create!(:name => 'foo')
@account2 = Account.create!(:name => 'bar')
@project1 = @account1.projects.create!(:name => 'foobar')
@project2 = @account2.projects.create!(:name => 'baz')
-
+
ActsAsTenant.current_tenant= @account1
@projects = Project.all
- #debugger
end
-
+
it { @projects.length.should == 1 }
it { @projects.should == [@project1] }
end
@@ -120,104 +113,104 @@ class SubTask < ActiveRecord::Base
@project1 = @account1.projects.create!(:name => 'foobar')
@project2 = @account2.projects.create!(:name => 'baz')
-
+
ActsAsTenant.current_tenant= @account1
@projects = Project.unscoped.all
end
-
+
it { @projects.length.should == 2 }
end
-
+
describe 'Associations should be correctly scoped by current tenant' do
before do
@account = Account.create!(:name => 'foo')
@project = @account.projects.create!(:name => 'foobar', :account_id => @account.id )
- # the next line would normally be nearly impossible: a task assigned to a tenant project,
+ # the next line would normally be nearly impossible: a task assigned to a tenant project,
# but the task has no tenant assigned
- @task1 = Task.create!(:name => 'no_tenant', :project => @project)
-
+ @task1 = Task.create!(:name => 'no_tenant', :project => @project)
+
ActsAsTenant.current_tenant = @account
@task2 = @project.tasks.create!(:name => 'baz')
@tasks = @project.tasks
end
-
+
it 'should correctly set the tenant on the task created with current_tenant set' do
@task2.account.should == @account
end
-
+
it 'should filter out the non-tenant task from the project' do
@tasks.length.should == 1
end
end
-
+
describe 'When dealing with a user defined default_scope' do
before do
@account = Account.create!(:name => 'foo')
@project1 = Project.create!(:name => 'inaccessible')
@task1 = Task.create!(:name => 'no_tenant', :project => @project1)
-
+
ActsAsTenant.current_tenant = @account
@project2 = Project.create!(:name => 'accessible')
@task2 = @project2.tasks.create!(:name => 'bar')
@task3 = @project2.tasks.create!(:name => 'baz')
@task4 = @project2.tasks.create!(:name => 'foo')
@task5 = @project2.tasks.create!(:name => 'foobar', :completed => true )
-
+
@tasks= Task.all
end
-
+
it 'should apply both the tenant scope and the user defined default_scope, including :order' do
- @tasks.length.should == 3
- @tasks.should == [@task2, @task3, @task4]
+ @tasks.length.should == 3
+ @tasks.should == [@task2, @task3, @task4]
end
end
-
+
describe 'tenant_id should be immutable' do
before do
@account = Account.create!(:name => 'foo')
@project = @account.projects.create!(:name => 'bar')
end
-
+
it { lambda {@project.account_id = @account.id + 1}.should raise_error }
end
-
+
describe 'Associations can only be made with in-scope objects' do
before do
@account = Account.create!(:name => 'foo')
@project1 = Project.create!(:name => 'inaccessible_project', :account_id => @account.id + 1)
-
+
ActsAsTenant.current_tenant = @account
@project2 = Project.create!(:name => 'accessible_project')
@task = @project2.tasks.create!(:name => 'bar')
end
-
+
it { @task.update_attributes(:project_id => @project1.id).should == false }
end
-
+
describe 'When using validates_uniqueness_to_tenant in a aat model' do
before do
@account = Account.create!(:name => 'foo')
ActsAsTenant.current_tenant = @account
@project1 = Project.create!(:name => 'bar')
end
-
+
it 'should not be possible to create a duplicate within the same tenant' do
Project.create(:name => 'bar').valid?.should == false
end
-
+
it 'should be possible to create a duplicate outside the tenant scope' do
account = Account.create!(:name => 'baz')
ActsAsTenant.current_tenant = account
Project.create(:name => 'bar').valid?.should == true
end
-
+
it 'applies additional scopes' do
subtask1 = SubTask.create!(:name => 'foo', :attribute2 => 'unique_scope')
SubTask.create(:name => 'foo', :attribute2 => 'another_scope').should be_valid
SubTask.create(:name => 'foo', :attribute2 => 'unique_scope').should_not be_valid
end
end
-
+
describe 'When using validates_uniqueness_of in a NON-aat model' do
before do
@city1 = City.create!(:name => 'foo')
@@ -226,11 +219,11 @@ class SubTask < ActiveRecord::Base
City.create(:name => 'foo').valid?.should == false
end
end
-
+
describe "It should be possible to use aliased associations" do
it { SubTask.create(:name => 'foo').valid?.should == true }
end
-
+
describe "It should be possible to create and save an AaT-enabled child without it having a parent" do
@account = Account.create!(:name => 'baz')
ActsAsTenant.current_tenant = @account
@@ -249,7 +242,7 @@ class SubTask < ActiveRecord::Base
it "should reset current_tenant to the previous tenant once exiting the block" do
@account1 = Account.create!(:name => 'foo')
@account2 = Account.create!(:name => 'bar')
-
+
ActsAsTenant.current_tenant = @account1
ActsAsTenant.with_tenant @account2 do
@@ -261,12 +254,12 @@ class SubTask < ActiveRecord::Base
it "should return the value of the block" do
@account1 = Account.create!(:name => 'foo')
@account2 = Account.create!(:name => 'bar')
-
+
ActsAsTenant.current_tenant = @account1
value = ActsAsTenant.with_tenant @account2 do
"something"
end
-
+
value.should eq "something"
end
@@ -279,36 +272,25 @@ class SubTask < ActiveRecord::Base
describe "raises exception if no tenant specified" do
before do
@account1 = Account.create!(:name => 'foo')
- @account2 = Account.create!(:name => 'bar')
-
@project1 = @account1.projects.create!(:name => 'foobar')
- @project2 = @account2.projects.create!(:name => 'baz')
-
- ActsAsTenant.require_tenant
+ ActsAsTenant.configuration.stub(require_tenant: true)
end
-
+
it "should raise an error when no tenant is provided" do
expect { Project.all }.to raise_error
end
-
- after { Thread.current[:tenant_required] = nil }
end
end
-
-
-
+
context "no tenant required" do
describe "does not raise exception if no tenant specified" do
before do
@account1 = Account.create!(:name => 'foo')
- @account2 = Account.create!(:name => 'bar')
-
@project1 = @account1.projects.create!(:name => 'foobar')
- @project2 = @account2.projects.create!(:name => 'baz')
end
it "should not raise an error when no tenant is provided" do
- expect { Project.all }.should_not raise_error
+ expect { Project.all }.to_not raise_error
end
end
end
View
11 spec/spec_helper.rb
@@ -6,6 +6,8 @@
require 'logger'
require 'database_cleaner'
+require 'acts_as_tenant'
+require 'acts_as_tenant/configuration'
require 'acts_as_tenant/model_extensions'
require 'acts_as_tenant/controller_extensions'
@@ -16,15 +18,7 @@
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), "debug.log"))
ActiveRecord::Base.establish_connection(config[ENV['DB'] || 'sqlite'])
-# Requires supporting files with custom matchers and macros, etc,
-# in ./support/ and its subdirectories.
-#Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
-
-#RSpec.configure do |config|
-#end
-
RSpec.configure do |config|
-
config.before(:suite) do
DatabaseCleaner.strategy = :transaction
DatabaseCleaner.clean_with(:truncation)
@@ -36,6 +30,7 @@
config.after(:each) do
DatabaseCleaner.clean
+ ActsAsTenant.current_tenant = nil
end
end

0 comments on commit fbd28aa

Please sign in to comment.
Something went wrong with that request. Please try again.