rom-sql 1.3.5 → 2.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 (103) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +13 -7
  3. data/Gemfile +7 -5
  4. data/lib/rom/plugins/relation/sql/auto_restrictions.rb +11 -17
  5. data/lib/rom/sql.rb +3 -2
  6. data/lib/rom/sql/associations.rb +5 -0
  7. data/lib/rom/sql/associations/core.rb +20 -0
  8. data/lib/rom/sql/associations/many_to_many.rb +83 -0
  9. data/lib/rom/sql/associations/many_to_one.rb +55 -0
  10. data/lib/rom/sql/associations/one_to_many.rb +31 -0
  11. data/lib/rom/sql/{association → associations}/one_to_one.rb +3 -2
  12. data/lib/rom/sql/{association → associations}/one_to_one_through.rb +3 -2
  13. data/lib/rom/sql/associations/self_ref.rb +39 -0
  14. data/lib/rom/sql/attribute.rb +44 -54
  15. data/lib/rom/sql/errors.rb +2 -0
  16. data/lib/rom/sql/extensions/mysql.rb +1 -1
  17. data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +10 -0
  18. data/lib/rom/sql/extensions/postgres.rb +1 -1
  19. data/lib/rom/sql/extensions/postgres/{inferrer.rb → attributes_inferrer.rb} +4 -4
  20. data/lib/rom/sql/extensions/postgres/types.rb +9 -19
  21. data/lib/rom/sql/extensions/sqlite.rb +1 -1
  22. data/lib/rom/sql/extensions/sqlite/{inferrer.rb → attributes_inferrer.rb} +2 -2
  23. data/lib/rom/sql/gateway.rb +29 -30
  24. data/lib/rom/sql/index.rb +13 -0
  25. data/lib/rom/sql/migration.rb +10 -0
  26. data/lib/rom/sql/migration/inline_runner.rb +86 -0
  27. data/lib/rom/sql/migration/migrator.rb +17 -0
  28. data/lib/rom/sql/migration/schema_diff.rb +177 -0
  29. data/lib/rom/sql/plugin/associates.rb +11 -45
  30. data/lib/rom/sql/plugin/pagination.rb +4 -4
  31. data/lib/rom/sql/relation.rb +22 -42
  32. data/lib/rom/sql/relation/reading.rb +3 -3
  33. data/lib/rom/sql/schema.rb +14 -21
  34. data/lib/rom/sql/schema/associations_dsl.rb +7 -6
  35. data/lib/rom/sql/schema/attributes_inferrer.rb +164 -0
  36. data/lib/rom/sql/schema/inferrer.rb +40 -141
  37. data/lib/rom/sql/type_extensions.rb +44 -0
  38. data/lib/rom/sql/version.rb +1 -1
  39. data/lib/rom/sql/wrap.rb +25 -0
  40. data/rom-sql.gemspec +2 -2
  41. data/spec/integration/{association → associations}/many_to_many/custom_fks_spec.rb +4 -2
  42. data/spec/integration/{association → associations}/many_to_many/from_view_spec.rb +2 -2
  43. data/spec/integration/{association → associations}/many_to_many_spec.rb +25 -30
  44. data/spec/integration/{association → associations}/many_to_one/custom_fks_spec.rb +5 -3
  45. data/spec/integration/{association → associations}/many_to_one/from_view_spec.rb +3 -3
  46. data/spec/integration/{association → associations}/many_to_one/self_ref_spec.rb +2 -2
  47. data/spec/integration/{association → associations}/many_to_one_spec.rb +20 -38
  48. data/spec/integration/{association → associations}/one_to_many/custom_fks_spec.rb +4 -2
  49. data/spec/integration/{association → associations}/one_to_many/from_view_spec.rb +2 -2
  50. data/spec/integration/{association → associations}/one_to_many/self_ref_spec.rb +2 -2
  51. data/spec/integration/{association → associations}/one_to_many_spec.rb +24 -11
  52. data/spec/integration/{association → associations}/one_to_one_spec.rb +13 -9
  53. data/spec/integration/{association → associations}/one_to_one_through_spec.rb +15 -11
  54. data/spec/integration/auto_migrations/errors_spec.rb +31 -0
  55. data/spec/integration/auto_migrations/indexes_spec.rb +109 -0
  56. data/spec/integration/auto_migrations/managing_columns_spec.rb +156 -0
  57. data/spec/integration/auto_migrations/postgres/column_types_spec.rb +63 -0
  58. data/spec/integration/commands/create_spec.rb +2 -4
  59. data/spec/integration/commands/delete_spec.rb +2 -2
  60. data/spec/integration/commands/update_spec.rb +2 -0
  61. data/spec/integration/graph_spec.rb +9 -3
  62. data/spec/integration/plugins/associates_spec.rb +16 -55
  63. data/spec/integration/plugins/auto_restrictions_spec.rb +0 -11
  64. data/spec/integration/relation_schema_spec.rb +49 -25
  65. data/spec/integration/schema/inferrer/postgres_spec.rb +1 -1
  66. data/spec/integration/schema/inferrer_spec.rb +7 -18
  67. data/spec/integration/setup_spec.rb +4 -0
  68. data/spec/integration/{plugins/auto_wrap_spec.rb → wrap_spec.rb} +13 -36
  69. data/spec/shared/accounts.rb +4 -0
  70. data/spec/shared/database_setup.rb +2 -1
  71. data/spec/shared/notes.rb +2 -0
  72. data/spec/shared/posts.rb +2 -0
  73. data/spec/shared/puppies.rb +2 -0
  74. data/spec/shared/relations.rb +2 -2
  75. data/spec/shared/users.rb +2 -0
  76. data/spec/shared/users_and_tasks.rb +4 -0
  77. data/spec/spec_helper.rb +3 -6
  78. data/spec/support/helpers.rb +11 -8
  79. data/spec/support/test_configuration.rb +16 -0
  80. data/spec/unit/plugin/associates_spec.rb +5 -10
  81. data/spec/unit/plugin/pagination_spec.rb +9 -9
  82. data/spec/unit/plugin/timestamp_spec.rb +9 -9
  83. data/spec/unit/relation/dataset_spec.rb +7 -5
  84. data/spec/unit/relation/inner_join_spec.rb +2 -15
  85. data/spec/unit/relation/primary_key_spec.rb +1 -1
  86. data/spec/unit/schema_spec.rb +6 -4
  87. metadata +65 -70
  88. data/lib/rom/plugins/relation/sql/auto_combine.rb +0 -71
  89. data/lib/rom/plugins/relation/sql/auto_wrap.rb +0 -62
  90. data/lib/rom/sql/association.rb +0 -103
  91. data/lib/rom/sql/association/many_to_many.rb +0 -119
  92. data/lib/rom/sql/association/many_to_one.rb +0 -73
  93. data/lib/rom/sql/association/name.rb +0 -78
  94. data/lib/rom/sql/association/one_to_many.rb +0 -60
  95. data/lib/rom/sql/extensions/mysql/inferrer.rb +0 -10
  96. data/lib/rom/sql/qualified_attribute.rb +0 -53
  97. data/lib/rom/sql/schema/dsl.rb +0 -75
  98. data/spec/unit/association/many_to_many_spec.rb +0 -89
  99. data/spec/unit/association/many_to_one_spec.rb +0 -81
  100. data/spec/unit/association/name_spec.rb +0 -68
  101. data/spec/unit/association/one_to_many_spec.rb +0 -82
  102. data/spec/unit/association/one_to_one_spec.rb +0 -83
  103. data/spec/unit/association/one_to_one_through_spec.rb +0 -69
