activerecord-multi-tenant 2.1.6 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (122) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/active-record-multi-tenant-tests.yml +80 -0
  3. data/.gitignore +6 -0
  4. data/.readthedocs.yaml +15 -0
  5. data/.rspec +0 -0
  6. data/.rubocop.yml +51 -0
  7. data/Appraisals +0 -24
  8. data/CHANGELOG.md +12 -0
  9. data/Gemfile +3 -1
  10. data/LICENSE +0 -0
  11. data/README.md +3 -2
  12. data/Rakefile +1 -1
  13. data/activerecord-multi-tenant.gemspec +28 -22
  14. data/docker-compose.yml +24 -18
  15. data/docs/.gitignore +3 -0
  16. data/docs/Makefile +28 -0
  17. data/docs/api-reference.sh +10 -0
  18. data/docs/requirements.in +4 -0
  19. data/docs/requirements.txt +62 -0
  20. data/docs/source/_static/api-reference/ActiveRecord/Associations/Association.html +285 -0
  21. data/docs/source/_static/api-reference/ActiveRecord/Associations/ClassMethods.html +255 -0
  22. data/docs/source/_static/api-reference/ActiveRecord/Associations.html +117 -0
  23. data/docs/source/_static/api-reference/ActiveRecord/ConnectionAdapters/SchemaStatements.html +232 -0
  24. data/docs/source/_static/api-reference/ActiveRecord/ConnectionAdapters.html +126 -0
  25. data/docs/source/_static/api-reference/ActiveRecord/QueryMethods.html +336 -0
  26. data/docs/source/_static/api-reference/ActiveRecord/SchemaDumper.html +121 -0
  27. data/docs/source/_static/api-reference/ActiveRecord.html +130 -0
  28. data/docs/source/_static/api-reference/MultiTenant/ArelTenantVisitor.html +755 -0
  29. data/docs/source/_static/api-reference/MultiTenant/ArelVisitorsDepthFirst.html +208 -0
  30. data/docs/source/_static/api-reference/MultiTenant/BaseTenantEnforcementClause.html +462 -0
  31. data/docs/source/_static/api-reference/MultiTenant/Context.html +659 -0
  32. data/docs/source/_static/api-reference/MultiTenant/ControllerExtensions.html +202 -0
  33. data/docs/source/_static/api-reference/MultiTenant/CopyFromClient.html +186 -0
  34. data/docs/source/_static/api-reference/MultiTenant/CopyFromClientHelper.html +362 -0
  35. data/docs/source/_static/api-reference/MultiTenant/Current.html +124 -0
  36. data/docs/source/_static/api-reference/MultiTenant/DatabaseStatements.html +366 -0
  37. data/docs/source/_static/api-reference/MultiTenant/FastTruncate.html +226 -0
  38. data/docs/source/_static/api-reference/MultiTenant/MigrationExtensions.html +554 -0
  39. data/docs/source/_static/api-reference/MultiTenant/MissingTenantError.html +124 -0
  40. data/docs/source/_static/api-reference/MultiTenant/ModelExtensionsClassMethods.html +492 -0
  41. data/docs/source/_static/api-reference/MultiTenant/QueryMonitor.html +257 -0
  42. data/docs/source/_static/api-reference/MultiTenant/Table.html +419 -0
  43. data/docs/source/_static/api-reference/MultiTenant/TenantEnforcementClause.html +148 -0
  44. data/docs/source/_static/api-reference/MultiTenant/TenantIsImmutable.html +135 -0
  45. data/docs/source/_static/api-reference/MultiTenant/TenantJoinEnforcementClause.html +310 -0
  46. data/docs/source/_static/api-reference/MultiTenant/TenantValueVisitor.html +239 -0
  47. data/docs/source/_static/api-reference/MultiTenant.html +1454 -0
  48. data/docs/source/_static/api-reference/MultiTenantFindBy.html +180 -0
  49. data/docs/source/_static/api-reference/Sidekiq/Client.html +302 -0
  50. data/docs/source/_static/api-reference/Sidekiq/Middleware/MultiTenant/Client.html +217 -0
  51. data/docs/source/_static/api-reference/Sidekiq/Middleware/MultiTenant/Server.html +219 -0
  52. data/docs/source/_static/api-reference/Sidekiq/Middleware/MultiTenant.html +126 -0
  53. data/docs/source/_static/api-reference/Sidekiq.html +126 -0
  54. data/docs/source/_static/api-reference/_index.html +399 -0
  55. data/docs/source/_static/api-reference/class_list.html +51 -0
  56. data/docs/source/_static/api-reference/css/common.css +1 -0
  57. data/docs/source/_static/api-reference/css/full_list.css +58 -0
  58. data/docs/source/_static/api-reference/css/style.css +497 -0
  59. data/docs/source/_static/api-reference/file.README.html +167 -0
  60. data/docs/source/_static/api-reference/file_list.html +56 -0
  61. data/docs/source/_static/api-reference/frames.html +17 -0
  62. data/docs/source/_static/api-reference/index.html +167 -0
  63. data/docs/source/_static/api-reference/js/app.js +314 -0
  64. data/docs/source/_static/api-reference/js/full_list.js +216 -0
  65. data/docs/source/_static/api-reference/js/jquery.js +4 -0
  66. data/docs/source/_static/api-reference/method_list.html +715 -0
  67. data/docs/source/_static/api-reference/top-level-namespace.html +126 -0
  68. data/docs/source/_templates/.gitignore +4 -0
  69. data/docs/source/api-reference.rst +8 -0
  70. data/docs/source/appendix.rst +26 -0
  71. data/docs/source/changelog.rst +8 -0
  72. data/docs/source/community-and-support.rst +26 -0
  73. data/docs/source/conf.py +30 -0
  74. data/docs/source/contributing.rst +70 -0
  75. data/docs/source/getting-started.rst +37 -0
  76. data/docs/source/guides-and-tutorials.rst +129 -0
  77. data/docs/source/index.rst +54 -0
  78. data/docs/source/introduction.rst +33 -0
  79. data/docs/source/license.rst +22 -0
  80. data/docs/source/troubleshooting.rst +41 -0
  81. data/docs/source/usage-guide.rst +59 -0
  82. data/lib/activerecord-multi-tenant/arel_visitors_depth_first.rb +183 -174
  83. data/lib/activerecord-multi-tenant/controller_extensions.rb +15 -4
  84. data/lib/activerecord-multi-tenant/copy_from_client.rb +4 -0
  85. data/lib/activerecord-multi-tenant/fast_truncate.rb +4 -2
  86. data/lib/activerecord-multi-tenant/habtm.rb +50 -0
  87. data/lib/activerecord-multi-tenant/migrations.rb +19 -9
  88. data/lib/activerecord-multi-tenant/model_extensions.rb +82 -40
  89. data/lib/activerecord-multi-tenant/multi_tenant.rb +42 -23
  90. data/lib/activerecord-multi-tenant/query_monitor.rb +21 -5
  91. data/lib/activerecord-multi-tenant/query_rewriter.rb +111 -80
  92. data/lib/activerecord-multi-tenant/sidekiq.rb +31 -20
  93. data/lib/activerecord-multi-tenant/version.rb +1 -1
  94. data/lib/activerecord-multi-tenant.rb +3 -12
  95. data/lib/activerecord_multi_tenant.rb +12 -0
  96. data/spec/activerecord-multi-tenant/associations_spec.rb +21 -0
  97. data/spec/activerecord-multi-tenant/controller_extensions_spec.rb +3 -2
  98. data/spec/activerecord-multi-tenant/fast_truncate_spec.rb +8 -6
  99. data/spec/activerecord-multi-tenant/model_extensions_spec.rb +243 -153
  100. data/spec/activerecord-multi-tenant/multi_tenant_spec.rb +15 -13
  101. data/spec/activerecord-multi-tenant/query_rewriter_spec.rb +60 -59
  102. data/spec/activerecord-multi-tenant/record_callback_spec.rb +0 -0
  103. data/spec/activerecord-multi-tenant/record_finding_spec.rb +11 -11
  104. data/spec/activerecord-multi-tenant/record_modifications_spec.rb +4 -4
  105. data/spec/activerecord-multi-tenant/sidekiq_spec.rb +10 -10
  106. data/spec/database.yml +0 -0
  107. data/spec/schema.rb +20 -2
  108. data/spec/spec_helper.rb +46 -17
  109. data/spec/support/format_sql.rb +20 -0
  110. metadata +132 -29
  111. data/.github/workflows/CI.yml +0 -63
  112. data/gemfiles/.bundle/config +0 -2
  113. data/gemfiles/active_record_5.2.gemfile +0 -16
  114. data/gemfiles/active_record_6.0.gemfile +0 -8
  115. data/gemfiles/active_record_6.1.gemfile +0 -8
  116. data/gemfiles/active_record_7.0.gemfile +0 -8
  117. data/gemfiles/rails_5.2.gemfile +0 -16
  118. data/gemfiles/rails_6.0.gemfile +0 -8
  119. data/gemfiles/rails_6.1.gemfile +0 -8
  120. data/gemfiles/rails_7.0.gemfile +0 -8
  121. data/lib/activerecord-multi-tenant/with_lock.rb +0 -15
  122. data/spec/activerecord-multi-tenant/schema_dumper_tester.rb +0 -0
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'spec_helper'
2
4
 
