error: undefined method 'scoped' solution:
# config/initializers/scoped.rb
class ActiveRecord::Base
# do things the modern way and silence Rails 4 deprecation warnings
def self.scoped(options=nil)
options ? where(nil).apply_finder_options(options, true) : where(nil)
end
end
override product_filters.rb copy original file to lib/spree/product_filters.rb
# libs/spree/product_filters.rb
module Spree
module Core
module ProductFilters
Spree::Product.add_search_scope :selective_brand_any do |*opts|
Spree::Product.brand_any(*opts)
end
def ProductFilters.selective_brand_filter(taxon = nil)
# your filter
end
end
end
end
use filter on Taxon show page
# app/models/taxon_decorator.rb
Spree::Taxon.class_eval do
def applicable_filters
fs = []
# fs << ProductFilters.taxons_below(self)
## unless it's a root taxon? left open for demo purposes
fs << Spree::Core::ProductFilters.price_filter if Spree::Core::ProductFilters.respond_to?(:price_filter)
#fs << Spree::Core::ProductFilters.brand_filter if Spree::Core::ProductFilters.respond_to?(:brand_filter)
fs << Spree::Core::ProductFilters.selective_brand_filter(self) if Spree::Core::ProductFilters.respond_to?(:selective_brand_filter)
fs
end
end
# lib/spree/product_filters.rb
module Spree
module Core
module ProductFilters
@@taxon = nil
Spree::Product.add_search_scope :brand_any do |*opts|
filter = ProductFilters.brand_filter(@@taxon)
conds = opts.map {|o| 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('brand').where(scope)
end
def ProductFilters.brand_filter(taxon = nil)
taxon ||= Spree::Taxonomy.first.root
@@taxon = taxon
property = Spree::Property.find_by(name: 'brand')
scope = Spree::ProductProperty.where(property: property).
joins(product: :taxons).
where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants)
rows = scope.pluck(:value).uniq
pp = Spree::ProductProperty.arel_table
conds = Hash[*rows.map { |b| [b, pp[:value].eq(b)] }.flatten]
{
name: 'Brand',
scope: :brand_any,
conds: conds,
labels: rows.sort.map { |k| [k, k] }
}
end
end
end
end
show filter on Taxon show page:
# app/models/taxon_decorator.rb
Spree::Taxon.class_eval do
def applicable_filters
fs = []
fs << Spree::Core::ProductFilters.price_filter if Spree::Core::ProductFilters.respond_to?(:price_filter)
fs << Spree::Core::ProductFilters.selective_brand_filter(self) if Spree::Core::ProductFilters.respond_to?(:selective_brand_filter)
fs
end
end
http://stackoverflow.com/questions/14853046/spree-search-filter-for-properties-and-variants
If you have several properties and select some values for each of them then it won't find any product.
To fix this create a custom search class and use it as a searcher class.
This solution was found at https://gist.github.com/killthekitten/4486585.
# lib/spree/custom_search.rb
module Spree
class CustomSearch < Spree::Core::Search::Base
protected
def add_search_scopes(base_scope)
statement = nil
search.each do |property_name, property_values|
name = property_name.gsub("_any", "").gsub("selective_","")
property = Spree::Property.find_by_name(name)
next unless property
substatement = product_property[:property_id].eq(property.id).and(product_property[:value].eq(property_values.first))
#substatement = Spree::Product.with_property_value(name, property_values.first)
property_values[1..-1].each do |pv|
substatement = substatement.or product_property[:value].eq(pv)
#substatement = substatement.or Spree::Product.with_property_value(name, pv)
end
tail = product[:id].in(Spree::ProductProperty.select(:product_id).where(substatement).map(&:product_id))
#ids = Spree::ProductProperty.select(:product_id).where(substatement).map(&:product_id)
#tail = product[:id].in(ids)
statement = statement.nil? ? tail : statement.and(tail)
end if search
statement ? base_scope.where(statement) : base_scope
end
def prepare(params)
super
@properties[:product] = Spree::Product.arel_table
@properties[:product_property] = Spree::ProductProperty.arel_table
end
end
end
Use our custom searcher:
# config/initializers/spree.rb
...
require "#{Rails.root}/lib/spree/custom_search"
Spree::Config.searcher_class = Spree::CustomSearch
Awesome!