Skip to content

Instantly share code, notes, and snippets.

@stuartbates
Created March 12, 2014 10:42
Show Gist options
  • Save stuartbates/9504523 to your computer and use it in GitHub Desktop.
Save stuartbates/9504523 to your computer and use it in GitHub Desktop.
Numerous examples of Spree filters
module Spree
module Core
module ProductFilters
# Example: filtering by price
# The named scope just maps incoming labels onto their conditions, and builds the conjunction
# 'price' is in the base scope's context (ie, "select foo from products where ...") so
# we can access the field right away
# The filter identifies which scope to use, then sets the conditions for each price range
#
# If user checks off three different price ranges then the argument passed to
# below scope would be something like ["$10 - $15", "$15 - $18", "$18 - $20"]
Spree::Product.add_search_scope :price_range_any do |*opts|
conds = opts.map {|o| Spree::Core::ProductFilters.price_filter[:conds][o]}.reject { |c| c.nil? }
scope = conds.shift
conds.each do |new_scope|
scope = scope.or(new_scope)
end
Spree::Product.joins(master: :default_price).where(scope)
end
def ProductFilters.format_price(amount)
Spree::Money.new(amount)
end
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
# COLOUR
Spree::Product.add_search_scope :colour_any do |*opts|
conds = opts.map {|o| ProductFilters.colour_filter[:conds][o]}.reject {|c| c.nil?}
scope = conds.shift
conds.each do |new_scope|
scope = scope.or(new_scope)
end
Spree::Product.with_property("Colour").where(scope)
end
def ProductFilters.colour_filter
colour_property = Spree::Property.find_by_name("Colour")
colours = Spree::ProductProperty.where(:property_id => colour_property).pluck(:value).uniq
pp = Spree::ProductProperty.arel_table
conds = Hash[*colours.map { |b| [b, pp[:value].eq(b)] }.flatten]
{
:name => "Colours",
:scope => :colour_any,
:conds => conds,
:labels => (colours.sort).map { |k| [k, k] }
}
end
# Benefits
Spree::Product.add_search_scope :benefit_any do |*opts|
conds = opts.map {|o| ProductFilters.benefit_filter[:conds][o]}.reject {|c| c.nil?}
scope = conds.shift
conds.each do |new_scope|
scope = scope.or(new_scope)
end
Spree::Product.with_property("Benefits").where(scope)
end
def ProductFilters.benefit_filter
benefit_property = Spree::Property.find_by_name("Benefits")
benefits = Spree::ProductProperty.where(:property_id => benefit_property).pluck(:value).uniq
pp = Spree::ProductProperty.arel_table
conds = Hash[*benefits.map { |b| [b, pp[:value].eq(b)] }.flatten]
{
:name => "Benefits",
:scope => :benefit_any,
:conds => conds,
:labels => (benefits.sort).map { |k| [k, k] }
}
end
end
end
end
@jakemumu
Copy link

jakemumu commented Oct 1, 2017

Hey Stuart, I have an application built with solidus with filter exactly like this, however they don't interoperate.

They work individually but not together, I tried adding a custom search class given another gist I found online, but I couldn't understand why this was necessary

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment