rails_multitenant 0.13.0 → 0.14.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/lib/rails_multitenant/global_context_registry.rb +27 -199
- 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/multitenant_model.rb +3 -1
- data/lib/rails_multitenant/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7cee7c42f683984c490e56705e9de15107c6cdca9458abae424e733907450d1e
|
4
|
+
data.tar.gz: 0be7d4f76a8ba047e66b4316d601f507c4c2c0b97bad4015dff06e8368280bc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cb2fb69f85325ddc3a05af7a26a244e1a40fe2c7eb5082711bd3c33f3ff27339fb911d80f5b689dcc86f5d3842bc450aa31c78901afb3926041ce5711d594ccc
|
7
|
+
data.tar.gz: 4bb540fec11d2f8eaa77468bd7b35cf3d823ce35f4c057757c136b581dd0935455ad62b2245cf3425806f4ea176d04c5adb9c3b2acbcdcf5381c3ebf3d52df8a
|
@@ -1,5 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'global_context_registry/current'
|
4
|
+
require_relative 'global_context_registry/current_instance'
|
5
|
+
require_relative 'global_context_registry/registry_dependent_on'
|
6
|
+
|
3
7
|
# Handles storing of global state that may be swapped out or unset at
|
4
8
|
# various points. We use this in dandelion to store the current user,
|
5
9
|
# org, catalog, etc.
|
@@ -8,207 +12,8 @@
|
|
8
12
|
#
|
9
13
|
module RailsMultitenant
|
10
14
|
module GlobalContextRegistry
|
11
|
-
|
12
15
|
extend self
|
13
16
|
|
14
|
-
module RegistryDependentOn
|
15
|
-
|
16
|
-
# Is this class dependent on changes in another GlobalContextRegistry-
|
17
|
-
# stored object? Register that dependency here.
|
18
|
-
def global_context_dependent_on(*klasses)
|
19
|
-
klasses.each { |klass| GlobalContextRegistry.send(:add_dependency, klass, self) }
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
# This module allows your to have a current, thread-local instance
|
24
|
-
# of this class. It currently assumes your class has a zero-arg
|
25
|
-
# constructor.
|
26
|
-
module Current
|
27
|
-
extend ActiveSupport::Concern
|
28
|
-
|
29
|
-
included do
|
30
|
-
class_attribute :default_provider, instance_writer: false
|
31
|
-
end
|
32
|
-
|
33
|
-
module ClassMethods
|
34
|
-
def current
|
35
|
-
GlobalContextRegistry.fetch(current_registry_obj) { __current_default }
|
36
|
-
end
|
37
|
-
|
38
|
-
def current=(object)
|
39
|
-
raise "#{object} is not a #{self}" if object.present? && !object.is_a?(self)
|
40
|
-
|
41
|
-
GlobalContextRegistry.set(current_registry_obj, object)
|
42
|
-
__clear_dependents!
|
43
|
-
end
|
44
|
-
|
45
|
-
def current?
|
46
|
-
GlobalContextRegistry.get(current_registry_obj).present?
|
47
|
-
end
|
48
|
-
|
49
|
-
def current!
|
50
|
-
current || raise("No current #{name} set")
|
51
|
-
end
|
52
|
-
|
53
|
-
def clear_current!
|
54
|
-
GlobalContextRegistry.delete(current_registry_obj)
|
55
|
-
end
|
56
|
-
|
57
|
-
def as_current(object)
|
58
|
-
old_object = current if current?
|
59
|
-
self.current = object
|
60
|
-
yield
|
61
|
-
ensure
|
62
|
-
self.current = old_object
|
63
|
-
end
|
64
|
-
|
65
|
-
include RegistryDependentOn
|
66
|
-
|
67
|
-
def provide_default(provider = nil, &block)
|
68
|
-
self.default_provider = provider ? provider.to_proc : block
|
69
|
-
end
|
70
|
-
|
71
|
-
private
|
72
|
-
|
73
|
-
def current_registry_obj
|
74
|
-
return @current_registry_obj if @current_registry_obj
|
75
|
-
|
76
|
-
@current_registry_obj = "#{__key_class.name.underscore}_obj".to_sym
|
77
|
-
end
|
78
|
-
|
79
|
-
def current_registry_default_provider
|
80
|
-
"#{__key_class.name.underscore}_default_provider".to_sym
|
81
|
-
end
|
82
|
-
|
83
|
-
def __current_default
|
84
|
-
if default_provider
|
85
|
-
default = default_provider.call(self)
|
86
|
-
raise "#{default} is not a #{self}" if default.present? && !default.is_a?(self)
|
87
|
-
|
88
|
-
default
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def __clear_dependents!
|
93
|
-
GlobalContextRegistry.send(:dependencies_for, __key_class).each(&:clear_current!)
|
94
|
-
end
|
95
|
-
|
96
|
-
def __key_class
|
97
|
-
respond_to?(:base_class) ? base_class : self
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def as_current
|
102
|
-
old_object = self.class.current if self.class.current?
|
103
|
-
self.class.current = self
|
104
|
-
yield
|
105
|
-
ensure
|
106
|
-
self.class.current = old_object
|
107
|
-
end
|
108
|
-
|
109
|
-
def current?
|
110
|
-
self.class.current? && equal?(self.class.current)
|
111
|
-
end
|
112
|
-
|
113
|
-
end
|
114
|
-
|
115
|
-
# This module allows you to have a current, thread-local instance
|
116
|
-
# of a class. This module assumes that you are mixing into a Rails
|
117
|
-
# model, and separately stores and id in thread local storage for
|
118
|
-
# lazy loading.
|
119
|
-
module CurrentInstance
|
120
|
-
extend ActiveSupport::Concern
|
121
|
-
|
122
|
-
module ClassMethods
|
123
|
-
def current_id=(id)
|
124
|
-
GlobalContextRegistry.delete(current_instance_registry_obj)
|
125
|
-
GlobalContextRegistry.set(current_instance_registry_id, id)
|
126
|
-
__clear_dependents!
|
127
|
-
end
|
128
|
-
|
129
|
-
def current=(object)
|
130
|
-
raise "#{object} is not a #{self}" if object.present? && !object.is_a?(self)
|
131
|
-
|
132
|
-
GlobalContextRegistry.set(current_instance_registry_obj, object)
|
133
|
-
GlobalContextRegistry.set(current_instance_registry_id, object.try(:id))
|
134
|
-
__clear_dependents!
|
135
|
-
end
|
136
|
-
|
137
|
-
def current_id
|
138
|
-
GlobalContextRegistry.get(current_instance_registry_id)
|
139
|
-
end
|
140
|
-
|
141
|
-
def current
|
142
|
-
GlobalContextRegistry.fetch(current_instance_registry_obj) do
|
143
|
-
(current_id ? find(current_id) : nil)
|
144
|
-
end
|
145
|
-
end
|
146
|
-
|
147
|
-
def current?
|
148
|
-
!!current
|
149
|
-
end
|
150
|
-
|
151
|
-
def current!
|
152
|
-
current || raise("No current #{name} set")
|
153
|
-
end
|
154
|
-
|
155
|
-
def as_current_id(id)
|
156
|
-
old_id = current_id
|
157
|
-
self.current_id = id
|
158
|
-
yield
|
159
|
-
ensure
|
160
|
-
self.current_id = old_id
|
161
|
-
end
|
162
|
-
|
163
|
-
def as_current(model)
|
164
|
-
old_model = current
|
165
|
-
self.current = model
|
166
|
-
yield
|
167
|
-
ensure
|
168
|
-
self.current = old_model
|
169
|
-
end
|
170
|
-
|
171
|
-
def clear_current!
|
172
|
-
GlobalContextRegistry.delete(current_instance_registry_obj)
|
173
|
-
end
|
174
|
-
|
175
|
-
private
|
176
|
-
|
177
|
-
def __clear_dependents!
|
178
|
-
key_class = respond_to?(:base_class) ? base_class : self
|
179
|
-
GlobalContextRegistry.send(:dependencies_for, key_class).each(&:clear_current!)
|
180
|
-
end
|
181
|
-
|
182
|
-
def current_instance_registry_id
|
183
|
-
return @current_instance_registry_id if @current_instance_registry_id
|
184
|
-
|
185
|
-
key_class = respond_to?(:base_class) ? base_class : self
|
186
|
-
@current_instance_registry_id = "#{key_class.name.underscore}_id".to_sym
|
187
|
-
end
|
188
|
-
|
189
|
-
def current_instance_registry_obj
|
190
|
-
return @current_instance_registry_obj if @current_instance_registry_obj
|
191
|
-
|
192
|
-
key_class = respond_to?(:base_class) ? base_class : self
|
193
|
-
@current_instance_registry_obj = "#{key_class.name.underscore}_obj".to_sym
|
194
|
-
end
|
195
|
-
include RegistryDependentOn
|
196
|
-
end
|
197
|
-
|
198
|
-
def as_current
|
199
|
-
old_id = self.class.current_id
|
200
|
-
self.class.current = self
|
201
|
-
yield
|
202
|
-
ensure
|
203
|
-
self.class.current_id = old_id
|
204
|
-
end
|
205
|
-
|
206
|
-
def current?
|
207
|
-
id == self.class.current_id
|
208
|
-
end
|
209
|
-
|
210
|
-
end
|
211
|
-
|
212
17
|
# Set this global
|
213
18
|
def set(symbol, value)
|
214
19
|
globals[symbol] = value
|
@@ -280,6 +85,29 @@ module RailsMultitenant
|
|
280
85
|
self.globals = registry
|
281
86
|
end
|
282
87
|
|
88
|
+
# Run a block of code that disregards scoping during read queries
|
89
|
+
def with_unscoped_queries
|
90
|
+
with_merged_registry(__use_unscoped_queries: true) do
|
91
|
+
yield
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def use_unscoped_queries?
|
96
|
+
self[:__use_unscoped_queries] == true
|
97
|
+
end
|
98
|
+
|
99
|
+
# Prefer .with_unscoped_queries to the following two methods.
|
100
|
+
# Note: these methods are intended for use in a manner like .with_admin_registry,
|
101
|
+
# but in contexts where around semantics are not allowed.
|
102
|
+
|
103
|
+
def disable_scoped_queries
|
104
|
+
self[:__use_unscoped_queries] = true
|
105
|
+
end
|
106
|
+
|
107
|
+
def enable_scoped_queries
|
108
|
+
self[:__use_unscoped_queries] = nil
|
109
|
+
end
|
110
|
+
|
283
111
|
private
|
284
112
|
|
285
113
|
@dependencies = {}
|
@@ -0,0 +1,98 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'registry_dependent_on'
|
4
|
+
|
5
|
+
module RailsMultitenant
|
6
|
+
module GlobalContextRegistry
|
7
|
+
# This module allows your to have a current, thread-local instance
|
8
|
+
# of this class. It currently assumes your class has a zero-arg
|
9
|
+
# constructor.
|
10
|
+
module Current
|
11
|
+
extend ActiveSupport::Concern
|
12
|
+
|
13
|
+
included do
|
14
|
+
class_attribute :default_provider, instance_writer: false
|
15
|
+
end
|
16
|
+
|
17
|
+
module ClassMethods
|
18
|
+
def current
|
19
|
+
GlobalContextRegistry.fetch(current_registry_obj) { __current_default }
|
20
|
+
end
|
21
|
+
|
22
|
+
def current=(object)
|
23
|
+
raise "#{object} is not a #{self}" if object.present? && !object.is_a?(self)
|
24
|
+
|
25
|
+
GlobalContextRegistry.set(current_registry_obj, object)
|
26
|
+
__clear_dependents!
|
27
|
+
end
|
28
|
+
|
29
|
+
def current?
|
30
|
+
GlobalContextRegistry.get(current_registry_obj).present?
|
31
|
+
end
|
32
|
+
|
33
|
+
def current!
|
34
|
+
current || raise("No current #{name} set")
|
35
|
+
end
|
36
|
+
|
37
|
+
def clear_current!
|
38
|
+
GlobalContextRegistry.delete(current_registry_obj)
|
39
|
+
end
|
40
|
+
|
41
|
+
def as_current(object)
|
42
|
+
old_object = current if current?
|
43
|
+
self.current = object
|
44
|
+
yield
|
45
|
+
ensure
|
46
|
+
self.current = old_object
|
47
|
+
end
|
48
|
+
|
49
|
+
include RegistryDependentOn
|
50
|
+
|
51
|
+
def provide_default(provider = nil, &block)
|
52
|
+
self.default_provider = provider ? provider.to_proc : block
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def current_registry_obj
|
58
|
+
return @current_registry_obj if @current_registry_obj
|
59
|
+
|
60
|
+
@current_registry_obj = "#{__key_class.name.underscore}_obj".to_sym
|
61
|
+
end
|
62
|
+
|
63
|
+
def current_registry_default_provider
|
64
|
+
"#{__key_class.name.underscore}_default_provider".to_sym
|
65
|
+
end
|
66
|
+
|
67
|
+
def __current_default
|
68
|
+
if default_provider
|
69
|
+
default = default_provider.call(self)
|
70
|
+
raise "#{default} is not a #{self}" if default.present? && !default.is_a?(self)
|
71
|
+
|
72
|
+
default
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def __clear_dependents!
|
77
|
+
GlobalContextRegistry.send(:dependencies_for, __key_class).each(&:clear_current!)
|
78
|
+
end
|
79
|
+
|
80
|
+
def __key_class
|
81
|
+
respond_to?(:base_class) ? base_class : self
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def as_current
|
86
|
+
old_object = self.class.current if self.class.current?
|
87
|
+
self.class.current = self
|
88
|
+
yield
|
89
|
+
ensure
|
90
|
+
self.class.current = old_object
|
91
|
+
end
|
92
|
+
|
93
|
+
def current?
|
94
|
+
self.class.current? && equal?(self.class.current)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'registry_dependent_on'
|
4
|
+
|
5
|
+
module RailsMultitenant
|
6
|
+
module GlobalContextRegistry
|
7
|
+
# This module allows you to have a current, thread-local instance
|
8
|
+
# of a class. This module assumes that you are mixing into a Rails
|
9
|
+
# model, and separately stores and id in thread local storage for
|
10
|
+
# lazy loading.
|
11
|
+
module CurrentInstance
|
12
|
+
extend ActiveSupport::Concern
|
13
|
+
|
14
|
+
module ClassMethods
|
15
|
+
def current_id=(id)
|
16
|
+
GlobalContextRegistry.delete(current_instance_registry_obj)
|
17
|
+
GlobalContextRegistry.set(current_instance_registry_id, id)
|
18
|
+
__clear_dependents!
|
19
|
+
end
|
20
|
+
|
21
|
+
def current=(object)
|
22
|
+
raise "#{object} is not a #{self}" if object.present? && !object.is_a?(self)
|
23
|
+
|
24
|
+
GlobalContextRegistry.set(current_instance_registry_obj, object)
|
25
|
+
GlobalContextRegistry.set(current_instance_registry_id, object.try(:id))
|
26
|
+
__clear_dependents!
|
27
|
+
end
|
28
|
+
|
29
|
+
def current_id
|
30
|
+
GlobalContextRegistry.get(current_instance_registry_id)
|
31
|
+
end
|
32
|
+
|
33
|
+
def current
|
34
|
+
GlobalContextRegistry.fetch(current_instance_registry_obj) do
|
35
|
+
(current_id ? find(current_id) : nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def current?
|
40
|
+
!!current
|
41
|
+
end
|
42
|
+
|
43
|
+
def current!
|
44
|
+
current || raise("No current #{name} set")
|
45
|
+
end
|
46
|
+
|
47
|
+
def as_current_id(id)
|
48
|
+
old_id = current_id
|
49
|
+
self.current_id = id
|
50
|
+
yield
|
51
|
+
ensure
|
52
|
+
self.current_id = old_id
|
53
|
+
end
|
54
|
+
|
55
|
+
def as_current(model)
|
56
|
+
old_model = current
|
57
|
+
self.current = model
|
58
|
+
yield
|
59
|
+
ensure
|
60
|
+
self.current = old_model
|
61
|
+
end
|
62
|
+
|
63
|
+
def clear_current!
|
64
|
+
GlobalContextRegistry.delete(current_instance_registry_obj)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
def __clear_dependents!
|
70
|
+
key_class = respond_to?(:base_class) ? base_class : self
|
71
|
+
GlobalContextRegistry.send(:dependencies_for, key_class).each(&:clear_current!)
|
72
|
+
end
|
73
|
+
|
74
|
+
def current_instance_registry_id
|
75
|
+
return @current_instance_registry_id if @current_instance_registry_id
|
76
|
+
|
77
|
+
key_class = respond_to?(:base_class) ? base_class : self
|
78
|
+
@current_instance_registry_id = "#{key_class.name.underscore}_id".to_sym
|
79
|
+
end
|
80
|
+
|
81
|
+
def current_instance_registry_obj
|
82
|
+
return @current_instance_registry_obj if @current_instance_registry_obj
|
83
|
+
|
84
|
+
key_class = respond_to?(:base_class) ? base_class : self
|
85
|
+
@current_instance_registry_obj = "#{key_class.name.underscore}_obj".to_sym
|
86
|
+
end
|
87
|
+
include RegistryDependentOn
|
88
|
+
end
|
89
|
+
|
90
|
+
def as_current
|
91
|
+
old_id = self.class.current_id
|
92
|
+
self.class.current = self
|
93
|
+
yield
|
94
|
+
ensure
|
95
|
+
self.class.current_id = old_id
|
96
|
+
end
|
97
|
+
|
98
|
+
def current?
|
99
|
+
id == self.class.current_id
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RailsMultitenant
|
4
|
+
module GlobalContextRegistry
|
5
|
+
module RegistryDependentOn
|
6
|
+
# Is this class dependent on changes in another GlobalContextRegistry-
|
7
|
+
# stored object? Register that dependency here.
|
8
|
+
def global_context_dependent_on(*klasses)
|
9
|
+
klasses.each { |klass| GlobalContextRegistry.send(:add_dependency, klass, self) }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -18,7 +18,9 @@ module RailsMultitenant
|
|
18
18
|
scope_sym = "from_current_#{context_entity}".to_sym
|
19
19
|
|
20
20
|
scope scope_sym, -> do
|
21
|
-
|
21
|
+
unless GlobalContextRegistry.use_unscoped_queries?
|
22
|
+
where(context_entity_id_field => GlobalContextRegistry[context_entity_id_field])
|
23
|
+
end
|
22
24
|
end
|
23
25
|
|
24
26
|
default_scope { send(scope_sym) }
|
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.14.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: 2020-04-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -172,6 +172,9 @@ files:
|
|
172
172
|
- LICENSE.txt
|
173
173
|
- lib/rails_multitenant.rb
|
174
174
|
- lib/rails_multitenant/global_context_registry.rb
|
175
|
+
- lib/rails_multitenant/global_context_registry/current.rb
|
176
|
+
- lib/rails_multitenant/global_context_registry/current_instance.rb
|
177
|
+
- lib/rails_multitenant/global_context_registry/registry_dependent_on.rb
|
175
178
|
- lib/rails_multitenant/middleware/extensions.rb
|
176
179
|
- lib/rails_multitenant/middleware/isolated_context_registry.rb
|
177
180
|
- lib/rails_multitenant/middleware/railtie.rb
|