rom-repository 0.2.0 → 0.3.0

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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -5
  4. data/CHANGELOG.md +24 -0
  5. data/Gemfile +21 -5
  6. data/README.md +6 -110
  7. data/lib/rom/repository/changeset/create.rb +26 -0
  8. data/lib/rom/repository/changeset/pipe.rb +40 -0
  9. data/lib/rom/repository/changeset/update.rb +82 -0
  10. data/lib/rom/repository/changeset.rb +99 -0
  11. data/lib/rom/repository/class_interface.rb +142 -0
  12. data/lib/rom/repository/command_compiler.rb +214 -0
  13. data/lib/rom/repository/command_proxy.rb +22 -0
  14. data/lib/rom/repository/header_builder.rb +13 -16
  15. data/lib/rom/repository/mapper_builder.rb +7 -14
  16. data/lib/rom/repository/{loading_proxy → relation_proxy}/wrap.rb +7 -7
  17. data/lib/rom/repository/relation_proxy.rb +225 -0
  18. data/lib/rom/repository/root.rb +110 -0
  19. data/lib/rom/repository/struct_attributes.rb +46 -0
  20. data/lib/rom/repository/struct_builder.rb +31 -14
  21. data/lib/rom/repository/version.rb +1 -1
  22. data/lib/rom/repository.rb +192 -31
  23. data/lib/rom/struct.rb +13 -8
  24. data/rom-repository.gemspec +9 -10
  25. data/spec/integration/changeset_spec.rb +86 -0
  26. data/spec/integration/command_macros_spec.rb +175 -0
  27. data/spec/integration/command_spec.rb +224 -0
  28. data/spec/integration/multi_adapter_spec.rb +3 -3
  29. data/spec/integration/repository_spec.rb +97 -2
  30. data/spec/integration/root_repository_spec.rb +88 -0
  31. data/spec/shared/database.rb +47 -3
  32. data/spec/shared/mappers.rb +35 -0
  33. data/spec/shared/models.rb +41 -0
  34. data/spec/shared/plugins.rb +66 -0
  35. data/spec/shared/relations.rb +76 -0
  36. data/spec/shared/repo.rb +38 -17
  37. data/spec/shared/seeds.rb +19 -0
  38. data/spec/spec_helper.rb +4 -1
  39. data/spec/support/mapper_registry.rb +1 -3
  40. data/spec/unit/changeset_spec.rb +58 -0
  41. data/spec/unit/header_builder_spec.rb +34 -35
  42. data/spec/unit/relation_proxy_spec.rb +170 -0
  43. data/spec/unit/sql/relation_spec.rb +5 -5
  44. data/spec/unit/struct_builder_spec.rb +7 -4
  45. data/spec/unit/struct_spec.rb +22 -0
  46. metadata +38 -41
  47. data/lib/rom/plugins/relation/key_inference.rb +0 -31
  48. data/lib/rom/repository/loading_proxy/combine.rb +0 -158
  49. data/lib/rom/repository/loading_proxy.rb +0 -182
  50. data/spec/unit/loading_proxy_spec.rb +0 -147
