activerecord-multi-tenant 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (120) 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 -0
  8. data/CHANGELOG.md +6 -0
  9. data/Gemfile +3 -1
  10. data/LICENSE +0 -0
  11. data/README.md +2 -1
  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 +18 -8
  88. data/lib/activerecord-multi-tenant/model_extensions.rb +78 -37
  89. data/lib/activerecord-multi-tenant/multi_tenant.rb +40 -21
  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 +233 -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 +130 -25
  111. data/.github/workflows/CI.yml +0 -47
  112. data/gemfiles/.bundle/config +0 -2
  113. data/gemfiles/active_record_6.0.gemfile +0 -8
  114. data/gemfiles/active_record_6.1.gemfile +0 -8
  115. data/gemfiles/active_record_7.0.gemfile +0 -8
  116. data/gemfiles/rails_6.0.gemfile +0 -8
  117. data/gemfiles/rails_6.1.gemfile +0 -8
  118. data/gemfiles/rails_7.0.gemfile +0 -8
  119. data/lib/activerecord-multi-tenant/with_lock.rb +0 -15
  120. 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
@@ -237,7 +246,7 @@ describe MultiTenant do
237
246
  MultiTenant.with(account) do
238
247
  sub_task
239
248
  manager
240
- 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
241
250
  end
242
251
  end
243
252
  end
@@ -248,7 +257,8 @@ describe MultiTenant do
248
257
 
249
258
  it 'rewrites sub-selects correctly' do
250
259
  MultiTenant.with(account) do
251
- 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
252
262
  end
253
263
  end
254
264
  end
@@ -277,34 +287,34 @@ describe MultiTenant do
277
287
  end
278
288
 
279
289
  describe 'non-STI Subclass of abstract Multi Tenant Model' do
280
- let(:tenant_id_1) { 42 }
281
- let(:tenant_id_2) { 314158 }
290
+ let(:tenant_id1) { 42 }
291
+ let(:tenant_id2) { 314_158 }
282
292
  let(:name) { 'fooname' }
283
- let(:subclass_task_1) do
284
- MultiTenant.with(tenant_id_1) { SubclassTask.create! name: name }
293
+ let(:subclass_task1) do
294
+ MultiTenant.with(tenant_id1) { SubclassTask.create! name: name }
285
295
  end
286
- let(:subclass_task_2) do
287
- MultiTenant.with(tenant_id_2) { SubclassTask.create! name: name }
296
+ let(:subclass_task2) do
297
+ MultiTenant.with(tenant_id2) { SubclassTask.create! name: name }
288
298
  end
289
299
 
290
300
  before do
291
- subclass_task_1
292
- subclass_task_2
301
+ subclass_task1
302
+ subclass_task2
293
303
  end
294
304
 
295
305
  it 'injects tenant_id on create' do
296
- expect(subclass_task_1.non_model_id).to be tenant_id_1
297
- 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
298
308
  end
299
309
 
300
310
  it 'rewrites query' do
301
- MultiTenant.with(tenant_id_1) do
311
+ MultiTenant.with(tenant_id1) do
302
312
  expect(SubclassTask.where(name: name).count).to eq 1
303
- expect(SubclassTask.where(name: name).first).to eq subclass_task_1
313
+ expect(SubclassTask.where(name: name).first).to eq subclass_task1
304
314
  end
305
- MultiTenant.with(tenant_id_2) do
315
+ MultiTenant.with(tenant_id2) do
306
316
  expect(SubclassTask.where(name: name).count).to eq 1
307
- expect(SubclassTask.where(name: name).first).to eq subclass_task_2
317
+ expect(SubclassTask.where(name: name).first).to eq subclass_task2
308
318
  end
309
319
  end
310
320
  end
@@ -316,20 +326,27 @@ describe MultiTenant do
316
326
 
317
327
  it 'should add tenant condition to the queries when tenant is set' do
318
328
  expected_join_sql = <<-SQL.strip
319
- 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
320
334
  SQL
321
335
 
322
336
  MultiTenant.with(account) do
323
- 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))
324
338
  end
325
339
  end
326
340
 
327
341
  it 'should add tenant condition to the queries when tenant is not set' do
328
342
  MultiTenant.without do
329
343
  expected_join_sql = <<-SQL.strip
330
- 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"
331
348
  SQL
332
- 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))
333
350
  end
334
351
  end
335
352
  end
@@ -339,57 +356,63 @@ describe MultiTenant do
339
356
 
340
357
  it 'should add tenant condition to the queries when tenant is set' do
341
358
  expected_join_sql = <<-SQL.strip
342
- 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
343
364
  SQL
344
365
 
345
366
  MultiTenant.with(account) do
346
- 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))
347
368
  end
348
369
  end
349
370
 
350
371
  it 'should add tenant condition to the queries when tenant is not set' do
351
372
  MultiTenant.without do
352
373
  expected_join_sql = <<-SQL.strip
353
- 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"
354
378
  SQL
355
- 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))
356
380
  end
357
381
  end
358
382
  end
