rom-sql 0.9.1 → 1.0.0.beta1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (93) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +1 -1
  3. data/CHANGELOG.md +32 -0
  4. data/Gemfile +4 -1
  5. data/lib/rom/plugins/relation/sql/auto_wrap.rb +1 -3
  6. data/lib/rom/sql/association.rb +33 -14
  7. data/lib/rom/sql/association/many_to_many.rb +17 -10
  8. data/lib/rom/sql/association/many_to_one.rb +29 -13
  9. data/lib/rom/sql/association/name.rb +12 -4
  10. data/lib/rom/sql/association/one_to_many.rb +21 -10
  11. data/lib/rom/sql/commands/create.rb +0 -1
  12. data/lib/rom/sql/commands/update.rb +1 -49
  13. data/lib/rom/sql/dsl.rb +29 -0
  14. data/lib/rom/sql/expression.rb +26 -0
  15. data/lib/rom/sql/function.rb +23 -0
  16. data/lib/rom/sql/gateway.rb +24 -9
  17. data/lib/rom/sql/migration.rb +6 -7
  18. data/lib/rom/sql/migration/migrator.rb +7 -8
  19. data/lib/rom/sql/order_dsl.rb +20 -0
  20. data/lib/rom/sql/plugin/associates.rb +58 -45
  21. data/lib/rom/sql/plugin/pagination.rb +8 -11
  22. data/lib/rom/sql/plugins.rb +0 -2
  23. data/lib/rom/sql/projection_dsl.rb +41 -0
  24. data/lib/rom/sql/qualified_attribute.rb +2 -2
  25. data/lib/rom/sql/relation.rb +35 -67
  26. data/lib/rom/sql/relation/reading.rb +77 -25
  27. data/lib/rom/sql/restriction_dsl.rb +24 -0
  28. data/lib/rom/sql/schema.rb +73 -7
  29. data/lib/rom/sql/schema/associations_dsl.rb +4 -3
  30. data/lib/rom/sql/schema/dsl.rb +5 -2
  31. data/lib/rom/sql/schema/inferrer.rb +21 -11
  32. data/lib/rom/sql/transaction.rb +19 -0
  33. data/lib/rom/sql/type.rb +76 -0
  34. data/lib/rom/sql/version.rb +1 -1
  35. data/rom-sql.gemspec +3 -4
  36. data/spec/extensions/postgres/inferrer_spec.rb +19 -9
  37. data/spec/integration/association/many_to_many/custom_fks_spec.rb +73 -0
  38. data/spec/integration/association/many_to_many/from_view_spec.rb +81 -0
  39. data/spec/integration/association/many_to_many_spec.rb +2 -2
  40. data/spec/integration/association/many_to_one/custom_fks_spec.rb +59 -0
  41. data/spec/integration/association/many_to_one/from_view_spec.rb +74 -0
  42. data/spec/integration/association/many_to_one/self_ref_spec.rb +51 -0
  43. data/spec/integration/association/many_to_one_spec.rb +4 -2
  44. data/spec/integration/association/one_to_many/custom_fks_spec.rb +48 -0
  45. data/spec/integration/association/one_to_many/from_view_spec.rb +57 -0
  46. data/spec/integration/association/one_to_many/self_ref_spec.rb +52 -0
  47. data/spec/integration/association/one_to_many_spec.rb +1 -1
  48. data/spec/integration/association/one_to_one_spec.rb +1 -1
  49. data/spec/integration/association/one_to_one_through_spec.rb +2 -2
  50. data/spec/integration/commands/create_spec.rb +11 -27
  51. data/spec/integration/commands/update_spec.rb +54 -109
  52. data/spec/integration/gateway_spec.rb +31 -17
  53. data/spec/integration/plugins/associates_spec.rb +27 -0
  54. data/spec/integration/plugins/auto_wrap_spec.rb +8 -8
  55. data/spec/integration/schema/call_spec.rb +24 -0
  56. data/spec/integration/schema/prefix_spec.rb +18 -0
  57. data/spec/integration/schema/qualified_spec.rb +18 -0
  58. data/spec/integration/schema/rename_spec.rb +23 -0
  59. data/spec/integration/schema/view_spec.rb +29 -0
  60. data/spec/integration/schema_inference_spec.rb +31 -14
  61. data/spec/spec_helper.rb +2 -2
  62. data/spec/support/helpers.rb +7 -0
  63. data/spec/unit/gateway_spec.rb +5 -4
  64. data/spec/unit/projection_dsl_spec.rb +54 -0
  65. data/spec/unit/relation/dataset_spec.rb +3 -3
  66. data/spec/unit/relation/distinct_spec.rb +8 -7
  67. data/spec/unit/relation/exclude_spec.rb +2 -4
  68. data/spec/unit/relation/having_spec.rb +6 -4
  69. data/spec/unit/relation/inner_join_spec.rb +47 -2
  70. data/spec/unit/relation/invert_spec.rb +2 -3
  71. data/spec/unit/relation/left_join_spec.rb +44 -3
  72. data/spec/unit/relation/order_spec.rb +40 -0
  73. data/spec/unit/relation/prefix_spec.rb +2 -0
  74. data/spec/unit/relation/project_spec.rb +3 -1
  75. data/spec/unit/relation/qualified_columns_spec.rb +2 -0
  76. data/spec/unit/relation/rename_spec.rb +2 -0
  77. data/spec/unit/relation/right_join_spec.rb +59 -0
  78. data/spec/unit/relation/select_append_spec.rb +21 -0
  79. data/spec/unit/relation/select_spec.rb +41 -0
  80. data/spec/unit/relation/where_spec.rb +28 -0
  81. data/spec/unit/restriction_dsl_spec.rb +34 -0
  82. metadata +62 -40
  83. data/lib/rom/plugins/relation/sql/base_view.rb +0 -31
  84. data/lib/rom/sql/header.rb +0 -61
  85. data/lib/rom/sql/plugin/assoc_macros.rb +0 -133
  86. data/lib/rom/sql/plugin/assoc_macros/class_interface.rb +0 -128
  87. data/spec/integration/read_spec.rb +0 -111
  88. data/spec/unit/association_errors_spec.rb +0 -19
  89. data/spec/unit/plugin/assoc_macros/combined_associations_spec.rb +0 -73
  90. data/spec/unit/plugin/assoc_macros/many_to_many_spec.rb +0 -53
  91. data/spec/unit/plugin/assoc_macros/many_to_one_spec.rb +0 -61
  92. data/spec/unit/plugin/assoc_macros/one_to_many_spec.rb +0 -78
  93. data/spec/unit/plugin/base_view_spec.rb +0 -18
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::Schema, '#prefix' do
4
+ include_context 'database setup'
5
+
6
+ with_adapters :postgres do
7
+ before do
8
+ conf.relation(:users) do
9
+ schema(infer: true)
10
+ end
11
+ end
12
+
13
+ it 'auto-projects a relation with renamed columns using provided prefix' do
14
+ expect(relations[:users].schema.prefix(:user).(relations[:users]).dataset.sql)
15
+ .to eql('SELECT "id" AS "user_id", "name" AS "user_name" FROM "users" ORDER BY "users"."id"')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::Schema, '#qualified' do
4
+ include_context 'database setup'
5
+
6
+ with_adapters :postgres do
7
+ before do
8
+ conf.relation(:users) do
9
+ schema(infer: true)
10
+ end
11
+ end
12
+
13
+ it 'qualifies column names' do
14
+ expect(relations[:users].schema.qualified.(relations[:users]).dataset.sql)
15
+ .to eql('SELECT "users"."id", "users"."name" FROM "users" ORDER BY "users"."id"')
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::Schema, '#rename' do
4
+ include_context 'database setup'
5
+
6
+ with_adapters :postgres do
7
+ before do
8
+ conf.relation(:users) do
9
+ schema(infer: true)
10
+ end
11
+ end
12
+
13
+ it 'auto-projects a relation with renamed columns' do
14
+ expect(relations[:users].schema.rename(id: :user_id, name: :user_name).(relations[:users]).dataset.sql)
15
+ .to eql('SELECT "id" AS "user_id", "name" AS "user_name" FROM "users" ORDER BY "users"."id"')
16
+ end
17
+
18
+ it 'auto-projects a relation with renamed and qualified columns' do
19
+ expect(relations[:users].schema.qualified.rename(id: :user_id, name: :user_name).(relations[:users]).dataset.sql)
20
+ .to eql('SELECT "users"."id" AS "user_id", "users"."name" AS "user_name" FROM "users" ORDER BY "users"."id"')
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe 'Defining a view using schemas' do
4
+ include_context 'database setup'
5
+
6
+ with_adapters do
7
+ describe 'defining a projected view' do
8
+ before do
9
+ conf.relation(:users) do
10
+ schema(infer: true)
11
+
12
+ view(:names) do
13
+ schema { project(:name) }
14
+ relation { order(:name, :id) }
15
+ end
16
+ end
17
+
18
+ container.relations[:users].insert(name: 'Joe')
19
+ container.relations[:users].insert(name: 'Jane')
20
+ container.relations[:users].insert(name: 'Jade')
21
+ end
22
+
23
+ it 'automatically projects a relation view' do
24
+ expect(relations[:users].names.to_a)
25
+ .to eql([{ name: 'Jade' }, { name: 'Jane' }, { name: 'Joe' }])
26
+ end
27
+ end
28
+ end
29
+ end
@@ -19,25 +19,28 @@ RSpec.describe 'Schema inference for common datatypes' do
19
19
 
