hoodoo 1.11.0 → 1.12.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- Y2FmMmNkOGIxNmI3Yjc3Njk2ZGU4MmJlMzVkZDkyYWQ2ZGI2NGNiNQ==
5
- data.tar.gz: !binary |-
6
- YWNkMjFhNmMwODQ2OGYxYjZmNDI1ZGIxZGJmNzg3YjQyY2I5ZDMxYw==
2
+ SHA1:
3
+ metadata.gz: 30fd454d84a35502e8c324645a1c8c981521aa7e
4
+ data.tar.gz: fae766337e9034cf46e9c030c64d5d6ea0609827
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- ZWJjN2JjMjA3Zjc1YTRmMzYwN2ZkODYyMzE4M2I2N2VkOTg4M2I1MDBjMDhj
10
- ZGE3N2RhNWZlOGMwMDQ2MWVmNzNhMzQ3MWEwZTRiZDhjMjBkMDNjNDdhZjdh
11
- ZjYxOGUwYTk1NDFlYTJmY2VhNGYxYWI5ODk5YzdmNDNkOThjYTE=
12
- data.tar.gz: !binary |-
13
- MmQzNzQxZWI0OTQ2YjI2Nzg1ODAxMzA0ODVlNmM0ODRmMTE2YTY0YmEwYzA2
14
- YTdjMzZkMTY4NWRlNjlmMzdhNTc1NDdiYWM4OTQ1YjNkNzQzNjYzZTlmNDFl
15
- Nzc3Mzk5ZmFhMDIxOTk0NmY2MzIyMTc2MGQ2YjFlYWQ5MDQxMGQ=
6
+ metadata.gz: be4607dfff0f5f798b48eb83abbd3985562df696570137f1c7c9fa7fbaad5df227659c274c758c323fb12901365d665c9a1642d743c17103708cb1509b23db3f
7
+ data.tar.gz: 0c35e38a6740d1e689c361fcf2f0ab07bac09540eb46a9bb1d7ac2f3ab40319c3711b26741fe85c0836e5b1d277208c9c06152f3aa5369745c936714de7a4bf7
@@ -20,8 +20,8 @@ module Hoodoo
20
20
  #
21
21
  # It is _STRONGLY_ _RECOMMENDED_ that you use the likes of:
22
22
  #
23
- # * Hoodoo::ActiveRecord::Finder::ClassMethods::acquire_in
24
- # * Hoodoo::ActiveRecord::Finder::ClassMethods::list_in
23
+ # * Hoodoo::ActiveRecord::Finder::ClassMethods#acquire_in
24
+ # * Hoodoo::ActiveRecord::Finder::ClassMethods#list_in
25
25
  #
26
26
  # ...to retrieve model data related to resource instances and participate
27
27
  # "for free" in whatever plug-in ActiveRecord modules are mixed into the
@@ -428,20 +428,14 @@ module Hoodoo
428
428
  finder = all.offset( list_parameters.offset ).limit( list_parameters.limit )
429
429
  finder = finder.order( list_parameters.sort_data )
430
430
 
431
- # DRY up the 'each' loops below. Use a Proc not a method because any
432
- # methods we define will end up being defined on the including Model,
433
- # increasing the chance of a name collision.
434
- #
435
- dry_proc = Proc.new do | data, attr, proc |
436
- value = data[ attr ]
437
- proc.call( attr, value ) unless value.nil?
438
- end
439
-
440
431
  search_map = self.nz_co_loyalty_hoodoo_search_with
441
432
 
442
433
  unless search_map.nil?
443
- search_map.each do | attr, proc |
444
- args = dry_proc.call( list_parameters.search_data, attr, proc )
434
+ search_map.each do | attr, finder_args_proc |
435
+ value = list_parameters.search_data[ attr ]
436
+ next if value.nil?
437
+
438
+ args = finder_args_proc.call( attr, value )
445
439
  finder = finder.where( *args ) unless args.nil?
