rom-sql 1.0.1 → 1.0.2
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/CHANGELOG.md +10 -0
- data/Gemfile +1 -0
- data/lib/rom/sql/attribute.rb +1 -1
- data/lib/rom/sql/projection_dsl.rb +6 -0
- data/lib/rom/sql/version.rb +1 -1
- data/rom-sql.gemspec +1 -1
- data/spec/integration/association/many_to_many/custom_fks_spec.rb +9 -13
- data/spec/integration/association/many_to_many/from_view_spec.rb +9 -8
- data/spec/integration/association/many_to_many_spec.rb +103 -102
- data/spec/integration/association/many_to_one/custom_fks_spec.rb +6 -7
- data/spec/integration/association/many_to_one/from_view_spec.rb +8 -4
- data/spec/integration/association/many_to_one_spec.rb +61 -54
- data/spec/integration/association/one_to_many/custom_fks_spec.rb +7 -6
- data/spec/integration/association/one_to_many/from_view_spec.rb +7 -10
- data/spec/integration/association/one_to_many/self_ref_spec.rb +6 -6
- data/spec/integration/association/one_to_many_spec.rb +0 -3
- data/spec/integration/association/one_to_one_spec.rb +17 -11
- data/spec/integration/association/one_to_one_through_spec.rb +3 -5
- data/spec/integration/commands/create_spec.rb +33 -22
- data/spec/integration/commands/update_spec.rb +3 -3
- data/spec/integration/commands/upsert_spec.rb +1 -1
- data/spec/integration/gateway_spec.rb +12 -8
- data/spec/integration/migration_spec.rb +4 -3
- data/spec/integration/plugins/associates/many_to_many_spec.rb +2 -2
- data/spec/integration/plugins/associates_spec.rb +1 -1
- data/spec/integration/relation_schema_spec.rb +4 -5
- data/spec/integration/schema/call_spec.rb +1 -1
- data/spec/integration/schema/inferrer/mysql_spec.rb +22 -23
- data/spec/integration/schema/inferrer/postgres_spec.rb +83 -82
- data/spec/integration/schema/inferrer/sqlite_spec.rb +18 -19
- data/spec/integration/schema/inferrer_spec.rb +54 -33
- data/spec/integration/schema/prefix_spec.rb +9 -11
- data/spec/integration/schema/qualified_spec.rb +9 -11
- data/spec/integration/schema/rename_spec.rb +13 -15
- data/spec/integration/schema/view_spec.rb +2 -2
- data/spec/integration/sequel_api_spec.rb +1 -1
- data/spec/integration/setup_spec.rb +5 -5
- data/spec/integration/support/active_support_notifications_spec.rb +2 -2
- data/spec/integration/support/rails_log_subscriber_spec.rb +2 -2
- data/spec/shared/accounts.rb +44 -0
- data/spec/shared/database_setup.rb +42 -81
- data/spec/shared/notes.rb +21 -0
- data/spec/shared/posts.rb +32 -0
- data/spec/shared/puppies.rb +13 -0
- data/spec/shared/relations.rb +1 -1
- data/spec/shared/users.rb +29 -0
- data/spec/shared/users_and_tasks.rb +32 -18
- data/spec/spec_helper.rb +18 -30
- data/spec/support/env_helper.rb +25 -0
- data/spec/support/oracle/create_users.sql +7 -0
- data/spec/support/oracle/set_sys_passwords.sql +2 -0
- data/spec/unit/plugin/pagination_spec.rb +2 -2
- data/spec/unit/plugin/timestamp_spec.rb +1 -1
- data/spec/unit/projection_dsl_spec.rb +8 -0
- data/spec/unit/relation/group_spec.rb +5 -3
- data/spec/unit/relation/max_spec.rb +1 -1
- data/spec/unit/relation/select_spec.rb +7 -0
- metadata +33 -5
- data/spec/shared/users_and_accounts.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e3faf5e4b8e2aa655c4a646421cf148cad3e137e
|
4
|
+
data.tar.gz: 2b1ac9258b8f15111297a71acf92f46f0f19607c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d11f6ab0d5a70192f29b1028d5d3acd81ce8b06f3d0edb6a74c24f8c869006837630476fcda3260aa021adbd3f0b5aa321e70df50feeb6d480b701524ff34329
|
7
|
+
data.tar.gz: b3f894dc4a8eddc3cca586186beaa530a0bf6317593622fca1ab86a568083dbeb88564bcba1c4110ee8230fb04c39792df0a760993908feaa999bed601e708a3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,11 @@
|
|
1
|
+
## v1.0.2 2017-02-16
|
2
|
+
|
3
|
+
### Added
|
4
|
+
|
5
|
+
* Support for selecting literal strings via `select { `'foo'`.as(:bar) }` (solnic)
|
6
|
+
|
7
|
+
[Compare v1.0.1...v1.0.2](https://github.com/rom-rb/rom-sql/compare/v1.0.1...v1.0.2)
|
8
|
+
|
1
9
|
## v1.0.1 2017-02-09
|
2
10
|
|
3
11
|
### Added
|
@@ -11,6 +19,8 @@
|
|
11
19
|
|
12
20
|
* Missing primary key now leads to a more meaningful error (flash-gordon)
|
13
21
|
|
22
|
+
[Compare v1.0.0...v1.0.1](https://github.com/rom-rb/rom-sql/compare/v1.0.0...v1.0.1)
|
23
|
+
|
14
24
|
## v1.0.0 2017-01-29
|
15
25
|
|
16
26
|
This release is based on rom core 3.0.0 with its improved Schema API, which is extended with SQL-specific features.
|
data/Gemfile
CHANGED
data/lib/rom/sql/attribute.rb
CHANGED
@@ -5,6 +5,12 @@ module ROM
|
|
5
5
|
module SQL
|
6
6
|
# @api private
|
7
7
|
class ProjectionDSL < DSL
|
8
|
+
# @api public
|
9
|
+
def `(value)
|
10
|
+
expr = ::Sequel::VIRTUAL_ROW.instance_eval { `#{value}` }
|
11
|
+
::ROM::SQL::Attribute.new(type(:string)).meta(sql_expr: expr)
|
12
|
+
end
|
13
|
+
|
8
14
|
# @api private
|
9
15
|
def respond_to_missing?(name, include_private = false)
|
10
16
|
super || type(name)
|
data/lib/rom/sql/version.rb
CHANGED
data/rom-sql.gemspec
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# coding: utf-8
|
2
1
|
lib = File.expand_path('../lib', __FILE__)
|
3
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
3
|
require 'rom/sql/version'
|
@@ -26,4 +25,5 @@ Gem::Specification.new do |spec|
|
|
26
25
|
|
27
26
|
spec.add_development_dependency 'bundler'
|
28
27
|
spec.add_development_dependency 'rake', '~> 10.0'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 3.5'
|
29
29
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
2
|
+
include_context 'users'
|
3
|
+
|
4
|
+
before do
|
5
|
+
inferrable_relations.concat %i(puzzles puzzle_solvers)
|
6
|
+
end
|
7
|
+
|
2
8
|
subject(:assoc) do
|
3
9
|
relations[:users].associations[:puzzles]
|
4
10
|
end
|
5
11
|
|
6
|
-
include_context 'database setup'
|
7
|
-
|
8
12
|
with_adapters do
|
9
13
|
before do
|
10
14
|
conn.create_table(:puzzles) do
|
@@ -36,9 +40,6 @@ RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
|
36
40
|
end
|
37
41
|
end
|
38
42
|
|
39
|
-
joe_id = relations[:users].insert(name: 'Joe')
|
40
|
-
jane_id = relations[:users].insert(name: 'Jane')
|
41
|
-
|
42
43
|
p1_id = relations[:puzzles].insert(text: 'P1')
|
43
44
|
p2_id = relations[:puzzles].insert(text: 'P2')
|
44
45
|
p3_id = relations[:puzzles].insert(text: 'P3')
|
@@ -50,23 +51,18 @@ RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
|
50
51
|
relations[:puzzle_solvers].insert(solver_id: jane_id, puzzle_id: p3_id)
|
51
52
|
end
|
52
53
|
|
53
|
-
after do
|
54
|
-
conn.drop_table?(:puzzle_solvers)
|
55
|
-
conn.drop_table?(:puzzles)
|
56
|
-
end
|
57
|
-
|
58
54
|
it 'prepares joined relations using custom FK' do
|
59
|
-
relation = assoc.call(relations).order(:puzzles__text)
|
55
|
+
relation = assoc.call(relations).order(:puzzles__text, :puzzle_solvers__solver_id)
|
60
56
|
|
61
57
|
expect(relation.schema.map(&:to_sym)).
|
62
58
|
to eql(%i[puzzles__id puzzles__text puzzle_solvers__solver_id])
|
63
59
|
|
64
60
|
expect(relation.to_a).
|
65
61
|
to eql([
|
66
|
-
{ id: 1, solver_id:
|
62
|
+
{ id: 1, solver_id: 2, text: 'P1' },
|
67
63
|
{ id: 2, solver_id: 1, text: 'P2' },
|
68
64
|
{ id: 2, solver_id: 2, text: 'P2' },
|
69
|
-
{ id: 3, solver_id:
|
65
|
+
{ id: 3, solver_id: 1, text: 'P3' }
|
70
66
|
])
|
71
67
|
end
|
72
68
|
end
|
@@ -1,10 +1,14 @@
|
|
1
1
|
RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
2
|
+
include_context 'users'
|
3
|
+
|
4
|
+
before do
|
5
|
+
inferrable_relations.concat %i(puzzles puzzle_solvers)
|
6
|
+
end
|
7
|
+
|
2
8
|
subject(:assoc) do
|
3
9
|
relations[:users].associations[:solved_puzzles]
|
4
10
|
end
|
5
11
|
|
6
|
-
include_context 'database setup'
|
7
|
-
|
8
12
|
with_adapters do
|
9
13
|
before do
|
10
14
|
conn.create_table(:puzzles) do
|
@@ -46,9 +50,6 @@ RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
|
46
50
|
end
|
47
51
|
end
|
48
52
|
|
49
|
-
joe_id = relations[:users].insert(name: 'Joe')
|
50
|
-
jane_id = relations[:users].insert(name: 'Jane')
|
51
|
-
|
52
53
|
p1_id = relations[:puzzles].insert(text: 'P1')
|
53
54
|
p2_id = relations[:puzzles].insert(text: 'P2', solved: true)
|
54
55
|
p3_id = relations[:puzzles].insert(text: 'P3')
|
@@ -66,15 +67,15 @@ RSpec.describe ROM::SQL::Association::ManyToMany, '#call' do
|
|
66
67
|
end
|
67
68
|
|
68
69
|
it 'prepares joined relations using custom FK' do
|
69
|
-
relation = assoc.call(relations).order(:puzzles__text)
|
70
|
+
relation = assoc.call(relations).order(:puzzles__text, :puzzle_solvers__user_id)
|
70
71
|
|
71
72
|
expect(relation.schema.map(&:to_sym)).
|
72
73
|
to eql(%i[puzzles__id puzzles__text puzzles__solved puzzle_solvers__user_id])
|
73
74
|
|
74
75
|
expect(relation.to_a).
|
75
76
|
to eql([
|
76
|
-
{ id: 2, user_id: 1, solved:
|
77
|
-
{ id: 2, user_id: 2, solved:
|
77
|
+
{ id: 2, user_id: 1, solved: db_true, text: 'P2' },
|
78
|
+
{ id: 2, user_id: 2, solved: db_true, text: 'P2' }
|
78
79
|
])
|
79
80
|
end
|
80
81
|
end
|
@@ -1,145 +1,146 @@
|
|
1
1
|
RSpec.describe ROM::SQL::Association::ManyToMany do
|
2
2
|
include_context 'users and tasks'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
conf.default.create_table(:users_tasks) do
|
10
|
-
foreign_key :user_id, :users
|
11
|
-
foreign_key :task_id, :tasks
|
12
|
-
primary_key [:user_id, :task_id]
|
13
|
-
end
|
4
|
+
with_adapters do
|
5
|
+
context 'through a relation with a composite PK' do
|
6
|
+
subject(:assoc) {
|
7
|
+
ROM::SQL::Association::ManyToMany.new(:tasks, :tags, through: :task_tags)
|
8
|
+
}
|
14
9
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
end
|
10
|
+
let(:tasks) { container.relations[:tasks] }
|
11
|
+
let(:tags) { container.relations[:tags] }
|
12
|
+
|
13
|
+
before do
|
14
|
+
conf.relation(:task_tags) do
|
15
|
+
schema do
|
16
|
+
attribute :task_id, ROM::SQL::Types::ForeignKey(:tasks)
|
17
|
+
attribute :tag_id, ROM::SQL::Types::ForeignKey(:tags)
|
24
18
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
end
|
19
|
+
primary_key :task_id, :tag_id
|
20
|
+
|
21
|
+
associations do
|
22
|
+
many_to_one :tasks
|
23
|
+
many_to_one :tags
|
31
24
|
end
|
32
25
|
end
|
26
|
+
end
|
33
27
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
28
|
+
conf.relation(:tasks) do
|
29
|
+
schema do
|
30
|
+
attribute :id, ROM::SQL::Types::Serial
|
31
|
+
attribute :user_id, ROM::SQL::Types::ForeignKey(:users)
|
32
|
+
attribute :title, ROM::SQL::Types::String
|
33
|
+
|
34
|
+
associations do
|
35
|
+
one_to_many :task_tags
|
36
|
+
one_to_many :tags, through: :task_tags
|
40
37
|
end
|
41
38
|
end
|
42
39
|
end
|
43
40
|
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
assoc = users.associations[:tasks]
|
42
|
+
describe '#result' do
|
43
|
+
specify { expect(ROM::SQL::Association::ManyToMany.result).to be(:many) }
|
44
|
+
end
|
49
45
|
|
50
|
-
|
46
|
+
describe '#call' do
|
47
|
+
it 'prepares joined relations' do
|
48
|
+
relation = assoc.call(container.relations)
|
51
49
|
|
52
|
-
|
50
|
+
expect(relation.schema.map(&:to_sym)).to eql(%i[tags__id tags__name task_tags__task_id])
|
51
|
+
expect(relation.to_a).to eql([id: 1, name: 'important', task_id: 1])
|
52
|
+
end
|
53
53
|
end
|
54
54
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
55
|
+
describe ':through another assoc' do
|
56
|
+
subject(:assoc) do
|
57
|
+
ROM::SQL::Association::ManyToMany.new(:users, :tags, through: :tasks)
|
58
|
+
end
|
59
59
|
|
60
|
-
|
60
|
+
it 'prepares joined relations through other association' do
|
61
|
+
relation = assoc.call(container.relations)
|
61
62
|
|
62
|
-
|
63
|
+
expect(relation.schema.map(&:to_sym)).to eql(%i[tags__id tags__name tasks__user_id])
|
64
|
+
expect(relation.to_a).to eql([id: 1, name: 'important', user_id: 2])
|
65
|
+
end
|
63
66
|
end
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
with_adapters do
|
68
|
-
subject(:assoc) {
|
69
|
-
ROM::SQL::Association::ManyToMany.new(:tasks, :tags, through: :task_tags)
|
70
|
-
}
|
71
67
|
|
72
|
-
|
73
|
-
|
68
|
+
describe ROM::Plugins::Relation::SQL::AutoCombine, '#for_combine' do
|
69
|
+
it 'preloads relation based on association' do
|
70
|
+
relation = tags.for_combine(assoc).call(tasks.call)
|
74
71
|
|
75
|
-
|
76
|
-
|
77
|
-
schema do
|
78
|
-
attribute :task_id, ROM::SQL::Types::ForeignKey(:tasks)
|
79
|
-
attribute :tag_id, ROM::SQL::Types::ForeignKey(:tags)
|
72
|
+
expect(relation.to_a).to eql([id: 1, name: 'important', task_id: 1])
|
73
|
+
end
|
80
74
|
|
81
|
-
|
75
|
+
it 'maintains original relation' do
|
76
|
+
relation = tags.
|
77
|
+
select_append(tags[:name].as(:tag)).
|
78
|
+
for_combine(assoc).call(tasks.call)
|
82
79
|
|
83
|
-
|
84
|
-
many_to_one :tasks
|
85
|
-
many_to_one :tags
|
86
|
-
end
|
80
|
+
expect(relation.to_a).to eql([id: 1, tag: 'important', name: 'important', task_id: 1])
|
87
81
|
end
|
88
82
|
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context 'with two associations pointing to the same target relation' do
|
86
|
+
before do
|
87
|
+
inferrable_relations.concat %i(users_tasks)
|
88
|
+
end
|
89
89
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
90
|
+
before do
|
91
|
+
conn.create_table(:users_tasks) do
|
92
|
+
foreign_key :user_id, :users
|
93
|
+
foreign_key :task_id, :tasks
|
94
|
+
primary_key [:user_id, :task_id]
|
95
|
+
end
|
95
96
|
|
96
|
-
|
97
|
-
|
98
|
-
|
97
|
+
conf.relation(:users) do
|
98
|
+
schema(infer: true) do
|
99
|
+
associations do
|
100
|
+
has_many :users_tasks
|
101
|
+
has_many :tasks, through: :users_tasks
|
102
|
+
has_many :tasks, as: :priv_tasks
|
103
|
+
end
|
99
104
|
end
|
100
105
|
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
describe '#result' do
|
105
|
-
specify { expect(ROM::SQL::Association::ManyToMany.result).to be(:many) }
|
106
|
-
end
|
107
106
|
|
108
|
-
|
109
|
-
|
110
|
-
|
107
|
+
conf.relation(:users_tasks) do
|
108
|
+
schema(infer: true) do
|
109
|
+
associations do
|
110
|
+
belongs_to :user
|
111
|
+
belongs_to :task
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
111
115
|
|
112
|
-
|
113
|
-
|
116
|
+
conf.relation(:tasks) do
|
117
|
+
schema(infer: true) do
|
118
|
+
associations do
|
119
|
+
has_many :users_tasks
|
120
|
+
has_many :users, through: :users_tasks
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
114
124
|
end
|
115
|
-
end
|
116
125
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
126
|
+
it 'does not conflict with two FKs' do
|
127
|
+
users = container.relations[:users]
|
128
|
+
tasks = container.relations[:tasks]
|
129
|
+
assoc = users.associations[:tasks]
|
121
130
|
|
122
|
-
|
123
|
-
relation = assoc.call(container.relations)
|
131
|
+
relation = tasks.for_combine(assoc).call(users.call)
|
124
132
|
|
125
|
-
expect(relation.
|
126
|
-
expect(relation.to_a).to eql([id: 1, name: 'important', user_id: 2])
|
133
|
+
expect(relation.to_a).to be_empty
|
127
134
|
end
|
128
|
-
end
|
129
135
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
expect(relation.to_a).to eql([id: 1, name: 'important', task_id: 1])
|
135
|
-
end
|
136
|
+
it 'preloads using FK' do
|
137
|
+
users = container.relations[:users]
|
138
|
+
tasks = container.relations[:tasks]
|
139
|
+
assoc = users.associations[:priv_tasks]
|
136
140
|
|
137
|
-
|
138
|
-
relation = tags.
|
139
|
-
select_append(tags[:name].as(:tag)).
|
140
|
-
for_combine(assoc).call(tasks.call)
|
141
|
+
relation = tasks.for_combine(assoc).call(users.where(id: 2).call)
|
141
142
|
|
142
|
-
expect(relation.to_a).to eql([id: 1,
|
143
|
+
expect(relation.to_a).to eql([id: 1, user_id: 2, title: "Joe's task"])
|
143
144
|
end
|
144
145
|
end
|
145
146
|
end
|
@@ -1,11 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
RSpec.describe ROM::SQL::Association::ManyToOne, '#call' do
|
4
|
+
include_context 'database setup'
|
5
|
+
|
6
|
+
before do
|
7
|
+
inferrable_relations.concat %i(destinations flights)
|
8
|
+
end
|
9
|
+
|
4
10
|
let(:assoc_from) { relations[:flights].associations[:from] }
|
5
11
|
let(:assoc_to) { relations[:flights].associations[:to] }
|
6
12
|
|
7
|
-
include_context 'database setup'
|
8
|
-
|
9
13
|
with_adapters do
|
10
14
|
before do
|
11
15
|
conn.create_table(:destinations) do
|
@@ -35,11 +39,6 @@ RSpec.describe ROM::SQL::Association::ManyToOne, '#call' do
|
|
35
39
|
relations[:flights].insert(code: 'F1', from_id: from_id, to_id: to_id)
|
36
40
|
end
|
37
41
|
|
38
|
-
after do
|
39
|
-
conn.drop_table(:flights)
|
40
|
-
conn.drop_table(:destinations)
|
41
|
-
end
|
42
|
-
|
43
42
|
it 'prepares joined relations using correct FKs based on association aliases' do
|
44
43
|
relation = assoc_from.call(relations)
|
45
44
|
|