rails_multitenant 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|