359
383
  end
360
384
 
361
385
  # ::with
362
- describe "::with" do
363
- it "should set current_tenant to the specified tenant inside the block" do
364
- @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')
365
389
 
366
390
  MultiTenant.with(@account) do
367
391
  expect(MultiTenant.current_tenant).to eq(@account)
368
392
  end
369
393
  end
370
394
 
371
- it "should reset current_tenant to the previous tenant once exiting the block" do
372
- @account1 = Account.create!(:name => 'foo')
373
- @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')
374
398
 
375
399
  MultiTenant.current_tenant = @account1
376
400
  MultiTenant.with @account2 do
377
-
378
401
  end
379
402
 
380
403
  expect(MultiTenant.current_tenant).to eq(@account1)
381
404
  end
382
405
 
383
- it "should return the value of the block" do
384
- @account1 = Account.create!(:name => 'foo')
385
- @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')
386
409
 
387
410
  MultiTenant.current_tenant = @account1
388
411
  value = MultiTenant.with @account2 do
389
- "something"
412
+ 'something'
390
413
  end
391
414
 
392
- expect(value).to eq "something"
415
+ expect(value).to eq 'something'
393
416
  end
394
417
 
395
418
  it 'supports reload inside the block' do
@@ -404,9 +427,9 @@ describe MultiTenant do
404
427
  end
405
428
 
406
429
  # ::without
407
- describe "::without" do
408
- it "should unset current_tenant inside the block" do
409
- @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')
410
433
 
411
434
  MultiTenant.current_tenant = @account
412
435
  MultiTenant.without do
@@ -414,39 +437,25 @@ describe MultiTenant do
414
437
  end
415
438
  end
416
439
 
417
- it "should reset current_tenant to the previous tenant once exiting the block" do
418
- @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')
419
442
 
420
443
  MultiTenant.current_tenant = @account1
421
444
  MultiTenant.without do
422
-
423
445
  end
424
446
 
425
447
  expect(MultiTenant.current_tenant).to eq(@account1)
426
448
  end
427
449
 
428
- it "should return the value of the block" do
429
- @account1 = Account.create!(:name => 'foo')
450
+ it 'should return the value of the block' do
451
+ @account1 = Account.create!(name: 'foo')
430
452
 
431
453
  MultiTenant.current_tenant = @account1
432
454
  value = MultiTenant.without do
433
- "something"
455
+ 'something'
434
456
  end
435
457
 
436
- expect(value).to eq "something"
437
- end
438
- end
439
-
440
- describe '.with_lock' do
441
- it 'supports with_lock blocks inside the block' do
442
- @account = Account.create!(name: 'foo')
443
-
444
- MultiTenant.with @account do
445
- project = @account.projects.create!(name: 'project')
446
- project.with_lock do
447
- expect(project.name).to eq 'project'
448
- end
449
- end
458
+ expect(value).to eq 'something'
450
459
  end
451
460
  end
452
461
 
@@ -471,13 +480,20 @@ describe MultiTenant do
471
480
  end
472
481
  end
473
482
 
474
- it "applies the team_id conditions in the where clause" do
475
- option1 = <<-sql.strip
476
- 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
477
- sql
478
- option2 = <<-sql.strip
479
- 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
480
- 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
481
497
 
482
498
  account1 = Account.create! name: 'Account 1'
483
499
 
@@ -485,27 +501,38 @@ describe MultiTenant do
485
501
  project1 = Project.create! name: 'Project 1'
486
502
  task1 = Task.create! name: 'Task 1', project: project1
487
503
  subtask1 = SubTask.create! task: task1
488
- 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)))
489
506
  expect(project1.sub_tasks).to include(subtask1)
490
507
  end
491
508
 
492
509
  MultiTenant.without do
493
- expected_sql = <<-sql
494
- 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
495
- 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
496
517
 
497
518
  project = Project.first
498
- 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))
499
520
  end
500
521
  end
501
522
 
502
- it "tests joins between distributed and reference table" do
503
- option1 = <<-sql.strip
504
- 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
505
- sql
506
- option2 = <<-sql.strip
507
- 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
508
- 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
509
536
 
510
537
  account1 = Account.create! name: 'Account 1'
511
538
  category1 = Category.create! name: 'Category 1'
@@ -514,47 +541,72 @@ describe MultiTenant do
514
541
  project1 = Project.create! name: 'Project 1'
515
542
  projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
516
543
 
517
- 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)))
518
546
  expect(project1.categories).to include(category1)
519
547
  expect(project1.project_categories).to include(projectcategory)
520
548
  end
521
549
 
522
550
  MultiTenant.without do
523
- expected_sql = <<-sql
524
- SELECT "categories".* FROM "categories" INNER JOIN "project_categories" ON "categories"."id" = "project_categories"."category_id" WHERE "project_categories"."project_id" = 1
525
- 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
526
557
 
527
558
  project = Project.first
528
- 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))
529
561
  expect(project.categories).to include(category1)
530
562
 
531
- expected_sql = <<-sql
532
- 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
533
- 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
534
570
 
