rom-sql 0.6.1 → 0.7.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/.rubocop.yml +1 -5
- data/.rubocop_todo.yml +12 -6
- data/.travis.yml +3 -2
- data/CHANGELOG.md +27 -0
- data/Gemfile +1 -0
- data/lib/rom/plugins/relation/sql/auto_combine.rb +45 -0
- data/lib/rom/plugins/relation/sql/auto_wrap.rb +48 -0
- data/lib/rom/plugins/relation/sql/base_view.rb +31 -0
- data/lib/rom/sql.rb +17 -10
- data/lib/rom/sql/commands/error_wrapper.rb +1 -1
- data/lib/rom/sql/commands/update.rb +1 -1
- data/lib/rom/sql/gateway.rb +8 -2
- data/lib/rom/sql/header.rb +1 -1
- data/lib/rom/sql/migration.rb +11 -20
- data/lib/rom/sql/migration/migrator.rb +4 -0
- data/lib/rom/sql/{relation/associations.rb → plugin/assoc_macros.rb} +17 -2
- data/lib/rom/sql/plugin/assoc_macros/class_interface.rb +128 -0
- data/lib/rom/sql/plugin/associates.rb +2 -4
- data/lib/rom/sql/plugin/pagination.rb +1 -1
- data/lib/rom/sql/plugins.rb +4 -2
- data/lib/rom/sql/relation.rb +46 -6
- data/lib/rom/sql/relation/reading.rb +63 -0
- data/lib/rom/sql/tasks/migration_tasks.rake +37 -16
- data/lib/rom/sql/version.rb +1 -1
- data/rom-sql.gemspec +2 -2
- data/spec/fixtures/migrations/20150403090603_create_carrots.rb +1 -1
- data/spec/integration/combine_spec.rb +6 -6
- data/spec/integration/commands/create_spec.rb +25 -25
- data/spec/integration/commands/delete_spec.rb +6 -6
- data/spec/integration/commands/update_spec.rb +5 -5
- data/spec/integration/{repository_spec.rb → gateway_spec.rb} +34 -21
- data/spec/integration/migration_spec.rb +3 -3
- data/spec/integration/read_spec.rb +13 -7
- data/spec/shared/database_setup.rb +3 -5
- data/spec/spec_helper.rb +3 -6
- data/spec/support/active_support_notifications_spec.rb +1 -1
- data/spec/support/rails_log_subscriber_spec.rb +1 -1
- data/spec/unit/association_errors_spec.rb +4 -3
- data/spec/unit/combined_associations_spec.rb +7 -5
- data/spec/unit/gateway_spec.rb +2 -2
- data/spec/unit/logger_spec.rb +1 -1
- data/spec/unit/many_to_many_spec.rb +7 -4
- data/spec/unit/many_to_one_spec.rb +14 -8
- data/spec/unit/migration_tasks_spec.rb +7 -6
- data/spec/unit/one_to_many_spec.rb +16 -10
- data/spec/unit/plugin/base_view_spec.rb +18 -0
- data/spec/unit/plugin/pagination_spec.rb +10 -10
- data/spec/unit/relation_spec.rb +69 -3
- data/spec/unit/schema_spec.rb +5 -3
- metadata +19 -26
- data/lib/rom/sql/relation/class_methods.rb +0 -116
- data/lib/rom/sql/relation/inspection.rb +0 -16
@@ -3,22 +3,22 @@ require 'spec_helper'
|
|
3
3
|
describe 'Commands / Delete' do
|
4
4
|
include_context 'users and tasks'
|
5
5
|
|
6
|
-
subject(:users) {
|
6
|
+
subject(:users) { container.commands.users }
|
7
7
|
|
8
8
|
before do
|
9
|
-
|
9
|
+
configuration.relation(:users) do
|
10
10
|
def by_name(name)
|
11
11
|
where(name: name)
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
|
15
|
+
configuration.commands(:users) do
|
16
16
|
define(:delete) do
|
17
17
|
result :one
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
|
21
|
+
container.relations.users.insert(id: 2, name: 'Jane')
|
22
22
|
end
|
23
23
|
|
24
24
|
context '#transaction' do
|
@@ -27,7 +27,7 @@ describe 'Commands / Delete' do
|
|
27
27
|
users.delete.transaction do
|
28
28
|
users.delete.by_name('Jane').call
|
29
29
|
end
|
30
|
-
}.to change {
|
30
|
+
}.to change { container.relations.users.count }.by(-1)
|
31
31
|
end
|
32
32
|
|
33
33
|
it 'delete nothing if error was raised' do
|
@@ -36,7 +36,7 @@ describe 'Commands / Delete' do
|
|
36
36
|
users.delete.by_name('Jane').call
|
37
37
|
raise ROM::SQL::Rollback
|
38
38
|
end
|
39
|
-
}.to_not change {
|
39
|
+
}.to_not change { container.relations.users.count }
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -4,14 +4,14 @@ require 'anima'
|
|
4
4
|
describe 'Commands / Update' do
|
5
5
|
include_context 'database setup'
|
6
6
|
|
7
|
-
subject(:users) {
|
7
|
+
subject(:users) { container.command(:users) }
|
8
8
|
|
9
|
-
let(:relation) {
|
9
|
+
let(:relation) { container.relations.users }
|
10
10
|
let(:piotr) { relation.by_name('Piotr').one }
|
11
11
|
let(:peter) { { name: 'Peter' } }
|
12
12
|
|
13
13
|
before do
|
14
|
-
|
14
|
+
configuration.relation(:users) do
|
15
15
|
def by_id(id)
|
16
16
|
where(id: id).limit(1)
|
17
17
|
end
|
@@ -21,13 +21,13 @@ describe 'Commands / Update' do
|
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
|
-
|
24
|
+
configuration.commands(:users) do
|
25
25
|
define(:update)
|
26
26
|
end
|
27
27
|
|
28
28
|
User = Class.new { include Anima.new(:id, :name) }
|
29
29
|
|
30
|
-
|
30
|
+
configuration.mappers do
|
31
31
|
register :users, entity: -> tuples { tuples.map { |tuple| User.new(tuple) } }
|
32
32
|
end
|
33
33
|
|
@@ -5,12 +5,10 @@ describe ROM::SQL::Gateway do
|
|
5
5
|
let(:conn) { Sequel.connect(DB_URI) }
|
6
6
|
|
7
7
|
context 'creating migrations inline' do
|
8
|
-
subject(:gateway) {
|
8
|
+
subject(:gateway) { container.gateways[:default] }
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
ROM.finalize
|
13
|
-
end
|
10
|
+
let(:configuration) { ROM::Configuration.new(:sql, conn) }
|
11
|
+
let!(:container) { ROM.container(configuration) }
|
14
12
|
|
15
13
|
after do
|
16
14
|
[:rabbits, :carrots].each do |name|
|
@@ -19,7 +17,7 @@ describe ROM::SQL::Gateway do
|
|
19
17
|
end
|
20
18
|
|
21
19
|
it 'allows creating and running migrations' do
|
22
|
-
migration =
|
20
|
+
migration = gateway.migration do
|
23
21
|
up do
|
24
22
|
create_table(:rabbits) do
|
25
23
|
primary_key :id
|
@@ -43,19 +41,27 @@ describe ROM::SQL::Gateway do
|
|
43
41
|
end
|
44
42
|
|
45
43
|
context 'running migrations from a file system' do
|
44
|
+
include_context 'database setup'
|
45
|
+
|
46
46
|
let(:migration_dir) do
|
47
47
|
Pathname(__FILE__).dirname.join('../fixtures/migrations').realpath
|
48
48
|
end
|
49
49
|
|
50
50
|
let(:migrator) { ROM::SQL::Migration::Migrator.new(conn, path: migration_dir) }
|
51
|
+
let(:configuration) { ROM::Configuration.new(:sql, [conn, migrator: migrator]) }
|
52
|
+
let!(:container) { ROM.container(configuration) }
|
53
|
+
|
54
|
+
it 'returns true for pending migrations' do
|
55
|
+
expect(container.gateways[:default].pending_migrations?).to be_truthy
|
56
|
+
end
|
51
57
|
|
52
|
-
|
53
|
-
|
54
|
-
|
58
|
+
it 'returns false for non pending migrations' do
|
59
|
+
container.gateways[:default].run_migrations
|
60
|
+
expect(container.gateways[:default].pending_migrations?).to be_falsy
|
55
61
|
end
|
56
62
|
|
57
63
|
it 'runs migrations from a specified directory' do
|
58
|
-
|
64
|
+
container.gateways[:default].run_migrations
|
59
65
|
end
|
60
66
|
end
|
61
67
|
end
|
@@ -64,24 +70,31 @@ describe ROM::SQL::Gateway do
|
|
64
70
|
include_context 'database setup'
|
65
71
|
|
66
72
|
it 'skips settings up associations when tables are missing' do
|
67
|
-
ROM.
|
73
|
+
configuration = ROM::Configuration.new(:sql, uri) do |config|
|
74
|
+
config.use(:macros)
|
68
75
|
|
69
|
-
|
70
|
-
|
76
|
+
config.relation(:foos) do
|
77
|
+
use :assoc_macros
|
78
|
+
primary_key :id
|
79
|
+
one_to_many :bars, key: :foo_id
|
80
|
+
end
|
71
81
|
end
|
72
|
-
|
73
|
-
expect { ROM.finalize }.not_to raise_error
|
82
|
+
expect { ROM.container(configuration) }.not_to raise_error
|
74
83
|
end
|
75
84
|
|
76
85
|
it 'skips finalization a relation when table is missing' do
|
77
|
-
ROM.
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
86
|
+
configuration = ROM::Configuration.new(:sql, uri) do |config|
|
87
|
+
config.use(:macros)
|
88
|
+
|
89
|
+
class Foos < ROM::Relation[:sql]
|
90
|
+
dataset :foos
|
91
|
+
use :assoc_macros
|
92
|
+
primary_key :id
|
93
|
+
one_to_many :bars, key: :foo_id
|
94
|
+
end
|
82
95
|
end
|
83
96
|
|
84
|
-
expect { ROM.
|
97
|
+
expect { ROM.container(configuration) }.not_to raise_error
|
85
98
|
expect { Foos.model.dataset }.to raise_error(Sequel::Error, /no dataset/i)
|
86
99
|
end
|
87
100
|
end
|
@@ -2,14 +2,14 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe ROM::SQL, '.migration' do
|
4
4
|
let(:connection) { ROM::SQL.gateway.connection }
|
5
|
+
let(:configuration) { ROM::Configuration.new(:sql, DB_URI) }
|
5
6
|
|
6
7
|
before do
|
7
|
-
|
8
|
+
configuration
|
8
9
|
connection.drop_table?(:dragons)
|
9
10
|
end
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
xit 'creates a migration for a specific gateway' do
|
13
13
|
migration = ROM::SQL.migration do
|
14
14
|
change do
|
15
15
|
create_table :dragons do
|
@@ -34,12 +34,16 @@ describe 'Reading relations' do
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
|
37
|
+
configuration.relation(:goals) do
|
38
|
+
use :assoc_macros
|
39
|
+
|
38
40
|
register_as :goals
|
39
41
|
dataset :tasks
|
40
42
|
end
|
41
43
|
|
42
|
-
|
44
|
+
configuration.relation(:users) do
|
45
|
+
use :assoc_macros
|
46
|
+
|
43
47
|
one_to_many :goals, key: :user_id
|
44
48
|
|
45
49
|
def by_name(name)
|
@@ -55,7 +59,9 @@ describe 'Reading relations' do
|
|
55
59
|
end
|
56
60
|
end
|
57
61
|
|
58
|
-
|
62
|
+
configuration.relation(:user_goal_counts) do
|
63
|
+
use :assoc_macros
|
64
|
+
|
59
65
|
dataset :users
|
60
66
|
register_as :user_goal_counts
|
61
67
|
one_to_many :goals, key: :user_id
|
@@ -71,7 +77,7 @@ describe 'Reading relations' do
|
|
71
77
|
end
|
72
78
|
end
|
73
79
|
|
74
|
-
|
80
|
+
configuration.mappers do
|
75
81
|
define(:users) do
|
76
82
|
model User
|
77
83
|
|
@@ -90,7 +96,7 @@ describe 'Reading relations' do
|
|
90
96
|
end
|
91
97
|
|
92
98
|
it 'loads domain objects' do
|
93
|
-
user =
|
99
|
+
user = container.relation(:users).as(:users).with_goals.by_name('Piotr').to_a.first
|
94
100
|
|
95
101
|
expect(user).to eql(
|
96
102
|
User.new(
|
@@ -99,9 +105,9 @@ describe 'Reading relations' do
|
|
99
105
|
end
|
100
106
|
|
101
107
|
it 'works with grouping and aggregates' do
|
102
|
-
|
108
|
+
container.relations[:goals].insert(id: 2, user_id: 1, title: 'Get Milk')
|
103
109
|
|
104
|
-
users_with_goal_count =
|
110
|
+
users_with_goal_count = container.relation(:user_goal_counts).as(:user_goal_counts).all
|
105
111
|
|
106
112
|
expect(users_with_goal_count.to_a).to eq([
|
107
113
|
UserGoalCount.new(id: 1, name: "Piotr", goal_count: 2)
|
@@ -1,10 +1,8 @@
|
|
1
1
|
shared_context 'database setup' do
|
2
|
-
subject(:rom) { setup.finalize }
|
3
|
-
|
4
2
|
let(:uri) { DB_URI }
|
5
3
|
let(:conn) { Sequel.connect(uri) }
|
6
|
-
|
7
|
-
let(:
|
4
|
+
let(:configuration) { ROM::Configuration.new(:sql, conn).use(:macros) }
|
5
|
+
let(:container) { ROM.container(configuration) }
|
8
6
|
|
9
7
|
def drop_tables
|
10
8
|
[:tasks, :users, :tags, :task_tags, :rabbits, :carrots, :schema_migrations].each do |name|
|
@@ -36,7 +34,7 @@ shared_context 'database setup' do
|
|
36
34
|
end
|
37
35
|
|
38
36
|
conn.create_table :task_tags do
|
39
|
-
primary_key :tag_id, :task_id
|
37
|
+
primary_key [:tag_id, :task_id]
|
40
38
|
Integer :tag_id
|
41
39
|
Integer :task_id
|
42
40
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -4,7 +4,7 @@ require 'bundler'
|
|
4
4
|
Bundler.setup
|
5
5
|
|
6
6
|
if RUBY_ENGINE == 'rbx'
|
7
|
-
require
|
7
|
+
require 'codeclimate-test-reporter'
|
8
8
|
CodeClimate::TestReporter.start
|
9
9
|
end
|
10
10
|
|
@@ -18,13 +18,11 @@ require 'active_support/inflector'
|
|
18
18
|
require 'logger'
|
19
19
|
begin
|
20
20
|
require 'byebug'
|
21
|
-
rescue LoadError
|
21
|
+
rescue LoadError # rubocop:disable Lint/HandleExceptions
|
22
22
|
end
|
23
23
|
|
24
|
-
ROM.use :auto_registration
|
25
|
-
|
26
24
|
LOGGER = Logger.new(File.open('./log/test.log', 'a'))
|
27
|
-
DB_URI = 'postgres://localhost/
|
25
|
+
DB_URI = 'postgres://localhost/rom_sql'
|
28
26
|
|
29
27
|
root = Pathname(__FILE__).dirname
|
30
28
|
TMP_PATH = root.join('../tmp')
|
@@ -45,6 +43,5 @@ RSpec.configure do |config|
|
|
45
43
|
config.after do
|
46
44
|
added_constants = Object.constants - @constants
|
47
45
|
added_constants.each { |name| Object.send(:remove_const, name) }
|
48
|
-
ROM.instance_variable_get('@environment').instance_variable_set('@gateways', {})
|
49
46
|
end
|
50
47
|
end
|
@@ -5,16 +5,17 @@ describe 'Association errors' do
|
|
5
5
|
|
6
6
|
describe 'accessing an undefined association' do
|
7
7
|
specify do
|
8
|
-
|
8
|
+
configuration.relation(:users) do
|
9
|
+
use :assoc_macros
|
10
|
+
|
9
11
|
def with_undefined
|
10
12
|
association_join(:undefined)
|
11
13
|
end
|
12
14
|
end
|
13
15
|
|
14
16
|
expect {
|
15
|
-
|
17
|
+
container.relations.users.with_undefined
|
16
18
|
}.to raise_error ROM::SQL::NoAssociationError, 'Association :undefined has not been defined for relation :users'
|
17
19
|
end
|
18
20
|
end
|
19
21
|
end
|
20
|
-
|
@@ -8,11 +8,13 @@ describe 'Defining multiple associations' do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'extends relation with association methods' do
|
11
|
-
|
11
|
+
configuration.relation(:users) { use :assoc_macros }
|
12
12
|
|
13
|
-
|
13
|
+
configuration.relation(:tags) { use :assoc_macros }
|
14
|
+
|
15
|
+
configuration.relation(:tasks) do
|
16
|
+
use :assoc_macros
|
14
17
|
|
15
|
-
setup.relation(:tasks) do
|
16
18
|
many_to_one :users, key: :user_id
|
17
19
|
|
18
20
|
many_to_many :tags,
|
@@ -49,7 +51,7 @@ describe 'Defining multiple associations' do
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
52
|
-
tasks =
|
54
|
+
tasks = container.relations.tasks
|
53
55
|
|
54
56
|
expect(tasks.with_user_and_tags.to_a).to eql([
|
55
57
|
{ id: 1, title: 'Finish ROM', name: 'Piotr', tags_name: 'important' },
|
@@ -67,7 +69,7 @@ describe 'Defining multiple associations' do
|
|
67
69
|
|
68
70
|
expect(tasks.all.with_user.to_a).to eql([
|
69
71
|
{ id: 1, title: 'Finish ROM', name: 'Piotr' },
|
70
|
-
{ id: 2, title: 'Go to sleep', name: 'Piotr'
|
72
|
+
{ id: 2, title: 'Go to sleep', name: 'Piotr' }
|
71
73
|
])
|
72
74
|
|
73
75
|
expect(tasks.by_title('Go to sleep').to_a).to eql(
|
data/spec/unit/gateway_spec.rb
CHANGED
@@ -5,12 +5,12 @@ require 'rom/lint/spec'
|
|
5
5
|
describe ROM::SQL::Gateway do
|
6
6
|
include_context 'users and tasks'
|
7
7
|
|
8
|
-
let(:gateway) {
|
8
|
+
let(:gateway) { container.gateways[:default] }
|
9
9
|
|
10
10
|
it_behaves_like 'a rom gateway' do
|
11
11
|
let(:identifier) { :sql }
|
12
12
|
let(:gateway) { ROM::SQL::Gateway }
|
13
|
-
let(:uri) {
|
13
|
+
let(:uri) { DB_URI }
|
14
14
|
end
|
15
15
|
|
16
16
|
describe '#dataset?' do
|
data/spec/unit/logger_spec.rb
CHANGED
@@ -8,7 +8,12 @@ describe 'Defining many-to-one association' do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it 'extends relation with association methods' do
|
11
|
-
|
11
|
+
configuration.relation(:tags) { use :assoc_macros }
|
12
|
+
configuration.relation(:task_tags) { use :assoc_macros }
|
13
|
+
|
14
|
+
configuration.relation(:tasks) do
|
15
|
+
use :assoc_macros
|
16
|
+
|
12
17
|
many_to_many :tags,
|
13
18
|
join_table: :task_tags,
|
14
19
|
left_key: :task_id,
|
@@ -33,9 +38,7 @@ describe 'Defining many-to-one association' do
|
|
33
38
|
end
|
34
39
|
end
|
35
40
|
|
36
|
-
|
37
|
-
|
38
|
-
tasks = rom.relations.tasks
|
41
|
+
tasks = container.relations.tasks
|
39
42
|
|
40
43
|
expect(tasks.all.with_tags.to_a).to eql([
|
41
44
|
{ id: 1, title: 'Finish ROM', name: 'important' },
|
@@ -6,10 +6,14 @@ describe 'Defining many-to-one association' do
|
|
6
6
|
before do
|
7
7
|
conn[:users].insert id: 2, name: 'Jane'
|
8
8
|
conn[:tasks].insert id: 2, user_id: 2, title: 'Task one'
|
9
|
+
|
10
|
+
configuration.relation(:users) { use :assoc_macros }
|
9
11
|
end
|
10
12
|
|
11
13
|
it 'extends relation with association methods' do
|
12
|
-
|
14
|
+
configuration.relation(:tasks) do
|
15
|
+
use :assoc_macros
|
16
|
+
|
13
17
|
many_to_one :users, key: :user_id, on: { name: 'Piotr' }
|
14
18
|
|
15
19
|
def all
|
@@ -21,7 +25,7 @@ describe 'Defining many-to-one association' do
|
|
21
25
|
end
|
22
26
|
end
|
23
27
|
|
24
|
-
|
28
|
+
configuration.mappers do
|
25
29
|
define(:tasks)
|
26
30
|
|
27
31
|
define(:with_user, parent: :tasks) do
|
@@ -31,21 +35,21 @@ describe 'Defining many-to-one association' do
|
|
31
35
|
end
|
32
36
|
end
|
33
37
|
|
34
|
-
|
35
|
-
|
36
|
-
tasks = rom.relations.tasks
|
38
|
+
tasks = container.relations.tasks
|
37
39
|
|
38
40
|
expect(tasks.all.with_user.to_a).to eql(
|
39
41
|
[{ id: 1, name: 'Piotr', title: 'Finish ROM' }]
|
40
42
|
)
|
41
43
|
|
42
|
-
expect(
|
44
|
+
expect(container.relation(:tasks).map_with(:with_user).all.with_user.to_a).to eql(
|
43
45
|
[{ id: 1, title: 'Finish ROM', user: { name: 'Piotr' } }]
|
44
46
|
)
|
45
47
|
end
|
46
48
|
|
47
49
|
it "joins on specified key" do
|
48
|
-
|
50
|
+
configuration.relation(:task_tags) do
|
51
|
+
use :assoc_macros
|
52
|
+
|
49
53
|
many_to_one :tags, key: :tag_id
|
50
54
|
|
51
55
|
def with_tags
|
@@ -53,7 +57,9 @@ describe 'Defining many-to-one association' do
|
|
53
57
|
end
|
54
58
|
end
|
55
59
|
|
56
|
-
|
60
|
+
configuration.relation(:tags) { use :assoc_macros }
|
61
|
+
|
62
|
+
expect(container.relation(:task_tags).with_tags.to_a).to eq(
|
57
63
|
[{ tag_id: 1, task_id: 1, id: 1, name: "important" }]
|
58
64
|
)
|
59
65
|
end
|