cell 0.1.2 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +1 -1
- data/cell.gemspec +5 -5
- data/lib/cell/clone_schema.rb +195 -192
- data/lib/cell/console.rb +11 -4
- data/lib/cell/context.rb +7 -7
- data/lib/cell/ext/active_job.rb +33 -0
- data/lib/cell/ext/active_record.rb +81 -0
- data/lib/cell/ext/migration.rb +198 -0
- data/lib/cell/meta.rb +3 -2
- data/lib/cell/railtie.rb +6 -7
- data/lib/cell/sanity_check.rb +9 -10
- data/lib/cell/schema.rb +8 -13
- data/lib/cell/tenant.rb +13 -12
- data/lib/cell/version.rb +1 -1
- metadata +16 -22
- data/lib/cell/active_job.rb +0 -32
- data/lib/cell/migration.rb +0 -201
- data/lib/cell/model_extensions.rb +0 -85
@@ -0,0 +1,198 @@
|
|
1
|
+
#
|
2
|
+
# This is the messiest part of Cell, I think by necessity.
|
3
|
+
#
|
4
|
+
# A migration has two execution modes, global and targeted, with correspond to "db:migrate" and
|
5
|
+
# "cell:db:migrate"
|
6
|
+
#
|
7
|
+
# "global" is ran with a "db:migrate", which means no Tenant is activated. DDL commands here are
|
8
|
+
# directed to either 'public' or 'cell_prototype'
|
9
|
+
#
|
10
|
+
# "targeted" is ran with a tenant activated (cell:db:migrate), and all DDL commands are directed to
|
11
|
+
# the current tenant's schema.
|
12
|
+
#
|
13
|
+
# In 'rails db:migrate' (global mode), we actually execute each migration twice: once with a
|
14
|
+
# pass_context set to :global, where ONLY commands in a 'global {}' block are executed, and then
|
15
|
+
# with pass_context set to :prototype, where ONLY commands outside of a 'global {}' block are
|
16
|
+
# executed.
|
17
|
+
#
|
18
|
+
# ContextTracker keeps up with this.
|
19
|
+
|
20
|
+
require 'cell/meta'
|
21
|
+
require 'cell/schema'
|
22
|
+
require 'cell/clone_schema'
|
23
|
+
|
24
|
+
|
25
|
+
module Cell
|
26
|
+
module Ext
|
27
|
+
module Migration
|
28
|
+
# OK, ContextTracker keeps up with:
|
29
|
+
# * The context in which this migration is being ran, e.g. the :global first pass, the
|
30
|
+
# :prototype second pass, OR the :targeted per tenant pass.
|
31
|
+
# * If it's in a global block or not, which determines if actions are actually executed
|
32
|
+
# * If force_execution is set, which is for the benefit of playing back CommandRecorder
|
33
|
+
# commands.
|
34
|
+
module ContextTracker
|
35
|
+
mattr_accessor :pass_context
|
36
|
+
mattr_accessor :global_block
|
37
|
+
mattr_accessor :force_execution
|
38
|
+
|
39
|
+
def execute_ddl?
|
40
|
+
force_execution ||
|
41
|
+
(pass_context == :global && global_block) ||
|
42
|
+
(pass_context == :prototype && !global_block) ||
|
43
|
+
(pass_context == :target && !global_block)
|
44
|
+
end
|
45
|
+
|
46
|
+
# When the CommandRecorder's commands are executed, they're rewritten to go through
|
47
|
+
# force_call, because the "effective set of commands" have already been determined by the
|
48
|
+
# CommandRecorder run.
|
49
|
+
def force_call(*args, &block)
|
50
|
+
saved, self.force_execution = self.force_execution, true
|
51
|
+
send(*args, &block)
|
52
|
+
ensure
|
53
|
+
self.force_execution = saved
|
54
|
+
end
|
55
|
+
|
56
|
+
def with_context(context, search_path, exclusive: false)
|
57
|
+
Meta::with_schema(search_path, exclusive: exclusive) do
|
58
|
+
begin
|
59
|
+
saved, self.pass_context = self.pass_context, context
|
60
|
+
yield
|
61
|
+
ensure
|
62
|
+
self.pass_context = saved
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def global
|
68
|
+
saved, self.global_block = self.global_block, true
|
69
|
+
yield
|
70
|
+
ensure
|
71
|
+
self.global_block = saved
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# This module intercepts create_table and drop_table, and updates the list of global tables
|
77
|
+
# in ::ActiveRecord::InternalMetadata['cell.global'].
|
78
|
+
module MetadataIntercept
|
79
|
+
def create_table(name, *args, &block)
|
80
|
+
super.tap do
|
81
|
+
Meta.add_global_table(name) if pass_context == :global
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def drop_table(name, *args, &block)
|
86
|
+
super.tap do
|
87
|
+
Meta.remove_global_table(name) if pass_context == :global
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
# We intercept these methods, and only execute if appropriate according to execute_ddl?
|
93
|
+
def self.intercept(methods)
|
94
|
+
methods.each do |method|
|
95
|
+
define_method(method) do |*args, &block|
|
96
|
+
super(*args, &block) if execute_ddl?
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# This sucks. In the future, we may want to pull these from SchemaStatements
|
102
|
+
intercept %i(add_belongs_to add_column add_foreign_key add_index
|
103
|
+
add_index_sort_order add_reference add_timestamps
|
104
|
+
change_column change_column_default change_column_null
|
105
|
+
change_table change_table_comment create_join_table
|
106
|
+
create_table drop_join_table drop_table
|
107
|
+
initialize_schema_migrations_table remove_belongs_to
|
108
|
+
remove_column remove_columns remove_foreign_key remove_index
|
109
|
+
remove_reference remove_timestamps rename_column
|
110
|
+
rename_column_indexes rename_index rename_table
|
111
|
+
rename_table_indexes table_alias_for table_comment) +
|
112
|
+
%i(enable_extension disable_extension truncate) +
|
113
|
+
%i(execute)
|
114
|
+
|
115
|
+
def global_schema
|
116
|
+
Meta.global_schema
|
117
|
+
end
|
118
|
+
|
119
|
+
def prototype_schema
|
120
|
+
Meta.prototype_schema
|
121
|
+
end
|
122
|
+
|
123
|
+
def tenant_schema
|
124
|
+
target.schema_name
|
125
|
+
end
|
126
|
+
|
127
|
+
def target
|
128
|
+
Model.current
|
129
|
+
end
|
130
|
+
|
131
|
+
def targeted?
|
132
|
+
!! target
|
133
|
+
end
|
134
|
+
|
135
|
+
# This is our super-special initialization function.
|
136
|
+
def initialize_cell!
|
137
|
+
CloneSchema.install_function!
|
138
|
+
execute "CREATE SCHEMA #{connection.quote_schema_name(prototype_schema)}"
|
139
|
+
end
|
140
|
+
|
141
|
+
def exec_migration(con, direction)
|
142
|
+
if ! targeted?
|
143
|
+
with_context(:global, global_schema) do
|
144
|
+
super
|
145
|
+
end
|
146
|
+
|
147
|
+
with_context(:prototype, prototype_schema) do
|
148
|
+
super
|
149
|
+
end
|
150
|
+
else
|
151
|
+
with_context(:target, tenant_schema, exclusive: true) do
|
152
|
+
super
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
# Patches to CommandRecorder, which let us roll back.
|
158
|
+
module CommandRecorderFilter
|
159
|
+
# This maybe should've been attr_reader in CommandRecorder
|
160
|
+
def commands=(*)
|
161
|
+
# If this is actually used, we're fucked.
|
162
|
+
fail "The problem with monkey patching is..."
|
163
|
+
end
|
164
|
+
|
165
|
+
def commands
|
166
|
+
@commands.select do |command|
|
167
|
+
command[0]
|
168
|
+
end.map do |command|
|
169
|
+
[:force_call, [command[1], *command[2]], command[3]]
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
# saves the state of a recorded command with the context it was in.
|
174
|
+
def add_command(command)
|
175
|
+
@commands << [execute_ddl?, *command]
|
176
|
+
end
|
177
|
+
|
178
|
+
# We override #record to proxy through add_command
|
179
|
+
def record(*command, &block)
|
180
|
+
if @reverting
|
181
|
+
add_command inverse_of(*command, &block)
|
182
|
+
else
|
183
|
+
add_command (command << block)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
ActiveSupport.on_load(:active_record) do
|
192
|
+
ActiveRecord::Migration.prepend(Cell::Ext::Migration::ContextTracker)
|
193
|
+
ActiveRecord::Migration.prepend(Cell::Ext::Migration::MetadataIntercept)
|
194
|
+
ActiveRecord::Migration.prepend(Cell::Ext::Migration)
|
195
|
+
|
196
|
+
ActiveRecord::Migration::CommandRecorder.prepend(Cell::Ext::Migration::ContextTracker)
|
197
|
+
ActiveRecord::Migration::CommandRecorder.prepend(Cell::Ext::Migration::CommandRecorderFilter)
|
198
|
+
end
|
data/lib/cell/meta.rb
CHANGED
@@ -32,7 +32,8 @@ module Cell
|
|
32
32
|
end
|
33
33
|
|
34
34
|
def self.global_schema
|
35
|
-
|
35
|
+
# This could be racy?
|
36
|
+
@global_schema ||= ::ActiveRecord::Base.connection.schema_search_path
|
36
37
|
end
|
37
38
|
|
38
39
|
def self.prototype_schema
|
@@ -40,7 +41,7 @@ module Cell
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def self.structural_schema
|
43
|
-
"#{prototype_schema}
|
44
|
+
"#{prototype_schema},#{global_schema}"
|
44
45
|
end
|
45
46
|
|
46
47
|
def self.with_global_schema(&block)
|
data/lib/cell/railtie.rb
CHANGED
@@ -11,21 +11,20 @@ module Cell
|
|
11
11
|
config.after_initialize do
|
12
12
|
require 'cell/tenant'
|
13
13
|
require 'cell/sanity_check'
|
14
|
-
require 'cell/
|
15
|
-
require 'cell/migration'
|
16
|
-
require 'cell/active_job'
|
14
|
+
require 'cell/ext/active_record'
|
15
|
+
require 'cell/ext/migration'
|
16
|
+
require 'cell/ext/active_job'
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
|
21
20
|
def self.const_missing(name)
|
22
21
|
return super unless name == :Model
|
23
22
|
|
24
23
|
Rails.application.eager_load!
|
25
24
|
unless const_defined?(:Model)
|
26
|
-
fail "Eager loaded models to find
|
27
|
-
"Make sure one of your models has `prepend Cell::Tenant`"
|
25
|
+
fail "Eager loaded models to find one that uses `include Cell::Tenant`. Didn't pan out."
|
28
26
|
end
|
29
|
-
|
27
|
+
|
28
|
+
Model
|
30
29
|
end
|
31
30
|
end
|
data/lib/cell/sanity_check.rb
CHANGED
@@ -3,7 +3,7 @@ require 'active_record/connection_adapters/postgresql_adapter'
|
|
3
3
|
module Cell
|
4
4
|
module SanityCheck
|
5
5
|
def self.check_active_record_adapter!
|
6
|
-
pg_base_adapter =
|
6
|
+
pg_base_adapter = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
|
7
7
|
whitelist = []
|
8
8
|
adapter_name = ActiveRecord::Base.connection.adapter_name
|
9
9
|
|
@@ -18,6 +18,8 @@ module Cell
|
|
18
18
|
EOD
|
19
19
|
fail msg
|
20
20
|
end
|
21
|
+
rescue ActiveRecord::NoDatabaseError
|
22
|
+
# Not our problem
|
21
23
|
end
|
22
24
|
|
23
25
|
|
@@ -43,7 +45,7 @@ module Cell
|
|
43
45
|
Rails will not dump this schema by default with `db:structure:dump` without explicitly
|
44
46
|
setting `dump_schemas`.
|
45
47
|
|
46
|
-
You can configure this
|
48
|
+
You can configure this by adding a line like the following in application.rb:
|
47
49
|
|
48
50
|
Rails.application.config.active_record.dump_schemas = "public,cell_prototype"
|
49
51
|
EOD
|
@@ -51,14 +53,11 @@ module Cell
|
|
51
53
|
end
|
52
54
|
end
|
53
55
|
|
54
|
-
def self.sanity_check!
|
55
|
-
ActiveSupport.on_load(:active_record) do
|
56
|
-
Cell::SanityCheck.check_active_record_adapter!
|
57
|
-
Cell::SanityCheck.check_schema_format!
|
58
|
-
Cell::SanityCheck.check_dump_schemas!
|
59
|
-
end
|
60
|
-
end
|
61
56
|
end
|
62
57
|
end
|
63
58
|
|
64
|
-
|
59
|
+
ActiveSupport.on_load(:active_record) do
|
60
|
+
Cell::SanityCheck.check_active_record_adapter!
|
61
|
+
Cell::SanityCheck.check_schema_format!
|
62
|
+
Cell::SanityCheck.check_dump_schemas!
|
63
|
+
end
|
data/lib/cell/schema.rb
CHANGED
@@ -8,29 +8,26 @@ module Cell
|
|
8
8
|
MAX_SCHEMA_NAME_LENGTH = 63 # PostgreSQL baked-in default
|
9
9
|
MAX_CELL_ID_SIZE = MAX_SCHEMA_NAME_LENGTH - SCHEMA_PREFIX.size
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
SCHEMA_PREFIX + cell_id.to_s.gsub(/[^a-z0-9_]/i, '-')
|
14
|
-
end
|
11
|
+
def self.schema_name_for_cell_id(cell_id)
|
12
|
+
SCHEMA_PREFIX + cell_id.to_s.gsub(/[^a-z0-9_]/i, '-')
|
15
13
|
end
|
16
14
|
|
17
15
|
def schema_name
|
18
|
-
|
16
|
+
Schema.schema_name_for_cell_id(cell_id)
|
19
17
|
end
|
20
18
|
|
21
19
|
private
|
22
20
|
def create_schema!
|
23
21
|
con = self.class.connection
|
24
22
|
con.transaction do
|
25
|
-
|
26
|
-
|
23
|
+
CloneSchema.clone_schema(Meta.prototype_schema, schema_name)
|
24
|
+
CloneSchema.copy_schema_migrations_to(schema_name)
|
27
25
|
end
|
28
26
|
end
|
29
27
|
|
30
28
|
def destroy_schema!
|
31
29
|
con = self.class.connection
|
32
|
-
con.execute
|
33
|
-
"DROP SCHEMA #{con.quote_schema_name(schema_name)} CASCADE"
|
30
|
+
con.execute "DROP SCHEMA #{con.quote_schema_name(schema_name)} CASCADE"
|
34
31
|
end
|
35
32
|
|
36
33
|
def update_schema!
|
@@ -38,13 +35,11 @@ module Cell
|
|
38
35
|
src = self.class.schema_name_for_cell_id(src)
|
39
36
|
|
40
37
|
con = self.class.connection
|
41
|
-
con.execute
|
42
|
-
|
43
|
-
"TO #{con.quote_schema_name(schema_name)}"
|
38
|
+
con.execute "ALTER SCHEMA #{con.quote_schema_name(src)} RENAME " +
|
39
|
+
"TO #{con.quote_schema_name(schema_name)}"
|
44
40
|
end
|
45
41
|
|
46
42
|
def self.prepended(cls)
|
47
|
-
cls.extend(ClassMethods)
|
48
43
|
cls.after_create_commit :create_schema!
|
49
44
|
cls.after_update_commit :update_schema!, if: :cell_id_changed?
|
50
45
|
cls.after_destroy_commit :destroy_schema!
|
data/lib/cell/tenant.rb
CHANGED
@@ -4,10 +4,6 @@ require 'cell/url_options'
|
|
4
4
|
|
5
5
|
module Cell
|
6
6
|
module Tenant
|
7
|
-
class << self
|
8
|
-
attr_accessor :cls
|
9
|
-
end
|
10
|
-
|
11
7
|
module ClassMethods
|
12
8
|
def cell_id_column
|
13
9
|
:id
|
@@ -35,21 +31,26 @@ module Cell
|
|
35
31
|
previous_changes[self.class.cell_id_column]
|
36
32
|
end
|
37
33
|
|
38
|
-
def self.
|
39
|
-
|
34
|
+
def self.append_features(cls)
|
35
|
+
cls.prepend(self)
|
40
36
|
end
|
41
37
|
|
42
|
-
def self.
|
43
|
-
|
38
|
+
def self.extend_object(cls)
|
39
|
+
cls.prepend(self)
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
end
|
48
|
-
::Cell.const_set(:Model, model)
|
42
|
+
def self.prepended(model)
|
43
|
+
Cell.assign_model(model)
|
49
44
|
|
45
|
+
model.extend(ClassMethods)
|
50
46
|
model.prepend(::Cell::Schema)
|
51
47
|
model.prepend(::Cell::Context)
|
52
48
|
model.prepend(::Cell::UrlOptions)
|
53
49
|
end
|
54
50
|
end
|
51
|
+
|
52
|
+
def self.assign_model(model)
|
53
|
+
remove_const(:Model) if const_defined?(:Model)
|
54
|
+
const_set(:Model, model)
|
55
|
+
end
|
55
56
|
end
|
data/lib/cell/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cell
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Owens
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,76 +16,70 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
20
|
-
- - ">="
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: 5.0.0.1
|
19
|
+
version: 5.2.0
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - "~>"
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: 5.
|
30
|
-
- - ">="
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: 5.0.0.1
|
26
|
+
version: 5.2.0
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: pg
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
31
|
- - "~>"
|
38
32
|
- !ruby/object:Gem::Version
|
39
|
-
version:
|
33
|
+
version: 1.1.3
|
40
34
|
type: :runtime
|
41
35
|
prerelease: false
|
42
36
|
version_requirements: !ruby/object:Gem::Requirement
|
43
37
|
requirements:
|
44
38
|
- - "~>"
|
45
39
|
- !ruby/object:Gem::Version
|
46
|
-
version:
|
40
|
+
version: 1.1.3
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: minitest
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
50
44
|
requirements:
|
51
45
|
- - "~>"
|
52
46
|
- !ruby/object:Gem::Version
|
53
|
-
version: 5.
|
47
|
+
version: '5.11'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
51
|
requirements:
|
58
52
|
- - "~>"
|
59
53
|
- !ruby/object:Gem::Version
|
60
|
-
version: 5.
|
54
|
+
version: '5.11'
|
61
55
|
- !ruby/object:Gem::Dependency
|
62
56
|
name: bundler
|
63
57
|
requirement: !ruby/object:Gem::Requirement
|
64
58
|
requirements:
|
65
59
|
- - "~>"
|
66
60
|
- !ruby/object:Gem::Version
|
67
|
-
version: '1.
|
61
|
+
version: '1.16'
|
68
62
|
type: :development
|
69
63
|
prerelease: false
|
70
64
|
version_requirements: !ruby/object:Gem::Requirement
|
71
65
|
requirements:
|
72
66
|
- - "~>"
|
73
67
|
- !ruby/object:Gem::Version
|
74
|
-
version: '1.
|
68
|
+
version: '1.16'
|
75
69
|
- !ruby/object:Gem::Dependency
|
76
70
|
name: rake
|
77
71
|
requirement: !ruby/object:Gem::Requirement
|
78
72
|
requirements:
|
79
73
|
- - "~>"
|
80
74
|
- !ruby/object:Gem::Version
|
81
|
-
version: '
|
75
|
+
version: '12.3'
|
82
76
|
type: :development
|
83
77
|
prerelease: false
|
84
78
|
version_requirements: !ruby/object:Gem::Requirement
|
85
79
|
requirements:
|
86
80
|
- - "~>"
|
87
81
|
- !ruby/object:Gem::Version
|
88
|
-
version: '
|
82
|
+
version: '12.3'
|
89
83
|
description:
|
90
84
|
email:
|
91
85
|
- mike@meter.md
|
@@ -103,13 +97,13 @@ files:
|
|
103
97
|
- bin/test
|
104
98
|
- cell.gemspec
|
105
99
|
- lib/cell.rb
|
106
|
-
- lib/cell/active_job.rb
|
107
100
|
- lib/cell/clone_schema.rb
|
108
101
|
- lib/cell/console.rb
|
109
102
|
- lib/cell/context.rb
|
103
|
+
- lib/cell/ext/active_job.rb
|
104
|
+
- lib/cell/ext/active_record.rb
|
105
|
+
- lib/cell/ext/migration.rb
|
110
106
|
- lib/cell/meta.rb
|
111
|
-
- lib/cell/migration.rb
|
112
|
-
- lib/cell/model_extensions.rb
|
113
107
|
- lib/cell/railtie.rb
|
114
108
|
- lib/cell/sanity_check.rb
|
115
109
|
- lib/cell/schema.rb
|
@@ -138,7 +132,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
138
132
|
version: '0'
|
139
133
|
requirements: []
|
140
134
|
rubyforge_project:
|
141
|
-
rubygems_version: 2.
|
135
|
+
rubygems_version: 2.7.8
|
142
136
|
signing_key:
|
143
137
|
specification_version: 4
|
144
138
|
summary: Provides isolation and tenancy for Rails
|
data/lib/cell/active_job.rb
DELETED
@@ -1,32 +0,0 @@
|
|
1
|
-
module Cell
|
2
|
-
module ActiveJob
|
3
|
-
KEY = :'Cell.tenant'
|
4
|
-
|
5
|
-
def serialize
|
6
|
-
if (current_id = ::Cell::Model.current&.cell_id)
|
7
|
-
super.merge(KEY => current_id)
|
8
|
-
else
|
9
|
-
super
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
def deserialize(job_data)
|
14
|
-
if job_data.key?(KEY)
|
15
|
-
self.cell_tenant = ::Cell::Model.cell_find(job_data[KEY])
|
16
|
-
end
|
17
|
-
super
|
18
|
-
end
|
19
|
-
|
20
|
-
def self.prepended(cls)
|
21
|
-
cls.send(:attr_accessor, :cell_tenant)
|
22
|
-
cls.around_perform do |job, block|
|
23
|
-
::Cell::Model.use(job.cell_tenant, &block)
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
|
30
|
-
if defined?(::ActiveJob)
|
31
|
-
::ActiveJob::Base.prepend(::Cell::ActiveJob)
|
32
|
-
end
|