446
440
  end
447
441
  end
@@ -449,8 +443,11 @@ module Hoodoo
449
443
  filter_map = self.nz_co_loyalty_hoodoo_filter_with
450
444
 
451
445
  unless filter_map.nil?
452
- filter_map.each do | attr, proc |
453
- args = dry_proc.call( list_parameters.filter_data, attr, proc )
446
+ filter_map.each do | attr, finder_args_proc |
447
+ value = list_parameters.filter_data[ attr ]
448
+ next if value.nil?
449
+
450
+ args = finder_args_proc.call( attr, value )
454
451
  finder = finder.where.not( *args ) unless args.nil?
455
452
  end
456
453
  end
@@ -714,7 +711,8 @@ module Hoodoo
714
711
  # which assist with filling in non-nil values for this Hash.
715
712
  #
716
713
  def search_with( hash )
717
- self.nz_co_loyalty_hoodoo_search_with = Hoodoo::ActiveRecord::Support.process_to_map( hash )
714
+ self.nz_co_loyalty_hoodoo_search_with ||= Hoodoo::ActiveRecord::Support.framework_search_and_filter_data()
715
+ self.nz_co_loyalty_hoodoo_search_with.merge!( Hoodoo::ActiveRecord::Support.process_to_map( hash ) )
718
716
  end
719
717
 
720
718
  # As #search_with, but used in +where.not+ queries.
@@ -735,7 +733,8 @@ module Hoodoo
735
733
  # +map+:: As #search_with.
736
734
  #
737
735
  def filter_with( hash )
738
- self.nz_co_loyalty_hoodoo_filter_with = Hoodoo::ActiveRecord::Support.process_to_map( hash )
736
+ self.nz_co_loyalty_hoodoo_filter_with ||= Hoodoo::ActiveRecord::Support.framework_search_and_filter_data()
737
+ self.nz_co_loyalty_hoodoo_filter_with.merge!( Hoodoo::ActiveRecord::Support.process_to_map( hash ) )
739
738
  end
740
739
 
741
740
  # Deprecated interface replaced by #acquire. Instead of:
@@ -14,8 +14,9 @@ module Hoodoo
14
14
  module Finder
15
15
 
16
16
  # Help build up Hash maps to pass into Hoodoo::ActiveRecord::Finder
17
- # methods Hoodoo::ActiveRecord::Finder#search_with and
18
- # Hoodoo::ActiveRecord::Finder#filter_with.
17
+ # methods Hoodoo::ActiveRecord::Finder::ClassMethods#search_with and
18
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with. Used also
19
+ # by the default framework search scopes.
19
20
  #
20
21
  # The usage pattern is as follows, using "sh" as a local variable
21
22
  # just for brevity - it isn't required:
@@ -31,7 +32,7 @@ module Hoodoo
31
32
  # end
32
33
  #
33
34
  # The helper methods just provide values to pass into the Hash used
34
- # with the search/fitler Hoodoo::ActiveRecord::Finder methods, so
35
+ # with the search/filter Hoodoo::ActiveRecord::Finder methods, so
35
36
  # they're optional and compatible with calls that write it out "by
36
37
  # hand".
37
38
  #
@@ -48,15 +49,16 @@ module Hoodoo
48
49
  # will be case sensitive only if your database is configured for
49
50
  # case sensitive matching by default.
50
51
  #
51
- # Results in a <tt>foo = bar</tt> query.
52
+ # Results in a <tt>foo = bar AND foo IS NOT NULL</tt> query.
52
53
  #
53
54
  # +model_field_name+:: If the model attribute name differs from the
54
55
  # search key you want to use in the URI, give
55
56
  # the model attribute name here, else omit.
56
57
  #
57
58
  # Returns a value that can be asssigned to a URI query string key in
