Class: WCC::Contentful::Store::Query
- Inherits:
-
Object
- Object
- WCC::Contentful::Store::Query
- Includes:
- Enumerable, Interface
- Defined in:
- lib/wcc/contentful/store/query.rb,
lib/wcc/contentful/store/query/condition.rb,
lib/wcc/contentful/store/query/interface.rb
Overview
The default query object returned by Stores that extend WCC::Contentful::Store::Base. It exposes several chainable query methods to apply query filters. Enumerating the query executes it, caching the result.
Direct Known Subclasses
Defined Under Namespace
Modules: Interface Classes: Condition
Constant Summary collapse
- FALSE_VALUES =
[ false, 0, '0', :'0', 'f', :f, 'F', :F, 'false', :false, # rubocop:disable Lint/BooleanSymbol 'FALSE', :FALSE, 'off', :off, 'OFF', :OFF ].to_set.freeze
- RESERVED_NAMES =
%w[fields sys].freeze
Constants included from Interface
Instance Attribute Summary collapse
- #conditions ⇒ Object readonly
- #content_type ⇒ Object readonly
- #store ⇒ Object readonly
Class Method Summary collapse
-
.flatten_filter_hash(hash, path = []) ⇒ Object
Turns a hash into a flat array of individual conditions, where each element can be passed as params to apply_operator.
- .known_locales ⇒ Object
-
.normalize_condition_path(path, options = nil) ⇒ Object
Takes a path array in non-normal form and inserts ‘sys’, ‘fields’, and the current locale as appropriate to normalize it.
- .op?(key) ⇒ Boolean
Instance Method Summary collapse
-
#apply(filter, context = nil) ⇒ Object
Called with a filter object by Base#find_by in order to apply the filter.
-
#apply_operator(operator, field, expected, _context = nil) ⇒ Object
Returns a new chained Query that has a new condition.
-
#initialize(store, content_type:, conditions: nil, options: nil, configuration: nil, **extra) ⇒ Query
constructor
rubocop:disable Metrics/ParameterLists.
-
#result_set ⇒ Object
Override this to provide a result set from the Query object itself rather than from calling #execute in the store.
-
#to_enum ⇒ Object
Executes the query against the store and memoizes the resulting enumerable.
Methods included from Interface
Constructor Details
#initialize(store, content_type:, conditions: nil, options: nil, configuration: nil, **extra) ⇒ Query
rubocop:disable Metrics/ParameterLists
30 31 32 33 34 35 36 37 |
# File 'lib/wcc/contentful/store/query.rb', line 30 def initialize(store, content_type:, conditions: nil, options: nil, configuration: nil, **extra) # rubocop:disable Metrics/ParameterLists @store = store @content_type = content_type @conditions = conditions || [] @options = || {} @configuration = configuration || WCC::Contentful.configuration @extra = extra end |
Instance Attribute Details
#conditions ⇒ Object (readonly)
28 29 30 |
# File 'lib/wcc/contentful/store/query.rb', line 28 def conditions @conditions end |
#content_type ⇒ Object (readonly)
28 29 30 |
# File 'lib/wcc/contentful/store/query.rb', line 28 def content_type @content_type end |
#store ⇒ Object (readonly)
28 29 30 |
# File 'lib/wcc/contentful/store/query.rb', line 28 def store @store end |
Class Method Details
.flatten_filter_hash(hash, path = []) ⇒ Object
Turns a hash into a flat array of individual conditions, where each element can be passed as params to apply_operator
163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'lib/wcc/contentful/store/query.rb', line 163 def flatten_filter_hash(hash, path = []) hash.flat_map do |(k, v)| k = k.to_s if k.include?('.') k, *rest = k.split('.') v = { rest.join('.') => v } end if v.is_a? Hash flatten_filter_hash(v, path + [k]) elsif op?(k) { path: path, op: k.to_sym, expected: v } else { path: path + [k], op: nil, expected: v } end end end |
.known_locales ⇒ Object
181 182 183 |
# File 'lib/wcc/contentful/store/query.rb', line 181 def known_locales @known_locales ||= WCC::Contentful.locales&.keys || ['en-US'] end |
.normalize_condition_path(path, options = nil) ⇒ Object
Takes a path array in non-normal form and inserts ‘sys’, ‘fields’, and the current locale as appropriate to normalize it. rubocop:disable Metrics/BlockNesting
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
# File 'lib/wcc/contentful/store/query.rb', line 189 def normalize_condition_path(path, = nil) context_locale = [:locale]&.to_s if .present? context_locale ||= 'en-US' rev_path = path.reverse new_path = [] current_tuple = [] current_locale_was_inferred = false until rev_path.empty? && current_tuple.empty? raise ArgumentError, "Query too complex: #{path.join('.')}" if new_path.length > 7 case current_tuple.length when 0 # expect a locale current_tuple << if known_locales.include?(rev_path[0]) current_locale_was_inferred = false rev_path.shift else # infer locale current_locale_was_inferred = true context_locale end when 1 # expect a path current_tuple << rev_path.shift when 2 # expect 'sys' or 'fields' current_tuple << if RESERVED_NAMES.include?(rev_path[0]) rev_path.shift else # infer 'sys' or 'fields' current_tuple.last == 'id' ? 'sys' : 'fields' end if current_tuple.last == 'sys' && current_locale_was_inferred # remove the inferred current locale current_tuple.shift end new_path << current_tuple current_tuple = [] end end new_path.flat_map { |x| x }.reverse.freeze end |
Instance Method Details
#apply(filter, context = nil) ⇒ Object
Called with a filter object by Base#find_by in order to apply the filter. The filter in this case is a hash where the keys are paths and the values are expectations.
98 99 100 101 102 |
# File 'lib/wcc/contentful/store/query.rb', line 98 def apply(filter, context = nil) self.class.flatten_filter_hash(filter).reduce(self) do |query, cond| query.apply_operator(cond[:op], cond[:path], cond[:expected], context) end end |
#apply_operator(operator, field, expected, _context = nil) ⇒ Object
Returns a new chained Query that has a new condition. The new condition represents the WHERE comparison being applied here. The underlying store implementation translates this condition statement into an appropriate query against the datastore.
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
# File 'lib/wcc/contentful/store/query.rb', line 65 def apply_operator(operator, field, expected, _context = nil) operator ||= expected.is_a?(Array) ? :in : :eq raise ArgumentError, "Operator #{operator} not supported" unless respond_to?(operator) raise ArgumentError, 'value cannot be nil (try using exists: false)' if expected.nil? case operator when :in, :nin, :all expected = Array(expected) when :exists expected = !FALSE_VALUES.include?(expected) end field = field.to_s if field.is_a? Symbol path = field.is_a?(Array) ? field : field.split('.') path = self.class.normalize_condition_path(path, @options) _append_condition( Condition.new(path, operator, expected, @configuration&.locale_fallbacks || {}) ) end |
#result_set ⇒ Object
Override this to provide a result set from the Query object itself rather than from calling #execute in the store.
106 107 108 |
# File 'lib/wcc/contentful/store/query.rb', line 106 def result_set @result_set ||= store.execute(self) end |
#to_enum ⇒ Object
Executes the query against the store and memoizes the resulting enumerable.
Subclasses can override this to provide a more efficient implementation.
23 24 25 26 |
# File 'lib/wcc/contentful/store/query.rb', line 23 def to_enum @to_enum ||= result_set.lazy.map { |row| resolve_includes(row, @options[:include]) } end |