535
- 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))
536
573
  project = Project.where(account_id: 1).joins(:categories).first
537
574
  expect(project.categories).to include(category1)
538
575
  end
539
576
  end
540
577
 
541
-
542
- it "test eager_load" do
578
+ it 'test eager_load' do
543
579
  account1 = Account.create! name: 'Account 1'
544
580
  category1 = Category.create! name: 'Category 1'
545
581
 
546
- option1 = <<-sql.strip
547
- 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
548
- sql
549
- option2 = <<-sql.strip
550
- 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
551
- 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
552
603
 
553
604
  MultiTenant.with(account1) do
554
605
  project1 = Project.create! name: 'Project 1'
555
606
  projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
556
607
 
557
- 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)))
558
610
 
559
611
  project = Project.eager_load(:categories).first
560
612
  expect(project.categories).to include(category1)
@@ -562,92 +614,120 @@ describe MultiTenant do
562
614
  end
563
615
 
564
616
  MultiTenant.without do
565
- expected_sql = <<-sql
566
- 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
567
- sql
568
-
569
- 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))
570
629
 
571
630
  project = Project.where(account_id: 1).eager_load(:categories).first
572
631
  expect(project.categories).to include(category1)
573
-
574
632
  end
575
633
  end
576
634
 
577
- it "test raw SQL joins" do
635
+ it 'test raw SQL joins' do
578
636
  account1 = Account.create! name: 'Account 1'
579
637
  category1 = Category.create! name: 'Category 1'
580
638
 
581
639
  MultiTenant.with(account1) do
582
- option1 = <<-sql.strip
583
- 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
584
- sql
585
- option2 = <<-sql.strip
586
- 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
587
- 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
588
653
 
589
654
  project1 = Project.create! name: 'Project 1'
590
- projectcategory = ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
655
+ ProjectCategory.create! name: 'project cat 1', project: project1, category: category1
591
656
 
592
657
  project1.tasks.create! name: 'baz'
593
- 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)))
594
663
  end
595
664
 
596
665
  MultiTenant.without do
597
- expected_sql = <<-sql
598
- 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
599
- sql
600
-
601
- 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)
602
-
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))
603
677
  end
604
-
605
678
  end
606
679
 
607
- it "only applies clauses when a tenant is set" do
680
+ it 'only applies clauses when a tenant is set' do
608
681
  account = Account.create! name: 'Account 1'
609
682
  project = Project.create! name: 'Project 1', account: account
610
683
  project2 = Project.create! name: 'Project 2', account: Account.create!(name: 'Account2')
611
684
 
612
685
  MultiTenant.with(account) do
613
- option1 = <<-sql.strip
614
- SELECT "projects".* FROM "projects" WHERE "projects"."account_id" = #{account.id} AND "projects"."id" = $1 LIMIT $2
615
- sql
616
- option2 = <<-sql.strip
617
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 AND "projects"."account_id" = #{account.id} LIMIT $2
618
- sql
619
- option3 = <<-sql.strip
620
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 AND "projects"."account_id" = #{account.id} LIMIT $2
621
- 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
622
699
 
623
700
  # Couldn't make the following line pass for some reason, so came up with an uglier alternative
624
- # 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
625
703
  expect(Project).to receive(:find_by_sql).and_wrap_original do |m, *args|
626
- expect(args[0]).to(eq(option1).or(eq(option2)).or(eq(option3)))
627
- 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])
628
707
  end
629
708
  expect(Project.find(project.id)).to eq(project)
630
709
  end
631
710
 
632
711
  MultiTenant.without do
633
- option1 = <<-sql.strip
634
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
635
- sql
636
- option2 = <<-sql.strip
637
- SELECT "projects".* FROM "projects" WHERE "projects"."id" = $1 LIMIT $2
638
- 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
639
720
 
640
721
  # Couldn't make the following line pass for some reason, so came up with an uglier alternative
641
722
  # expect(Project).to receive(:find_by_sql).with(eq(option1).or(eq(option2)), any_args).and_call_original
642
723
  expect(Project).to receive(:find_by_sql).and_wrap_original do |m, *args|
643
- expect(args[0]).to(eq(option1).or(eq(option2)))
644
- 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])
645
726
  end
646
727
  expect(Project.find(project2.id)).to eq(project2)
647
728
  end
648
729
  end
649
730
 
650
-
651
731
  describe 'with unsaved association' do
652
732
  before do
653
733
  @account = Account.create!(name: 'reflection tenant')
@@ -661,13 +741,13 @@ describe MultiTenant do
661
741
  end
662
742
  end
663
743
 
664
- 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
665
745
  account1 = Account.create(name: 'test1')
666
746
 
667
747
  MultiTenant.with(account1) do
668
- allowed_place = AllowedPlace.create! name: 'something1'
748
+ AllowedPlace.create! name: 'something1'
669
749
 
670
- project = Project.create! name: 'Project 1'
750
+ Project.create! name: 'Project 1'
671
751
  end
672
752
  end
673
753
  end