3
5
  describe MultiTenant do
@@ -10,11 +12,11 @@ describe MultiTenant do
10
12
  end
11
13
 
12
14
  describe 'is_scoped_as_tenant should return the correct value when true' do
13
- it {expect(Project.respond_to?(:scoped_by_tenant?)).to eq(true)}
15
+ it { expect(Project.respond_to?(:scoped_by_tenant?)).to eq(true) }
14
16
  end
15
17
 
16
18
  describe 'is_scoped_as_tenant should return the correct value when false' do
17
- it {expect(UnscopedModel.respond_to?(:scoped_by_tenant?)).to eq(false)}
19
+ it { expect(UnscopedModel.respond_to?(:scoped_by_tenant?)).to eq(false) }
18
20
  end
19
21
 
20
22
  context 'immutability' do
@@ -43,17 +45,17 @@ describe MultiTenant do
43
45
  @account = Account.create! name: 'foo'
44
46
  MultiTenant.current_tenant = @account
45
47
  end
46
- it {expect(Project.new.account_id).to eq(@account.id)}
48
+ it { expect(Project.new.account_id).to eq(@account.id) }
47
49
  it 'should handle partial selects' do
48
50
  project = Project.create!
49
- expect{project = Project.select(:name).find(project.id)}.not_to raise_error
51
+ expect { project = Project.select(:name).find(project.id) }.not_to raise_error
50
52
  expect(project.account_id).to eq(@account.id)
51
53
  end
52
54
  end
53
55
 
54
56
  describe 'Handles custom partition_key on tenant model' do
55
57
  before do
56
- @account = Account.create! name: 'foo'
58
+ @account = Account.create! name: 'foo'
57
59
  MultiTenant.current_tenant = @account
58
60
  @custom_partition_key_task = CustomPartitionKeyTask.create! name: 'foo'
59
61
  end
@@ -70,11 +72,11 @@ describe MultiTenant do
70
72
  it { expect(@partition_key_not_model_task.non_model_id).to be 77 }
71
73
  end
72
74
 
73
-
74
75
  describe 'Tenant model with a nonstandard class name' do
75
76
  let(:account_klass) do
