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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/CHANGELOG.md +32 -0
- data/Gemfile +4 -1
- data/lib/rom/plugins/relation/sql/auto_wrap.rb +1 -3
- data/lib/rom/sql/association.rb +33 -14
- data/lib/rom/sql/association/many_to_many.rb +17 -10
- data/lib/rom/sql/association/many_to_one.rb +29 -13
- data/lib/rom/sql/association/name.rb +12 -4
- data/lib/rom/sql/association/one_to_many.rb +21 -10
- data/lib/rom/sql/commands/create.rb +0 -1
- data/lib/rom/sql/commands/update.rb +1 -49
- data/lib/rom/sql/dsl.rb +29 -0
- data/lib/rom/sql/expression.rb +26 -0
- data/lib/rom/sql/function.rb +23 -0
- data/lib/rom/sql/gateway.rb +24 -9
- data/lib/rom/sql/migration.rb +6 -7
- data/lib/rom/sql/migration/migrator.rb +7 -8
- data/lib/rom/sql/order_dsl.rb +20 -0
- data/lib/rom/sql/plugin/associates.rb +58 -45
- data/lib/rom/sql/plugin/pagination.rb +8 -11
- data/lib/rom/sql/plugins.rb +0 -2
- data/lib/rom/sql/projection_dsl.rb +41 -0
- data/lib/rom/sql/qualified_attribute.rb +2 -2
- data/lib/rom/sql/relation.rb +35 -67
- data/lib/rom/sql/relation/reading.rb +77 -25
- data/lib/rom/sql/restriction_dsl.rb +24 -0
- data/lib/rom/sql/schema.rb +73 -7
- data/lib/rom/sql/schema/associations_dsl.rb +4 -3
- data/lib/rom/sql/schema/dsl.rb +5 -2
- data/lib/rom/sql/schema/inferrer.rb +21 -11
- data/lib/rom/sql/transaction.rb +19 -0
- data/lib/rom/sql/type.rb +76 -0
- data/lib/rom/sql/version.rb +1 -1
- data/rom-sql.gemspec +3 -4
- data/spec/extensions/postgres/inferrer_spec.rb +19 -9
- data/spec/integration/association/many_to_many/custom_fks_spec.rb +73 -0
- data/spec/integration/association/many_to_many/from_view_spec.rb +81 -0
- data/spec/integration/association/many_to_many_spec.rb +2 -2
- data/spec/integration/association/many_to_one/custom_fks_spec.rb +59 -0
- data/spec/integration/association/many_to_one/from_view_spec.rb +74 -0
- data/spec/integration/association/many_to_one/self_ref_spec.rb +51 -0
- data/spec/integration/association/many_to_one_spec.rb +4 -2
- data/spec/integration/association/one_to_many/custom_fks_spec.rb +48 -0
- data/spec/integration/association/one_to_many/from_view_spec.rb +57 -0
- data/spec/integration/association/one_to_many/self_ref_spec.rb +52 -0
- data/spec/integration/association/one_to_many_spec.rb +1 -1
- data/spec/integration/association/one_to_one_spec.rb +1 -1
- data/spec/integration/association/one_to_one_through_spec.rb +2 -2
- data/spec/integration/commands/create_spec.rb +11 -27
- data/spec/integration/commands/update_spec.rb +54 -109
- data/spec/integration/gateway_spec.rb +31 -17
- data/spec/integration/plugins/associates_spec.rb +27 -0
- data/spec/integration/plugins/auto_wrap_spec.rb +8 -8
- data/spec/integration/schema/call_spec.rb +24 -0
- data/spec/integration/schema/prefix_spec.rb +18 -0
- data/spec/integration/schema/qualified_spec.rb +18 -0
- data/spec/integration/schema/rename_spec.rb +23 -0
- data/spec/integration/schema/view_spec.rb +29 -0
- data/spec/integration/schema_inference_spec.rb +31 -14
- data/spec/spec_helper.rb +2 -2
- data/spec/support/helpers.rb +7 -0
- data/spec/unit/gateway_spec.rb +5 -4
- data/spec/unit/projection_dsl_spec.rb +54 -0
- data/spec/unit/relation/dataset_spec.rb +3 -3
- data/spec/unit/relation/distinct_spec.rb +8 -7
- data/spec/unit/relation/exclude_spec.rb +2 -4
- data/spec/unit/relation/having_spec.rb +6 -4
- data/spec/unit/relation/inner_join_spec.rb +47 -2
- data/spec/unit/relation/invert_spec.rb +2 -3
- data/spec/unit/relation/left_join_spec.rb +44 -3
- data/spec/unit/relation/order_spec.rb +40 -0
- data/spec/unit/relation/prefix_spec.rb +2 -0
- data/spec/unit/relation/project_spec.rb +3 -1
- data/spec/unit/relation/qualified_columns_spec.rb +2 -0
- data/spec/unit/relation/rename_spec.rb +2 -0
- data/spec/unit/relation/right_join_spec.rb +59 -0
- data/spec/unit/relation/select_append_spec.rb +21 -0
- data/spec/unit/relation/select_spec.rb +41 -0
- data/spec/unit/relation/where_spec.rb +28 -0
- data/spec/unit/restriction_dsl_spec.rb +34 -0
- metadata +62 -40
- data/lib/rom/plugins/relation/sql/base_view.rb +0 -31
- data/lib/rom/sql/header.rb +0 -61
- data/lib/rom/sql/plugin/assoc_macros.rb +0 -133
- data/lib/rom/sql/plugin/assoc_macros/class_interface.rb +0 -128
- data/spec/integration/read_spec.rb +0 -111
- data/spec/unit/association_errors_spec.rb +0 -19
- data/spec/unit/plugin/assoc_macros/combined_associations_spec.rb +0 -73
- data/spec/unit/plugin/assoc_macros/many_to_many_spec.rb +0 -53
- data/spec/unit/plugin/assoc_macros/many_to_one_spec.rb +0 -61
- data/spec/unit/plugin/assoc_macros/one_to_many_spec.rb +0 -78
- 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.
|
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.
|
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
|
-
|
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.
|
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 '
|
48
|
-
|
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
|
|
data/spec/support/helpers.rb
CHANGED
data/spec/unit/gateway_spec.rb
CHANGED
@@ -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, :
|
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) {
|
2
|
+
subject(:relation) { relations[:users] }
|
3
3
|
|
4
4
|
include_context 'users and tasks'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
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) {
|
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.
|
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
|
-
|
3
|
+
relations[:users]
|
4
4
|
.inner_join(:tasks, user_id: :id)
|
5
|
-
.
|
6
|
-
.
|
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(
|
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) {
|
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
|
-
|
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) {
|
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.
|
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
|