lhs 6.7.2 → 6.8.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +3 -0
- data/lib/lhs/complex.rb +180 -0
- data/lib/lhs/concerns/record/chainable.rb +93 -31
- data/lib/lhs/concerns/record/first.rb +4 -4
- data/lib/lhs/concerns/record/request.rb +16 -4
- data/lib/lhs/record.rb +0 -1
- data/lib/lhs/version.rb +1 -1
- data/spec/complex/merge_spec.rb +180 -0
- data/spec/record/includes_spec.rb +20 -4
- metadata +5 -3
- data/lib/lhs/concerns/record/includes.rb +0 -47
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 49f6aad4dc7d9f73ffaabcc3d433b4ea1e22aa9b
|
4
|
+
data.tar.gz: 9b913652093f6587c121d8e8e2da7ddbf8633ae5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6a97f63461df816e36ac3ca2f837db9b330702683a0a320747f39258b3aa6b73ed6c3d37d7f5c2e014a9db9007ce774c58d1f52d0a0bf4d206e3880f41863ae5
|
7
|
+
data.tar.gz: 71c16105809625cd8c2b598f1d8e5934cb7d0152bb067ed904ca41db1604838d5997f36dea4dbbc225d32d578743447067e189f5673e0210ec95254d8328008a
|
data/.rubocop.yml
CHANGED
data/lib/lhs/complex.rb
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
# Complex is the main data structure for includes:
|
2
|
+
# Can be for example :place, [:place, :customer],
|
3
|
+
# [{ places: [:customer] }, { places: { customer: :contract }}]
|
4
|
+
# and so on
|
5
|
+
class LHS::Complex
|
6
|
+
|
7
|
+
# Merge an array of complex that is created
|
8
|
+
# when chaining includes/references and
|
9
|
+
# reducing values is required for further handling
|
10
|
+
def self.merge(data)
|
11
|
+
result = []
|
12
|
+
data.flatten.uniq.each do |datum|
|
13
|
+
result = merge_first_level!(result, datum)
|
14
|
+
end
|
15
|
+
reduce!(result)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.reduce!(array)
|
19
|
+
array.flatten!
|
20
|
+
array.uniq!
|
21
|
+
return array.first if array.length == 1
|
22
|
+
reduce_symbols!(array)
|
23
|
+
return nil if array.blank?
|
24
|
+
array
|
25
|
+
end
|
26
|
+
private_class_method :reduce!
|
27
|
+
|
28
|
+
def self.reduce_symbols!(array)
|
29
|
+
array.each do |element|
|
30
|
+
if element.is_a?(Symbol)
|
31
|
+
array.each do |other_element|
|
32
|
+
array.delete(element) if other_element.is_a?(Hash) && other_element.key?(element)
|
33
|
+
array.delete(element) if other_element.is_a?(Array) && other_element.include?(element)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
private_class_method :reduce_symbols!
|
39
|
+
|
40
|
+
# Merging the addition into the base array (first level)
|
41
|
+
def self.merge_first_level!(base, addition)
|
42
|
+
return [addition] if base.empty?
|
43
|
+
base.each do |element|
|
44
|
+
merge_multi_level!(base, element, addition)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
private_class_method :merge_first_level!
|
48
|
+
|
49
|
+
# Merge nested complex (addition) into
|
50
|
+
# an hash or an array (element) of the parent
|
51
|
+
def self.merge_multi_level!(parent, element, addition, key = nil)
|
52
|
+
return if element == addition
|
53
|
+
if addition.is_a?(Symbol) && element.is_a?(Hash)
|
54
|
+
merge_symbol_into_hash!(parent, element, addition, key)
|
55
|
+
elsif addition.is_a?(Symbol) && element.is_a?(Array)
|
56
|
+
merge_symbol_into_array!(parent, element, addition, key)
|
57
|
+
elsif addition.is_a?(Symbol) && element.is_a?(Symbol)
|
58
|
+
add_symbol_to_parent!(parent, element, addition, key)
|
59
|
+
elsif addition.is_a?(Hash) && element.is_a?(Symbol)
|
60
|
+
merge_hash_into_symbol!(parent, element, addition, key)
|
61
|
+
elsif addition.is_a?(Hash) && element.is_a?(Hash)
|
62
|
+
merge_hash_into_hash!(parent, element, addition, key)
|
63
|
+
elsif addition.is_a?(Hash) && element.is_a?(Array)
|
64
|
+
merge_hash_into_array!(element, addition)
|
65
|
+
elsif addition.is_a?(Array) && element.is_a?(Symbol)
|
66
|
+
merge_array_into_symbol!(parent, element, addition, key)
|
67
|
+
elsif addition.is_a?(Array) && element.is_a?(Hash)
|
68
|
+
merge_array_into_hash!(parent, element, addition, key)
|
69
|
+
elsif addition.is_a?(Array) && element.is_a?(Array)
|
70
|
+
merge_array_into_array!(parent, element, addition, key)
|
71
|
+
else
|
72
|
+
raise "Can't merge that complex: #{addition} -> #{parent} (#{element})#{key ? " for #{key}" : ''}"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
private_class_method :merge_multi_level!
|
76
|
+
|
77
|
+
def self.merge_symbol_into_hash!(parent, element, addition, key = nil)
|
78
|
+
return if element.key?(addition)
|
79
|
+
if parent.is_a?(Array)
|
80
|
+
parent.push(addition)
|
81
|
+
reduce!(parent)
|
82
|
+
elsif parent.is_a?(Hash)
|
83
|
+
parent[key] = reduce!([element, addition])
|
84
|
+
else
|
85
|
+
raise "Can't merge that complex: #{addition} -> #{parent} (#{element})#{key ? " for #{key}" : ''}"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
private_class_method :merge_symbol_into_hash!
|
89
|
+
|
90
|
+
def self.merge_symbol_into_array!(_parent, element, addition, _key = nil)
|
91
|
+
return if element.include?(addition)
|
92
|
+
element.push(addition)
|
93
|
+
reduce!(element)
|
94
|
+
end
|
95
|
+
private_class_method :merge_symbol_into_array!
|
96
|
+
|
97
|
+
def self.merge_hash_into_symbol!(parent, element, addition, key = nil)
|
98
|
+
parent.delete(element) if addition.key?(element)
|
99
|
+
if parent.is_a?(Array)
|
100
|
+
merge_hash_into_array!(parent, addition)
|
101
|
+
elsif parent.is_a?(Hash)
|
102
|
+
if addition.key?(element)
|
103
|
+
parent[key] = addition
|
104
|
+
else
|
105
|
+
parent[key] = reduce!([element, addition])
|
106
|
+
end
|
107
|
+
else
|
108
|
+
raise "Can't merge that complex: #{addition} -> #{parent} (#{element})"
|
109
|
+
end
|
110
|
+
end
|
111
|
+
private_class_method :merge_hash_into_symbol!
|
112
|
+
|
113
|
+
def self.merge_array_into_symbol!(parent, element, addition, key = nil)
|
114
|
+
addition.unshift(element)
|
115
|
+
reduce!(addition)
|
116
|
+
parent[key] = addition
|
117
|
+
end
|
118
|
+
private_class_method :merge_array_into_symbol!
|
119
|
+
|
120
|
+
def self.merge_hash_into_hash!(parent, element, addition, _key = nil)
|
121
|
+
addition.keys.each do |key|
|
122
|
+
if element[key]
|
123
|
+
parent.delete(addition)
|
124
|
+
merge_multi_level!(element, element[key], addition[key], key)
|
125
|
+
else
|
126
|
+
parent.delete(addition)
|
127
|
+
element[key] = addition[key]
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
private_class_method :merge_hash_into_hash!
|
132
|
+
|
133
|
+
def self.merge_array_into_hash!(parent, element, addition, key = nil)
|
134
|
+
addition.each do |element_to_add|
|
135
|
+
merge_multi_level!(parent, element, element_to_add, key)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
private_class_method :merge_array_into_hash!
|
139
|
+
|
140
|
+
def self.merge_array_into_array!(_parent, element, addition, _key = nil)
|
141
|
+
addition.each do |element_to_add|
|
142
|
+
merge_multi_level!(element, element, element_to_add)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
private_class_method :merge_array_into_array!
|
146
|
+
|
147
|
+
def self.merge_hash_into_array!(array, addition)
|
148
|
+
array.each do |element|
|
149
|
+
next unless element.is_a?(Hash)
|
150
|
+
element.keys.each do |key|
|
151
|
+
next unless addition.key?(key)
|
152
|
+
return merge_multi_level!(element, element[key], addition[key], key)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
array.push(addition)
|
156
|
+
reduce!(array)
|
157
|
+
end
|
158
|
+
private_class_method :merge_hash_into_array!
|
159
|
+
|
160
|
+
def self.add_symbol_to_parent!(parent, element, addition, key = nil)
|
161
|
+
if parent.is_a?(Array)
|
162
|
+
unless parent.include?(addition)
|
163
|
+
parent.push(addition)
|
164
|
+
reduce!(parent)
|
165
|
+
end
|
166
|
+
elsif parent.is_a?(Hash)
|
167
|
+
add_symbol_to_hash_parent!(parent, element, addition, key)
|
168
|
+
else
|
169
|
+
raise "Can't merge that complex: #{addition} -> #{parent} (#{element})"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
private_class_method :add_symbol_to_parent!
|
173
|
+
|
174
|
+
def self.add_symbol_to_hash_parent!(parent, element, addition, key)
|
175
|
+
return if parent[key] == addition
|
176
|
+
return if parent[key].is_a?(Array) && parent[key].include?(addition)
|
177
|
+
parent[key] = reduce!([element, addition])
|
178
|
+
end
|
179
|
+
private_class_method :add_symbol_to_hash_parent!
|
180
|
+
end
|
@@ -34,20 +34,27 @@ class LHS::Record
|
|
34
34
|
def handle(error_class, handler)
|
35
35
|
Chain.new(self, ErrorHandling.new(error_class => handler))
|
36
36
|
end
|
37
|
+
|
38
|
+
def includes(*args)
|
39
|
+
Chain.new(self, Include.new(Chain.unfold(args)))
|
40
|
+
end
|
41
|
+
|
42
|
+
def references(*args)
|
43
|
+
Chain.new(self, Reference.new(Chain.unfold(args)))
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
# Link: A part of a chain
|
40
48
|
class Link
|
41
|
-
def initialize(hash = nil)
|
42
|
-
@hash = hash
|
43
|
-
end
|
44
49
|
|
45
|
-
|
46
|
-
|
50
|
+
attr_reader :data
|
51
|
+
|
52
|
+
def initialize(data = nil)
|
53
|
+
@data = data
|
47
54
|
end
|
48
55
|
|
49
|
-
def
|
50
|
-
@
|
56
|
+
def [](parameter)
|
57
|
+
@data[parameter]
|
51
58
|
end
|
52
59
|
end
|
53
60
|
|
@@ -63,16 +70,25 @@ class LHS::Record
|
|
63
70
|
class Pagination < Link
|
64
71
|
end
|
65
72
|
|
73
|
+
# Include: Part of the chain that will be used to include linked resources
|
74
|
+
class Include < Link
|
75
|
+
end
|
76
|
+
|
77
|
+
# Reference: Part of the chain that will be used to pass options to requests
|
78
|
+
# made to include linked resources
|
79
|
+
class Reference < Link
|
80
|
+
end
|
81
|
+
|
66
82
|
# ErrorHandling: Catch and resolve errors when resolving the chain
|
67
83
|
class ErrorHandling < Link
|
68
84
|
delegate :call, to: :handler
|
69
85
|
|
70
86
|
def handler
|
71
|
-
@
|
87
|
+
@data.values.first
|
72
88
|
end
|
73
89
|
|
74
90
|
def class
|
75
|
-
@
|
91
|
+
@data.keys.first
|
76
92
|
end
|
77
93
|
end
|
78
94
|
|
@@ -91,6 +107,10 @@ class LHS::Record
|
|
91
107
|
|
92
108
|
attr_accessor :_links
|
93
109
|
|
110
|
+
def self.unfold(args)
|
111
|
+
args.size == 1 ? args[0] : args
|
112
|
+
end
|
113
|
+
|
94
114
|
def initialize(record_class, link, record = nil)
|
95
115
|
@record_class = record_class
|
96
116
|
@record = record
|
@@ -98,46 +118,46 @@ class LHS::Record
|
|
98
118
|
end
|
99
119
|
|
100
120
|
def create(data = {})
|
101
|
-
@record_class.create(data,
|
121
|
+
@record_class.create(data, resolved_options)
|
102
122
|
end
|
103
123
|
|
104
124
|
def create!(data = {})
|
105
|
-
@record_class.create!(data,
|
125
|
+
@record_class.create!(data, resolved_options)
|
106
126
|
end
|
107
127
|
|
108
128
|
def save!(options = nil)
|
109
129
|
options ||= {}
|
110
|
-
@record.save!(
|
130
|
+
@record.save!(resolved_options.merge(options))
|
111
131
|
end
|
112
132
|
|
113
133
|
def save(options = nil)
|
114
134
|
options ||= {}
|
115
|
-
@record.save(
|
135
|
+
@record.save(resolved_options.merge(options))
|
116
136
|
end
|
117
137
|
|
118
138
|
def destroy(options = nil)
|
119
139
|
options ||= {}
|
120
140
|
options = options.respond_to?(:to_h) ? options : { id: options }
|
121
141
|
if @record
|
122
|
-
@record.destroy(
|
142
|
+
@record.destroy(resolved_options.merge(options))
|
123
143
|
else
|
124
|
-
@record_class.destroy(options,
|
144
|
+
@record_class.destroy(options, resolved_options)
|
125
145
|
end
|
126
146
|
end
|
127
147
|
|
128
148
|
def update(data = {}, options = nil)
|
129
149
|
options ||= {}
|
130
|
-
@record.update(data,
|
150
|
+
@record.update(data, resolved_options.merge(options))
|
131
151
|
end
|
132
152
|
|
133
153
|
def update!(data = {}, options = nil)
|
134
154
|
options ||= {}
|
135
|
-
@record.update!(data,
|
155
|
+
@record.update!(data, resolved_options.merge(options))
|
136
156
|
end
|
137
157
|
|
138
158
|
def valid?(options = nil)
|
139
159
|
options ||= {}
|
140
|
-
@record.valid?(
|
160
|
+
@record.valid?(resolved_options.merge(options))
|
141
161
|
end
|
142
162
|
alias validate valid?
|
143
163
|
|
@@ -166,18 +186,28 @@ class LHS::Record
|
|
166
186
|
push ErrorHandling.new(error_class => handler)
|
167
187
|
end
|
168
188
|
|
189
|
+
def includes(*args)
|
190
|
+
push Include.new(Chain.unfold(args))
|
191
|
+
end
|
192
|
+
|
193
|
+
def references(*args)
|
194
|
+
push Reference.new(Chain.unfold(args))
|
195
|
+
end
|
196
|
+
|
169
197
|
def find(*args)
|
170
|
-
|
171
|
-
options = options.merge(error_handler: chain_error_handler) if chain_error_handler.any?
|
172
|
-
@record_class.find(*args.push(options))
|
198
|
+
@record_class.find(*args.push(resolved_options))
|
173
199
|
end
|
174
200
|
|
175
201
|
def find_by(params = {})
|
176
|
-
@record_class.find_by(params,
|
202
|
+
@record_class.find_by(params, resolved_options)
|
177
203
|
end
|
178
204
|
|
179
205
|
def find_by!(params = {})
|
180
|
-
@record_class.find_by!(params,
|
206
|
+
@record_class.find_by!(params, resolved_options)
|
207
|
+
end
|
208
|
+
|
209
|
+
def first!
|
210
|
+
@record_class.first!(resolved_options)
|
181
211
|
end
|
182
212
|
|
183
213
|
# Returns a hash of where conditions
|
@@ -195,6 +225,16 @@ class LHS::Record
|
|
195
225
|
chain_pagination
|
196
226
|
end
|
197
227
|
|
228
|
+
# Returns a hash of include conditions
|
229
|
+
def includes_values
|
230
|
+
chain_includes
|
231
|
+
end
|
232
|
+
|
233
|
+
# Returns a hash of reference options
|
234
|
+
def references_values
|
235
|
+
chain_references
|
236
|
+
end
|
237
|
+
|
198
238
|
protected
|
199
239
|
|
200
240
|
def method_missing(name, *args, &block)
|
@@ -209,14 +249,20 @@ class LHS::Record
|
|
209
249
|
end
|
210
250
|
|
211
251
|
def resolve
|
212
|
-
options = chain_options
|
213
|
-
options = options.merge(params: chain_parameters.merge(chain_pagination))
|
214
|
-
options = options.merge(error_handler: chain_error_handler) if chain_error_handler.any?
|
215
252
|
@resolved ||= @record_class.new(
|
216
|
-
@record_class.request(
|
253
|
+
@record_class.request(resolved_options)
|
217
254
|
)
|
218
255
|
end
|
219
256
|
|
257
|
+
def resolved_options
|
258
|
+
options = chain_options
|
259
|
+
options = options.merge(params: chain_parameters.merge(chain_pagination))
|
260
|
+
options = options.merge(error_handler: chain_error_handler) if chain_error_handler.present?
|
261
|
+
options = options.merge(including: chain_includes) if chain_includes.present?
|
262
|
+
options = options.merge(referencing: chain_references) if chain_references.present?
|
263
|
+
options
|
264
|
+
end
|
265
|
+
|
220
266
|
private
|
221
267
|
|
222
268
|
def push(link)
|
@@ -226,11 +272,11 @@ class LHS::Record
|
|
226
272
|
end
|
227
273
|
|
228
274
|
def chain_parameters
|
229
|
-
merge_links
|
275
|
+
merge_links(_links.select { |link| link.is_a? Parameter })
|
230
276
|
end
|
231
277
|
|
232
278
|
def chain_options
|
233
|
-
merge_links
|
279
|
+
merge_links(_links.select { |link| link.is_a? Option })
|
234
280
|
end
|
235
281
|
|
236
282
|
def chain_error_handler
|
@@ -241,6 +287,22 @@ class LHS::Record
|
|
241
287
|
resolve_pagination _links.select { |link| link.is_a? Pagination }
|
242
288
|
end
|
243
289
|
|
290
|
+
def chain_includes
|
291
|
+
LHS::Complex.merge(
|
292
|
+
_links
|
293
|
+
.select { |link| link.is_a?(Include) && link.data.present? }
|
294
|
+
.map { |link| link.data }
|
295
|
+
)
|
296
|
+
end
|
297
|
+
|
298
|
+
def chain_references
|
299
|
+
LHS::Complex.merge(
|
300
|
+
_links
|
301
|
+
.select { |link| link.is_a?(Reference) && link.data.present? }
|
302
|
+
.map { |link| link.data }
|
303
|
+
)
|
304
|
+
end
|
305
|
+
|
244
306
|
def resolve_pagination(links)
|
245
307
|
return {} if links.empty?
|
246
308
|
page = 1
|
@@ -259,8 +321,8 @@ class LHS::Record
|
|
259
321
|
def merge_links(links)
|
260
322
|
hash = {}
|
261
323
|
links.each do |link|
|
262
|
-
next if link.
|
263
|
-
hash.deep_merge!(link.
|
324
|
+
next if link.data.blank?
|
325
|
+
hash.deep_merge!(link.data)
|
264
326
|
end
|
265
327
|
hash
|
266
328
|
end
|
@@ -6,12 +6,12 @@ class LHS::Record
|
|
6
6
|
extend ActiveSupport::Concern
|
7
7
|
|
8
8
|
module ClassMethods
|
9
|
-
def first
|
10
|
-
find_by
|
9
|
+
def first(options = nil)
|
10
|
+
find_by({}, options)
|
11
11
|
end
|
12
12
|
|
13
|
-
def first!
|
14
|
-
find_by!
|
13
|
+
def first!(options = nil)
|
14
|
+
find_by!({}, options)
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
@@ -93,10 +93,13 @@ class LHS::Record
|
|
93
93
|
|
94
94
|
def handle_includes(includes, data, references = {})
|
95
95
|
references ||= {}
|
96
|
+
references = [references] if includes.is_a?(Array) && !references.is_a?(Array)
|
96
97
|
if includes.is_a? Hash
|
97
98
|
includes.each { |included, sub_includes| handle_include(included, data, sub_includes, references[included]) }
|
98
99
|
elsif includes.is_a? Array
|
99
|
-
includes.
|
100
|
+
includes.each_with_index do |included, index|
|
101
|
+
handle_includes(included, data, references[index])
|
102
|
+
end
|
100
103
|
else
|
101
104
|
handle_include(includes, data, nil, references[includes])
|
102
105
|
end
|
@@ -123,7 +126,7 @@ class LHS::Record
|
|
123
126
|
record = record_for_options(options) || self
|
124
127
|
options = convert_options_to_endpoints(options) if record_for_options(options)
|
125
128
|
expanded_data = begin
|
126
|
-
record.
|
129
|
+
record.request(options)
|
127
130
|
rescue LHC::NotFound
|
128
131
|
LHS::Data.new({}, data, record)
|
129
132
|
end
|
@@ -163,7 +166,12 @@ class LHS::Record
|
|
163
166
|
record = record_for_options(options) || self
|
164
167
|
options = convert_options_to_endpoints(options) if record_for_options(options)
|
165
168
|
begin
|
166
|
-
|
169
|
+
if options.is_a?(Array)
|
170
|
+
options.each { |options| options.merge!(including: sub_includes) if sub_includes.present? }
|
171
|
+
elsif sub_includes.present?
|
172
|
+
options.merge!(including: sub_includes)
|
173
|
+
end
|
174
|
+
record.request(options)
|
167
175
|
rescue LHC::NotFound
|
168
176
|
LHS::Data.new({}, data, record)
|
169
177
|
end
|
@@ -185,9 +193,11 @@ class LHS::Record
|
|
185
193
|
data = LHC.request(options.compact).map do |response|
|
186
194
|
LHS::Data.new(response.body, nil, self, response.request)
|
187
195
|
end
|
196
|
+
including = LHS::Complex.merge options.compact.map { |options| options.delete(:including) }.compact
|
197
|
+
referencing = LHS::Complex.merge options.compact.map { |options| options.delete(:referencing) }.compact
|
188
198
|
data = restore_with_nils(data, locate_nils(options)) # nil objects in data provide location information for mapping
|
189
199
|
data = LHS::Data.new(data, nil, self)
|
190
|
-
handle_includes(including, data, referencing) if including && !data.empty?
|
200
|
+
handle_includes(including, data, referencing) if including.present? && !data.empty?
|
191
201
|
data
|
192
202
|
end
|
193
203
|
|
@@ -260,6 +270,8 @@ class LHS::Record
|
|
260
270
|
|
261
271
|
def single_request(options)
|
262
272
|
options ||= {}
|
273
|
+
including = options.delete(:including)
|
274
|
+
referencing = options.delete(:referencing)
|
263
275
|
options = options.dup
|
264
276
|
endpoint = find_endpoint(options[:params])
|
265
277
|
response = LHC.request(process_options(options, endpoint))
|
data/lib/lhs/record.rb
CHANGED
data/lib/lhs/version.rb
CHANGED
@@ -0,0 +1,180 @@
|
|
1
|
+
require 'rails_helper'
|
2
|
+
|
3
|
+
describe LHS::Complex do
|
4
|
+
context 'first level' do
|
5
|
+
context 'merges symbols into/with X' do
|
6
|
+
it 'merges symbols into hash' do
|
7
|
+
expect(LHS::Complex.merge([
|
8
|
+
{ entries: :contract },
|
9
|
+
:entries
|
10
|
+
])).to eq(entries: :contract)
|
11
|
+
end
|
12
|
+
|
13
|
+
it 'merges symbols into array' do
|
14
|
+
expect(LHS::Complex.merge([
|
15
|
+
[:contracts],
|
16
|
+
:entries
|
17
|
+
])).to eq([:contracts, :entries])
|
18
|
+
expect(LHS::Complex.merge([
|
19
|
+
[:entries],
|
20
|
+
:entries
|
21
|
+
])).to eq(:entries)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'merges symbols with symbols' do
|
25
|
+
expect(LHS::Complex.merge([
|
26
|
+
:contracts,
|
27
|
+
:entries
|
28
|
+
])).to eq([:contracts, :entries])
|
29
|
+
expect(LHS::Complex.merge([
|
30
|
+
:entries,
|
31
|
+
:entries
|
32
|
+
])).to eq(:entries)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'merges arrays into/with X' do
|
37
|
+
it 'merges arrays into an hash' do
|
38
|
+
expect(LHS::Complex.merge([
|
39
|
+
{ entries: :contract },
|
40
|
+
[:entries]
|
41
|
+
])).to eq(entries: :contract)
|
42
|
+
expect(LHS::Complex.merge([
|
43
|
+
{ entries: :contract },
|
44
|
+
[:products]
|
45
|
+
])).to eq([{ entries: :contract }, :products])
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'merges arrays into an arrays' do
|
49
|
+
expect(LHS::Complex.merge([
|
50
|
+
[:entries],
|
51
|
+
[:entries]
|
52
|
+
])).to eq(:entries)
|
53
|
+
expect(LHS::Complex.merge([
|
54
|
+
[:entries],
|
55
|
+
[:products]
|
56
|
+
])).to eq([:entries, :products])
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'merges arrays into an symbols' do
|
60
|
+
expect(LHS::Complex.merge([
|
61
|
+
:entries,
|
62
|
+
[:entries]
|
63
|
+
])).to eq(:entries)
|
64
|
+
expect(LHS::Complex.merge([
|
65
|
+
:entries,
|
66
|
+
[:products]
|
67
|
+
])).to eq([:entries, :products])
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'merges hashes into/with X' do
|
72
|
+
it 'merges hash into an hash' do
|
73
|
+
expect(LHS::Complex.merge([
|
74
|
+
{ entries: :contract },
|
75
|
+
{ entries: :products }
|
76
|
+
])).to eq(entries: [:contract, :products])
|
77
|
+
expect(LHS::Complex.merge([
|
78
|
+
{ entries: :contract },
|
79
|
+
{ entries: :contract }
|
80
|
+
])).to eq(entries: :contract)
|
81
|
+
end
|
82
|
+
|
83
|
+
it 'merges hash into an array' do
|
84
|
+
expect(LHS::Complex.merge([
|
85
|
+
[:entries],
|
86
|
+
{ entries: :products }
|
87
|
+
])).to eq(entries: :products)
|
88
|
+
expect(LHS::Complex.merge([
|
89
|
+
[{ entries: :contract }],
|
90
|
+
{ entries: :contract }
|
91
|
+
])).to eq(entries: :contract)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'merges hash into a symbol' do
|
95
|
+
expect(LHS::Complex.merge([
|
96
|
+
:entries,
|
97
|
+
{ entries: :products }
|
98
|
+
])).to eq(entries: :products)
|
99
|
+
expect(LHS::Complex.merge([
|
100
|
+
:products,
|
101
|
+
{ entries: :contract }
|
102
|
+
])).to eq([:products, { entries: :contract }])
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
context 'merges array into/with X' do
|
107
|
+
it 'merges array into hash' do
|
108
|
+
expect(LHS::Complex.merge([
|
109
|
+
{ entries: :contract },
|
110
|
+
[:entries, :products]
|
111
|
+
])).to eq([{ entries: :contract }, :products])
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'merges array into array' do
|
115
|
+
expect(LHS::Complex.merge([
|
116
|
+
[:contracts],
|
117
|
+
[:entries, :products, :contracts]
|
118
|
+
])).to eq([:contracts, :entries, :products])
|
119
|
+
end
|
120
|
+
|
121
|
+
it 'merges array with symbols' do
|
122
|
+
expect(LHS::Complex.merge([
|
123
|
+
:contracts,
|
124
|
+
[:entries, :products]
|
125
|
+
])).to eq([:contracts, :entries, :products])
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
context 'multi-level' do
|
131
|
+
it 'merges a complex multi-level example' do
|
132
|
+
expect(LHS::Complex.merge([
|
133
|
+
:contracts,
|
134
|
+
[:entries, products: { content_ads: :address }],
|
135
|
+
products: { content_ads: { place: :location } }
|
136
|
+
])).to eq([
|
137
|
+
:contracts,
|
138
|
+
:entries,
|
139
|
+
products: { content_ads: [:address, { place: :location }] }
|
140
|
+
])
|
141
|
+
end
|
142
|
+
|
143
|
+
it 'merges another complex multi-level example' do
|
144
|
+
expect(LHS::Complex.merge([
|
145
|
+
[entries: :content_ads, products: :price],
|
146
|
+
[:entries, products: { content_ads: :address }],
|
147
|
+
[entries: { content_ads: :owner }, products: [{ price: :region }, :image, { content_ads: :owner }]]
|
148
|
+
])).to eq(
|
149
|
+
entries: { content_ads: :owner },
|
150
|
+
products: [{ content_ads: [:address, :owner] }, { price: :region }, :image]
|
151
|
+
)
|
152
|
+
end
|
153
|
+
|
154
|
+
it 'merges another complex multi-level example' do
|
155
|
+
expect(LHS::Complex.merge([
|
156
|
+
{ entries: :products },
|
157
|
+
{ entries: [:customer, :contracts] }
|
158
|
+
])).to eq(
|
159
|
+
entries: [:products, :customer, :contracts]
|
160
|
+
)
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'merges another complex multi-level example' do
|
164
|
+
expect(LHS::Complex.merge([
|
165
|
+
{ entries: { customer: :contracts } },
|
166
|
+
{ entries: [:customer, :content_ads] }
|
167
|
+
])).to eq(
|
168
|
+
entries: [{ customer: :contracts }, :content_ads]
|
169
|
+
)
|
170
|
+
end
|
171
|
+
|
172
|
+
it 'reduces properly' do
|
173
|
+
expect(LHS::Complex.merge([
|
174
|
+
[:entries, :place, :content_ads], [{ place: :content_ads }], { content_ads: :place }
|
175
|
+
])).to eq(
|
176
|
+
[:entries, { place: :content_ads, content_ads: :place }]
|
177
|
+
)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
@@ -366,11 +366,17 @@ describe LHS::Record do
|
|
366
366
|
before(:each) do
|
367
367
|
class Customer < LHS::Record
|
368
368
|
endpoint ':datastore/customers/:id'
|
369
|
+
endpoint ':datastore/customers'
|
369
370
|
end
|
370
371
|
|
371
372
|
class Place < LHS::Record
|
372
373
|
endpoint ':datastore/places'
|
373
374
|
end
|
375
|
+
|
376
|
+
stub_request(:get, "#{datastore}/places?forwarded_params=123")
|
377
|
+
.to_return(body: {
|
378
|
+
'items' => [{ id: 1 }]
|
379
|
+
}.to_json)
|
374
380
|
end
|
375
381
|
|
376
382
|
it 'forwards includes options to requests made for those includes' do
|
@@ -380,15 +386,25 @@ describe LHS::Record do
|
|
380
386
|
'href' => "#{datastore}/places"
|
381
387
|
}
|
382
388
|
}.to_json)
|
383
|
-
stub_request(:get, "#{datastore}/places?forwarded_params=123")
|
384
|
-
.to_return(body: {
|
385
|
-
'items' => [{ id: 1 }]
|
386
|
-
}.to_json)
|
387
389
|
customer = Customer
|
388
390
|
.includes(:places)
|
389
391
|
.references(places: { params: { forwarded_params: 123 } })
|
390
392
|
.find(1)
|
391
393
|
expect(customer.places.first.id).to eq 1
|
392
394
|
end
|
395
|
+
|
396
|
+
it 'is chain-able' do
|
397
|
+
stub_request(:get, "#{datastore}/customers?name=Steve")
|
398
|
+
.to_return(body: [
|
399
|
+
'places' => {
|
400
|
+
'href' => "#{datastore}/places"
|
401
|
+
}
|
402
|
+
].to_json)
|
403
|
+
customers = Customer
|
404
|
+
.where(name: 'Steve')
|
405
|
+
.references(places: { params: { forwarded_params: 123 } })
|
406
|
+
.includes(:places)
|
407
|
+
expect(customers.first.places.first.id).to eq 1
|
408
|
+
end
|
393
409
|
end
|
394
410
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhs
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 6.
|
4
|
+
version: 6.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- https://github.com/local-ch/lhs/graphs/contributors
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-11-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: lhc
|
@@ -178,6 +178,7 @@ files:
|
|
178
178
|
- lhs.gemspec
|
179
179
|
- lib/lhs.rb
|
180
180
|
- lib/lhs/collection.rb
|
181
|
+
- lib/lhs/complex.rb
|
181
182
|
- lib/lhs/concerns/collection/internal_collection.rb
|
182
183
|
- lib/lhs/concerns/data/equality.rb
|
183
184
|
- lib/lhs/concerns/data/json.rb
|
@@ -198,7 +199,6 @@ files:
|
|
198
199
|
- lib/lhs/concerns/record/find.rb
|
199
200
|
- lib/lhs/concerns/record/find_by.rb
|
200
201
|
- lib/lhs/concerns/record/first.rb
|
201
|
-
- lib/lhs/concerns/record/includes.rb
|
202
202
|
- lib/lhs/concerns/record/mapping.rb
|
203
203
|
- lib/lhs/concerns/record/model.rb
|
204
204
|
- lib/lhs/concerns/record/pagination.rb
|
@@ -221,6 +221,7 @@ files:
|
|
221
221
|
- spec/collection/meta_data_spec.rb
|
222
222
|
- spec/collection/respond_to_spec.rb
|
223
223
|
- spec/collection/without_object_items_spec.rb
|
224
|
+
- spec/complex/merge_spec.rb
|
224
225
|
- spec/data/collection_spec.rb
|
225
226
|
- spec/data/equality_spec.rb
|
226
227
|
- spec/data/inspect_spec.rb
|
@@ -371,6 +372,7 @@ test_files:
|
|
371
372
|
- spec/collection/meta_data_spec.rb
|
372
373
|
- spec/collection/respond_to_spec.rb
|
373
374
|
- spec/collection/without_object_items_spec.rb
|
375
|
+
- spec/complex/merge_spec.rb
|
374
376
|
- spec/data/collection_spec.rb
|
375
377
|
- spec/data/equality_spec.rb
|
376
378
|
- spec/data/inspect_spec.rb
|
@@ -1,47 +0,0 @@
|
|
1
|
-
require 'active_support'
|
2
|
-
|
3
|
-
class LHS::Record
|
4
|
-
|
5
|
-
module Includes
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
cattr_accessor :including, :referencing
|
10
|
-
end
|
11
|
-
|
12
|
-
module ClassMethods
|
13
|
-
def includes(*args)
|
14
|
-
class_clone_factory(args).tap do |class_clone|
|
15
|
-
class_clone.including = unfold_args(args)
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def references(*args)
|
20
|
-
class_clone_factory(args).tap do |class_clone|
|
21
|
-
class_clone.referencing = unfold_args(args)
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def without_including
|
26
|
-
class_clone_factory(rand.to_s.gsub(/\D/, '')).tap do |class_clone|
|
27
|
-
class_clone.including = nil
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def unfold_args(args)
|
34
|
-
args.size == 1 ? args[0] : args
|
35
|
-
end
|
36
|
-
|
37
|
-
def class_clone_factory(args)
|
38
|
-
name = "#{self}#{args.object_id}"
|
39
|
-
constant = Object.const_set(name.demodulize, self.dup) # rubocop:disable Style/RedundantSelf
|
40
|
-
class_clone = constant
|
41
|
-
class_clone.endpoints = endpoints
|
42
|
-
class_clone.mapping = mapping
|
43
|
-
class_clone
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
47
|
-
end
|