20
20
  context 'for simple table' do
21
21
  let(:dataset) { :users }
22
+ let(:source) { ROM::Relation::Name[dataset] }
22
23
 
23
24
  it 'can infer attributes for dataset' do
24
- expect(schema.attributes).to eql(
25
- id: ROM::SQL::Types::Serial.meta(name: :id),
26
- name: ROM::SQL::Types::String.meta(name: :name)
25
+ expect(schema.to_h).to eql(
26
+ id: ROM::SQL::Types::Serial.meta(name: :id, source: source),
27
+ name: ROM::SQL::Types::String.meta(name: :name, source: source)
27
28
  )
28
29
  end
29
30
  end
30
31
 
31
32
  context 'for a table with FKs' do
32
33
  let(:dataset) { :tasks }
34
+ let(:source) { ROM::Relation::Name[:tasks] }
33
35
 
34
36
  it 'can infer attributes for dataset' do
35
- expect(schema.attributes).to eql(
36
- id: ROM::SQL::Types::Serial.meta(name: :id),
37
- title: ROM::SQL::Types::String.optional.meta(name: :title),
37
+ expect(schema.to_h).to eql(
38
+ id: ROM::SQL::Types::Serial.meta(name: :id, source: source),
39
+ title: ROM::SQL::Types::String.optional.meta(name: :title, source: source),
38
40
  user_id: ROM::SQL::Types::Int.optional.meta(name: :user_id,
39
41
  foreign_key: true,
40
- relation: :users)
42
+ source: source,
43
+ target: :users)
41
44
  )
42
45
  end
43
46
  end
@@ -63,15 +66,16 @@ RSpec.describe 'Schema inference for common datatypes' do
63
66
  end
64
67
 
65
68
  let(:dataset) { :test_inferrence }
69
+ let(:source) { ROM::Relation::Name[dataset] }
66
70
 
67
71
  it 'can infer attributes for dataset' do
68
- expect(schema.attributes).to eql(
69
- id: ROM::SQL::Types::Serial.meta(name: :id),
70
- text: ROM::SQL::Types::String.meta(name: :text),
71
- flag: ROM::SQL::Types::Bool.meta(name: :flag),
72
- date: ROM::SQL::Types::Date.optional.meta(name: :date),
73
- datetime: ROM::SQL::Types::Time.meta(name: :datetime),
74
- data: ROM::SQL::Types::Blob.optional.meta(name: :data)
72
+ expect(schema.to_h).to eql(
73
+ id: ROM::SQL::Types::Serial.meta(name: :id, source: source),
74
+ text: ROM::SQL::Types::String.meta(name: :text, source: source),
75
+ flag: ROM::SQL::Types::Bool.meta(name: :flag, source: source),
76
+ date: ROM::SQL::Types::Date.optional.meta(name: :date, source: source),
77
+ datetime: ROM::SQL::Types::Time.meta(name: :datetime, source: source),
78
+ data: ROM::SQL::Types::Blob.optional.meta(name: :data, source: source)
75
79
  )
76
80
  end
77
81
  end
@@ -226,4 +230,17 @@ RSpec.describe 'Schema inference for common datatypes' do
226
230
  end
227
231
  end
228
232
  end
233
+
234
+ with_adapters(:postgres) do
235
+ context 'with a table without columns' do
236
+ before do
237
+ conn.create_table(:dummy) unless conn.table_exists?(:dummy)
238
+ conf.relation(:dummy) { schema(infer: true) }
239
+ end
240
+
241
+ it 'does not fail with a weird error when a relation does not have attributes' do
242
+ expect(container.relations[:dummy].schema).to be_empty
243
+ end
244
+ end
245
+ end
229
246
  end
data/spec/spec_helper.rb CHANGED
@@ -44,8 +44,8 @@ TMP_PATH = root.join('../tmp')
44
44
  Dir[root.join('shared/**/*')].each { |f| require f }
45
45
  Dir[root.join('support/**/*')].each { |f| require f }
46
46
 
47
- require 'rom/support/deprecations'
48
- ROM::Deprecations.set_logger!(root.join('../log/deprecations.log'))
47
+ require 'dry/core/deprecations'
48
+ Dry::Core::Deprecations.set_logger!(root.join('../log/deprecations.log'))
49
49
 
50
50
  ROM::SQL.load_extensions(:postgres)
51
51
 
@@ -6,4 +6,11 @@ module Helpers
6
6
  def assoc_name(*args)
7
7
  ROM::SQL::Association::Name[*args]
8
8
  end
9
+
10
+ def define_schema(name, attrs)
11
+ ROM::SQL::Schema.define(
12
+ name,
13
+ attributes: attrs.map { |key, value| ROM::SQL::Type.new(value.meta(name: key)) }
14
+ )
15
+ end
9
16
  end
@@ -38,19 +38,20 @@ RSpec.describe ROM::SQL::Gateway, :postgres do
38
38
  migrator = double('migrator')
39
39
 
40
40
  expect(Sequel).to receive(:connect)
41
- .with(uri, host: '127.0.0.1')
41
+ .with(uri, host: '127.0.0.1', migrator: migrator)
42
42
  .and_return(conn)
43
43
 
44
44
  gateway = ROM::SQL::Gateway.new(uri, migrator: migrator, host: '127.0.0.1')
45
45
 
46
- expect(gateway.options).to eql(migrator: migrator)
46
+ expect(gateway.options).to eql(migrator: migrator, host: '127.0.0.1')
47
47
  end
48
48
 
49
49
  it 'allows extensions' do
50
- extensions = [:pg_array, :pg_enum]
50
+ extensions = [:pg_array, :pg_array_ops]
51
51
  connection = Sequel.connect uri
52
52
 
53
- expect(connection).to receive(:extension).with(:pg_array, :pg_json, :pg_enum)
53
+ expect(connection).to receive(:extension).with(:pg_array, :pg_json, :pg_enum, :pg_array_ops)
54
+ expect(connection).to receive(:extension).with(:freeze_datasets) unless RUBY_ENGINE == 'rbx'
54
55
 
55
56
  ROM::SQL::Gateway.new(connection, extensions: extensions)
56
57
  end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ RSpec.describe ROM::SQL::ProjectionDSL, :sqlite, helpers: true do
4
+ include_context 'database setup'
5
+
6
+ subject(:dsl) do
7
+ ROM::SQL::ProjectionDSL.new(schema)
8
+ end
9
+
10
+ let(:schema) do
11
+ define_schema(:users, id: ROM::SQL::Types::Serial, name: ROM::SQL::Types::String)
12
+ end
13
+
14
+ let(:ds) do
15
+ conn[:users]
16
+ end
17
+
18
+ describe '#call' do
19
+ it 'evaluates the block and returns an array with attribute types' do
20
+ literals = dsl
21
+ .call { int::count(id).as(:count) }
22
+ .map { |attr| attr.sql_literal(ds) }
23
+
24
+ expect(literals).to eql(["count(`id`) AS 'count'"])
25
+ end
26
+ end
27
+
28
+ describe '#method_missing' do
29
+ it 'responds to methods matching attribute names' do
30
+ expect(dsl.id).to eql(schema[:id])
31
+ expect(dsl.name).to eql(schema[:name])
32
+ end
33
+
34
+ it 'responds to methods matching type identifiers' do
35
+ expect(dsl.int).to eql(ROM::SQL::Types::Int)
36
+ expect(dsl.string).to eql(ROM::SQL::Types::String)
37
+ expect(dsl.bool).to eql(ROM::SQL::Types::Bool)
38
+ end
39
+
40
+ it 'responds to methods matching type names' do
41
+ expect(dsl.DateTime).to eql(ROM::SQL::Types::DateTime)
42
+ end
43
+
44
+ it 'returns sql functions with return type specified' do
45
+ function = ROM::SQL::Function.new(ROM::SQL::Types::String).upper(schema[:name])
46
+
47
+ expect(dsl.string::upper(schema[:name])).to eql(function)
48
+ end
49
+
50
+ it 'raises NoMethodError when there is no matching attribute or type' do
51
+ expect { dsl.not_here }.to raise_error(NoMethodError, /not_here/)
52
+ end
53
+ end
54
+ end
@@ -17,7 +17,7 @@ RSpec.describe ROM::Relation, '#dataset' do
17
17
  end
18
18
 
19
19
  it 'uses schema to infer default dataset' do
20
- expect(relation.dataset).to eql(dataset.select(:id, :name).order(:users__id))
20
+ expect(relation.dataset.sql).to eql(dataset.select(:id, :name).order(:users__id).sql)
21
21
  end
22
22
  end
23
23
 
@@ -31,7 +31,7 @@ RSpec.describe ROM::Relation, '#dataset' do
31
31
  end
32
32
 
33
33
  it 'uses schema to infer default dataset' do
34
- expect(relation.dataset).to eql(dataset.select(:id).order(:users__id))
34
+ expect(relation.dataset.sql).to eql(dataset.select(:id).order(:users__id).sql)
35
35
  end
36
36
  end
37
37
 
@@ -41,7 +41,7 @@ RSpec.describe ROM::Relation, '#dataset' do
41
41
  end
42
42
 
43
43
  it 'selects all qualified columns and sorts by pk' do
44
- expect(relation.dataset).to eql(dataset.select(*relation.columns).order(:users__id))
44
+ expect(relation.dataset.sql).to eql(dataset.select(*relation.columns).order(:users__id).sql)
45
45
  end
46
46
  end
47
47
  end
@@ -1,14 +1,15 @@
1
1
  RSpec.describe ROM::Relation, '#distinct' do
2
- subject(:relation) { container.relations.users }
2
+ subject(:relation) { relations[:users] }
3
3
 
4
4
  include_context 'users and tasks'
5
5
 
6
- with_adapters do
7
- if !metadata[:sqlite]
8
- it 'delegates to dataset and returns a new relation' do
9
- expect(relation.dataset).to receive(:distinct).with(:name).and_call_original
10
- expect(relation.distinct(:name)).to_not eql(relation)
11
- end
6
+ before do
7
+ relation.insert id: 3, name: 'Jane'
8
+ end
9
+
10
+ with_adapters :postgres do
11
+ it 'delegates to dataset and returns a new relation' do
12
+ expect(relation.distinct(:name).order(:name).group(:name, :id).to_a).to eql([{ id: 1, name: 'Jane' }, { id: 2, name: 'Joe' }])
12
13
  end
13
14
  end
14
15
  end
@@ -1,13 +1,11 @@
1
1
  RSpec.describe ROM::Relation, '#exclude' do
2
- subject(:relation) { container.relations.users }
2
+ subject(:relation) { relations[:users] }
3
3
 
4
4
  include_context 'users and tasks'
5
5
 
6
6
  with_adapters do
7
7
  it 'delegates to dataset and returns a new relation' do
8
- expect(relation.dataset)
9
- .to receive(:exclude).with(name: 'Jane').and_call_original
10
- expect(relation.exclude(name: 'Jane')).to_not eq(relation)
8
+ expect(relation.exclude(name: 'Jane').to_a).to eql([{ id: 2, name: 'Joe' }])
11
9
  end
12
10
  end
13
11
  end
@@ -1,9 +1,10 @@
1
1
  RSpec.describe ROM::Relation, '#having' do
2
2
  subject(:relation) do
3
- container.relations.users
3
+ relations[:users]
4
4
  .inner_join(:tasks, user_id: :id)
5
- .select_group(:users__id, :users__name)
6
- .select_append { count(:tasks).as(:task_count) }
5
+ .qualified
6
+ .select_group(:id, :name)
7
+ .select_append { int::count(:tasks).as(:task_count) }
7
8
  end
8
9
 
9
10
  include_context 'users and tasks'
@@ -14,7 +15,8 @@ RSpec.describe ROM::Relation, '#having' do
14
15
  end
15
16
 
16
17
  it 'restricts a relation using HAVING clause' do
17
- expect(relation.having { count(:tasks__id) >= 2 }.to_a).to eq([{ id: 2, name: 'Joe', task_count: 2 }])
18
+ expect(relation.having { count(id.qualified) >= 2 }.to_a).
19
+ to eq([{ id: 2, name: 'Joe', task_count: 2 }])
18
20
  end
19
21
  end
20
22
  end
@@ -1,11 +1,19 @@
1
1
  RSpec.describe ROM::Relation, '#inner_join' do
2
- subject(:relation) { container.relations.users }
2
+ subject(:relation) { relations[:users] }
3
+
4
+ let(:tasks) { relations[:tasks] }
3
5
 
4
6
  include_context 'users and tasks'
5
7
 
6
8
  with_adapters do
7
9
  it 'joins relations using inner join' do
8
- result = relation.inner_join(:tasks, user_id: :id).select(:name, :title)
10
+ relation.insert id: 3, name: 'Jade'
11
+
12
+ result = relation.
13
+ inner_join(:tasks, user_id: :id).
14
+ select(:name, tasks[:title])
15
+
16
+ expect(result.schema.map(&:name)).to eql(%i[name title])
9
17
 
10
18
  expect(result.to_a).to eql([
11
19
  { name: 'Jane', title: "Jane's task" },
@@ -13,10 +21,47 @@ RSpec.describe ROM::Relation, '#inner_join' do
13
21
  ])
14
22
  end
15
23
 
24
+ context 'with associations' do
25
+ before do
26
+ conf.relation(:users) do
27
+ schema(infer: true) do
28
+ associations { has_many :tasks }
29
+ end
30
+ end
31
+
32
+ conf.relation(:tasks) do
33
+ schema(infer: true) do
34
+ associations { belongs_to :user }
35
+ end
36
+ end
37
+
38
+ relation.insert id: 3, name: 'Jade'
39
+ end
40
+
41
+ it 'joins relation with join keys inferred' do
42
+ result = relation.
43
+ inner_join(tasks).
44
+ select(:name, tasks[:title])
45
+
46
+ expect(result.schema.map(&:name)).to eql(%i[name title])
47
+
48
+ expect(result.to_a).to eql([
49
+ { name: 'Jane', title: "Jane's task" },
50
+ { name: 'Joe', title: "Joe's task" }
51
+ ])
52
+ end
53
+ end
54
+
16
55
  it 'raises error when column names are ambiguous' do
17
56
  expect {
18
57
  relation.inner_join(:tasks, user_id: :id).to_a
19
58
  }.to raise_error(Sequel::DatabaseError, /ambiguous/)
20
59
  end
60
+
61
+ it 'raises error when join arg is unsupported' do
62
+ expect {
63
+ relation.inner_join(421)
64
+ }.to raise_error(ArgumentError, /other/)
65
+ end
21
66
  end
22
67
  end
@@ -1,12 +1,11 @@
1
1
  RSpec.describe ROM::Relation, '#invert' do
2
- subject(:relation) { container.relations.users }
2
+ subject(:relation) { relations[:users] }
3
3
 
4
4
  include_context 'users and tasks'
5
5
 
6
6
  with_adapters do
7
7
  it 'delegates to dataset and returns a new relation' do
8
- expect(relation.dataset).to receive(:invert).and_call_original
9
- expect(relation.invert).to_not eq(relation)
8
+ expect(relation.where(name: 'Jane').invert.to_a).to eql([{ id: 2, name: 'Joe' }])
10
9
  end
11
10
  end
12
11
  end