76
77
  Class.new(ActiveRecord::Base) do
77
78
  self.table_name = 'account'
79
+
78
80
  def self.name
79
81
  'UserAccount'
80
82
  end
@@ -82,7 +84,7 @@ describe MultiTenant do
82
84
  multi_tenant(:account)
83
85
  end
84
86
  end
85
- it "does not register the tenant model" do
87
+ it 'does not register the tenant model' do
86
88
  expect(MultiTenant).not_to receive(:register_multi_tenant_model)
87
89
  account_klass
88
90
  end
@@ -129,6 +131,13 @@ describe MultiTenant do
129
131
  it { expect(@posts).to eq([@post1]) }
130
132
  end
131
133
 
134
+ describe 'inspect method filters senstive column values' do
135
+ it 'filters senstive value' do
136
+ account = Account.new(name: 'foo', password: 'baz')
137
+ expect(account.inspect).to eq '#<Account id: nil, name: nil, subdomain: nil, domain: nil, password: [FILTERED]>'
138
+ end
139
+ end
140
+
132
141
  # Scoping models
133
142
  describe 'Project.all should be scoped to the current tenant if set' do
134
143
  before do
@@ -171,16 +180,16 @@ describe MultiTenant do
171
180
  end
172
181
  end
173
182
 
174
- describe "It should be possible to use aliased associations" do
183
+ describe 'It should be possible to use aliased associations' do
175
184
  before do
176
185
  @account = Account.create! name: 'baz'
177
186
  MultiTenant.current_tenant = @account
178
187
  end
179
188
 
180
- it { expect(AliasedTask.create(:name => 'foo', :project_alias => @project2).valid?).to eq(true) }
189
+ it { expect(AliasedTask.create(name: 'foo', project_alias: @project2).valid?).to eq(true) }
181
190
  end
182
191
 
183
- describe "It should be possible to use associations with partition_key from polymorphic" do
192
+ describe 'It should be possible to use associations with partition_key from polymorphic' do
184
193
  before do
185
194
  @account = Account.create!(name: 'foo')
186
195
  MultiTenant.current_tenant = @account
@@ -209,6 +218,16 @@ describe MultiTenant do
209
218
  expect(record.account_id).to eq(nil)
210
219
  end
211
220
 
221
+ it 'handles changing tenant from nil to a value' do
222
+ record = OptionalSubTask.create(sub_task_id: sub_task.id)
223
+ expect(record.reload.sub_task).to eq(sub_task)
224
+ expect(record.account_id).to eq(nil)
225
+
226
+ record.account = account
227
+ record.save!
228
+ expect(record.reload.account_id).to eq(account.id)
229
+ end
230
+
212
231
  it 'handles has_many through' do
213
232
  MultiTenant.with(account) do
214
233
  expect(project.sub_tasks).to eq [sub_task]
@@ -227,7 +246,7 @@ describe MultiTenant do
227
246
  MultiTenant.with(account) do
228
247
  sub_task
229
248
  manager
230
- expect(Project.eager_load([{manager: :project}, {tasks: :project}]).first).to eq project
249
+ expect(Project.eager_load([{ manager: :project }, { tasks: :project }]).first).to eq project
231
250
  end
232
251
  end
233
252
  end
@@ -238,7 +257,8 @@ describe MultiTenant do
238
257
 
239
258
  it 'rewrites sub-selects correctly' do
240
259
  MultiTenant.with(account) do
241
- expect(Project.where(id: Project.where(id: project.id)).where(id: Project.where(id: project.id)).first).to eq project
260
+ expect(Project.where(id: Project.where(id: project.id))
261
+ .where(id: Project.where(id: project.id)).first).to eq project
242
262
  end
243
263
  end
244
264
  end
@@ -267,34 +287,34 @@ describe MultiTenant do
267
287
  end
268
288
 
269
289
  describe 'non-STI Subclass of abstract Multi Tenant Model' do
270
- let(:tenant_id_1) { 42 }
271
- let(:tenant_id_2) { 314158 }
290
+ let(:tenant_id1) { 42 }
291
+ let(:tenant_id2) { 314_158 }
272
292
  let(:name) { 'fooname' }
273
- let(:subclass_task_1) do
274
- MultiTenant.with(tenant_id_1) { SubclassTask.create! name: name }
293
+ let(:subclass_task1) do
294
+ MultiTenant.with(tenant_id1) { SubclassTask.create! name: name }
275
295
  end
276
- let(:subclass_task_2) do
277
- MultiTenant.with(tenant_id_2) { SubclassTask.create! name: name }
296
+ let(:subclass_task2) do
297
+ MultiTenant.with(tenant_id2) { SubclassTask.create! name: name }
278
298
  end
279
299
 
280
300
  before do
281
- subclass_task_1
282
- subclass_task_2
301
+ subclass_task1
302
+ subclass_task2
283
303
  end
284
304
 
285
305
  it 'injects tenant_id on create' do
286
- expect(subclass_task_1.non_model_id).to be tenant_id_1
287
- expect(subclass_task_2.non_model_id).to be tenant_id_2
306
+ expect(subclass_task1.non_model_id).to be tenant_id1
307
+ expect(subclass_task2.non_model_id).to be tenant_id2
288
308
  end
289
309
 
290
310
  it 'rewrites query' do
291
- MultiTenant.with(tenant_id_1) do
311
+ MultiTenant.with(tenant_id1) do
292
312
  expect(SubclassTask.where(name: name).count).to eq 1
293
- expect(SubclassTask.where(name: name).first).to eq subclass_task_1
313
+ expect(SubclassTask.where(name: name).first).to eq subclass_task1
294
314
  end
295
- MultiTenant.with(tenant_id_2) do
315
+ MultiTenant.with(tenant_id2) do
296
316
  expect(SubclassTask.where(name: name).count).to eq 1