@@ -0,0 +1,170 @@
1
+ RSpec.describe 'loading proxy' do
2
+ include_context 'database'
3
+ include_context 'relations'
4
+ include_context 'repo'
5
+ include_context 'structs'
6
+ include_context 'seeds'
7
+
8
+ let(:users) do
9
+ ROM::Repository::RelationProxy.new(rom.relation(:users), name: :users)
10
+ end
11
+
12
+ let(:tasks) do
13
+ ROM::Repository::RelationProxy.new(rom.relation(:tasks), name: :tasks)
14
+ end
15
+
16
+ let(:tags) do
17
+ ROM::Repository::RelationProxy.new(rom.relation(:tags), name: :tags)
18
+ end
19
+
20
+ describe '#each' do
21
+ it 'yields loaded structs' do
22
+ result = []
23
+
24
+ users.each { |user| result << user }
25
+
26
+ expect(result).to eql([jane, joe])
27
+ end
28
+
29
+ it 'returns an enumerator when block is not given' do
30
+ expect(users.each.to_a).to eql([jane, joe])
31
+ end
32
+ end
33
+
34
+ describe '#map_with/#as' do
35
+ context 'with custom mappers' do
36
+ before do
37
+ configuration.mappers do
38
+ register :users, {
39
+ name_list: -> users { users.map { |u| u[:name] } },
40
+ upcase_names: -> names { names.map(&:upcase) },
41
+ identity: -> users { users }
42
+ }
43
+ end
44
+ end
45
+
46
+ it 'sends the relation through custom mappers' do
47
+ expect(users.map_with(:name_list, :upcase_names).to_a).to match_array(%w(JANE JOE))
48
+ end
49
+
50
+ it 'does not use the default(ROM::Struct) mapper' do
51
+ expect(users.map_with(:identity).to_a).to match_array(
52
+ [{ id: 1, name: 'Jane' }, {id: 2, name: 'Joe' }]
53
+ )
54
+ end
55
+ end
56
+
57
+ context 'setting custom model type' do
58
+ let(:user_type) do
59
+ Class.new(Dry::Types::Struct) do
60
+ attribute :id, Dry::Types['strict.int']
61
+ attribute :name, Dry::Types['strict.string']
62
+ end
63
+ end
64
+
65
+ let(:custom_users) { users.as(user_type) }
66
+
67
+ it 'instantiates custom model' do
68
+ expect(custom_users.where(name: 'Jane').one).to be_instance_of(user_type)
69
+ end
70
+ end
71
+ end
72
+
73
+ describe 'retrieving a single struct' do
74
+ describe '#first' do
75
+ it 'returns exactly one struct' do
76
+ expect(users.first).to eql(jane)
77
+ end
78
+ end
79
+
80
+ describe '#one' do
81
+ it 'returns exactly one struct' do
82
+ expect(users.find(id: 1).one).to eql(jane)
83
+
84
+ expect(users.find(id: 3).one).to be(nil)
85
+
86
+ expect { users.find(id: [1,2]).one }.to raise_error(ROM::TupleCountMismatchError)
87
+ end
88
+ end
89
+
90
+ describe '#one!' do
91
+ it 'returns exactly one struct' do
92
+ expect(users.find(id: 1).one!).to eql(jane)
93
+
94
+ expect { users.find(id: [1, 2]).one! }.to raise_error(ROM::TupleCountMismatchError)
95
+ expect { users.find(id: [3]).one! }.to raise_error(ROM::TupleCountMismatchError)
96
+ end
97
+ end
98
+ end
99
+
100
+ describe '#to_ast' do
101
+ it 'returns valid ast for a single relation' do
102
+ expect(users.to_ast).to eql(
103
+ [:relation, [
104
+ :users,
105
+ { dataset: :users },
106
+ [:header, [[:attribute, :id], [:attribute, :name]]]]
107
+ ]
108
+ )
109
+ end
110
+
111
+ it 'returns valid ast for a combined relation' do
112
+ relation = users.combine(many: { user_tasks: [tasks, id: :user_id] })
113
+
114
+ expect(relation.to_ast).to eql(
115
+ [:relation, [
116
+ :users,
117
+ { dataset: :users },
118
+ [:header, [
119
+ [:attribute, :id],
120
+ [:attribute, :name],
121
+ [:relation, [
122
+ :tasks,
123
+ { dataset: :tasks, keys: { id: :user_id }, combine_type: :many, combine_name: :user_tasks },
124
+ [:header, [[:attribute, :id], [:attribute, :user_id], [:attribute, :title]]]
125
+ ]]
126
+ ]
127
+ ]]]
128
+ )
129
+ end
130
+
131
+ it 'returns valid ast for a wrapped relation' do
132
+ relation = tags.wrap_parent(task: tasks)
133
+
134
+ expect(relation.to_ast).to eql(
135
+ [:relation, [
136
+ :tags,
137
+ { dataset: :tags },
138
+ [:header, [
139
+ [:attribute, :id],
140
+ [:attribute, :task_id],
141
+ [:attribute, :name],
142
+ [:relation, [
143
+ :tasks,
144
+ { dataset: :tasks, keys: { id: :task_id }, wrap: true, combine_name: :task },
145
+ [:header, [ [:attribute, :id], [:attribute, :user_id], [:attribute, :title]]]
146
+ ]]
147
+ ]]
148
+ ]]
149
+ )
150
+ end
151
+ end
152
+
153
+ describe '#method_missing' do
154
+ it 'proxies to the underlying relation' do
155
+ expect(users.gateway).to be(:default)
156
+ end
157
+
158
+ it 'returns proxy when response was not materialized' do
159
+ expect(users.by_pk(1)).to be_instance_of(ROM::Repository::RelationProxy)
160
+ end
161
+
162
+ it 'returns curried proxy when response was curried' do
163
+ expect(users.by_pk).to be_instance_of(ROM::Repository::RelationProxy)
164
+ end
165
+
166
+ it 'raises when method is missing' do
167
+ expect { users.not_here }.to raise_error(NoMethodError, /not_here/)
168
+ end
169
+ end
170
+ end
@@ -7,8 +7,8 @@ RSpec.describe 'SQL Relation extensions' do
7
7
  it 'has valid column names' do
8
8
  expect(users.attributes).to eql([:id, :name])
9
9
 
10
- expect(users.by_id.attributes).to eql([:name])
11
- expect(users.by_id(1).attributes).to eql([:name])
10
+ expect(users.by_pk.attributes).to eql([:name])
11
+ expect(users.by_pk(1).attributes).to eql([:name])
12
12
  end
13
13
  end
14
14
 
@@ -16,7 +16,7 @@ RSpec.describe 'SQL Relation extensions' do
16
16
  context 'using short syntax' do
17
17
  before do
18
18
  configuration.relation(:users) do
19
- view(:by_id, [:name]) do |name|
19
+ view(:by_pk, [:name]) do |name|
20
20
  where(name: name).select(:name)
21
21
  end
22
22
  end
@@ -28,7 +28,7 @@ RSpec.describe 'SQL Relation extensions' do
28
28
  context 'with multi-block syntax' do
29
29
  before do
30
30
  configuration.relation(:users) do
31
- view(:by_id) do
31
+ view(:by_pk) do
32
32
  header [:name]
33
33
 
34
34
  relation do |name|
@@ -45,7 +45,7 @@ RSpec.describe 'SQL Relation extensions' do
45
45
  it 'raises error' do
46
46
  expect {
47
47
  configuration.relation(:users) do
48
- view(:by_id) { |args| }
48
+ view(:by_pk) { |args| }
49
49
  end
50
50
  }.to raise_error(ArgumentError)
51
51
  end
@@ -1,12 +1,12 @@
1
1
  RSpec.describe 'struct builder', '#call' do
2
2
  subject(:builder) { ROM::Repository::StructBuilder.new }
3
3
 
4
- let(:input) { [:users, [:id, :name]] }
4
+ let(:input) { [:users, [:header, [[:attribute, :id], [:attribute, :name]]]] }
5
5
 
6
6
  before { builder[*input] }
7
7
 
8
8
  it 'generates a struct for a given relation name and columns' do
9
- struct = builder.registry[input.hash]
9
+ struct = builder.class.cache[input.hash]
10
10
 
11
11
  user = struct.new(id: 1, name: 'Jane')
12
12
 
@@ -17,9 +17,12 @@ RSpec.describe 'struct builder', '#call' do
17
17
  expect(user[:name]).to eql('Jane')
18
18
 
19
19
  expect(Hash[user]).to eql(id: 1, name: 'Jane')