@@ -0,0 +1,109 @@
1
+ RSpec.describe ROM::SQL::Gateway, :postgres, :helpers do
2
+ include_context 'database setup'
3
+
4
+ before do
5
+ conn.drop_table?(:users)
6
+ end
7
+
8
+ let(:table_name) { :users }
9
+
10
+ subject(:gateway) { container.gateways[:default] }
11
+
12
+ let(:inferrer) { ROM::SQL::Schema::Inferrer.new }
13
+
14
+ let(:migrated_schema) do
15
+ empty = define_schema(table_name)
16
+ empty.with(inferrer.(empty, gateway))
17
+ end
18
+
19
+ let(:attributes) { migrated_schema.to_a }
20
+
21
+ describe 'create table' do
22
+ describe 'one-column indexes' do
23
+ before do
24
+ conf.relation(:users) do
25
+ schema do
26
+ attribute :id, ROM::SQL::Types::Serial
27
+ attribute :name, ROM::SQL::Types::String.meta(index: true)
28
+ end
29
+ end
30
+ end
31
+
32
+ it 'creates ordinary b-tree indexes' do
33
+ gateway.auto_migrate!(conf)
34
+
35
+ expect(attributes.map(&:to_ast))
36
+ .to eql([
37
+ [:attribute,
38
+ [:id,
39
+ [:definition, [Integer, {}]],
40
+ primary_key: true, source: :users]],
41
+ [:attribute,
42
+ [:name,
43
+ [:definition, [String, {}]],
44
+ source: :users]],
45
+ ])
46
+ end
47
+ end
48
+ end
49
+
50
+ describe 'alter table' do
51
+ describe 'one-column indexes' do
52
+ context 'adding' do
53
+ before do
54
+ conf.relation(:users) do
55
+ schema do
56
+ attribute :id, ROM::SQL::Types::Serial
57
+ attribute :name, ROM::SQL::Types::String.meta(index: true)
58
+ end
59
+ end
60
+ end
61
+
62
+ it 'adds indexed column' do
63
+ conn.create_table :users do
64
+ primary_key :id
65
+ end
66
+
67
+ gateway.auto_migrate!(conf)
68
+
69
+ expect(migrated_schema.attributes[1].name).to eql(:name)
70
+ expect(migrated_schema.indexes.map { |idx| idx.attributes.map(&:name) }).to eql([%i(name)])
71
+ end
72
+
73
+ it 'adds index to existing column' do
74
+ conn.create_table :users do
75
+ primary_key :id
76
+ column :name, String
77
+ end
78
+
79
+ gateway.auto_migrate!(conf)
80
+
81
+ expect(migrated_schema.indexes.map { |idx| idx.attributes.map(&:name) }).to eql([%i(name)])
82
+ end
83
+ end
84
+
85
+ context 'removing' do
86
+ before do
87
+ conf.relation(:users) do
88
+ schema do
89
+ attribute :id, ROM::SQL::Types::Serial
90
+ attribute :name, ROM::SQL::Types::String
91
+ end
92
+ end
93
+
94
+ conn.create_table :users do
95
+ primary_key :id
96
+ column :name, String
97
+
98
+ index :name
99
+ end
100
+ end
101
+
102
+ it 'removes index' do
103
+ gateway.auto_migrate!(conf)
104
+ expect(migrated_schema.indexes).to be_empty
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
@@ -0,0 +1,156 @@
1
+ RSpec.describe ROM::SQL::Gateway, :postgres, :helpers do
2
+ include_context 'database setup'
3
+
4
+ before do
5
+ conn.drop_table?(:users)
6
+ end
7
+
8
+ before do
9
+ conf.relation(:users) do
10
+ schema do
11
+ attribute :id, ROM::SQL::Types::Serial
12
+ attribute :name, ROM::SQL::Types::String
13
+ attribute :email, ROM::SQL::Types::String.optional
14
+ end
15
+ end
16
+ end
17
+
18
+ let(:table_name) { :users }
19
+
20
+ subject(:gateway) { container.gateways[:default] }
21
+
22
+ let(:inferrer) { ROM::SQL::Schema::Inferrer.new }
23
+
24
+ let(:migrated_schema) do
25
+ empty = define_schema(table_name)
26
+ empty.with(inferrer.(empty, gateway))
27
+ end
28
+
29
+ let(:attributes) { migrated_schema.to_a }
30
+
31
+ describe 'create a table' do
32
+ it 'creates a table from a relation' do
33
+ gateway.auto_migrate!(conf)
34
+
35
+ expect(attributes.map(&:to_ast))
36
+ .to eql([
37
+ [:attribute,
38
+ [:id,
39
+ [:definition, [Integer, {}]],
40
+ primary_key: true, source: :users]],
41
+ [:attribute, [:name, [:definition, [String, {}]], source: :users]],
42
+ [:attribute,
43
+ [:email,
44
+ [:sum,
45
+ [[:constrained,
46
+ [[:definition, [NilClass, {}]],
47
+ [:predicate, [:type?, [[:type, NilClass], [:input, ROM::Undefined]]]],
48
+ {}]],
49
+ [:definition, [String, {}]],
50
+ {}]],
51
+ source: :users]]
52
+ ])
53
+ end
54
+ end
55
+
56
+ describe 'adding columns' do
57
+ before do
58
+ conn.create_table :users do
59
+ primary_key :id
60
+ end
61
+ end
62
+
63
+ it 'adds columns to an existing table' do
64
+ gateway.auto_migrate!(conf)
65
+
66
+ expect(attributes[1].to_ast)
67
+ .to eql(
68
+ [:attribute, [:name, [:definition, [String, {}]], source: :users]]
69
+ )
70
+ expect(attributes[2].to_ast)
71
+ .to eql(
72
+ [:attribute,
73
+ [:email,
74
+ [:sum,
75
+ [[:constrained,
76
+ [[:definition, [NilClass, {}]],
77
+ [:predicate, [:type?, [[:type, NilClass], [:input, ROM::Undefined]]]],
78
+ {}]],
79
+ [:definition, [String, {}]],
80
+ {}]],
81
+ source: :users]]
82
+ )
83
+ end
84
+ end
85
+
86
+ describe 'removing columns' do
87
+ before do
88
+ conn.create_table :users do
89
+ primary_key :id
90
+ column :name, String, null: false
91
+ column :email, String
92
+ column :age, Integer, null: false
93
+ end
94
+ end
95
+
96
+ it 'removes columns from a table' do
97
+ gateway.auto_migrate!(conf)
98
+
99
+ expect(attributes.map(&:name)).to eql(%i(id name email))
100
+ end
101
+ end
102
+
103
+ describe 'empty diff' do
104
+ before do
105
+ conn.create_table :users do
106
+ primary_key :id
107
+ column :name, String, null: false
108
+ column :email, String
109
+ end
110
+ end
111
+
112
+ it 'leaves existing schema' do
113
+ current = container.relations[:users].schema
114
+
115
+ gateway.auto_migrate!(conf)
116
+
117
+ expect(attributes).to eql(current.to_a)
118
+ end
119
+ end
120
+
121
+ describe 'changing NOTNULL' do
122
+ describe 'adding' do
123
+ before do
124
+ conn.create_table :users do
125
+ primary_key :id
126
+ column :name, String
127
+ column :email, String
128
+ end
129
+ end
130
+
131
+ it 'adds the constraint' do
132
+ gateway.auto_migrate!(conf)
133
+
134
+ expect(attributes[1].name).to eql(:name)
135
+ expect(attributes[1]).not_to be_optional
136
+ end
137
+ end
138
+
139
+ describe 'removing' do
140
+ before do
141
+ conn.create_table :users do
142
+ primary_key :id
143
+ column :name, String, null: false
144
+ column :email, String, null: false
145
+ end
146
+ end
147
+
148
+ it 'removes the constraint' do
149
+ gateway.auto_migrate!(conf)
150
+
151
+ expect(attributes[2].name).to eql(:email)
152
+ expect(attributes[2]).to be_optional
153
+ end
154
+ end
155
+ end
156
+ end
@@ -0,0 +1,63 @@
1
+ RSpec.describe ROM::SQL::Gateway, :postgres, :helpers do
2
+ include_context 'database setup'
3
+
4
+ before do
5
+ conn.drop_table?(:test_pg_types)
6
+ end
7
+
8
+ let(:table_name) { :test_pg_types }
9
+
10
+ subject(:gateway) { container.gateways[:default] }
11
+
12
+ let(:inferrer) { ROM::SQL::Schema::Inferrer.new }
13
+
14
+ let(:migrated_schema) do
15
+ empty = define_schema(table_name)
16
+ empty.with(inferrer.(empty, gateway))
17
+ end
18
+
19
+ let(:attributes) { migrated_schema.to_a }
20
+
21
+ describe 'common types' do
22
+ before do
23
+ conf.relation(:test_pg_types) do
24
+ schema do
25
+ attribute :id, ROM::SQL::Types::Serial
26
+ attribute :string, ROM::SQL::Types::String
27
+ attribute :int, ROM::SQL::Types::Int
28
+ attribute :time, ROM::SQL::Types::Time
29
+ attribute :date, ROM::SQL::Types::Date
30
+ attribute :decimal, ROM::SQL::Types::Decimal
31
+ attribute :string_nullable, ROM::SQL::Types::String.optional
32
+ end
33
+ end
34
+ end
35
+
36
+ it 'has support for PG data types' do
37
+ gateway.auto_migrate!(conf)
38
+
39
+ expect(attributes.map(&:to_ast))
40
+ .to eql([
41
+ [:attribute,
42
+ [:id,
43
+ [:definition, [Integer, {}]],
44
+ primary_key: true, source: :test_pg_types]],
45
+ [:attribute, [:string, [:definition, [String, {}]], source: :test_pg_types]],
46
+ [:attribute, [:int, [:definition, [Integer, {}]], source: :test_pg_types]],
47
+ [:attribute, [:time, [:definition, [Time, {}]], source: :test_pg_types]],
48
+ [:attribute, [:date, [:definition, [Date, {}]], source: :test_pg_types]],
49
+ [:attribute, [:decimal, [:definition, [BigDecimal, {}]], source: :test_pg_types]],
50
+ [:attribute,
51
+ [:string_nullable,
52
+ [:sum,
53
+ [[:constrained,
54
+ [[:definition, [NilClass, {}]],
55
+ [:predicate, [:type?, [[:type, NilClass], [:input, ROM::Undefined]]]],
56
+ {}]],
57
+ [:definition, [String, {}]],
58
+ {}]],
59
+ source: :test_pg_types]]
60
+ ])
61
+ end
62
+ end
63
+ end
@@ -137,10 +137,8 @@ RSpec.describe 'Commands / Create', :postgres, seeds: false do
137
137
  end