297
- expect(SubclassTask.where(name: name).first).to eq subclass_task_2
317
+ expect(SubclassTask.where(name: name).first).to eq subclass_task2
298
318
  end
299
319
  end
300
320
  end
@@ -306,20 +326,27 @@ describe MultiTenant do
306
326
 
307
327
  it 'should add tenant condition to the queries when tenant is set' do
308
328
  expected_join_sql = <<-SQL.strip
309
- SELECT "comments".* FROM "comments" INNER JOIN "tasks" ON "tasks"."id" = "comments"."commentable_id" AND "comments"."commentable_type" = 'Task' AND "tasks"."account_id" = 1 WHERE "comments"."account_id" = 1
329
+ SELECT "comments".*#{' '}
330
+ FROM "comments"#{' '}
331
+ INNER JOIN "tasks" ON "tasks"."id" = "comments"."commentable_id"#{' '}
332
+ AND "comments"."commentable_type" = 'Task' AND "tasks"."account_id" = 1#{' '}
333
+ WHERE "comments"."account_id" = 1
310
334
  SQL
311
335
 
312
336
  MultiTenant.with(account) do
313
- expect(Comment.joins(:task).to_sql).to eq(expected_join_sql)
337
+ expect(format_sql(Comment.joins(:task).to_sql)).to eq(format_sql(expected_join_sql))
314
338
  end
315
339
  end
316
340
 
317
341
  it 'should add tenant condition to the queries when tenant is not set' do
318
342
  MultiTenant.without do
319
343
  expected_join_sql = <<-SQL.strip
320
- SELECT "comments".* FROM "comments" INNER JOIN "tasks" ON "tasks"."id" = "comments"."commentable_id" AND "comments"."commentable_type" = 'Task' AND "comments"."account_id" = "tasks"."account_id"
344
+ SELECT "comments".*#{' '}
345
+ FROM "comments"#{' '}
346
+ INNER JOIN "tasks" ON "tasks"."id" = "comments"."commentable_id"#{' '}
347
+ AND "comments"."commentable_type" = 'Task' AND "comments"."account_id" = "tasks"."account_id"
321
348
  SQL
322
- expect(Comment.joins(:task).to_sql).to eq(expected_join_sql)
349
+ expect(format_sql(Comment.joins(:task).to_sql)).to eq(format_sql(expected_join_sql))
323
350
  end
324
351
  end
325
352
  end
@@ -329,57 +356,63 @@ describe MultiTenant do
329
356
 
330
357
  it 'should add tenant condition to the queries when tenant is set' do
331
358
  expected_join_sql = <<-SQL.strip
332
- SELECT "projects".* FROM "projects" INNER JOIN "tasks" ON "tasks"."project_id" = "projects"."id" AND "tasks"."account_id" = 1 WHERE "projects"."account_id" = 1
359
+ SELECT "projects".*#{' '}
360
+ FROM "projects"#{' '}
361
+ INNER JOIN "tasks" ON "tasks"."project_id" = "projects"."id"#{' '}
362
+ AND "tasks"."account_id" = 1#{' '}
363
+ WHERE "projects"."account_id" = 1
333
364
  SQL
334
365
 
335
366
  MultiTenant.with(account) do
336
- expect(Project.joins(:tasks).to_sql).to eq(expected_join_sql)
367
+ expect(format_sql(Project.joins(:tasks).to_sql)).to eq(format_sql(expected_join_sql))
337
368
  end
338
369
  end
339
370
 
340
371
  it 'should add tenant condition to the queries when tenant is not set' do
341
372
  MultiTenant.without do
342
373
  expected_join_sql = <<-SQL.strip
343
- SELECT "projects".* FROM "projects" INNER JOIN "tasks" ON "tasks"."project_id" = "projects"."id" AND "projects"."account_id" = "tasks"."account_id"
374
+ SELECT "projects".*
375
+ FROM "projects"
376
+ INNER JOIN "tasks" ON "tasks"."project_id" = "projects"."id"
377
+ AND "projects"."account_id" = "tasks"."account_id"
344
378
  SQL
345
- expect(Project.joins(:tasks).to_sql).to eq(expected_join_sql)
379
+ expect(format_sql(Project.joins(:tasks).to_sql)).to eq(format_sql(expected_join_sql))
346
380
  end
347
381
  end
348
382
  end
349
383
  end
350
384
 
351
385
  # ::with
352
- describe "::with" do
353
- it "should set current_tenant to the specified tenant inside the block" do
354
- @account = Account.create!(:name => 'baz')
386
+ describe '::with' do
387
+ it 'should set current_tenant to the specified tenant inside the block' do
388
+ @account = Account.create!(name: 'baz')
355
389
 
356
390
  MultiTenant.with(@account) do
357
391
  expect(MultiTenant.current_tenant).to eq(@account)
358
392
  end
359
393
  end
360
394
 
361
- it "should reset current_tenant to the previous tenant once exiting the block" do
362
- @account1 = Account.create!(:name => 'foo')
363
- @account2 = Account.create!(:name => 'bar')
395
+ it 'should reset current_tenant to the previous tenant once exiting the block' do
396
+ @account1 = Account.create!(name: 'foo')
397
+ @account2 = Account.create!(name: 'bar')
364
398
 
365
399
  MultiTenant.current_tenant = @account1
366
400
  MultiTenant.with @account2 do
367
-
368
401
  end
369
402
 
370
403
  expect(MultiTenant.current_tenant).to eq(@account1)
371
404
  end
372
405
 
373
- it "should return the value of the block" do
374
- @account1 = Account.create!(:name => 'foo')
375
- @account2 = Account.create!(:name => 'bar')
406
+ it 'should return the value of the block' do
407
+ @account1 = Account.create!(name: 'foo')
408
+ @account2 = Account.create!(name: 'bar')
376
409
 
