Created
March 12, 2014 10:42
-
-
Save stuartbates/9504523 to your computer and use it in GitHub Desktop.
Numerous examples of Spree filters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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