rails_multitenant 0.11.0 → 0.15.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/LICENSE.txt +21 -0
- data/lib/rails_multitenant.rb +7 -4
- data/lib/rails_multitenant/global_context_registry.rb +43 -198
- data/lib/rails_multitenant/global_context_registry/current.rb +98 -0
- data/lib/rails_multitenant/global_context_registry/current_instance.rb +103 -0
- data/lib/rails_multitenant/global_context_registry/registry_dependent_on.rb +13 -0
- data/lib/rails_multitenant/middleware/extensions.rb +3 -3
- data/lib/rails_multitenant/middleware/isolated_context_registry.rb +2 -0
- data/lib/rails_multitenant/middleware/railtie.rb +3 -1
- data/lib/rails_multitenant/multitenant_model.rb +6 -2
- data/lib/rails_multitenant/rspec.rb +2 -0
- data/lib/rails_multitenant/version.rb +3 -1
- metadata +69 -76
- data/.gitignore +0 -14
- data/.rspec +0 -3
- data/.ruby-version +0 -1
- data/.travis.yml +0 -29
- data/CHANGELOG.md +0 -57
- data/CODE_OF_CONDUCT.md +0 -13
- data/Gemfile +0 -4
- data/README.md +0 -120
- data/Rakefile +0 -8
- data/bin/console +0 -14
- data/bin/setup +0 -7
- data/rails_multitenant.gemspec +0 -33
- data/spec/be_multitenant_on_matcher_spec.rb +0 -15
- data/spec/current_spec.rb +0 -118
- data/spec/db/database.yml +0 -3
- data/spec/db/schema.rb +0 -60
- data/spec/external_item_spec.rb +0 -36
- data/spec/external_item_with_optional_org_spec.rb +0 -25
- data/spec/global_context_registry_spec.rb +0 -113
- data/spec/item_spec.rb +0 -78
- data/spec/item_subtype_spec.rb +0 -37
- data/spec/item_with_optional_org_spec.rb +0 -26
- data/spec/middleware_isolated_context_registry_spec.rb +0 -15
- data/spec/rails_multitenant_spec.rb +0 -51
- data/spec/spec_helper.rb +0 -54
@@ -1,25 +0,0 @@
|
|
1
|
-
include RailsMultitenant
|
2
|
-
|
3
|
-
describe ExternalItemWithOptionalOrg do
|
4
|
-
|
5
|
-
let!(:external_item_without_org) { as_external_org(nil) { described_class.create! } }
|
6
|
-
|
7
|
-
let!(:external_item_with_org) { as_external_org(1) { described_class.create! } }
|
8
|
-
let!(:external_item_with_other_org) { as_external_org(2) { described_class.create! } }
|
9
|
-
|
10
|
-
specify 'the nil org has the correct external items' do
|
11
|
-
as_external_org(nil) do
|
12
|
-
expect(described_class.all).to eq([external_item_without_org])
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
specify 'org1 has the correct external items' do
|
17
|
-
as_external_org(1) do
|
18
|
-
expect(described_class.all).to eq([external_item_with_org])
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def as_external_org(id, &block)
|
23
|
-
GlobalContextRegistry.with_isolated_registry(external_organization_id: id, &block)
|
24
|
-
end
|
25
|
-
end
|
@@ -1,113 +0,0 @@
|
|
1
|
-
include RailsMultitenant
|
2
|
-
|
3
|
-
describe GlobalContextRegistry do
|
4
|
-
|
5
|
-
before do
|
6
|
-
# The framework will setup the organization; clear that out
|
7
|
-
GlobalContextRegistry.new_registry
|
8
|
-
GlobalContextRegistry.set(:foo, 'bar')
|
9
|
-
end
|
10
|
-
|
11
|
-
describe '.get and .set' do
|
12
|
-
specify do
|
13
|
-
expect(GlobalContextRegistry.get(:foo)).to eq 'bar'
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
describe '.[] and .[]=' do
|
18
|
-
before do
|
19
|
-
GlobalContextRegistry[:boo] = 'baz'
|
20
|
-
end
|
21
|
-
|
22
|
-
specify do
|
23
|
-
expect(GlobalContextRegistry[:boo]).to eq 'baz'
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
describe '.delete' do
|
28
|
-
specify do
|
29
|
-
expect(GlobalContextRegistry.delete(:foo)).to eq 'bar'
|
30
|
-
expect(GlobalContextRegistry.get(:foo)).to be_nil
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
describe '.with_isolated_registry' do
|
35
|
-
specify do
|
36
|
-
GlobalContextRegistry.with_isolated_registry do
|
37
|
-
expect(GlobalContextRegistry.get(:foo)).to be_nil
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
specify do
|
42
|
-
GlobalContextRegistry.with_isolated_registry(foo: 'updated') do
|
43
|
-
expect(GlobalContextRegistry.get(:foo)).to eq 'updated'
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
describe '.replace_registry and .new_registry' do
|
49
|
-
let!(:old_registry) { GlobalContextRegistry.new_registry }
|
50
|
-
|
51
|
-
specify do
|
52
|
-
expect(old_registry).to eq({ foo: 'bar' })
|
53
|
-
end
|
54
|
-
specify do
|
55
|
-
expect(GlobalContextRegistry.get(:foo)).to be_nil
|
56
|
-
end
|
57
|
-
specify do
|
58
|
-
GlobalContextRegistry.replace_registry(old_registry)
|
59
|
-
expect(GlobalContextRegistry.get(:foo)).to eq 'bar'
|
60
|
-
end
|
61
|
-
|
62
|
-
context 'when a new registry is specified' do
|
63
|
-
let!(:old_registry) { GlobalContextRegistry.new_registry(bar: 'foo') }
|
64
|
-
|
65
|
-
specify do
|
66
|
-
expect(old_registry).to eq({ foo: 'bar' })
|
67
|
-
end
|
68
|
-
specify do
|
69
|
-
expect(GlobalContextRegistry.get(:foo)).to be_nil
|
70
|
-
end
|
71
|
-
specify do
|
72
|
-
expect(GlobalContextRegistry.get(:bar)).to eq 'foo'
|
73
|
-
end
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
describe '.duplicate_registry' do
|
78
|
-
def setup_registry; end
|
79
|
-
|
80
|
-
before { setup_registry }
|
81
|
-
let!(:dupe) { GlobalContextRegistry.duplicate_registry }
|
82
|
-
|
83
|
-
specify do
|
84
|
-
expect(GlobalContextRegistry.new_registry).to eq dupe
|
85
|
-
end
|
86
|
-
specify do
|
87
|
-
expect(GlobalContextRegistry.new_registry.object_id).not_to eq dupe.object_id
|
88
|
-
end
|
89
|
-
specify do
|
90
|
-
expect(GlobalContextRegistry.get(:foo).object_id).not_to eq dupe[:foo].object_id
|
91
|
-
end
|
92
|
-
|
93
|
-
context 'with nils' do
|
94
|
-
def setup_registry
|
95
|
-
GlobalContextRegistry.set(:bar, nil)
|
96
|
-
end
|
97
|
-
|
98
|
-
specify do
|
99
|
-
expect(dupe).to eq GlobalContextRegistry.new_registry
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
context 'with integers' do
|
104
|
-
def setup_registry
|
105
|
-
GlobalContextRegistry.set(:bar, 5)
|
106
|
-
end
|
107
|
-
|
108
|
-
specify do
|
109
|
-
expect(dupe).to eq GlobalContextRegistry.new_registry
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
data/spec/item_spec.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
# Create multiple orgs
|
2
|
-
# Create an item in each
|
3
|
-
# Make sure you can only see one org's item in one org
|
4
|
-
|
5
|
-
describe Item do
|
6
|
-
|
7
|
-
let!(:item1) { Item.create! }
|
8
|
-
|
9
|
-
let!(:org2) { Organization.create! }
|
10
|
-
let!(:item2) { org2.as_current { Item.create! } }
|
11
|
-
let!(:item3) { org2.as_current { Item.create! } }
|
12
|
-
|
13
|
-
specify 'default org should have one item' do
|
14
|
-
expect(Item.all).to eq [ item1 ]
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'does not return item2' do
|
18
|
-
expect(Item.where(id: item2.id)).to eq []
|
19
|
-
end
|
20
|
-
|
21
|
-
specify 'org2 should have two items' do
|
22
|
-
org2.as_current do
|
23
|
-
expect(Item.all).to eq [ item2, item3]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
it 'does not return item1' do
|
28
|
-
org2.as_current do
|
29
|
-
expect(Item.where(id: item1.id)).to eq []
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
class DependentClass
|
34
|
-
include RailsMultitenant::GlobalContextRegistry::Current
|
35
|
-
global_context_dependent_on Organization
|
36
|
-
end
|
37
|
-
|
38
|
-
class SubOrganization < Organization
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
describe '.as_current' do
|
43
|
-
it 'returns the correct items with an org supplied' do
|
44
|
-
Organization.as_current(org2) do
|
45
|
-
expect(Item.all).to eq [ item2, item3]
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'allows a nil org to be supplied' do
|
50
|
-
Organization.as_current(nil) do
|
51
|
-
expect(Item.all).to eq []
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
it 'rejects models of the wrong type' do
|
56
|
-
model = Item.new
|
57
|
-
expect { Organization.as_current(model) {}}.to raise_error("#{model} is not a Organization")
|
58
|
-
end
|
59
|
-
|
60
|
-
it 'invalidates dependent models' do
|
61
|
-
DependentModel.current = DependentModel.create!
|
62
|
-
dependent = DependentModel.current
|
63
|
-
|
64
|
-
SubOrganization.create!.as_current do
|
65
|
-
expect(DependentModel.current).not_to equal(dependent)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
it 'invalidates dependent objects' do
|
70
|
-
dependent = DependentClass.current
|
71
|
-
|
72
|
-
SubOrganization.create!.as_current do
|
73
|
-
expect(DependentClass.current).not_to equal(dependent)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
|
78
|
-
end
|
data/spec/item_subtype_spec.rb
DELETED
@@ -1,37 +0,0 @@
|
|
1
|
-
# Create multiple orgs
|
2
|
-
# Create an item in each
|
3
|
-
# Make sure you can only see one org's item in one org
|
4
|
-
|
5
|
-
describe ItemSubtype do
|
6
|
-
|
7
|
-
let!(:item1) { ItemSubtype.create! }
|
8
|
-
|
9
|
-
let!(:org2) { Organization.create! }
|
10
|
-
let!(:item2) { org2.as_current { ItemSubtype.create! } }
|
11
|
-
let!(:item3) { org2.as_current { ItemSubtype.create! } }
|
12
|
-
|
13
|
-
it 'inherits the multitenant settings from its parent class' do
|
14
|
-
expect(ItemSubtype).to be_multitenant_on(:organization_id)
|
15
|
-
end
|
16
|
-
|
17
|
-
specify 'default org should have one item' do
|
18
|
-
expect(ItemSubtype.all).to eq([item1])
|
19
|
-
end
|
20
|
-
|
21
|
-
it 'does not return item2' do
|
22
|
-
expect(ItemSubtype.where(id: item2.id)).to eq([])
|
23
|
-
end
|
24
|
-
|
25
|
-
specify 'org2 should have two items' do
|
26
|
-
org2.as_current do
|
27
|
-
expect(ItemSubtype.all).to eq([item2, item3])
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
it 'does not return item1' do
|
32
|
-
org2.as_current do
|
33
|
-
expect(ItemSubtype.where(id: item1.id)).to eq([])
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
describe ItemWithOptionalOrg do
|
2
|
-
|
3
|
-
let!(:item_without_org) { without_org { described_class.create! } }
|
4
|
-
|
5
|
-
let!(:org) { Organization.create! }
|
6
|
-
let!(:item_with_org) { org.as_current { described_class.create! } }
|
7
|
-
|
8
|
-
let!(:other_org) { Organization.create! }
|
9
|
-
let!(:item_with_other_org) { other_org.as_current { described_class.create! } }
|
10
|
-
|
11
|
-
it "returns the correct items when no org is set" do
|
12
|
-
without_org do
|
13
|
-
expect(described_class.all).to eq([item_without_org])
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
it "returns the correct items when an org is set" do
|
18
|
-
org.as_current do
|
19
|
-
expect(described_class.all).to eq([item_with_org])
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def without_org(&block)
|
24
|
-
GlobalContextRegistry.with_isolated_registry(&block)
|
25
|
-
end
|
26
|
-
end
|
@@ -1,15 +0,0 @@
|
|
1
|
-
describe Middleware::IsolatedContextRegistry do
|
2
|
-
let(:payload) { [200, {'Content-Type' => 'text/plain'}, ['OK']] }
|
3
|
-
let(:app) { lambda { |env| env[2] = GlobalContextRegistry.get(:foo); env } }
|
4
|
-
let(:middleware) { described_class.new(app) }
|
5
|
-
|
6
|
-
describe '.call' do
|
7
|
-
specify do
|
8
|
-
GlobalContextRegistry.set(:foo, 'bar')
|
9
|
-
# Assert that a new global registry is created and read from, where :foo is not set
|
10
|
-
expect(middleware.call(payload)).to eq [200, {'Content-Type' => 'text/plain'}, nil]
|
11
|
-
# Assert that the outer global context registry is restored
|
12
|
-
expect(GlobalContextRegistry.get(:foo)).to eq 'bar'
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
@@ -1,51 +0,0 @@
|
|
1
|
-
describe "delegating to GlobalContextRegistry" do
|
2
|
-
it "RailsMultitenant.get returns values from the GlobalContextRegistry" do
|
3
|
-
RailsMultitenant::GlobalContextRegistry.set(:organization_id, 'Salsify Housing Authority')
|
4
|
-
|
5
|
-
expect(RailsMultitenant.get(:organization_id)).to eq('Salsify Housing Authority')
|
6
|
-
end
|
7
|
-
|
8
|
-
it "RailsMultitenant[] returns values from the GlobalContextRegistry" do
|
9
|
-
RailsMultitenant::GlobalContextRegistry.set(:organization_id, 'Salsify Farmland Inc.')
|
10
|
-
|
11
|
-
expect(RailsMultitenant[:organization_id]).to eq('Salsify Farmland Inc.')
|
12
|
-
end
|
13
|
-
|
14
|
-
it "RailsMultitenant.set assigns values in the GlobalContextRegistry" do
|
15
|
-
RailsMultitenant.set(:organization_id, 'Salsify Eminient Domain')
|
16
|
-
|
17
|
-
expect(RailsMultitenant::GlobalContextRegistry.get(:organization_id)).to eq('Salsify Eminient Domain')
|
18
|
-
end
|
19
|
-
|
20
|
-
it "RailsMultitenant[]= assigns values in the GlobalContextRegistry" do
|
21
|
-
RailsMultitenant[:organization_id] = 'Salsify Co-op'
|
22
|
-
|
23
|
-
expect(RailsMultitenant::GlobalContextRegistry[:organization_id]).to eq('Salsify Co-op')
|
24
|
-
end
|
25
|
-
|
26
|
-
it "RailsMultitenant.fetch checks and sets the GlobalContextRegistry" do
|
27
|
-
RailsMultitenant::GlobalContextRegistry[:organization_id] = nil
|
28
|
-
|
29
|
-
expect(RailsMultitenant.fetch(:organization_id) { 'Salsify Anarchists' }).to eq('Salsify Anarchists')
|
30
|
-
|
31
|
-
expect(RailsMultitenant.fetch(:organization_id) { 'Salsify Crypto Anarchists' }).to eq('Salsify Anarchists')
|
32
|
-
end
|
33
|
-
|
34
|
-
it "RailsMultitenant.delete removes from the GlobalContextRegistry" do
|
35
|
-
RailsMultitenant::GlobalContextRegistry[:organization_id] = 'Not Salsify'
|
36
|
-
|
37
|
-
RailsMultitenant.delete(:organization_id)
|
38
|
-
|
39
|
-
expect(RailsMultitenant.get(:organization_id)).to be_nil
|
40
|
-
end
|
41
|
-
|
42
|
-
it "RailsMultitenant.with_isolated_registry leverages the GlobalContextRegistry" do
|
43
|
-
RailsMultitenant::GlobalContextRegistry[:organization_id] = 'Salsify Mainland'
|
44
|
-
|
45
|
-
RailsMultitenant.with_isolated_registry({ organization_id: 'Salsify Private Island' }) do
|
46
|
-
expect(RailsMultitenant::GlobalContextRegistry[:organization_id]).to eq('Salsify Private Island')
|
47
|
-
end
|
48
|
-
|
49
|
-
expect(RailsMultitenant::GlobalContextRegistry[:organization_id]).to eq('Salsify Mainland')
|
50
|
-
end
|
51
|
-
end
|
data/spec/spec_helper.rb
DELETED
@@ -1,54 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
|
3
|
-
require 'simplecov'
|
4
|
-
require 'coveralls'
|
5
|
-
|
6
|
-
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new([
|
7
|
-
SimpleCov::Formatter::HTMLFormatter,
|
8
|
-
Coveralls::SimpleCov::Formatter
|
9
|
-
])
|
10
|
-
SimpleCov.start do
|
11
|
-
add_filter 'spec'
|
12
|
-
end
|
13
|
-
|
14
|
-
require 'active_record'
|
15
|
-
if ActiveRecord::VERSION::MAJOR >= 5
|
16
|
-
ActiveRecord::Base.belongs_to_required_by_default = true
|
17
|
-
end
|
18
|
-
|
19
|
-
require 'logger'
|
20
|
-
require 'database_cleaner'
|
21
|
-
require 'rails_multitenant'
|
22
|
-
require 'yaml'
|
23
|
-
|
24
|
-
FileUtils.makedirs('log')
|
25
|
-
|
26
|
-
ActiveRecord::Base.logger = Logger.new('log/test.log')
|
27
|
-
ActiveRecord::Base.logger.level = Logger::DEBUG
|
28
|
-
ActiveRecord::Migration.verbose = false
|
29
|
-
|
30
|
-
db_adapter = ENV.fetch('ADAPTER', 'sqlite3')
|
31
|
-
config = YAML.load(File.read('spec/db/database.yml'))
|
32
|
-
ActiveRecord::Base.establish_connection(config[db_adapter])
|
33
|
-
require 'db/schema'
|
34
|
-
|
35
|
-
RSpec.configure do |config|
|
36
|
-
config.order = 'random'
|
37
|
-
|
38
|
-
config.before(:suite) do
|
39
|
-
DatabaseCleaner.clean_with(:truncation)
|
40
|
-
end
|
41
|
-
|
42
|
-
config.before(:each) do
|
43
|
-
DatabaseCleaner.strategy = :transaction
|
44
|
-
DatabaseCleaner.start
|
45
|
-
RailsMultitenant::GlobalContextRegistry.new_registry
|
46
|
-
Organization.current_id = Organization.create!.id
|
47
|
-
end
|
48
|
-
|
49
|
-
config.after(:each) do
|
50
|
-
DatabaseCleaner.clean
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
puts "Testing with Ruby #{RUBY_VERSION} and ActiveRecord #{ActiveRecord::VERSION::STRING}"
|