Module: Spree::Core::ProductFilters

Defined in:
lib/spree/core/product_filters.rb

Overview

See specific filters below for concrete examples.

Class Method Summary collapse

Class Method Details

.all_taxonsObject

Filtering by the list of all taxons

Similar idea as above, but we don’t want the descendants’ products, hence it uses one of the auto-generated scopes from Ransack.

idea: expand the format to allow nesting of labels?



183
184
185
186
187
188
189
190
191
# File 'lib/spree/core/product_filters.rb', line 183

def ProductFilters.all_taxons
  taxons = Spree::Taxonomy.all.map { |t| [t.root] + t.root.descendants }.flatten
  {
    name:   'All taxons',
    scope:  :taxons_id_equals_any,
    labels: taxons.sort_by(&:name).map { |t| [t.name, t.id] },
    conds:  nil # not needed
  }
end

.brand_filterObject



105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/spree/core/product_filters.rb', line 105

def ProductFilters.brand_filter
  brand_property = Spree::Property.find_by(name: 'brand')
  brands = brand_property ? Spree::ProductProperty.where(property_id: brand_property.id).pluck(:value).uniq.map(&:to_s) : []
  pp = Spree::ProductProperty.arel_table
  conds = Hash[*brands.map { |b| [b, pp[:value].eq(b)] }.flatten]
  {
    name:   'Brands',
    scope:  :brand_any,
    conds:  conds,
    labels: (brands.sort).map { |k| [k, k] }
  }
end

.format_price(amount) ⇒ Object



64
65
66
# File 'lib/spree/core/product_filters.rb', line 64

def ProductFilters.format_price(amount)
  Spree::Money.new(amount)
end

.price_filterObject



68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/spree/core/product_filters.rb', line 68

def ProductFilters.price_filter
  v = Spree::Price.arel_table
  conds = [ [ Spree.t(:under_price, price: format_price(10))     , v[:amount].lteq(10)],
            [ "#{format_price(10)} - #{format_price(15)}"        , v[:amount].in(10..15)],
            [ "#{format_price(15)} - #{format_price(18)}"        , v[:amount].in(15..18)],
            [ "#{format_price(18)} - #{format_price(20)}"        , v[:amount].in(18..20)],
            [ Spree.t(:or_over_price, price: format_price(20)) , v[:amount].gteq(20)]]
  {
    name:   Spree.t(:price_range),
    scope:  :price_range_any,
    conds:  Hash[*conds.flatten],
    labels: conds.map { |k,v| [k, k] }
  }
end

.selective_brand_filter(taxon = nil) ⇒ Object



141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/spree/core/product_filters.rb', line 141

def ProductFilters.selective_brand_filter(taxon = nil)
  taxon ||= Spree::Taxonomy.first.root
  brand_property = Spree::Property.find_by(name: 'brand')
  scope = Spree::ProductProperty.where(property: brand_property).
    joins(product: :taxons).
    where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants)
  brands = scope.pluck(:value).uniq
  {
    name:   'Applicable Brands',
    scope:  :selective_brand_any,
    labels: brands.sort.map { |k| [k, k] }
  }
end

.taxons_below(taxon) ⇒ Object

Provide filtering on the immediate children of a taxon

This doesn’t fit the pattern of the examples above, so there’s a few changes. Firstly, it uses an existing scope which was not built for filtering - and so has no need of a conditions mapping, and secondly, it has a mapping of name to the argument type expected by the other scope.

This technique is useful for filtering on objects (by passing ids) or with a scope that can be used directly (eg. testing only ever on a single property).

This scope selects products in any of the active taxons or their children.



167
168
169
170
171
172
173
174
175
# File 'lib/spree/core/product_filters.rb', line 167

def ProductFilters.taxons_below(taxon)
  return Spree::Core::ProductFilters.all_taxons if taxon.nil?
  {
    name:   'Taxons under ' + taxon.name,
    scope:  :taxons_id_in_tree_any,
    labels: taxon.children.sort_by(&:position).map { |t| [t.name, t.id] },
    conds:  nil
  }
end