377
410
  MultiTenant.current_tenant = @account1
378
411
  value = MultiTenant.with @account2 do
379
- "something"
412
+ 'something'
380
413
  end
381
414
 
382
- expect(value).to eq "something"
415
+ expect(value).to eq 'something'
383
416
  end
384
417
 
385
418
  it 'supports reload inside the block' do
@@ -394,9 +427,9 @@ describe MultiTenant do
394
427
  end
395
428
 
396
429
  # ::without
397
- describe "::without" do
398
- it "should unset current_tenant inside the block" do
399
- @account = Account.create!(:name => 'baz')
430
+ describe '::without' do
431
+ it 'should unset current_tenant inside the block' do
432
+ @account = Account.create!(name: 'baz')
400
433
 
401
434
  MultiTenant.current_tenant = @account
402
435
  MultiTenant.without do
@@ -404,39 +437,25 @@ describe MultiTenant do
404
437
  end
405
438
  end
406
439
 
407
- it "should reset current_tenant to the previous tenant once exiting the block" do
408
- @account1 = Account.create!(:name => 'foo')
440
+ it 'should reset current_tenant to the previous tenant once exiting the block' do
441
+ @account1 = Account.create!(name: 'foo')
409
442
 
410
443
  MultiTenant.current_tenant = @account1
411
444
  MultiTenant.without do
412
-
413
445
  end
414
446
 
415
447
  expect(MultiTenant.current_tenant).to eq(@account1)
416
448
  end
417
449
 
418
- it "should return the value of the block" do
419
- @account1 = Account.create!(:name => 'foo')
450
+ it 'should return the value of the block' do
451
+ @account1 = Account.create!(name: 'foo')
420
452
 
421
453
  MultiTenant.current_tenant = @account1
422
454
  value = MultiTenant.without do
423
- "something"
455
+ 'something'
424
456
  end
425
457
 
426
- expect(value).to eq "something"
427
- end
428
- end
429
-
430
- describe '.with_lock' do
431
- it 'supports with_lock blocks inside the block' do
432
- @account = Account.create!(name: 'foo')
433
-
434
- MultiTenant.with @account do
435
- project = @account.projects.create!(name: 'project')
436
- project.with_lock do
437
- expect(project.name).to eq 'project'
438
- end
439
- end
458
+ expect(value).to eq 'something'
440
459
  end
441
460
  end
442
461
 
@@ -461,13 +480,20 @@ describe MultiTenant do
461
480
  end
462
481
  end
463
482
 
464
- it "applies the team_id conditions in the where clause" do
465
- option1 = <<-sql.strip
466
- SELECT "sub_tasks".* FROM "sub_tasks" INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id" AND "tasks"."account_id" = "sub_tasks"."account_id" WHERE "tasks"."project_id" = 1 AND "sub_tasks"."account_id" = 1 AND "tasks"."account_id" = 1
467
- sql
468
- option2 = <<-sql.strip
469
- SELECT "sub_tasks".* FROM "sub_tasks" INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id" AND "tasks"."account_id" = "sub_tasks"."account_id" WHERE "sub_tasks"."account_id" = 1 AND "tasks"."project_id" = 1 AND "tasks"."account_id" = 1
470
- sql
483
+ it 'applies the team_id conditions in the where clause' do
484
+ option1 = <<-SQL.strip
485
+ SELECT "sub_tasks".*#{' '}
486
+ FROM "sub_tasks"#{' '}
487
+ INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id" AND "tasks"."account_id" = "sub_tasks"."account_id"#{' '}
488
+ WHERE "tasks"."project_id" = 1 AND "sub_tasks"."account_id" = 1 AND "tasks"."account_id" = 1
489
+ SQL
490
+ option2 = <<-SQL.strip
491
+ SELECT "sub_tasks".*#{' '}
492
+ FROM "sub_tasks"#{' '}
493
+ INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id"#{' '}
494
+ AND "tasks"."account_id" = "sub_tasks"."account_id"#{' '}
495
+ WHERE "sub_tasks"."account_id" = 1 AND "tasks"."project_id" = 1 AND "tasks"."account_id" = 1
496
+ SQL
471
497
 
472
498
  account1 = Account.create! name: 'Account 1'
473
499
 
@@ -475,27 +501,38 @@ describe MultiTenant do
475
501
  project1 = Project.create! name: 'Project 1'
476
502
  task1 = Task.create! name: 'Task 1', project: project1
477
503
  subtask1 = SubTask.create! task: task1
478
- expect(project1.sub_tasks.to_sql).to eq(option1).or(eq(option2))
504
+ expect(format_sql(project1.sub_tasks.to_sql))
505
+ .to eq(format_sql(option1)).or(eq(format_sql(option2)))
479
506
  expect(project1.sub_tasks).to include(subtask1)
480
507
  end
481
508
 
482
509
  MultiTenant.without do
483
- expected_sql = <<-sql
484
- SELECT "sub_tasks".* FROM "sub_tasks" INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id" AND "tasks"."account_id" = "sub_tasks"."account_id" WHERE "tasks"."project_id" = 1
485
- sql
510
+ expected_sql = <<-SQL
511
+ SELECT "sub_tasks".*#{' '}
512
+ FROM "sub_tasks"#{' '}
513
+ INNER JOIN "tasks" ON "sub_tasks"."task_id" = "tasks"."id"#{' '}
514
+ AND "tasks"."account_id" = "sub_tasks"."account_id"#{' '}
515
+ WHERE "tasks"."project_id" = 1
516
+ SQL
486
517
 
487
518
  project = Project.first
488
- expect(project.sub_tasks.to_sql).to eq(expected_sql.strip)
519
+ expect(format_sql(project.sub_tasks.to_sql)).to eq(format_sql(expected_sql.strip))
489
520
  end
