rom-sql 2.0.0.beta2 → 2.0.0.beta3

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 (170) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +66 -0
  3. data/lib/rom/plugins/relation/sql/postgres/explain.rb +54 -0
  4. data/lib/rom/sql.rb +1 -1
  5. data/lib/rom/sql/attribute.rb +17 -18
  6. data/lib/rom/sql/errors.rb +3 -0
  7. data/lib/rom/sql/extensions/mysql.rb +1 -1
  8. data/lib/rom/sql/extensions/mysql/type_builder.rb +28 -0
  9. data/lib/rom/sql/extensions/postgres.rb +3 -1
  10. data/lib/rom/sql/extensions/postgres/commands.rb +30 -13
  11. data/lib/rom/sql/extensions/postgres/{attributes_inferrer.rb → type_builder.rb} +24 -28
  12. data/lib/rom/sql/extensions/postgres/type_serializer.rb +39 -0
  13. data/lib/rom/sql/extensions/postgres/types.rb +24 -477
  14. data/lib/rom/sql/extensions/postgres/types/array.rb +163 -0
  15. data/lib/rom/sql/extensions/postgres/types/geometric.rb +135 -0
  16. data/lib/rom/sql/extensions/postgres/types/json.rb +235 -0
  17. data/lib/rom/sql/extensions/postgres/types/network.rb +15 -0
  18. data/lib/rom/sql/extensions/sqlite.rb +1 -1
  19. data/lib/rom/sql/extensions/sqlite/{attributes_inferrer.rb → type_builder.rb} +5 -5
  20. data/lib/rom/sql/extensions/sqlite/types.rb +8 -3
  21. data/lib/rom/sql/foreign_key.rb +17 -0
  22. data/lib/rom/sql/function.rb +86 -8
  23. data/lib/rom/sql/gateway.rb +26 -26
  24. data/lib/rom/sql/index.rb +4 -0
  25. data/lib/rom/sql/migration.rb +3 -3
  26. data/lib/rom/sql/migration/inline_runner.rb +9 -83
  27. data/lib/rom/sql/migration/migrator.rb +35 -12
  28. data/lib/rom/sql/migration/recorder.rb +21 -0
  29. data/lib/rom/sql/migration/runner.rb +115 -0
  30. data/lib/rom/sql/migration/schema_diff.rb +108 -53
  31. data/lib/rom/sql/migration/writer.rb +61 -0
  32. data/lib/rom/sql/relation.rb +2 -1
  33. data/lib/rom/sql/relation/reading.rb +63 -3
  34. data/lib/rom/sql/relation/writing.rb +38 -0
  35. data/lib/rom/sql/schema.rb +9 -3
  36. data/lib/rom/sql/schema/attributes_inferrer.rb +3 -119
  37. data/lib/rom/sql/schema/inferrer.rb +99 -18
  38. data/lib/rom/sql/schema/type_builder.rb +94 -0
  39. data/lib/rom/sql/type_dsl.rb +30 -0
  40. data/lib/rom/sql/type_extensions.rb +11 -6
  41. data/lib/rom/sql/type_serializer.rb +46 -0
  42. data/lib/rom/sql/types.rb +12 -0
  43. data/lib/rom/sql/version.rb +1 -1
  44. metadata +26 -244
  45. data/.codeclimate.yml +0 -15
  46. data/.gitignore +0 -17
  47. data/.rspec +0 -3
  48. data/.travis.yml +0 -39
  49. data/.yardopts +0 -2
  50. data/Gemfile +0 -33
  51. data/Guardfile +0 -24
  52. data/LICENSE.txt +0 -22
  53. data/Rakefile +0 -19
  54. data/circle.yml +0 -10
  55. data/lib/rom/sql/extensions/mysql/attributes_inferrer.rb +0 -10
  56. data/lib/rom/sql/relation/sequel_api.rb +0 -133
  57. data/log/.gitkeep +0 -0
  58. data/rom-sql.gemspec +0 -29
  59. data/spec/extensions/postgres/attribute_spec.rb +0 -217
  60. data/spec/extensions/postgres/integration_spec.rb +0 -59
  61. data/spec/extensions/postgres/types_spec.rb +0 -252
  62. data/spec/extensions/sqlite/types_spec.rb +0 -11
  63. data/spec/fixtures/migrations/20150403090603_create_carrots.rb +0 -8
  64. data/spec/integration/associations/many_to_many/custom_fks_spec.rb +0 -76
  65. data/spec/integration/associations/many_to_many/from_view_spec.rb +0 -88
  66. data/spec/integration/associations/many_to_many_spec.rb +0 -162
  67. data/spec/integration/associations/many_to_one/custom_fks_spec.rb +0 -64
  68. data/spec/integration/associations/many_to_one/from_view_spec.rb +0 -84
  69. data/spec/integration/associations/many_to_one/self_ref_spec.rb +0 -53
  70. data/spec/integration/associations/many_to_one_spec.rb +0 -117
  71. data/spec/integration/associations/one_to_many/custom_fks_spec.rb +0 -54
  72. data/spec/integration/associations/one_to_many/from_view_spec.rb +0 -57
  73. data/spec/integration/associations/one_to_many/self_ref_spec.rb +0 -54
  74. data/spec/integration/associations/one_to_many_spec.rb +0 -86
  75. data/spec/integration/associations/one_to_one_spec.rb +0 -69
  76. data/spec/integration/associations/one_to_one_through_spec.rb +0 -92
  77. data/spec/integration/auto_migrations/errors_spec.rb +0 -31
  78. data/spec/integration/auto_migrations/indexes_spec.rb +0 -253
  79. data/spec/integration/auto_migrations/managing_columns_spec.rb +0 -156
  80. data/spec/integration/auto_migrations/postgres/column_types_spec.rb +0 -63
  81. data/spec/integration/combine_with_spec.rb +0 -43
  82. data/spec/integration/commands/create_spec.rb +0 -304
  83. data/spec/integration/commands/delete_spec.rb +0 -84
  84. data/spec/integration/commands/update_spec.rb +0 -90
  85. data/spec/integration/commands/upsert_spec.rb +0 -83
  86. data/spec/integration/gateway_spec.rb +0 -107
  87. data/spec/integration/migration_spec.rb +0 -55
  88. data/spec/integration/plugins/associates/many_to_many_spec.rb +0 -69
  89. data/spec/integration/plugins/associates_spec.rb +0 -250
  90. data/spec/integration/plugins/auto_restrictions_spec.rb +0 -74
  91. data/spec/integration/relation_schema_spec.rb +0 -271
  92. data/spec/integration/schema/call_spec.rb +0 -24
  93. data/spec/integration/schema/inferrer/mysql_spec.rb +0 -45
  94. data/spec/integration/schema/inferrer/postgres_spec.rb +0 -203
  95. data/spec/integration/schema/inferrer/sqlite_spec.rb +0 -37
  96. data/spec/integration/schema/inferrer_spec.rb +0 -390
  97. data/spec/integration/schema/prefix_spec.rb +0 -16
  98. data/spec/integration/schema/qualified_spec.rb +0 -16
  99. data/spec/integration/schema/rename_spec.rb +0 -21
  100. data/spec/integration/schema/view_spec.rb +0 -29
  101. data/spec/integration/sequel_api_spec.rb +0 -36
  102. data/spec/integration/setup_spec.rb +0 -26
  103. data/spec/integration/support/active_support_notifications_spec.rb +0 -24
  104. data/spec/integration/support/rails_log_subscriber_spec.rb +0 -30
  105. data/spec/integration/wrap_spec.rb +0 -91
  106. data/spec/shared/accounts.rb +0 -48
  107. data/spec/shared/database_setup.rb +0 -70
  108. data/spec/shared/notes.rb +0 -23
  109. data/spec/shared/posts.rb +0 -34
  110. data/spec/shared/puppies.rb +0 -15
  111. data/spec/shared/relations.rb +0 -8
  112. data/spec/shared/users.rb +0 -32
  113. data/spec/shared/users_and_tasks.rb +0 -50
  114. data/spec/spec_helper.rb +0 -122
  115. data/spec/support/env_helper.rb +0 -25
  116. data/spec/support/helpers.rb +0 -24
  117. data/spec/support/oracle/create_users.sql +0 -7
  118. data/spec/support/oracle/set_sys_passwords.sql +0 -2
  119. data/spec/support/test_configuration.rb +0 -16
  120. data/spec/unit/attribute_spec.rb +0 -104
  121. data/spec/unit/function_spec.rb +0 -48
  122. data/spec/unit/gateway_spec.rb +0 -70
  123. data/spec/unit/logger_spec.rb +0 -14
  124. data/spec/unit/migration_tasks_spec.rb +0 -111
  125. data/spec/unit/migrator_spec.rb +0 -25
  126. data/spec/unit/order_dsl_spec.rb +0 -43
  127. data/spec/unit/plugin/associates_spec.rb +0 -94
  128. data/spec/unit/plugin/pagination_spec.rb +0 -91
  129. data/spec/unit/plugin/timestamp_spec.rb +0 -117
  130. data/spec/unit/projection_dsl_spec.rb +0 -110
  131. data/spec/unit/relation/assoc_spec.rb +0 -87
  132. data/spec/unit/relation/associations_spec.rb +0 -27
  133. data/spec/unit/relation/avg_spec.rb +0 -11
  134. data/spec/unit/relation/by_pk_spec.rb +0 -62
  135. data/spec/unit/relation/dataset_spec.rb +0 -50
  136. data/spec/unit/relation/distinct_spec.rb +0 -15
  137. data/spec/unit/relation/exclude_spec.rb +0 -11
  138. data/spec/unit/relation/exist_predicate_spec.rb +0 -25
  139. data/spec/unit/relation/exists_spec.rb +0 -18
  140. data/spec/unit/relation/fetch_spec.rb +0 -21
  141. data/spec/unit/relation/group_spec.rb +0 -61
  142. data/spec/unit/relation/having_spec.rb +0 -22
  143. data/spec/unit/relation/inner_join_spec.rb +0 -158
  144. data/spec/unit/relation/inspect_spec.rb +0 -11
  145. data/spec/unit/relation/instrument_spec.rb +0 -45
  146. data/spec/unit/relation/invert_spec.rb +0 -11
  147. data/spec/unit/relation/left_join_spec.rb +0 -55
  148. data/spec/unit/relation/lock_spec.rb +0 -93
  149. data/spec/unit/relation/map_spec.rb +0 -16
  150. data/spec/unit/relation/max_spec.rb +0 -11
  151. data/spec/unit/relation/min_spec.rb +0 -11
  152. data/spec/unit/relation/order_spec.rb +0 -51
  153. data/spec/unit/relation/pluck_spec.rb +0 -11
  154. data/spec/unit/relation/prefix_spec.rb +0 -29
  155. data/spec/unit/relation/primary_key_spec.rb +0 -27
  156. data/spec/unit/relation/project_spec.rb +0 -24
  157. data/spec/unit/relation/qualified_columns_spec.rb +0 -30
  158. data/spec/unit/relation/qualified_spec.rb +0 -25
  159. data/spec/unit/relation/read_spec.rb +0 -25
  160. data/spec/unit/relation/rename_spec.rb +0 -23
  161. data/spec/unit/relation/right_join_spec.rb +0 -57
  162. data/spec/unit/relation/select_append_spec.rb +0 -21
  163. data/spec/unit/relation/select_spec.rb +0 -40
  164. data/spec/unit/relation/sum_spec.rb +0 -11
  165. data/spec/unit/relation/union_spec.rb +0 -19
  166. data/spec/unit/relation/unique_predicate_spec.rb +0 -18
  167. data/spec/unit/relation/where_spec.rb +0 -133
  168. data/spec/unit/restriction_dsl_spec.rb +0 -34
  169. data/spec/unit/schema_spec.rb +0 -25
  170. data/spec/unit/types_spec.rb +0 -65