138
138
 
139
139
  it 'uses relation schema for the default input handler' do
140
- conf.relation(:users) do
141
- register_as :users_with_schema
142
-
143
- schema do
140
+ conf.relation(:users_with_schema) do
141
+ schema(:users) do
144
142
  attribute :id, ROM::SQL::Types::Serial
145
143
  attribute :name, ROM::SQL::Types::String
146
144
  end
@@ -63,7 +63,7 @@ RSpec.describe 'Commands / Delete' do
63
63
  describe '#execute' do
64
64
  context 'with a single record' do
65
65
  it 'materializes the result' do
66
- result = container.command(:users).delete.by_name(%w(Jade)).execute
66
+ result = container.commands[:users].delete.by_name(%w(Jade)).execute
67
67
  expect(result).to eq([
68
68
  { id: 3, name: 'Jade' }
69
69
  ])
@@ -72,7 +72,7 @@ RSpec.describe 'Commands / Delete' do
72
72
 
73
73
  context 'with multiple records' do
74
74
  it 'materializes the results' do
75
- result = container.command(:users).delete.by_name(%w(Jade John)).execute
75
+ result = container.commands[:users].delete.by_name(%w(Jade John)).execute
76
76
  expect(result).to eq([
77
77
  { id: 3, name: 'Jade' },
78
78
  { id: 4, name: 'John' }
@@ -16,6 +16,8 @@ RSpec.describe 'Commands / Update', seeds: false do
16
16
  }
17
17
 
18
18
  conf.relation(:users) do
19
+ schema(infer: true)
20
+
19
21
  def by_id(id)
20
22
  where(id: id)
21
23
  end
@@ -4,18 +4,24 @@ RSpec.describe 'Eager loading' do
4
4
  with_adapters do
5
5
  before do
6
6
  conf.relation(:users) do
7
+ auto_map false
8
+
7
9
  def by_name(name)
8
10
  where(name: name)
9
11
  end
10
12
  end
11
13
 
12
14
  conf.relation(:tasks) do
15
+ auto_map false
16
+
13
17
  def for_users(users)
14
18
  where(user_id: users.map { |tuple| tuple[:id] })
15
19
  end
16
20
  end
17
21
 
18
22
  conf.relation(:tags) do
23
+ auto_map false
24
+
19
25
  def for_tasks(tasks)
20
26
  inner_join(:task_tags, task_id: :id)
21
27
  .where(task_id: tasks.map { |tuple| tuple[:id] })
@@ -24,9 +30,9 @@ RSpec.describe 'Eager loading' do
24
30
  end
25
31
 
26
32
  it 'issues 3 queries for 3.graphd relations' do
27
- users = container.relation(:users).by_name('Piotr')
28
- tasks = container.relation(:tasks)
29
- tags = container.relation(:tags)
33
+ users = container.relations[:users].by_name('Piotr')
34
+ tasks = container.relations[:tasks]
35
+ tags = container.relations[:tags]
30
36
 
31
37
  relation = users.graph(tasks.for_users.graph(tags.for_tasks))
32
38
 
@@ -8,6 +8,17 @@ RSpec.describe 'Plugins / :associates', seeds: false do
8
8
  let(:tags) { container.commands[:tags] }
9
9
 
10
10
  before do
11
+ conf.relation(:tasks) do
12
+ schema(infer: true) do
13
+ associations do
14
+ many_to_one :users, as: :user
15
+ many_to_one :users, as: :other
16
+ one_to_many :task_tags
17
+ one_to_many :tags, through: :task_tags
18
+ end
19
+ end
20
+ end
21
+
11
22
  conf.commands(:users) do
12
23
  define(:create) { result :one }
13
24
  end
@@ -82,35 +93,12 @@ RSpec.describe 'Plugins / :associates', seeds: false do
82
93
  end
83
94
  end
84
95
 
85
- context 'without a schema' do
86
- include_context 'automatic FK setting' do
87
- before do
88
- conf.commands(:tasks) do
89
- define(:create) do
90
- register_as :create_many
91
- associates :user, key: [:user_id, :id]
92
- end
93
-
94
- define(:create) do
95
- register_as :create_one
96
- result :one
97
- associates :user, key: [:user_id, :id]
98
- end
99
- end
100
- end
101
- end
102
- end
103
-
104
96
  context 'with a schema' do
105
97
  include_context 'automatic FK setting'
106
98
 
107
99
  before do
108
- conf.relation_classes[1].class_eval do
109
- schema do
110
- attribute :id, ROM::SQL::Types::Serial
111
- attribute :user_id, ROM::SQL::Types::ForeignKey(:users)
112
- attribute :title, ROM::SQL::Types::String
113
-
100
+ conf.relation(:tasks) do
101
+ schema(infer: true) do
114
102
  associations do
115
103
  many_to_one :users, as: :user
116
104
  one_to_many :task_tags
@@ -136,10 +124,7 @@ RSpec.describe 'Plugins / :associates', seeds: false do
136
124
  context 'with many-to-many association' do
137
125
  before do
138
126
  conf.relation(:tags) do
139
- schema do
140
- attribute :id, ROM::SQL::Types::Serial
141
- attribute :name, ROM::SQL::Types::String
142
-
127
+ schema(infer: true) do
143
128
  associations do
144
129
  one_to_many :task_tags
145
130
  one_to_many :tasks, through: :task_tags
@@ -183,7 +168,7 @@ RSpec.describe 'Plugins / :associates', seeds: false do
183
168
  command = create_user >> create_task >> create_tags
184
169
 
185
170
  result = command.call
186
- tags = relations[:tasks].associations[:tags].call(relations).to_a
171
+ tags = relations[:tasks].associations[:tags].().to_a
187
172
 
188
173
  expect(result).to eql([
189
174
  { id: 1, task_id: 1, name: 'red' }, { id: 2, task_id: 1, name: 'blue' }
@@ -231,7 +216,7 @@ RSpec.describe 'Plugins / :associates', seeds: false do
231
216
  end
232
217
 
233
218
  before do
234
- conf.relation_classes[1].class_eval do
219
+ conf.relation(:tasks) do
235
220
  schema(infer: true) do
236
221
  associations do
237
222
  belongs_to :user
@@ -262,28 +247,4 @@ RSpec.describe 'Plugins / :associates', seeds: false do
262
247
  end
263
248
  end
264
249
  end
265
-
266
- context 'misconfigured assocs', :sqlite do
267
- subject(:command) do
268
- container.commands[:users][:create]
269
- end
270
-
271
- context 'when keys are missing in class-level config' do
272
- before do
273
- conf.commands(:users) do
274
- define(:create) do
275
- associates :tasks
276
- end
277
- end
278
- end
279
-
280
- it 'raises error' do
281
- expect { command }.
282
- to raise_error(
283
- ROM::SQL::Plugin::Associates::MissingJoinKeysError,
284
- ':create command for :users relation is missing join keys configuration for :tasks association'
285
- )
286
- end
287
- end
288
- end
289
250
  end