490
521
  end
491
522
 
492
- it "tests joins between distributed and reference table" do
493
- option1 = <<-sql.strip
494
- SELECT "categories".* FROM "categories" INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id" WHERE "project_categories"."project_id" = 1 AND "project_categories"."account_id" = 1
495
- sql
496
- option2 = <<-sql.strip
497
- SELECT "categories".* FROM "categories" INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id" WHERE "project_categories"."account_id" = 1 AND "project_categories"."project_id" = 1
498
- sql
523
+ it 'tests joins between distributed and reference table' do
524
+ option1 = <<-SQL.strip
525
+ SELECT "categories".*#{' '}
526
+ FROM "categories"#{' '}
527
+ INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id"#{' '}
528
+ WHERE "project_categories"."project_id" = 1 AND "project_categories"."account_id" = 1
529
+ SQL
530
+ option2 = <<-SQL.strip
531
+ SELECT "categories".*#{' '}
532
+ FROM "categories"#{' '}
533
+ INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id"#{' '}
534
+ WHERE "project_categories"."account_id" = 1 AND "project_categories"."project_id" = 1
535
+ SQL
499
536
 
500
537
  account1 = Account.create! name: 'Account 1'
501
538
  category1 = Category.create! name: 'Category 1'
@@ -504,47 +541,72 @@ describe MultiTenant do
504
541
  project1 = Project.create! name: 'Project 1'
505
542
  projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
506
543
 
507
- expect(project1.categories.to_sql).to eq(option1).or(eq(option2))
544
+ expect(format_sql(project1.categories.to_sql))
545
+ .to eq(format_sql(option1)).or(eq(format_sql(option2)))
508
546
  expect(project1.categories).to include(category1)
509
547
  expect(project1.project_categories).to include(projectcategory)
510
548
  end
511
549
 
512
550
  MultiTenant.without do
513
- expected_sql = <<-sql
514
- SELECT "categories".* FROM "categories" INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id" WHERE "project_categories"."project_id" = 1
515
- sql
551
+ expected_sql = <<-SQL
552
+ SELECT "categories".*#{' '}
553
+ FROM "categories"#{' '}
554
+ INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id"#{' '}
555
+ WHERE "project_categories"."project_id" = 1
556
+ SQL
516
557
 
517
558
  project = Project.first
518
- expect(project.categories.to_sql).to eq(expected_sql.strip)
559
+ expect(format_sql(project.categories.to_sql))
560
+ .to eq(format_sql(expected_sql.strip))
519
561
  expect(project.categories).to include(category1)
520
562
 
521
- expected_sql = <<-sql
522
- SELECT "projects".* FROM "projects" INNER JOIN "project_categories" ON "project_categories"."project_id" = "projects"."id" AND "projects"."account_id" = "project_categories"."account_id" INNER JOIN "categories" ON "categories"."id" = "project_categories"."category_id" WHERE "projects"."account_id" = 1
523
- sql
563
+ expected_sql = <<-SQL
564
+ SELECT "projects".* FROM "projects"#{' '}
565
+ INNER JOIN "project_categories" ON "project_categories"."project_id" = "projects"."id"#{' '}
566
+ AND "projects"."account_id" = "project_categories"."account_id"#{' '}
567
+ INNER JOIN "categories" ON "categories"."id" = "project_categories"."category_id"#{' '}
568
+ WHERE "projects"."account_id" = 1
569
+ SQL
524
570
 
525
- expect(Project.where(account_id: 1).joins(:categories).to_sql).to eq(expected_sql.strip)
571
+ expect(format_sql(Project.where(account_id: 1).joins(:categories).to_sql))
572
+ .to eq(format_sql(expected_sql.strip))
526
573
  project = Project.where(account_id: 1).joins(:categories).first
527
574
  expect(project.categories).to include(category1)
528
575
  end
529
576
  end
530
577
 
531
-
532
- it "test eager_load" do
578
+ it 'test eager_load' do
533
579
  account1 = Account.create! name: 'Account 1'
534
580
  category1 = Category.create! name: 'Category 1'
535
581
 
536
- option1 = <<-sql.strip
537
- SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2, "categories"."id" AS t1_r0, "categories"."name" AS t1_r1 FROM "projects" LEFT OUTER JOIN "project_categories" ON "project_categories"."project_id" = "projects"."id" AND "project_categories"."account_id" = 1 AND "projects"."account_id" = 1 LEFT OUTER JOIN "categories" ON "categories"."id" = "project_categories"."category_id" AND "project_categories"."account_id" = 1 WHERE "projects"."account_id" = 1
538
- sql
539
- option2 = <<-sql.strip
540
- SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2, "categories"."id" AS t1_r0, "categories"."name" AS t1_r1 FROM "projects" LEFT OUTER JOIN "project_categories" ON "project_categories"."account_id" = 1 AND "project_categories"."project_id" = "projects"."id" AND "projects"."account_id" = 1 LEFT OUTER JOIN "categories" ON "categories"."id" = "project_categories"."category_id" AND "project_categories"."account_id" = 1 WHERE "projects"."account_id" = 1
541
- sql
582
+ option1 = <<-SQL.strip
583
+ SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2,
584
+ "categories"."id" AS t1_r0, "categories"."name" AS t1_r1
585
+ FROM "projects"
586
+ LEFT OUTER JOIN "project_categories"
587
+ ON "project_categories"."project_id" = "projects"."id" AND "project_categories"."account_id" = 1
588
+ AND "projects"."account_id" = 1#{' '}
589
+ LEFT OUTER JOIN "categories" ON "categories"."id" = "project_categories"."category_id"
590
+ AND "project_categories"."account_id" = 1
591
+ WHERE "projects"."account_id" = 1
592
+ SQL
593
+ option2 = <<-SQL.strip
594
+ SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2,#{' '}
595
+ "categories"."id" AS t1_r0, "categories"."name" AS t1_r1#{' '}
596
+ FROM "projects"#{' '}
597
+ LEFT OUTER JOIN "project_categories"#{' '}
598
+ ON "project_categories"."account_id" = 1#{' '}
599
+ AND "project_categories"."project_id" = "projects"."id" AND "projects"."account_id" = 1#{' '}
600
+ LEFT OUTER JOIN "categories" ON "categories"."id" = "project_categories"."category_id"#{' '}
601
+ AND "project_categories"."account_id" = 1 WHERE "projects"."account_id" = 1
602
+ SQL
542
603
 
