rails_multitenant 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +6 -0
- data/Rakefile +8 -1
- data/lib/rails_multitenant/global_context_registry.rb +8 -6
- data/lib/rails_multitenant/multitenant_model.rb +15 -13
- data/lib/rails_multitenant/rspec.rb +5 -0
- data/lib/rails_multitenant/version.rb +1 -1
- data/lib/rails_multitenant.rb +2 -0
- data/spec/be_multitenant_on_matcher_spec.rb +12 -0
- data/spec/db/schema.rb +12 -6
- data/spec/external_item_spec.rb +33 -0
- data/spec/global_context_registry_spec.rb +16 -0
- data/spec/item_spec.rb +4 -4
- data/spec/spec_helper.rb +1 -5
- metadata +8 -3
- data/log/test.log +0 -875
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7fa50760b463e1f9b31abc6a19d13e863dc5604a
|
4
|
+
data.tar.gz: 7af84280e893555c5c40a4e55cfad57bba8d4252
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7aca78e340f93da77d625dae54d1c372053fe732032ec7f4acf2b651a436d75fa502895ef212df9a37318a080bf683fa0d4ed785301138bc79ff70d20d06be3
|
7
|
+
data.tar.gz: 91f20b900cd76a6e8afae4ebd8d239b456c74ea1cc0170d660e05109156ac2b28c459fd330c54d56169de7efda6ee935489f1b64fc8697d3e69ed86c33181558
|
data/CHANGELOG.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# Changelog
|
2
|
+
|
3
|
+
### 0.2.0 (unreleased)
|
4
|
+
* Merged [PR 2](https://github.com/salsify/rails-multitenant/pull/2) which adds support for
|
5
|
+
multi-tenancy based on a foreign key to an external model. As part of this the `multitenant_model_on`
|
6
|
+
method was renamed to `multitenant_on_model`.
|
data/Rakefile
CHANGED
@@ -39,7 +39,7 @@ module RailsMultitenant
|
|
39
39
|
|
40
40
|
def current_registry_obj
|
41
41
|
key_class = respond_to?(:base_class) ? base_class : self
|
42
|
-
"#{key_class.name.
|
42
|
+
"#{key_class.name.underscore}_obj".to_sym
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
@@ -103,12 +103,12 @@ module RailsMultitenant
|
|
103
103
|
|
104
104
|
def current_instance_registry_id
|
105
105
|
key_class = respond_to?(:base_class) ? base_class : self
|
106
|
-
"#{key_class.name.
|
106
|
+
"#{key_class.name.underscore}_id".to_sym
|
107
107
|
end
|
108
108
|
|
109
109
|
def current_instance_registry_obj
|
110
110
|
key_class = respond_to?(:base_class) ? base_class : self
|
111
|
-
"#{key_class.name.
|
111
|
+
"#{key_class.name.underscore}_obj".to_sym
|
112
112
|
end
|
113
113
|
|
114
114
|
include RegistryDependentOn
|
@@ -132,6 +132,7 @@ module RailsMultitenant
|
|
132
132
|
def set(symbol, value)
|
133
133
|
globals[symbol] = value
|
134
134
|
end
|
135
|
+
alias_method :[]=, :set
|
135
136
|
|
136
137
|
# delete this global
|
137
138
|
def delete(symbol)
|
@@ -152,6 +153,7 @@ module RailsMultitenant
|
|
152
153
|
def get(symbol)
|
153
154
|
globals[symbol]
|
154
155
|
end
|
156
|
+
alias_method :[], :get
|
155
157
|
|
156
158
|
# Duplicate the registry
|
157
159
|
def duplicate_registry
|
@@ -160,10 +162,10 @@ module RailsMultitenant
|
|
160
162
|
end
|
161
163
|
end
|
162
164
|
|
163
|
-
# Run a block of code with an
|
164
|
-
def with_isolated_registry
|
165
|
+
# Run a block of code with an the given registry
|
166
|
+
def with_isolated_registry(registry = {})
|
165
167
|
prior_globals = globals
|
166
|
-
self.globals =
|
168
|
+
self.globals = registry
|
167
169
|
yield
|
168
170
|
ensure
|
169
171
|
self.globals = prior_globals
|
@@ -1,14 +1,6 @@
|
|
1
1
|
module RailsMultitenant
|
2
2
|
module MultitenantModel
|
3
3
|
extend ActiveSupport::Concern
|
4
|
-
=begin
|
5
|
-
included do
|
6
|
-
belongs_to :organization
|
7
|
-
validates_presence_of :organization_id
|
8
|
-
scope :from_current_org, -> { where(organization_id: Organization.current_id) }
|
9
|
-
default_scope { from_current_org }
|
10
|
-
end
|
11
|
-
=end
|
12
4
|
|
13
5
|
included do
|
14
6
|
class << self
|
@@ -18,19 +10,29 @@ module RailsMultitenant
|
|
18
10
|
|
19
11
|
module ClassMethods
|
20
12
|
|
21
|
-
def
|
22
|
-
|
13
|
+
def multitenant_on(context_entity_id_field)
|
14
|
+
self.context_entity_id_field = context_entity_id_field
|
15
|
+
validates_presence_of context_entity_id_field
|
16
|
+
|
17
|
+
context_entity = context_entity_id_field.to_s.gsub(/_id$/, '')
|
23
18
|
scope_sym = "from_current_#{context_entity}".to_sym
|
24
19
|
|
25
|
-
|
26
|
-
|
27
|
-
|
20
|
+
scope scope_sym, -> do
|
21
|
+
where(context_entity_id_field => GlobalContextRegistry[context_entity_id_field])
|
22
|
+
end
|
23
|
+
|
28
24
|
default_scope { send(scope_sym) }
|
25
|
+
|
29
26
|
define_method "strip_#{context_entity}_scope" do
|
30
27
|
unscope(where: context_entity_id_field)
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
31
|
+
def multitenant_on_model(context_entity)
|
32
|
+
multitenant_on("#{context_entity}_id".to_sym)
|
33
|
+
belongs_to context_entity
|
34
|
+
end
|
35
|
+
|
34
36
|
def validates_multitenant_uniqueness_of(*attr_names)
|
35
37
|
options = attr_names.extract_options!.symbolize_keys
|
36
38
|
existing_scope = Array.wrap(options.delete(:scope))
|
data/lib/rails_multitenant.rb
CHANGED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'rails_multitenant/rspec'
|
3
|
+
|
4
|
+
describe "be_multitenant_on matcher" do
|
5
|
+
it "accepts a valid context field id" do
|
6
|
+
expect(ExternalItem).to be_multitenant_on(:external_organization_id)
|
7
|
+
end
|
8
|
+
|
9
|
+
it "rejects an invalid context field id" do
|
10
|
+
expect(ExternalItem).not_to be_multitenant_on(:other_field)
|
11
|
+
end
|
12
|
+
end
|
data/spec/db/schema.rb
CHANGED
@@ -1,16 +1,16 @@
|
|
1
1
|
# encoding: UTF-8
|
2
2
|
|
3
|
-
ActiveRecord::Schema.define(:
|
3
|
+
ActiveRecord::Schema.define(version: 0) do
|
4
4
|
|
5
|
-
create_table(:organizations, force: true)
|
6
|
-
t.string :name
|
7
|
-
end
|
5
|
+
create_table(:organizations, force: true)
|
8
6
|
|
9
7
|
create_table(:items, force: true) do |t|
|
10
|
-
t.string :name
|
11
8
|
t.integer :organization_id
|
12
9
|
end
|
13
10
|
|
11
|
+
create_table(:external_items, force: true) do |t|
|
12
|
+
t.integer :external_organization_id
|
13
|
+
end
|
14
14
|
end
|
15
15
|
|
16
16
|
class Organization < ActiveRecord::Base
|
@@ -19,5 +19,11 @@ end
|
|
19
19
|
|
20
20
|
class Item < ActiveRecord::Base
|
21
21
|
include RailsMultitenant::MultitenantModel
|
22
|
-
|
22
|
+
multitenant_on_model :organization
|
23
|
+
end
|
24
|
+
|
25
|
+
class ExternalItem < ActiveRecord::Base
|
26
|
+
include RailsMultitenant::MultitenantModel
|
27
|
+
multitenant_on :external_organization_id
|
23
28
|
end
|
29
|
+
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
include RailsMultitenant
|
3
|
+
|
4
|
+
describe ExternalItem do
|
5
|
+
|
6
|
+
let!(:external_item1) { as_external_org(1) { ExternalItem.create! } }
|
7
|
+
|
8
|
+
let!(:external_item2) { as_external_org(2) { ExternalItem.create! } }
|
9
|
+
let!(:external_item3) { as_external_org(2) { ExternalItem.create! } }
|
10
|
+
|
11
|
+
specify 'org1 has the correct external items' do
|
12
|
+
as_external_org(1) do
|
13
|
+
expect(ExternalItem.all).to eq [external_item1]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
specify 'org2 has the correct external items' do
|
18
|
+
as_external_org(2) do
|
19
|
+
expect(ExternalItem.all).to match_array [external_item2, external_item3]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'does not return external items from other orgs' do
|
24
|
+
as_external_org(2) do
|
25
|
+
expect(ExternalItem.where(id: external_item1.id)).to eq []
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def as_external_org(id, &block)
|
30
|
+
GlobalContextRegistry.with_isolated_registry(external_organization_id: id, &block)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -15,6 +15,16 @@ describe GlobalContextRegistry do
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
+
describe '.[] and .[]=' do
|
19
|
+
before do
|
20
|
+
GlobalContextRegistry[:boo] = 'baz'
|
21
|
+
end
|
22
|
+
|
23
|
+
specify do
|
24
|
+
expect(GlobalContextRegistry[:boo]).to eq 'baz'
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
18
28
|
describe '.delete' do
|
19
29
|
specify do
|
20
30
|
expect(GlobalContextRegistry.delete(:foo)).to eq 'bar'
|
@@ -28,6 +38,12 @@ describe GlobalContextRegistry do
|
|
28
38
|
expect(GlobalContextRegistry.get(:foo)).to be_nil
|
29
39
|
end
|
30
40
|
end
|
41
|
+
|
42
|
+
specify do
|
43
|
+
GlobalContextRegistry.with_isolated_registry(foo: 'updated') do
|
44
|
+
expect(GlobalContextRegistry.get(:foo)).to eq 'updated'
|
45
|
+
end
|
46
|
+
end
|
31
47
|
end
|
32
48
|
|
33
49
|
describe '.replace_registry and .new_registry' do
|
data/spec/item_spec.rb
CHANGED
@@ -6,11 +6,11 @@ require 'spec_helper'
|
|
6
6
|
|
7
7
|
describe Item do
|
8
8
|
|
9
|
-
let!(:item1) { Item.create
|
9
|
+
let!(:item1) { Item.create! }
|
10
10
|
|
11
|
-
let!(:org2) { Organization.create
|
12
|
-
let!(:item2) { org2.as_current { Item.create
|
13
|
-
let!(:item3) { org2.as_current { Item.create
|
11
|
+
let!(:org2) { Organization.create! }
|
12
|
+
let!(:item2) { org2.as_current { Item.create! } }
|
13
|
+
let!(:item3) { org2.as_current { Item.create! } }
|
14
14
|
|
15
15
|
specify 'default org should have one item' do
|
16
16
|
expect(Item.all).to eq [ item1 ]
|
data/spec/spec_helper.rb
CHANGED
@@ -30,8 +30,6 @@ require 'db/schema'
|
|
30
30
|
RSpec.configure do |config|
|
31
31
|
config.order = 'random'
|
32
32
|
|
33
|
-
config.add_setting :test_org_id
|
34
|
-
|
35
33
|
config.before(:suite) do
|
36
34
|
DatabaseCleaner.clean_with(:truncation)
|
37
35
|
end
|
@@ -40,9 +38,7 @@ RSpec.configure do |config|
|
|
40
38
|
DatabaseCleaner.strategy = :transaction
|
41
39
|
DatabaseCleaner.start
|
42
40
|
RailsMultitenant::GlobalContextRegistry.new_registry
|
43
|
-
|
44
|
-
RSpec.configuration.test_org_id = org.id
|
45
|
-
Organization.current_id = RSpec.configuration.test_org_id
|
41
|
+
Organization.current_id = Organization.create!.id
|
46
42
|
end
|
47
43
|
|
48
44
|
config.after(:each) do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_multitenant
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pat Breault
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -158,6 +158,7 @@ files:
|
|
158
158
|
- ".gitignore"
|
159
159
|
- ".ruby-version"
|
160
160
|
- ".travis.yml"
|
161
|
+
- CHANGELOG.md
|
161
162
|
- CODE_OF_CONDUCT.md
|
162
163
|
- Gemfile
|
163
164
|
- README.md
|
@@ -167,11 +168,13 @@ files:
|
|
167
168
|
- lib/rails_multitenant.rb
|
168
169
|
- lib/rails_multitenant/global_context_registry.rb
|
169
170
|
- lib/rails_multitenant/multitenant_model.rb
|
171
|
+
- lib/rails_multitenant/rspec.rb
|
170
172
|
- lib/rails_multitenant/version.rb
|
171
|
-
- log/test.log
|
172
173
|
- rails_multitenant.gemspec
|
174
|
+
- spec/be_multitenant_on_matcher_spec.rb
|
173
175
|
- spec/db/database.yml
|
174
176
|
- spec/db/schema.rb
|
177
|
+
- spec/external_item_spec.rb
|
175
178
|
- spec/global_context_registry_spec.rb
|
176
179
|
- spec/item_spec.rb
|
177
180
|
- spec/spec_helper.rb
|
@@ -200,8 +203,10 @@ signing_key:
|
|
200
203
|
specification_version: 4
|
201
204
|
summary: Automatically configures multiple tenants in a Rails environment
|
202
205
|
test_files:
|
206
|
+
- spec/be_multitenant_on_matcher_spec.rb
|
203
207
|
- spec/db/database.yml
|
204
208
|
- spec/db/schema.rb
|
209
|
+
- spec/external_item_spec.rb
|
205
210
|
- spec/global_context_registry_spec.rb
|
206
211
|
- spec/item_spec.rb
|
207
212
|
- spec/spec_helper.rb
|