20
+
21
+ expect(user.inspect).to eql('#<ROM::Struct[User] id=1 name="Jane">')
22
+ expect(user.to_s).to match(/\A#<ROM::Struct\[User\]:0x[0-9a-f]+>\z/)
20
23
  end
21
24
 
22
- it 'stores struct in the registry' do
23
- expect(builder.registry[input.hash]).to be(builder[*input])
25
+ it 'stores struct in the cache' do
26
+ expect(builder.class.cache[input.hash]).to be(builder[*input])
24
27
  end
25
28
  end
@@ -0,0 +1,22 @@
1
+ RSpec.describe ROM::Struct do
2
+ subject(:struct) do
3
+ Class.new(ROM::Struct) do
4
+ attr_reader :id, :name
5
+
6
+ def initialize(id, name)
7
+ @id, @name = id, name
8
+ end
9
+
10
+ def id
11
+ @id.to_i
12
+ end
13
+ end.new("1", "Jane")
14
+ end
15
+
16
+ describe '#[]' do
17
+ it 'reads an attribute value' do
18
+ expect(struct.id).to be(1)
19
+ expect(struct.name).to eql("Jane")
20
+ end
21
+ end
22
+ end
metadata CHANGED
@@ -1,107 +1,88 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rom-repository
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Piotr Solnica
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-01-06 00:00:00.000000000 Z
11
+ date: 2016-07-27 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: anima
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '0.2'
20
- - - ">="
21
- - !ruby/object:Gem::Version
22
- version: '0.2'
23
- type: :runtime
24
- prerelease: false
25
- version_requirements: !ruby/object:Gem::Requirement
26
- requirements:
27
- - - "~>"
28
- - !ruby/object:Gem::Version
29
- version: '0.2'
30
- - - ">="
31
- - !ruby/object:Gem::Version
32
- version: '0.2'
33
13
  - !ruby/object:Gem::Dependency
34
14
  name: rom
35
15
  requirement: !ruby/object:Gem::Requirement
36
16
  requirements:
37
17
  - - "~>"
38
18
  - !ruby/object:Gem::Version
39
- version: 1.0.0
19
+ version: '2.0'
40
20
  type: :runtime
41
21
  prerelease: false
42
22
  version_requirements: !ruby/object:Gem::Requirement
43
23
  requirements:
44
24
  - - "~>"
45
25
  - !ruby/object:Gem::Version
46
- version: 1.0.0
26
+ version: '2.0'
47
27
  - !ruby/object:Gem::Dependency
48
28
  name: rom-support
49
29
  requirement: !ruby/object:Gem::Requirement
50
30
  requirements:
51
31
  - - "~>"
52
32
  - !ruby/object:Gem::Version
53
- version: 1.0.0
33
+ version: '2.0'
54
34
  type: :runtime
55
35
  prerelease: false
56
36
  version_requirements: !ruby/object:Gem::Requirement
57
37
  requirements:
58
38
  - - "~>"
59
39
  - !ruby/object:Gem::Version
60
- version: 1.0.0
40
+ version: '2.0'
61
41
  - !ruby/object:Gem::Dependency
62
42
  name: rom-mapper
63
43
  requirement: !ruby/object:Gem::Requirement
64
44
  requirements:
65
45
  - - "~>"
66
46
  - !ruby/object:Gem::Version
67
- version: 0.3.0
47
+ version: '0.4'
68
48
  type: :runtime
69
49
  prerelease: false
70
50
  version_requirements: !ruby/object:Gem::Requirement
71
51
  requirements:
72
52
  - - "~>"
73
53
  - !ruby/object:Gem::Version
74
- version: 0.3.0
54
+ version: '0.4'
75
55
  - !ruby/object:Gem::Dependency
76
56
  name: rake
77
57
  requirement: !ruby/object:Gem::Requirement
78
58
  requirements:
79
59
  - - "~>"
80
60
  - !ruby/object:Gem::Version
81
- version: '10.3'
61
+ version: '11.2'
82
62
  type: :development
83
63
  prerelease: false
84
64
  version_requirements: !ruby/object:Gem::Requirement
85
65
  requirements:
86
66
  - - "~>"
87
67
  - !ruby/object:Gem::Version
88
- version: '10.3'
68
+ version: '11.2'
89
69
  - !ruby/object:Gem::Dependency
90
70
  name: rspec
91
71
  requirement: !ruby/object:Gem::Requirement
92
72
  requirements:
93
73
  - - "~>"
94
74
  - !ruby/object:Gem::Version
95
- version: '3.3'
75
+ version: '3.5'
96
76
  type: :development
97
77
  prerelease: false
98
78
  version_requirements: !ruby/object:Gem::Requirement
99
79
  requirements:
100
80
  - - "~>"
101
81
  - !ruby/object:Gem::Version
102
- version: '3.3'
103
- description: Repository for ROM with auto-mapping and relation extensions
104
- email: piotr.solnica@gmail.com
82
+ version: '3.5'
83
+ description: rom-repository adds support for auto-mapping and commands on top of rom-rb
84
+ relations
85
+ email: piotr.solnica+oss@gmail.com
105
86
  executables: []
106
87
  extensions: []
107
88
  extra_rdoc_files: []
@@ -115,32 +96,48 @@ files:
115
96
  - README.md
116
97
  - Rakefile
117
98
  - lib/rom-repository.rb
118
- - lib/rom/plugins/relation/key_inference.rb
119
99
  - lib/rom/repository.rb
100
+ - lib/rom/repository/changeset.rb
101
+ - lib/rom/repository/changeset/create.rb
102
+ - lib/rom/repository/changeset/pipe.rb
103
+ - lib/rom/repository/changeset/update.rb
104
+ - lib/rom/repository/class_interface.rb
105
+ - lib/rom/repository/command_compiler.rb
106
+ - lib/rom/repository/command_proxy.rb
120
107
  - lib/rom/repository/header_builder.rb
121
- - lib/rom/repository/loading_proxy.rb
122
- - lib/rom/repository/loading_proxy/combine.rb
123
- - lib/rom/repository/loading_proxy/wrap.rb
124
108
  - lib/rom/repository/mapper_builder.rb
109
+ - lib/rom/repository/relation_proxy.rb
110
+ - lib/rom/repository/relation_proxy/wrap.rb
111
+ - lib/rom/repository/root.rb
112
+ - lib/rom/repository/struct_attributes.rb
125
113
  - lib/rom/repository/struct_builder.rb
126
114
  - lib/rom/repository/version.rb
127
115
  - lib/rom/struct.rb
128
116
  - log/.gitkeep
129
117
  - rom-repository.gemspec
118
+ - spec/integration/changeset_spec.rb
119
+ - spec/integration/command_macros_spec.rb
120
+ - spec/integration/command_spec.rb
130
121
  - spec/integration/multi_adapter_spec.rb
131
122
  - spec/integration/repository_spec.rb
123
+ - spec/integration/root_repository_spec.rb
132
124
  - spec/shared/database.rb
125
+ - spec/shared/mappers.rb
126
+ - spec/shared/models.rb
127
+ - spec/shared/plugins.rb
133
128
  - spec/shared/relations.rb
134
129
  - spec/shared/repo.rb
135
130
  - spec/shared/seeds.rb
136
131
  - spec/shared/structs.rb
137
132
  - spec/spec_helper.rb
138
133
  - spec/support/mapper_registry.rb
134
+ - spec/unit/changeset_spec.rb
139
135
  - spec/unit/header_builder_spec.rb
140
- - spec/unit/loading_proxy_spec.rb
141
136
  - spec/unit/plugins/view_spec.rb
137
+ - spec/unit/relation_proxy_spec.rb
142
138
  - spec/unit/sql/relation_spec.rb
143
139
  - spec/unit/struct_builder_spec.rb
140
+ - spec/unit/struct_spec.rb
144
141
  homepage: http://rom-rb.org
145
142
  licenses:
146
143
  - MIT
@@ -161,8 +158,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
158
  version: '0'
162
159
  requirements: []
163
160
  rubyforge_project:
164
- rubygems_version: 2.4.5.1
161
+ rubygems_version: 2.5.1
165
162
  signing_key:
166
163
  specification_version: 4
167
- summary: Repository for ROM with auto-mapping and relation extensions
164
+ summary: Repository abstraction for rom-rb
168
165
  test_files: []
@@ -1,31 +0,0 @@
1
- module ROM
2
- module Plugins
3
- module Relation
4
- module KeyInference
5
- # Infer foreign_key name for this relation
6
- #
7
- # TODO: this should be configurable and handled by an injected policy
8
- #
9
- # @return [Symbol]
10
- #
11
- # @api private
12
- def foreign_key
13
- :"#{Inflector.singularize(name)}_id"
14
- end
15
-
16
- # Return base name which defaults to name attribute
17
- #
18
- # @return [Symbol]
19
- #
20
- # @api private
21
- def base_name
22
- name
23
- end
24
- end
25
- end
26
- end
27
- end
28
-
29
- ROM.plugins do
30
- register :key_inference, ROM::Plugins::Relation::KeyInference, type: :relation
31
- end
@@ -1,158 +0,0 @@
1
- module ROM
2
- class Repository
3
- class LoadingProxy
4
- # Provides convenient methods for producing combined relations
5
- #
6
- # @api public
7
- module Combine
8
- # Combine with other relations
9
- #
10
- # @example
11
- # # combining many
12
- # users.combine(many: { tasks: [tasks, id: :task_id] })
13
- # users.combine(many: { tasks: [tasks.for_users, id: :task_id] })
14
- #
15
- # # combining one
16
- # users.combine(one: { task: [tasks, id: :task_id] })
17
- #
18
- # @param [Hash] options
19
- #
20
- # @return [LoadingProxy]
21
- #
22
- # @api public
23
- def combine(options)
24
- combine_opts = options.each_with_object({}) do |(type, relations), result|
25
- result[type] = relations.each_with_object({}) do |(name, (other, keys)), h|
26
- h[name] = [
27
- other.curried? ? other : other.combine_method(relation, keys), keys
28
- ]
29
- end
30
- end
31
-
32
- nodes = combine_opts.flat_map do |type, relations|
33
- relations.map { |name, (relation, keys)|
34
- relation.combined(name, keys, type)
35
- }
36
- end
37
-
38
- __new__(relation.combine(*nodes))
39
- end
40
-
41
- # Shortcut for combining with parents which infers the join keys
42
- #
43
- # @example
44
- # tasks.combine_parents(one: users)
45
- #
46
- # @param [Hash] options
47
- #
48
- # @return [LoadingProxy]
49
- #
50
- # @api public
51
- def combine_parents(options)
52
- combine(options.each_with_object({}) { |(type, parents), h|
53
- h[type] =
54
- if parents.is_a?(Hash)
55
- parents.each_with_object({}) { |(key, parent), r|
56
- r[key] = [parent, combine_keys(parent, :parent)]
57
- }
58
- else
59
- (parents.is_a?(Array) ? parents : [parents])
60
- .each_with_object({}) { |parent, r|
61
- r[parent.combine_tuple_key(type)] = [
62
- parent, combine_keys(parent, :parent)
63
- ]
64
- }
65
- end
66
- })
67
- end
68
-
69
- # Shortcut for combining with children which infers the join keys
70
- #
71
- # @example
72
- # users.combine_parents(many: tasks)
73
- #
74
- # @param [Hash] options
75
- #
76
- # @return [LoadingProxy]
77
- #
78
- # @api public
79
- def combine_children(options)
80
- combine(options.each_with_object({}) { |(type, children), h|
81
- h[type] =
82
- if children.is_a?(Hash)
83
- children.each_with_object({}) { |(key, child), r|
84
- r[key] = [child, combine_keys(relation, :children)]
85
- }
86
- else
87
- (children.is_a?(Array) ? children : [children])
88
- .each_with_object({}) { |child, r|
89
- r[child.combine_tuple_key(type)] = [
90
- child, combine_keys(relation, :children)
91
- ]
92
- }
93
- end
94
- })
95
- end
96
-
97
- # Infer join keys for a given relation and association type
98
- #
99
- # @param [LoadingProxy] relation
100
- # @param [Symbol] type The type can be either :parent or :children
101
- #
102
- # @return [Hash<Symbol=>Symbol>]
103
- #
104
- # @api private
105
- def combine_keys(relation, type)
106
- if type == :parent
107
- { relation.foreign_key => relation.primary_key }
108
- else
109
- { relation.primary_key => relation.foreign_key }
110
- end
111
- end
112
-
113
- # Infer relation for combine operation
114
- #
115
- # By default it uses `for_combine` which is implemented as SQL::Relation
116
- # extension
117
- #
118
- # @return [LoadingProxy]
119
- #
120
- # @api private
121
- def combine_method(other, keys)
122
- custom_name = :"for_#{other.base_name}"
123
-
124
- if relation.respond_to?(custom_name)
125
- __send__(custom_name)
126
- else
127
- for_combine(keys)
128
- end
129
- end
130
-
131
- # Infer key under which a combine relation will be loaded
132
- #
133
- # @return [Symbol]
134
- #
135
- # @api private
136
- def combine_tuple_key(arity)
137
- if arity == :one
138
- Inflector.singularize(base_name).to_sym
139
- else
140
- base_name
141
- end
142
- end
143
-
144
- # Return combine representation of a loading-proxy relation
145
- #
146
- # This will carry meta info used to produce a correct AST from a relation
147
- # so that correct mapper can be generated
148
- #
149
- # @return [LoadingProxy]
150
- #
151
- # @api private
152
- def combined(name, keys, type)
153
- with(name: name, meta: { keys: keys, combine_type: type })
154
- end
155
- end
156
- end
157
- end
158
- end