Module: MultiTenant
- Defined in:
- lib/activerecord-multi-tenant/fast_truncate.rb,
lib/activerecord-multi-tenant/version.rb,
lib/activerecord-multi-tenant/migrations.rb,
lib/activerecord-multi-tenant/multi_tenant.rb,
lib/activerecord-multi-tenant/query_monitor.rb,
lib/activerecord-multi-tenant/query_rewriter.rb,
lib/activerecord-multi-tenant/copy_from_client.rb,
lib/activerecord-multi-tenant/model_extensions.rb,
lib/activerecord-multi-tenant/controller_extensions.rb,
lib/activerecord-multi-tenant/arel_visitors_depth_first.rb
Overview
Add generic warning when queries fail and there is no tenant set
Defined Under Namespace
Modules: ControllerExtensions, CopyFromClient, DatabaseStatements, FastTruncate, MigrationExtensions, ModelExtensionsClassMethods, TenantValueVisitor
Classes: ArelTenantVisitor, ArelVisitorsDepthFirst, BaseTenantEnforcementClause, Context, CopyFromClientHelper, Current, QueryMonitor, Table, TenantEnforcementClause, TenantIsImmutable, TenantJoinEnforcementClause
Constant Summary
collapse
- VERSION =
'2.1.4'
- @@enable_with_lock_workaround =
false
- @@enable_query_monitor =
Option to enable query monitor
false
Class Method Summary
collapse
Class Method Details
.current_tenant ⇒ Object
63
64
65
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 63
def self.current_tenant
Current.tenant
end
|
.current_tenant=(tenant) ⇒ Object
59
60
61
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 59
def self.current_tenant=(tenant)
Current.tenant = tenant
end
|
.current_tenant_class ⇒ Object
75
76
77
78
79
80
81
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 75
def self.current_tenant_class
if current_tenant_is_id?
MultiTenant.default_tenant_class || fail('Only have tenant id, and no default tenant class set')
elsif current_tenant
MultiTenant.current_tenant.class.name
end
end
|
.current_tenant_id ⇒ Object
67
68
69
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 67
def self.current_tenant_id
current_tenant_is_id? ? current_tenant : current_tenant.try(:id)
end
|
.current_tenant_is_id? ⇒ Boolean
71
72
73
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 71
def self.current_tenant_is_id?
current_tenant.is_a?(String) || current_tenant.is_a?(Integer)
end
|
.default_tenant_class ⇒ Object
18
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 18
def self.default_tenant_class; @@default_tenant_class ||= nil; end
|
.default_tenant_class=(tenant_class) ⇒ Object
In some cases we only have an ID - if defined we'll return the default tenant class in such cases
17
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 17
def self.default_tenant_class=(tenant_class); @@default_tenant_class = tenant_class; end
|
.enable_query_monitor ⇒ Object
5
|
# File 'lib/activerecord-multi-tenant/query_monitor.rb', line 5
def self.enable_query_monitor; @@enable_query_monitor = true; end
|
.enable_with_lock_workaround ⇒ Object
27
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 27
def self.enable_with_lock_workaround; @@enable_with_lock_workaround = true; end
|
.enable_write_only_mode ⇒ Object
Write-only Mode - this only adds the tenant_id to new records, but doesn't require its presence for SELECTs/UPDATEs/DELETEs
22
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 22
def self.enable_write_only_mode; @@enable_write_only_mode = true; end
|
.load_current_tenant! ⇒ Object
.multi_tenant_model_for_arel(arel) ⇒ Object
.multi_tenant_model_for_table(table_name) ⇒ Object
38
39
40
41
42
43
44
45
46
47
48
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 38
def self.multi_tenant_model_for_table(table_name)
@@multi_tenant_models ||= []
if !defined?(@@multi_tenant_model_table_names)
@@multi_tenant_model_table_names = @@multi_tenant_models.map { |model|
[model.table_name, model] if model.table_name
}.compact.to_h
end
@@multi_tenant_model_table_names[table_name.to_s]
end
|
.partition_key(tenant_name) ⇒ Object
12
13
14
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 12
def self.partition_key(tenant_name)
"#{tenant_name.to_s}_id"
end
|
.query_monitor_enabled? ⇒ Boolean
6
|
# File 'lib/activerecord-multi-tenant/query_monitor.rb', line 6
def self.query_monitor_enabled?; @@enable_query_monitor; end
|
.register_multi_tenant_model(model_klass) ⇒ Object
Registry that maps table names to models (used by the query rewriter)
31
32
33
34
35
36
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 31
def self.register_multi_tenant_model(model_klass)
@@multi_tenant_models ||= []
@@multi_tenant_models.push(model_klass)
remove_class_variable(:@@multi_tenant_model_table_names) if defined?(@@multi_tenant_model_table_names)
end
|
.tenant_klass_defined?(tenant_name) ⇒ Boolean
8
9
10
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 8
def self.tenant_klass_defined?(tenant_name)
!!tenant_name.to_s.classify.safe_constantize
end
|
.with(tenant, &block) ⇒ Object
90
91
92
93
94
95
96
97
98
99
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 90
def self.with(tenant, &block)
return block.call if self.current_tenant == tenant
old_tenant = self.current_tenant
begin
self.current_tenant = tenant
return block.call
ensure
self.current_tenant = old_tenant
end
end
|
.with_lock_workaround_enabled? ⇒ Boolean
28
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 28
def self.with_lock_workaround_enabled?; @@enable_with_lock_workaround; end
|
.with_write_only_mode_enabled? ⇒ Boolean
23
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 23
def self.with_write_only_mode_enabled?; @@enable_write_only_mode ||= false; end
|
.without(&block) ⇒ Object
101
102
103
104
105
106
107
108
109
110
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 101
def self.without(&block)
return block.call if self.current_tenant.nil?
old_tenant = self.current_tenant
begin
self.current_tenant = nil
return block.call
ensure
self.current_tenant = old_tenant
end
end
|
.wrap_methods(klass, owner, *method_names) ⇒ Object
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
|
# File 'lib/activerecord-multi-tenant/multi_tenant.rb', line 114
def self.wrap_methods(klass, owner, *method_names)
method_names.each do |method_name|
original_method_name = :"_mt_original_#{method_name}"
klass.class_eval <<-CODE, __FILE__, __LINE__ + 1
alias_method :#{original_method_name}, :#{method_name}
def #{method_name}(*args, &block)
if MultiTenant.multi_tenant_model_for_table(#{owner}.class.table_name).present? && #{owner}.persisted? && MultiTenant.current_tenant_id.nil?
MultiTenant.with(#{owner}.public_send(#{owner}.class.partition_key)) { #{original_method_name}(*args, &block) }
else
#{original_method_name}(*args, &block)
end
end
CODE
end
end
|