58
- # the Hash given to Hoodoo::ActiveRecord::Finder#search_with or
59
- # Hoodoo::ActiveRecord::Finder#filter_with.
59
+ # the Hash given to
60
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
61
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
60
62
  #
61
63
  def self.cs_match( model_field_name = nil )
62
64
  Proc.new { | attr, value |
@@ -70,15 +72,17 @@ module Hoodoo
70
72
  # which are split into an array then processed by AREL back to
71
73
  # something SQL-safe.
72
74
  #
73
- # Results in a <tt>foo IN bar,baz,boo</tt> query.
75
+ # Results in a <tt>foo IN (bar,baz,boo) AND foo IS NOT NULL</tt>
76
+ # query.
74
77
  #
75
78
  # +model_field_name+:: If the model attribute name differs from the
76
79
  # search key you want to use in the URI, give
77
80
  # the model attribute name here, else omit.
78
81
  #
79
82
  # Returns a value that can be asssigned to a URI query string key in
80
- # the Hash given to Hoodoo::ActiveRecord::Finder#search_with or
81
- # Hoodoo::ActiveRecord::Finder#filter_with.
83
+ # the Hash given to
84
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
85
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
82
86
  #
83
87
  def self.cs_match_csv( model_field_name = nil )
84
88
  Proc.new { | attr, value |
@@ -92,17 +96,20 @@ module Hoodoo
92
96
  # Case-sensitive match of a series of values given as an Array.
93
97
  # Normally, query string information comes in as a String so the
94
98
  # use cases for this are quite unusual; you probably want to use
95
- # #cs_match_csv most of the time.
99
+ # Hoodoo::ActiveRecord::Finder::SearchHelper::cs_match_csv most of
100
+ # the time.
96
101
  #
97
- # Results in a <tt>foo IN bar,baz,boo</tt> query.
102
+ # Results in a <tt>foo IN (bar,baz,boo) AND foo IS NOT NULL</tt>
103
+ # query.
98
104
  #
99
105
  # +model_field_name+:: If the model attribute name differs from the
100
106
  # search key you want to use in the URI, give
101
107
  # the model attribute name here, else omit.
102
108
  #
103
109
  # Returns a value that can be asssigned to a URI query string key in
104
- # the Hash given to Hoodoo::ActiveRecord::Finder#search_with or
105
- # Hoodoo::ActiveRecord::Finder#filter_with.
110
+ # the Hash given to
111
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
112
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
106
113
  #
107
114
  def self.cs_match_array( model_field_name = nil )
108
115
  Proc.new { | attr, value |
@@ -113,8 +120,11 @@ module Hoodoo
113
120
  }
114
121
  end
115
122
 
116
- # As #cs_match, but adds wildcards at the front and end of the string
117
- # for a case-sensitive-all-wildcard match.
123
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::cs_match, but
124
+ # adds wildcards at the front and end of the string for a
125
+ # case-sensitive-all-wildcard match.
126
+ #
127
+ # Results in a <tt>foo LIKE bar AND foo IS NOT NULL</tt> query.
118
128
  #
119
129
  def self.csaw_match( model_field_name = nil )
120
130
  Proc.new { | attr, value |
@@ -127,19 +137,22 @@ module Hoodoo
127
137
 
128
138
  # Case-insensitive match which should be fairly database independent
129
139
  # but will run relatively slowly as a result. If you are using
130
- # PostgreSQL, consider using the faster #ci_match_postgres method
140
+ # PostgreSQL, consider using the faster
141
+ # Hoodoo::ActiveRecord::Finder::SearchHelper::ci_match_postgres method
131
142
  # instead.
132
143
  #
133
- # Results in a <tt>lower(foo) = bar</tt> query with +bar+ coerced to
134
- # a String and converted to lower case by Ruby first.
144
+ # Results in a <tt>lower(foo) = bar AND foo IS NOT NULL</tt> query
145
+ # with +bar+ coerced to a String and converted to lower case by Ruby
146
+ # first.
135
147
  #
136
148
  # +model_field_name+:: If the model attribute name differs from the
137
149
  # search key you want to use in the URI, give
138
150
  # the model attribute name here, else omit.
139
151
  #
140
152
  # Returns a value that can be asssigned to a URI query string key in
141
- # the Hash given to Hoodoo::ActiveRecord::Finder#search_with or
142
- # Hoodoo::ActiveRecord::Finder#filter_with.
153
+ # the Hash given to
154
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
155
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
143
156
  #
144
157
  def self.ci_match_generic( model_field_name = nil )
145
158
  Proc.new { | attr, value |
@@ -150,8 +163,11 @@ module Hoodoo
150
163
  }
151
164
  end
152
165
 
153
- # As #ci_match_generic, but adds wildcards at the front and end of
154
- # the string for a case-insensitive-all-wildcard match.
166
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::ci_match_generic,
167
+ # but adds wildcards at the front and end of the string for a
168
+ # case-insensitive-all-wildcard match.
169
+ #
170
+ # Results in a <tt>foo LIKE %bar% AND foo IS NOT NULL</tt> query.
155
171
  #
156
172
  def self.ciaw_match_generic( model_field_name = nil )
157
173
  Proc.new { | attr, value |
@@ -164,17 +180,20 @@ module Hoodoo
164
180
 
165
181
  # Case-insensitive match which requires PostgreSQL but should run
166
182
  # quickly. If you need a database agnostic solution, consider using
167
- # the slower #ci_match_generic method instead.
183
+ # the slower
184
+ # Hoodoo::ActiveRecord::Finder::SearchHelper::ci_match_generic method
185
+ # instead.
168
186
  #
169
- # Results in a <tt>foo ILIKE bar</tt> query.
187
+ # Results in a <tt>foo ILIKE bar AND foo IS NOT NULL</tt> query.
170
188
  #
171
189
  # +model_field_name+:: If the model attribute name differs from the
172
190
  # search key you want to use in the URI, give
173
191
  # the model attribute name here, else omit.
174
192
  #
175
193
  # Returns a value that can be asssigned to a URI query string key in
176
- # the Hash given to Hoodoo::ActiveRecord::Finder#search_with or
177
- # Hoodoo::ActiveRecord::Finder#filter_with.
194
+ # the Hash given to
195
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
196
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
178
197
  #
179
198
  def self.ci_match_postgres( model_field_name = nil )
180
199
  Proc.new { | attr, value |
@@ -184,8 +203,11 @@ module Hoodoo
184
203
  }
185
204
  end
186
205
 
187
- # As #ci_match_postgres, but adds wildcards at the front and end of
188
- # the string for a case-insensitive-all-wildcard match.
206
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::ci_match_postgres,
207
+ # but adds wildcards at the front and end of the string for a
208
+ # case-insensitive-all-wildcard match.
209
+ #
210
+ # Results in a <tt>foo ILIKE %bar% AND foo IS NOT NULL</tt> query.
189
211
  #
190
212
  def self.ciaw_match_postgres( model_field_name = nil )
191
213
  Proc.new { | attr, value |
@@ -194,8 +216,75 @@ module Hoodoo
194
216
  [ "#{ column } ILIKE ? AND #{ column } IS NOT NULL", "%#{ value }%" ]
195
217
  }
196
218
  end
197
- end
198
219
 
220
+ # Case-sensitive less-than (default-style comparison). *WARNING:* This
221
+ # will be case sensitive only if your database is configured for
222
+ # case sensitive matching by default.
223
+ #
224
+ # If comparing non-string column types be sure to pass in a value of an
225
+ # appropriate matching type (e.g. compare dates with DateTimes), else
226
+ # returned results will be incorrect but errors may not arise depending
227
+ # on database engine in use.
228
+ #
229
+ # Results in a <tt>foo < bar AND foo IS NOT NULL</tt> query.
230
+ #
231
+ # +model_field_name+:: If the model attribute name differs from the
232
+ # search key you want to use in the URI, give
233
+ # the model attribute name here, else omit.
234
+ #
235
+ # Returns a value that can be asssigned to a URI query string key in
236
+ # the Hash given to
237
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
238
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with.
239
+ #
240
+ def self.cs_lt( model_field_name = nil )
241
+ Proc.new { | attr, value |
242
+ column = model_field_name || attr
243
+
244
+ [ "#{ column } < ? AND #{ column } IS NOT NULL", value ]
245
+ }
246
+ end
247
+
248
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::cs_lt, but
249
+ # compares with less-than-or-equal-to.
250
+ #
251
+ # Results in a <tt>foo <= bar AND foo IS NOT NULL</tt> query.
252
+ #
253
+ def self.cs_lte( model_field_name = nil )
254
+ Proc.new { | attr, value |
255
+ column = model_field_name || attr
256
+
257
+ [ "#{ column } <= ? AND #{ column } IS NOT NULL", value ]
258
+ }
259
+ end
260
+
261
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::cs_lt, but
262
+ # compares with greater-than.
263
+ #
264
+ # Results in a <tt>foo > bar AND foo IS NOT NULL</tt> query.
265
+ #
266
+ def self.cs_gt( model_field_name = nil )
267
+ Proc.new { | attr, value |
268
+ column = model_field_name || attr
269
+
270
+ [ "#{ column } > ? AND #{ column } IS NOT NULL", value ]
271
+ }
272
+ end
273
+
274
+ # As Hoodoo::ActiveRecord::Finder::SearchHelper::cs_lt, but
275
+ # compares with greater-than-or-equal-to.
276
+ #
277
+ # Results in a <tt>foo >= bar AND foo IS NOT NULL</tt> query.
278
+ #
279
+ def self.cs_gte( model_field_name = nil )
280
+ Proc.new { | attr, value |
281
+ column = model_field_name || attr
282
+
283
+ [ "#{ column } >= ? AND #{ column } IS NOT NULL", value ]
284
+ }
285
+ end
286
+
287
+ end
199
288
  end
200
289
  end
201
290
  end
@@ -35,6 +35,51 @@ module Hoodoo
35
35
  #
36
36
  class Support
37
37
 
38
+ # Returns a (newly generated) Hash of search keys mapping to helper Procs
39
+ # which are in the same format as would be passed to
40
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#search_with or
41
+ # Hoodoo::ActiveRecord::Finder::ClassMethods#filter_with, describing the
42
+ # default framework search parameters. The middleware defines keys, but
43
+ # each ORM adapter module must specify how those keys actually get used
44
+ # to search inside supported database engines.
45
+ #
46
+ def self.framework_search_and_filter_data
47
+
48
+ # The middleware includes framework-level mappings between URI query
49
+ # string search keys and data validators and processors which convert
50
+ # types where necessary. For example, 'created_at' must be given a
51
+ # valid ISO 8601 subset string and a parsed DateTime will end up in
52
+ # the parsed search hash.
53
+ #
54
+ # Services opt out of framework-level searching at an interface level
55
+ # which means the Finder code herein, under normal flow, will never
56
+ # be asked to process something the interface omits. There is thus no
57
+ # need to try and break encapsulation and come up with a way to read
58
+ # the service interface's omissions. Instead, map everything.
59
+ #
60
+ # This could actually be useful if someone manually drives the #list
61
+ # mechanism with hand-constructed search or filter data that quite
62
+ # intentionally includes framework level parameters even if their own
63
+ # service interface for some reason opts out of allowing them to be
64
+ # exposed to API callers.
65
+ #
66
+ # Note that the #search_with / #filter_with DSL declaration in an
67
+ # appropriately extended model can be used to override the default
68
+ # values wired in below, because the defaults are established by
69
+ # design _before_ the model declarations are processed.
70
+ #
71
+ mapping = {
72
+ 'created_after' => Hoodoo::ActiveRecord::Finder::SearchHelper.cs_gt( :created_at ),
73
+ 'created_before' => Hoodoo::ActiveRecord::Finder::SearchHelper.cs_lt( :created_at )
74
+ }
75
+
76
+ if mapping.keys.length != ( mapping.keys | Hoodoo::Services::Middleware::FRAMEWORK_QUERY_DATA.keys ).length
77
+ raise 'Hoodoo::ActiveRecord::Support#framework_search_and_filter_data: Mismatch between internal mapping and Hoodoo::Services::Middleware::FRAMEWORK_QUERY_DATA'
78
+ end
79
+
80
+ return mapping
81
+ end
82
+
38
83
  # Takes a Hash of possibly-non-String keys and with +nil+ values or
39
84
  # Proc instances appropriate for Hoodoo::ActiveRecord::Finder#search_with
40
85
  # / #filter_with. Returns a similar Hash with all-String keys and a Proc
@@ -52,7 +52,7 @@ module Hoodoo
52
52
  if results.size > 0
53
53
 
54
54
  if results.platform_errors.has_errors?
55
- raise "Hoodoo::Client:: PaginatedEnumeration#enumerate_all: Unexpected internal state combination of results set and results error indication"
55
+ raise 'Hoodoo::Client::PaginatedEnumeration#enumerate_all: Unexpected internal state combination of results set and results error indication'
56
56
  end
57
57
 
58
58
  # Yield a resource at a time to the caller
@@ -175,6 +175,48 @@ module Hoodoo; module Services
175
175
  }
176
176
  } )
177
177
 
178
+ # A validation Proc for FRAMEWORK_QUERY_DATA - see that for details. This
179
+ # one ensures that the value is a valid ISO 8601 subset date/time string
180
+ # and evaluates to the parsed version of that string if so.
181
+ #
182
+ FRAMEWORK_QUERY_VALUE_DATE_PROC = -> ( value ) {
183
+ Hoodoo::Utilities.valid_iso8601_subset_datetime?( value ) ?
184
+ Hoodoo::Utilities.rationalise_datetime( value ) :
185
+ nil
186
+ }
187
+
188
+ # Out-of-box search and filter query keys. Interfaces can override the
189
+ # support for these inside the Hoodoo::Services::Interface.to_list block
190
+ # using Hoodoo::Services::Interface::ToListDSL.do_not_search and
191
+ # Hoodoo::Services::Interface::ToListDSL.do_not_filter.
192
+ #
193
+ # Keys, in order, are:
194
+ #
195
+ # * Query key to detect records with a +created_at+ date that is after the
196
+ # given value, in supporting resource; if used as a filter instead of a
197
+ # search string, would find records on-or-before the date.
198
+ #
199
+ # * Query key to detect records with a +created_at+ date that is before
200
+ # the given value, in supporting resource; if used as a filter instead
201
+ # of a search string, would find records on-or-after the date.
202
+ #
203
+ # Values are either a validation Proc or +nil+ for no validation. The
204
+ # Proc takes the search query value as its sole input paraeter and must
205
+ # evaluate to the input value either unmodified or in some canonicalised
206
+ # form if it is valid, else to +nil+ if the input value is invalid. The
207
+ # canonicalisation is typically used to coerce a URI query string based
208
+ # String type into a more useful comparable entity such as an Integer or
209
+ # DateTime.
210
+ #
211
+ # *IMPORTANT* - if this list is changed, any database support modules -
212
+ # e.g. in Hoodoo::ActiveRecord::Support - will need any internal mapping
213
+ # of "framework query keys to module-appropriate query code" updating.
214
+ #
215
+ FRAMEWORK_QUERY_DATA = {
216
+ 'created_after' => FRAMEWORK_QUERY_VALUE_DATE_PROC,
217
+ 'created_before' => FRAMEWORK_QUERY_VALUE_DATE_PROC,
218
+ }
219
+
178
220
  # Utility - returns the execution environment as a Rails-like environment
179
221
  # object which answers queries like +production?+ or +staging?+ with +true+
180
222
  # or +false+ according to the +RACK_ENV+ environment variable setting.
@@ -2770,21 +2812,52 @@ module Hoodoo; module Services
2770
2812
  end
2771
2813
  end
2772
2814
 
2773
- search = query_hash[ 'search' ] || {}
2774
- unrecognised_search_keys = search.keys - interface.to_list.search
2775
- malformed << "search: #{ unrecognised_search_keys.join(', ') }" unless unrecognised_search_keys.empty?
2815
+ search = query_hash[ 'search' ] || {}
2816
+ framework_search = FRAMEWORK_QUERY_DATA.keys - interface.to_list.do_not_search
2817
+ bad_search_keys = search.keys - framework_search - interface.to_list.search
2818
+
2819
+ framework_search.each do | search_key |
2820
+ next unless search.has_key?( search_key )
2821
+
2822
+ search_value = search[ search_key ]
2823
+ validator = FRAMEWORK_QUERY_DATA[ search_key ]
2824
+ canonical = validator.call( search_value )
2825
+
2826
+ if canonical.nil?
2827
+ bad_search_keys << search_key
2828
+ else
2829
+ search[ search_key ] = canonical
2830
+ end
2831
+ end
2832
+
2833
+ filter = query_hash[ 'filter' ] || {}
2834
+ framework_filter = FRAMEWORK_QUERY_DATA.keys - interface.to_list.do_not_filter
2835
+ bad_filter_keys = filter.keys - framework_filter - interface.to_list.filter
2836
+
2837
+ framework_filter.each do | filter_key |
2838
+ next unless filter.has_key?( filter_key )
2839
+
2840
+ filter_value = filter[ filter_key ]
2841
+ validator = FRAMEWORK_QUERY_DATA[ filter_key ]
2842
+ canonical = validator.call( filter_value )
2843
+
2844
+ if canonical.nil?
2845
+ bad_filter_keys << filter_key
2846
+ else
2847
+ filter[ filter_key ] = canonical
2848
+ end
2849
+ end
2776
2850
 
2777
- filter = query_hash[ 'filter' ] || {}
2778
- unrecognised_filter_keys = filter.keys - interface.to_list.filter
2779
- malformed << "filter: #{ unrecognised_filter_keys.join(', ') }" unless unrecognised_filter_keys.empty?
2851
+ embeds = query_hash[ '_embed' ] || []
2852
+ bad_embeds = embeds - interface.embeds
2780
2853
 
2781
- embeds = query_hash[ '_embed' ] || []
2782
- unrecognised_embeds = embeds - interface.embeds
2783
- malformed << "_embed: #{ unrecognised_embeds.join(', ') }" unless unrecognised_embeds.empty?
2854
+ references = query_hash[ '_reference' ] || []
2855
+ bad_references = references - interface.embeds # (sic.)
2784
2856
 
2785
- references = query_hash[ '_reference' ] || []
2786
- unrecognised_references = references - interface.embeds # (sic.)
2787
- malformed << "_reference: #{ unrecognised_references.join(', ') }" unless unrecognised_references.empty?
2857
+ malformed << "search: #{ bad_search_keys.join( ', ' ) }" unless bad_search_keys.empty?
2858
+ malformed << "filter: #{ bad_filter_keys.join( ', ' ) }" unless bad_filter_keys.empty?
2859
+ malformed << "_embed: #{ bad_embeds.join( ', ' ) }" unless bad_embeds.empty?
2860
+ malformed << "_reference: #{ bad_references.join( ', ' ) }" unless bad_references.empty?
2788
2861
 
2789
2862
  return response.add_error(
2790
2863
  'platform.malformed',