543
604
  MultiTenant.with(account1) do
544
605
  project1 = Project.create! name: 'Project 1'
545
606
  projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
546
607
 
547
- expect(Project.eager_load(:categories).to_sql).to eq(option1).or(eq(option2))
608
+ expect(format_sql(Project.eager_load(:categories).to_sql))
609
+ .to eq(format_sql(option1)).or(eq(format_sql(option2)))
548
610
 
549
611
  project = Project.eager_load(:categories).first
550
612
  expect(project.categories).to include(category1)
@@ -552,92 +614,120 @@ describe MultiTenant do
552
614
  end
553
615
 
554
616
  MultiTenant.without do
555
- expected_sql = <<-sql
556
- SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2, "categories"."id" AS t1_r0, "categories"."name" AS t1_r1 FROM "projects" LEFT OUTER JOIN "project_categories" ON "project_categories"."project_id" = "projects"."id" AND "projects"."account_id" = "project_categories"."account_id" LEFT OUTER JOIN "categories" ON "categories"."id" = "project_categories"."category_id" WHERE "projects"."account_id" = 1
557
- sql
558
-
559
- expect(Project.where(account_id: 1).eager_load(:categories).to_sql).to eq(expected_sql.strip)
617
+ expected_sql = <<-SQL
618
+ SELECT "projects"."id" AS t0_r0, "projects"."account_id" AS t0_r1, "projects"."name" AS t0_r2,#{' '}
619
+ "categories"."id" AS t1_r0, "categories"."name" AS t1_r1#{' '}
620
+ FROM "projects" LEFT OUTER JOIN "project_categories"#{' '}
621
+ ON "project_categories"."project_id" = "projects"."id" AND "projects"."account_id" = "project_categories"."account_id"#{' '}
622
+ LEFT OUTER JOIN "categories"#{' '}
623
+ ON "categories"."id" = "project_categories"."category_id"#{' '}
624
+ WHERE "projects"."account_id" = 1
625
+ SQL
626
+
627
+ expect(format_sql(Project.where(account_id: 1).eager_load(:categories).to_sql))
628
+ .to eq(format_sql(expected_sql.strip))
560
629
 
561
630
  project = Project.where(account_id: 1).eager_load(:categories).first
562
631
  expect(project.categories).to include(category1)
563
-
564
632
  end
565
633
  end
566
634
 
567
- it "test raw SQL joins" do
635
+ it 'test raw SQL joins' do
568
636
  account1 = Account.create! name: 'Account 1'
569
637
  category1 = Category.create! name: 'Category 1'
570
638
 
571
639
  MultiTenant.with(account1) do
572
- option1 = <<-sql.strip
573
- SELECT "tasks".* FROM "tasks" INNER JOIN "projects" ON "projects"."id" = "tasks"."project_id" AND "projects"."account_id" = 1 LEFT JOIN project_categories pc ON project.category_id = pc.id WHERE "tasks"."account_id" = 1
574
- sql
575
- option2 = <<-sql.strip
576
- SELECT "tasks".* FROM "tasks" INNER JOIN "projects" ON "projects"."account_id" = 1 AND "projects"."id" = "tasks"."project_id" LEFT JOIN project_categories pc ON project.category_id = pc.id WHERE "tasks"."account_id" = 1
577
- sql
640
+ option1 = <<-SQL.strip
641
+ SELECT "tasks".* FROM "tasks"
642
+ INNER JOIN "projects" ON "projects"."id" = "tasks"."project_id" AND "projects"."account_id" = 1
643
+ LEFT JOIN project_categories pc ON project.category_id = pc.id#{' '}
644
+ WHERE "tasks"."account_id" = 1
645
+ SQL
646
+ option2 = <<-SQL.strip
647
+ SELECT "tasks".* FROM "tasks"
648
+ INNER JOIN "projects" ON "projects"."account_id" = 1#{' '}
649
+ AND "projects"."id" = "tasks"."project_id"
650
+ LEFT JOIN project_categories pc ON project.category_id = pc.id#{' '}
651
+ WHERE "tasks"."account_id" = 1
652
+ SQL
578
653
 
579
654
  project1 = Project.create! name: 'Project 1'
580
- projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
655
+ ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
581
656
 
582
657
  project1.tasks.create! name: 'baz'
583
- expect(Task.joins(:project).joins('LEFT JOIN project_categories pc ON project.category_id = pc.id').to_sql).to eq(option1).or(eq(option2))
658
+ expect(
659
+ format_sql(
660
+ Task.joins(:project).joins('LEFT JOIN project_categories pc ON project.category_id = pc.id').to_sql
661
+ )
662
+ ).to eq(format_sql(option1)).or(eq(format_sql(option2)))
584
663
  end
585
664
 
586
665
  MultiTenant.without do
