Skip to content

Instantly share code, notes, and snippets.

@redglory
Created June 2, 2015 10:31
Show Gist options
  • Select an option

  • Save redglory/d0dc4240f12a30d5e702 to your computer and use it in GitHub Desktop.

Select an option

Save redglory/d0dc4240f12a30d5e702 to your computer and use it in GitHub Desktop.
Filtering Products by Option Types (Size and Color)
module Spree
module Core
module ProductFilters
# Test for discrete option values selection
def ProductFilters.option_with_values(option_scope, option, values)
# get values IDs for Option with name {@option} and value-names in {@values} for use in SQL below
option_values = Spree::OptionValue.where(:presentation => [values].flatten).joins(:option_type).where(OptionType.table_name => {:name => option}).pluck("#{OptionValue.table_name}.id")
return option_scope if option_values.empty?
option_scope = option_scope.where("#{Product.table_name}.id in (select product_id from #{Variant.table_name} v left join spree_option_values_variants ov on ov.variant_id = v.id where ov.option_value_id in (?))", option_values)
option_scope
puts option_scope.inspect
end
# multi-option scope
Spree::Product.scope :option_any,
lambda { |*opts|
option_scope = Spree::Product.includes(:variants_including_master)
opts.map { |opt|
# opt is an array => ['option-name', [value1, value2, value3, ...]]
option_scope = option_with_values(option_scope, *opt)
}
option_scope
}
# clothes size filter
def ProductFilters.clothes_size_filter
clothes_sizes = Spree::OptionValue.where(:option_type_id => Spree::OptionType.find_by_name!("clothes-size")).order("position").map(&:presentation).compact.uniq
{
:name => "Tam. Roupa",
:scope => :option_any,
:conds => nil,
:option => 'clothes-size',
:labels => clothes_sizes.map { |k| [k, k] }
}
end
# hat size filter
def ProductFilters.hat_size_filter
hat_sizes = Spree::OptionValue.where(:option_type_id => Spree::OptionType.find_by_name!("hat-size")).order("position").map(&:presentation).compact.uniq
{
:name => "Tam. Chapéus",
:scope => :option_any,
:conds => nil,
:option => 'hat-size',
:labels => hat_sizes.map { |k| [k, k] }
}
end
# shoes size filter
def ProductFilters.shoes_size_filter
shoes_sizes = Spree::OptionValue.where(:option_type_id => Spree::OptionType.find_by_name!("shoes-size")).order("position").map(&:presentation).compact.uniq
{
:name => "Tam. Sapatos",
:scope => :option_any,
:conds => nil,
:option => 'shoes-size',
:labels => shoes_sizes.map { |k| [k, k] }
}
end
# color filter
def ProductFilters.color_filter
colors = Spree::OptionValue.where(:option_type_id => Spree::OptionType.find_by_name("color")).order("position").map(&:presentation).compact.uniq
{
:name => "Cor",
:scope => :option_any,
:conds => nil,
:option => 'color',
:labels => colors.map { |k| [k, k] }
}
end
# price range scope
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
# price filter
def ProductFilters.price_filter
v = Spree::Price.arel_table
conds = [ [ Spree.t(:under_price, price: format_price(15)) , v[:amount].lteq(15)],
[ "#{format_price(15)} - #{format_price(20)}" , v[:amount].in(15..20)],
[ "#{format_price(20)} - #{format_price(25)}" , v[:amount].in(20..25)],
[ "#{format_price(25)} - #{format_price(30)}" , v[:amount].in(25..30)],
[ Spree.t(:or_over_price, price: format_price(30)) , v[:amount].gteq(30)]]
{
name: Spree.t(:price_range),
scope: :price_range_any,
conds: Hash[*conds.flatten],
labels: conds.map { |k,v| [k, k] }
}
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment