狂欢产品过滤器不再起作用

时间:2013-10-25 10:01:28

标签: ruby-on-rails ruby spree

我在为Spree 2.0.4定义新的动态ProductFilters时遇到了问题

我的客户有分类(例如Taxons)。产品属于一个类别,最多有8个属性但属性也取决于每个产品所在的类别,并且属性的位置也很重要。

我的解决方案是以非标准化的方式扩展数据库:

module Spree
  Taxon.class_eval do


    belongs_to :prop1,  class_name: "Spree::Property",
                        foreign_key: "p1_id"
    belongs_to :prop2,  class_name: "Spree::Property",
                        foreign_key: "p2_id"
    belongs_to :prop3,  class_name: "Spree::Property",
                        foreign_key: "p3_id"
    belongs_to :prop4,  class_name: "Spree::Property",
                        foreign_key: "p4_id"
    belongs_to :prop5,  class_name: "Spree::Property",
                        foreign_key: "p5_id"
    belongs_to :prop6,  class_name: "Spree::Property",
                        foreign_key: "p6_id"
    belongs_to :prop7,  class_name: "Spree::Property",
                        foreign_key: "p7_id"
    belongs_to :prop8,  class_name: "Spree::Property",
                        foreign_key: "p8_id"

    attr_accessible :prop1, :prop2, :prop3, :prop4, :prop5, :prop6, :prop7, :prop8


    def properties
      prop = []
      prop << prop1
      prop << prop2
      prop << prop3
      prop << prop4
      prop << prop5
      prop << prop6
      prop << prop7
      prop << prop8
      return prop
    end

    def applicable_filters
      fs = []
      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
    end


  end
end

这样我就可以在相应产品的分类单元中获得可能的属性。我现在为每个taxon属性(prop1 .. prop8)制作了8个过滤器,因为有些值是数字的,应该处理不同于文本值,所以即使这不是完全DRY我来到以下解决方案:

module Spree
  module Core
    module ProductFilters

      if Spree::Property.table_exists?
        Spree::Product.add_search_scope :selective_prop1_any do |*opts|
          conds = opts.map {|o| ProductFilters.selective_prop1_filter[:conds][o]}.reject {|c| c.nil?}
          scope = conds.shift
          conds.each do |new_scope|
            scope = scope.or(new_scope)
          end
          Spree::Product.where(scope)
        end

        def ProductFilters.selective_prop1_filter(taxon = nil, locale = 'en')
          return if taxon.nil? #||= Spree::Taxon.find_by_permalink!("categories")
          property = taxon.prop1
          scope = Spree::ProductProperty.where(:property_id => property, :locale => locale).
                                         joins(:product => :taxons).
                                         where("#{Spree::Taxon.table_name}.id" => [taxon] + taxon.descendants).
                                         scoped
          brands = scope.pluck(:value).uniq
          {
            :name   => property.presentation,
            :scope  => :selective_prop1_any,
            :labels => brands.sort.map { |k| [k,k] }
          }
        end
      end

      if Spree::Property.table_exists?
        Spree::Product.add_search_scope :selective_prop2_any do |*opts|
          conds = opts.map {|o| ProductFilters.selective_prop2_filter[:conds][o]}.reject {|c| c.nil?}
          Rails.logger.debug conds.inspect
          scope = conds.shift
          Rails.logger.debug scope.inspect
          conds.each do |new_scope|
            scope = scope.or(new_scope)
          end
          Rails.logger.debug scope.inspect
          Spree::Product.where(scope)
        end

# ... other filters cut out for brevity

      if Spree::Property.table_exists?
        Spree::Product.add_search_scope :selective_prop8_any do |*opts|
          [..]
        end

        def ProductFilters.selective_prop8_filter(taxon = nil, locale = 'en')
          [..]
        end
      end

      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
    end
  end
end

由于事实,甚至属性的值都应该进行本地化,因此在ProductProperties表中创建了一个列语言环境。我的选择性过滤器传递语言环境变量以检索正确的ProductProperty。

由于MVC限制无法将会话[:locale]和当前分类中的区域设置传递给模型,因此我覆盖了原始显示逻辑,该逻辑在CONTROLLER(!)中使用适用于taxon的tax_filters方法这样:

TaxonsController.class_eval do
    def show
      @taxon = Taxon.find_by_permalink(params[:id])

      return unless @taxon

      if @taxon
        @filters = []
        @filters << Spree::Core::ProductFilters.selective_prop1_filter(@taxon, locale) unless @taxon.prop1.nil?
        [...]
        @filters << Spree::Core::ProductFilters.selective_prop8_filter(@taxon, locale) unless @taxon.prop8.nil?
        @filters.concat(@taxon.applicable_filters)
      else
        @filters = Spree::Core::ProductFilters.all_taxons
      end
      p = params.merge(:taxon => @taxon.id)
      @searcher = Spree::Config.searcher_class.new(params)
      @searcher.current_user = try_spree_current_user
      @searcher.current_currency = current_currency

      @products = @searcher.retrieve_products
    end
  end

这是主要左侧的原始视图代码:

<% unless @filters.empty? %>
  <%= form_tag '', :method => :get, :id => 'sidebar_products_search' do %>
    <% params[:search] ||= {} %>
    <%= hidden_field_tag 'per_page', params[:per_page] %>
    <% @filters.each do |filter| %>
      <% labels = filter[:labels] || filter[:conds].map {|m,c| [m,m]} %>
      <% next if labels.empty? %>
      <div class="" data-hook="navigation">
        <h5 class="filter-title"> <%= filter[:name] %> </h5>
          <% labels.each do |nm,val| %>
            <% label = "#{filter[:name]}_#{nm}".gsub(/\s+/,'_') %>
            <label for="<%= label %>" class="checkbox" style="display:block;"><%= nm %><input type="checkbox"
                   id="<%= label %>"
                   name="search[<%= filter[:scope].to_s %>][]"
                   value="<%= val %>"
                   <%= params[:search][filter[:scope]] && params[:search][filter[:scope]].include?(val.to_s) ? "checked" : "" %> />
            </label>
          <% end %>
      </div>
    <% end %>
    <%= submit_tag Spree.t(:search), :name => nil, :class => 'button' %>
  <% end %>
<% end %>

显示的工作原理应该如下:根据用户所在的分类,会话[:locale]中的ProductProperties值被正确获取并显示,但现在问题出现了:

搜索不再起作用了。即使未修改的:price_range_any过滤器也不起作用。始终显示属于当前分类的所有产品。 params哈希中的搜索哈希是通过search => {"price_range_any":["10.00 € EUR - 15.00 € EUR"]}

形式构建的

我不知道。如果我通过删除覆盖切换回原始文件,一切正常。

如何让我的过滤器正常运行?

0 个答案:

没有答案