Class: Spree::SearchProvider::MetafieldSchema

Inherits:
Object
  • Object
show all
Defined in:
app/services/spree/search_provider/metafield_schema.rb

Overview

Product metafield definitions that participate in search/sort.

Constant Summary collapse

TEXT_FILTER_PREDICATES =

Ransack-style predicates accepted per field type. Mirrors the operator sets the admin dashboard's filter panel offers for string/number columns (see packages/dashboard-core/src/components/table-toolbar.tsx).

%w[i_cont cont eq not_eq start end present blank].freeze
NUMBER_FILTER_PREDICATES =
%w[eq gt gteq lt lteq present blank].freeze
ORDERED_FILTER_PREDICATES =

Longest first so a key ending in _i_cont isn't mis-split as the shorter _cont against a definition keyed ..._i.

(TEXT_FILTER_PREDICATES | NUMBER_FILTER_PREDICATES).
sort_by { |predicate| -predicate.length }.freeze

Instance Method Summary collapse

Instance Method Details

#entriesHash{String => Spree::MetafieldDefinition}

Returns:



19
20
21
# File 'app/services/spree/search_provider/metafield_schema.rb', line 19

def entries
  @entries ||= product_definitions.index_by(&:filter_key)
end

#entry_for(attribute_key) ⇒ Spree::MetafieldDefinition?

Parameters:

  • attribute_key (String)

Returns:



39
40
41
# File 'app/services/spree/search_provider/metafield_schema.rb', line 39

def entry_for(attribute_key)
  entries[attribute_key.to_s]
end

#filter_predicates_for(field_type) ⇒ Array<String>

Parameters:

  • field_type (String)

Returns:

  • (Array<String>)


112
113
114
# File 'app/services/spree/search_provider/metafield_schema.rb', line 112

def filter_predicates_for(field_type)
  field_type == 'number' ? NUMBER_FILTER_PREDICATES : TEXT_FILTER_PREDICATES
end

#filterable_attribute_keysArray<String>

Every schema attribute accepts filters — values are already indexed for search/sort, so filtering rides on the same document keys.

Returns:

  • (Array<String>)


47
48
49
# File 'app/services/spree/search_provider/metafield_schema.rb', line 47

def filterable_attribute_keys
  @filterable_attribute_keys ||= entries.keys
end

#parse_filter(key) ⇒ Hash?

Splits a Ransack-style predicate key (e.g. cf_custom_label_i_cont) into the definition it targets and the predicate. Both search keys and predicates contain underscores, so predicates are tried longest-first — otherwise cf_x_i_cont would resolve as key x_i with predicate cont. A key that itself ends in a predicate name (+..._eq_eq+) is only reachable if the shorter split names a real definition.

Parameters:

  • key (String, Symbol)

Returns:

  • (Hash, nil)

    { definition:, predicate: }



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'app/services/spree/search_provider/metafield_schema.rb', line 94

def parse_filter(key)
  value = key.to_s
  return unless value.start_with?('cf_')

  ORDERED_FILTER_PREDICATES.each do |predicate|
    next unless value.end_with?("_#{predicate}")

    definition = entries[value.delete_suffix("_#{predicate}")]
    next unless definition && filter_predicates_for(definition.field_type).include?(predicate)

    return { definition: definition, predicate: predicate }
  end

  nil
end

#parse_sort(sort) ⇒ Hash?

Returns { attribute:, direction: 'asc'|'desc' }.

Parameters:

  • sort (String, nil)

Returns:

  • (Hash, nil)

    { attribute:, direction: 'asc'|'desc' }



71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'app/services/spree/search_provider/metafield_schema.rb', line 71

def parse_sort(sort)
  value = sort.to_s.strip
  return if value.blank?

  attribute = value.delete_prefix('-')
  definition = entry_for(attribute)
  return unless definition&.sortable?

  {
    attribute: attribute,
    direction: value.start_with?('-') ? 'desc' : 'asc'
  }
end

#schema_versionString

Stamp for Store API filters cache keys.

Returns:

  • (String)


119
120
121
122
123
124
# File 'app/services/spree/search_provider/metafield_schema.rb', line 119

def schema_version
  @schema_version ||= [
    entries.size,
    entries.each_value.filter_map(&:updated_at).max&.utc&.iso8601(6)
  ].join('-')
end

#searchable_attribute_keysArray<String>

Returns:

  • (Array<String>)


24
25
26
27
28
# File 'app/services/spree/search_provider/metafield_schema.rb', line 24

def searchable_attribute_keys
  @searchable_attribute_keys ||= entries.each_value.filter_map do |definition|
    definition.filter_key if definition.searchable?
  end
end

#sort_idsArray<String>

Returns:

  • (Array<String>)


52
53
54
# File 'app/services/spree/search_provider/metafield_schema.rb', line 52

def sort_ids
  @sort_ids ||= sortable_attribute_keys.flat_map { |key| [key, "-#{key}"] }
end

#sort_optionsArray<Hash>

Returns { id:, label: }.

Returns:

  • (Array<Hash>)

    { id:, label: }



57
58
59
60
61
62
63
64
65
66
67
# File 'app/services/spree/search_provider/metafield_schema.rb', line 57

def sort_options
  @sort_options ||= entries.each_value.select(&:sortable?).flat_map do |definition|
    key = definition.filter_key
    name = definition.name.presence || key

    [
      { id: key, label: sort_option_label(name, definition.field_type, :asc) },
      { id: "-#{key}", label: sort_option_label(name, definition.field_type, :desc) }
    ]
  end
end

#sortable_attribute_keysArray<String>

Returns:

  • (Array<String>)


31
32
33
34
35
# File 'app/services/spree/search_provider/metafield_schema.rb', line 31

def sortable_attribute_keys
  @sortable_attribute_keys ||= entries.each_value.filter_map do |definition|
    definition.filter_key if definition.sortable?
  end
end