@@ -1,83 +0,0 @@
1
- RSpec.describe 'Commands / Postgres / Upsert', :postgres, seeds: false do
2
- subject(:command) { task_commands[:create_or_update] }
3
-
4
- include_context 'relations'
5
-
6
- before do
7
- conn.execute "ALTER TABLE tasks add CONSTRAINT tasks_title_key UNIQUE (title)"
8
-
9
- conn[:users].insert id: 1, name: 'Jane'
10
- conn[:users].insert id: 2, name: 'Joe'
11
- conn[:users].insert id: 3, name: 'Jean'
12
- end
13
-
14
- describe '#call' do
15
- let(:task) { { title: 'task 1', user_id: 1 } }
16
- let(:excluded) { task.merge(user_id: 3) }
17
-
18
- before do
19
- command_config = self.command_config
20
-
21
- conf.commands(:tasks) do
22
- define('Postgres::Upsert') do
23
- register_as :create_or_update
24
- result :one
25
-
26
- instance_exec(&command_config)
27
- end
28
- end
29
- end
30
-
31
- before { command.relation.upsert(task) }
32
-
33
- context 'on conflict do nothing' do
34
- let(:command_config) { -> { } }
35
-
36
- it 'returns nil' do
37
- expect(command.call(excluded)).to be nil
38
- end
39
- end
40
-
41
- context 'on conflict do update' do
42
- context 'with conflict target' do
43
- let(:command_config) do
44
- -> do
45
- conflict_target :title
46
- update_statement user_id: 2
47
- end
48
- end
49
-
50
- it 'returns updated data' do
51
- expect(command.call(excluded)).to eql(id: 1, user_id: 2, title: 'task 1')
52
- end
53
- end
54
-
55
- context 'with constraint name' do
56
- let(:command_config) do
57
- -> do
58
- constraint :tasks_title_key
59
- update_statement user_id: Sequel.qualify(:excluded, :user_id)
60
- end
61
- end
62
-
63
- it 'returns updated data' do
64
- expect(command.call(excluded)).to eql(id: 1, user_id: 3, title: 'task 1')
65
- end
66
- end
67
-
68
- context 'with where clause' do
69
- let(:command_config) do
70
- -> do
71
- conflict_target :title
72
- update_statement user_id: nil
73
- update_where Sequel.qualify(:tasks, :id) => 2
74
- end
75
- end
76
-
77
- it 'returns nil' do
78
- expect(command.call(excluded)).to be nil
79
- end
80
- end
81
- end
82
- end
83
- end if PG_LTE_95
@@ -1,107 +0,0 @@
1
- RSpec.describe ROM::SQL::Gateway, :postgres do
2
- include_context 'database setup'
3
-
4
- describe 'migration' do
5
- before do
6
- inferrable_relations.concat %i(rabbits carrots)
7
- end
8
-
9
- context 'creating migrations inline' do
10
- subject(:gateway) { container.gateways[:default] }
11
-
12
- let(:conf) { ROM::Configuration.new(:sql, conn) }
13
- let(:container) { ROM.container(conf) }
14
-
15
- it 'allows creating and running migrations' do
16
- migration = gateway.migration do
17
- up do
18
- create_table(:rabbits) do
19
- primary_key :id
20
- String :name
21
- end
22
- end
23
-
24
- down do
25
- drop_table(:rabbits)
26
- end
27
- end
28
-
29
- migration.apply(gateway.connection, :up)
30
-
31
- expect(gateway.connection[:rabbits]).to be_a(Sequel::Dataset)
32
-
33
- migration.apply(gateway.connection, :down)
34
-
35
- expect(gateway.connection.tables).to_not include(:rabbits)
36
- end
37
- end
38
-
39
- context 'running migrations from a file system' do
40
- before do
41
- inferrable_relations.concat %i(schema_migrations)
42
- end
43
-
44
- let(:migration_dir) do
45
- Pathname(__FILE__).dirname.join('../fixtures/migrations').realpath
46
- end
47
-
48
- let(:migrator) { ROM::SQL::Migration::Migrator.new(conn, path: migration_dir) }
49
- let(:conf) { ROM::Configuration.new(:sql, [conn, migrator: migrator]) }
50
- let(:container) { ROM.container(conf) }
51
-
52
- it 'returns true for pending migrations' do
53
- expect(container.gateways[:default].pending_migrations?).to be_truthy
54
- end
55
-
56
- it 'returns false for non pending migrations' do
57
- container.gateways[:default].run_migrations
58
- expect(container.gateways[:default].pending_migrations?).to be_falsy
59
- end
60
-
61
- it 'runs migrations from a specified directory' do
62
- container.gateways[:default].run_migrations
63
- end
64
- end
65
- end
66
-
67
- describe 'transactions' do
68
- before do
69
- inferrable_relations.concat %i(names)
70
- end
71
-
72
- before do
73
- conn.create_table(:names) do
74
- String :name
75
- end
76
- end
77
-
78
- let(:gw) { container.gateways[:default] }
79
- let(:names) { gw.dataset(:names) }
80
-
81
- it 'can run the code inside a transaction' do
82
- names.insert name: 'Jade'
83
-
84
- gw.transaction do |t|
85
- names.insert name: 'John'
86
-
87
- t.rollback!
88
- names.insert name: 'Jack'
89
- end
90
-
91
- expect(names.to_a).to eql([name: 'Jade'])
92
- end
93
-
94
- it 'sets isolation level to read commited' do
95
- gw = container.gateways[:default]
96
- names = gw.dataset(:names)
97
-
98
- gw.transaction do |t|
99
- names.insert name: 'John'
100
- concurrent_names = nil
101
- Thread.new { concurrent_names = names.to_a }.join
102
-
103
- expect(concurrent_names).to eql([])
104
- end
105
- end
106
- end
107
- end
@@ -1,55 +0,0 @@
1
- RSpec.describe ROM::SQL, '.migration' do
2
- include_context 'database setup'
3
-
4
- before do
5
- inferrable_relations.concat %i(dragons schema_migrations)
6
- end
7
-
8
- with_adapters do
9
- before { conf }
10
-
11
- it 'creates a migration for a specific gateway' do
12
- migration = ROM::SQL.migration(container) do
13
- change do
14
- create_table :dragons do
15
- primary_key :id
16
- column :name, String
17
- end
18
- end
19
- end
20
-
21
- migration.apply(conn, :up)
22
-
23
- expect(conn.table_exists?(:dragons)).to be(true)
24
- end
25
- end
26
-
27
- context 'with non-default gateway' do
28
- with_adapters(:postgres) do
29
- let(:conf) do
30
- ROM::Configuration.new(
31
- default: [:sql, conn, inferrable_relations: %i(schema_migrations)],
32
- in_memory: [:sql, DB_URIS[:sqlite], inferrable_relations: %i(schema_migrations)]
33
- )
34
- end
35
-
36
- let(:in_memory_connection) { container.gateways[:in_memory].connection }
37
-
38
- it 'creates a migration for a specific gateway' do
39
- in_memory_migration = ROM::SQL.migration(container, :in_memory) do
40
- change do
41
- create_table :turtles do
42
- primary_key :id
43
- column :name, String
44
- end
45
- end
46
- end
47
-
48
- in_memory_migration.apply(in_memory_connection, :up)
49
-
50
- expect(in_memory_connection.table_exists?(:dragons)).to be(false)
51
- expect(in_memory_connection.table_exists?(:turtles)).to be(true)
52
- end
53
- end
54
- end
55
- end
@@ -1,69 +0,0 @@
1
- RSpec.describe 'Plugins / :associates / with many-to-many', :sqlite, seeds: false do
2
- include_context 'users and tasks'
3
-
4
- let(:create_tag) { tag_commands.create }
5
- let(:create_task) { task_commands.create }
6
-
7
- let(:jane) do
8
- users.by_pk(users.insert(name: 'Jane')).one
9
- end
10
-
11
- let(:john) do
12
- users.by_pk(users.insert(name: 'John')).one
13
- end
14
-
15
- before do
16
- conf.relation(:tasks) do
17
- schema(infer: true) do
18
- associations do
19
- has_many :tags, through: :task_tags
20
- end
21
- end
22
- end
23
-
24
- conf.relation(:task_tags) do
25
- schema(infer: true) do
26
- associations do
27
- belongs_to :tasks, as: :task
28
- belongs_to :tags, as: :tag
29
- end
30
- end
31
- end
32
-
33
- conf.relation(:tags) do
34
- schema(infer: true) do
35
- associations do
36
- has_many :tasks, through: :task_tags
37
- end
38
- end
39
- end
40
-
41
- conf.commands(:tags) do
42
- define(:create) do
43
- result :many
44
- end
45
- end
46
-
47
- conf.commands(:tasks) do
48
- define(:create) do
49
- result :many
50
- associates :tags
51
- end
52
- end
53
- end
54
-
55
- it 'associates a child with many parents' do
56
- add_tags = create_tag.curry([{ name: 'red' }, { name: 'blue' }])
57
- add_task = create_task.curry(user_id: jane[:id], title: "Jade's task")
58
-
59
- command = add_tags >> add_task
60
-
61
- result = command.call
62
-
63
- expect(result).
64
- to eql([
65
- { id: 1, user_id: jane[:id], title: "Jade's task", tag_id: 1 },
66
- { id: 1, user_id: jane[:id], title: "Jade's task", tag_id: 2 }
67
- ])
68
- end
69
- end
@@ -1,250 +0,0 @@
1
- RSpec.describe 'Plugins / :associates', seeds: false do
2
- include_context 'relations'
3
-
4
- with_adapters do
5
- context 'with Create command' do
6
- let(:users) { container.commands[:users] }
7
- let(:tasks) { container.commands[:tasks] }
8
- let(:tags) { container.commands[:tags] }
9
-
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
-
22
- conf.commands(:users) do
23
- define(:create) { result :one }
24
- end
25
- end
26
-
27
- describe '#with_association' do
28
- let(:user) do
29
- users[:create].call(name: 'Jane')
30
- end
31
-
32
- let(:task) do
33
- { title: 'Task one' }
34
- end
35
-
36
- before do
37
- conf.commands(:users) do
38
- define(:create) { result :one }
39
- end
40
-
41
- conf.commands(:tasks) do
42
- define(:create) { result :one }
43
- end
44
- end
45
-
46
- it 'returns a command prepared for the given association' do
47
- command = tasks[:create].with_association(:user, key: %i[user_id id])
48
-
49
- expect(command.call(task, user)).
50
- to eql(id: 1, title: 'Task one', user_id: user[:id])
51
- end
52
-
53
- it 'allows passing a parent explicitly' do
54
- command = tasks[:create].with_association(:user, key: %i[user_id id], parent: user)
55
-
56
- expect(command.call(task)).
57
- to eql(id: 1, title: 'Task one', user_id: user[:id])
58
- end
59
-
60
- it 'allows setting up multiple associations' do
61
- command = tasks[:create].
62
- with_association(:user, key: %i[user_id id], parent: user).
63
- with_association(:other, key: %i[other_id id])
64
-
65
- expect(command.configured_associations).to eql(%i[user other])
66
- end
67
- end
68
-
69
- shared_context 'automatic FK setting' do
70
- it 'sets foreign key prior execution for many tuples' do
71
- create_user = users[:create].curry(name: 'Jade')
72
- create_task = tasks[:create_many].curry([{ title: 'Task one' }, { title: 'Task two' }])
73
-
74
- command = create_user >> create_task
75
-
76
- result = command.call
77
-
78
- expect(result).to match_array([
79
- { id: 1, user_id: 1, title: 'Task one' },
80
- { id: 2, user_id: 1, title: 'Task two' }
81
- ])
82
- end
83
-
84
- it 'sets foreign key prior execution for one tuple' do
85
- create_user = users[:create].curry(name: 'Jade')
86
- create_task = tasks[:create_one].curry(title: 'Task one')
87
-
88
- command = create_user >> create_task
89
-
90
- result = command.call
91
-
92
- expect(result).to match_array(id: 1, user_id: 1, title: 'Task one')
93
- end
94
- end
95
-
96
- context 'with a schema' do
97
- include_context 'automatic FK setting'
98
-
99
- before do
100
- conf.relation(:tasks) do
101
- schema(infer: true) do
102
- associations do
103
- many_to_one :users, as: :user
104
- one_to_many :task_tags
105
- one_to_many :tags, through: :task_tags
106
- end
107
- end
108
- end
109
-
110
- conf.commands(:tasks) do
111
- define(:create) do
112
- register_as :create_many
113
- associates :user
114
- end
115
-
116
- define(:create) do
117
- register_as :create_one
118
- result :one
119
- associates :user
120
- end
121
- end
122
- end
123
-
124
- context 'with many-to-many association' do
125
- before do
126
- conf.relation(:tags) do
127
- schema(infer: true) do
128
- associations do
129
- one_to_many :task_tags
130
- one_to_many :tasks, through: :task_tags
131
- end
132
- end
133
- end
134
-
135
- conf.relation(:task_tags) do
136
- schema do
137
- attribute :tag_id, ROM::SQL::Types::ForeignKey(:tags)
138
- attribute :task_id, ROM::SQL::Types::ForeignKey(:tasks)
139
-
140
- primary_key :tag_id, :task_id
141
-
142
- associations do
143
- many_to_one :tags
144
- many_to_one :tasks
145
- end
146
- end
147
- end
148
-
149
- conf.commands(:tasks) do
150
- define(:create) do
151
- result :one
152
- associates :user
153
- end
154
- end
155
-
156
- conf.commands(:tags) do
157
- define(:create) do
158
- associates :tasks
159
- end
160
- end
161
- end
162
-
163
- it 'sets FKs for the join table' do
164
- create_user = users[:create].curry(name: 'Jade')
165
- create_task = tasks[:create].curry(title: "Jade's task")
166
- create_tags = tags[:create].curry([{ name: 'red' }, { name: 'blue' }])
167
-
168
- command = create_user >> create_task >> create_tags
169
-
170
- result = command.call
171
- tags = relations[:tasks].associations[:tags].().to_a
172
-
173
- expect(result).to eql([
174
- { id: 1, task_id: 1, name: 'red' }, { id: 2, task_id: 1, name: 'blue' }
175
- ])
176
-
177
- expect(tags).to eql(result)
178
- end
179
- end
180
- end
181
-
182
- it 'raises when already defined' do
183
- expect {
184
- conf.commands(:tasks) do
185
- define(:create) do
186
- result :one
187
- associates :user, key: [:user_id, :id]
188
- associates :user, key: [:user_id, :id]
189
- end
190
- end
191
- }.to raise_error(ArgumentError, /user/)
192
- end
193
- end
194
- end
195
-
196
- with_adapters :sqlite do
197
- context 'with Update command' do
198
- subject(:command) do
199
- container.commands[:tasks][:update].with_association(:user).by_pk(jane_task[:id])
200
- end
201
-
202
- let(:john) do
203
- container.commands[:users][:create].call(name: 'John')
204
- end
205
-
206
- let(:jane) do
207
- container.commands[:users][:create].call(name: 'Jane')
208
- end
209
-
210
- let(:jane_task) do
211
- container.commands[:tasks][:create].call(user_id: jane[:id], title: 'Jane Task')
212
- end
213
-
214
- let(:john_task) do
215
- container.commands[:tasks][:create].call(user_id: john[:id], title: 'John Task')
216
- end
217
-
218
- before do
219
- conf.relation(:tasks) do
220
- schema(infer: true) do
221
- associations do
222
- belongs_to :user
223
- end
224
- end
225
- end
226
-
227
- conf.commands(:users) do
228
- define(:create) do
229
- result :one
230
- end
231
- end
232
-
233
- conf.commands(:tasks) do
234
- define(:create) do
235
- result :one
236
- end
237
-
238
- define(:update) do
239
- result :one
240
- end
241
- end
242
- end
243
-
244
- it 'automatically sets FK prior execution' do
245
- expect(command.curry(title: 'Another John task').call(john)).
246
- to eql(id: jane_task[:id], user_id: john[:id], title: 'Another John task')
247
- end
248
- end
249
- end
250
- end