587
- expected_sql = <<-sql
588
- SELECT "tasks".* FROM "tasks" INNER JOIN "projects" ON "projects"."id" = "tasks"."project_id" AND "tasks"."account_id" = "projects"."account_id" LEFT JOIN project_categories pc ON project.category_id = pc.id WHERE "tasks"."account_id" = 1
589
- sql
590
-
591
- expect(Task.where(account_id: 1).joins(:project).joins('LEFT JOIN project_categories pc ON project.category_id = pc.id').to_sql).to eq(expected_sql.strip)
592
-
666
+ expected_sql = <<-SQL.strip
667
+ SELECT "tasks".* FROM "tasks"
668
+ INNER JOIN "projects" ON "projects"."id" = "tasks"."project_id"
669
+ AND "tasks"."account_id" = "projects"."account_id"
670
+ LEFT JOIN project_categories pc ON project.category_id = pc.id
671
+ WHERE "tasks"."account_id" = 1
672
+ SQL
673
+
674
+ expect(format_sql(Task.where(account_id: 1).joins(:project)
675
+ .joins('LEFT JOIN project_categories pc ON project.category_id = pc.id')
676
+ .to_sql)).to eq(format_sql(expected_sql.strip))
593
677
  end
594
-
595
678
  end
596
679
 
597
- it "only applies clauses when a tenant is set" do
680
+ it 'only applies clauses when a tenant is set' do
598
681
  account = Account.create! name: 'Account 1'
599
682
  project = Project.create! name: 'Project 1', account: account
600
683
  project2 = Project.create! name: 'Project 2', account: Account.create!(name: 'Account2')
601
684
 
602
685
  MultiTenant.with(account) do
603
- option1 = <<-sql.strip
604
- SELECT "projects".* FROM "projects" WHERE "projects"."account_id" = #{account.id} AND "projects"."id" = $1 LIMIT $2
605
- sql
606
- option2 = <<-sql.strip
607
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 AND "projects"."account_id" = #{account.id} LIMIT $2
608
- sql
609
- option3 = <<-sql.strip
610
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 AND "projects"."account_id" = #{account.id} LIMIT $2
611
- sql
686
+ option1 = <<-SQL.strip
687
+ SELECT "projects".* FROM "projects"#{' '}
688
+ WHERE "projects"."account_id" = #{account.id} AND "projects"."id" = $1 LIMIT $2
689
+ SQL
690
+ option2 = <<-SQL.strip
691
+ SELECT "projects".* FROM "projects"#{' '}
692
+ WHERE "projects"."id" = $1 AND "projects"."account_id" = #{account.id} LIMIT $2
693
+ SQL
694
+ option3 = <<-SQL.strip
695
+ SELECT "projects".* FROM "projects"
696
+ WHERE "projects"."id" = $1
697
+ AND "projects"."account_id" = #{account.id} LIMIT $2
698
+ SQL
612
699
 
613
700
  # Couldn't make the following line pass for some reason, so came up with an uglier alternative
614
- # expect(Project).to receive(:find_by_sql).with(eq(option1).or(eq(option2)).or(eq(option3)), any_args).and_call_original
701
+ # expect(Project).to receive(:find_by_sql).with(eq(option1).
702
+ # or(eq(option2)).or(eq(option3)), any_args).and_call_original
615
703
  expect(Project).to receive(:find_by_sql).and_wrap_original do |m, *args|
616
- expect(args[0]).to(eq(option1).or(eq(option2)).or(eq(option3)))
617
- m.call(args[0], args[1], preparable:args[2][:preparable])
704
+ expect(format_sql(args[0])).to(eq(format_sql(option1))
705
+ .or(eq(format_sql(option2))).or(eq(format_sql(option3))))
706
+ m.call(args[0], args[1], preparable: args[2][:preparable])
618
707
  end
619
708
  expect(Project.find(project.id)).to eq(project)
620
709
  end
621
710
 
622
711
  MultiTenant.without do
623
- option1 = <<-sql.strip
624
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
625
- sql
626
- option2 = <<-sql.strip
627
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
628
- sql
712
+ option1 = <<-SQL.strip
713
+ SELECT "projects".* FROM "projects"#{' '}
714
+ WHERE "projects"."id" = $1 LIMIT $2
715
+ SQL
716
+ option2 = <<-SQL.strip
717
+ SELECT "projects".* FROM "projects"#{' '}
718
+ WHERE "projects"."id" = $1 LIMIT $2
719
+ SQL
629
720
 
630
721
  # Couldn't make the following line pass for some reason, so came up with an uglier alternative
631
722
  # expect(Project).to receive(:find_by_sql).with(eq(option1).or(eq(option2)), any_args).and_call_original
632
723
  expect(Project).to receive(:find_by_sql).and_wrap_original do |m, *args|
633
- expect(args[0]).to(eq(option1).or(eq(option2)))
634
- m.call(args[0], args[1], preparable:args[2][:preparable])
724
+ expect(format_sql(args[0])).to(eq(format_sql(option1)).or(eq(format_sql(option2))))
725
+ m.call(args[0], args[1], preparable: args[2][:preparable])
635
726
  end
636
727
  expect(Project.find(project2.id)).to eq(project2)
637
728
  end
638
729
  end
639
730
 
640
-
641
731
  describe 'with unsaved association' do
642
732
  before do
643
733
  @account = Account.create!(name: 'reflection tenant')
@@ -651,13 +741,13 @@ describe MultiTenant do
651
741
  end
652
742
  end
653
743
 
654
- it "test value of RETURNING insert in table with no pkey" do
744
+ it 'test value of RETURNING insert in table with no pkey' do
655
745
  account1 = Account.create(name: 'test1')
656
746
 
657
747
  MultiTenant.with(account1) do
658
- allowed_place = AllowedPlace.create! name: 'something1'
748
+ AllowedPlace.create! name: 'something1'
659
749
 
660
- project = Project.create! name: 'Project 1'
750
+ Project.create! name: 'Project 1'
661
751
  end
662
752
  end
663
753
  end