module Spree::Core::ProductFilters
See specific filters below for concrete examples.
Public Class Methods
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?
# File lib/spree/core/product_filters.rb, line 183 def self.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
# File lib/spree/core/product_filters.rb, line 104 def self.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: I18n.t('spree.taxonomy_brands_name'), scope: :brand_any, conds: conds, labels: brands.sort.map { |k| [k, k] } } end
# File lib/spree/core/product_filters.rb, line 64 def self.format_price(amount) Spree::Money.new(amount) end
# File lib/spree/core/product_filters.rb, line 68 def self.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].between(10..15)], ["#{format_price(15)} - #{format_price(18)}", v[:amount].between(15..18)], ["#{format_price(18)} - #{format_price(20)}", v[:amount].between(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
# File lib/spree/core/product_filters.rb, line 140 def self.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
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.
# File lib/spree/core/product_filters.rb, line 166 def self.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