@@ -9,46 +9,50 @@ module Core
99 #
1010 # To override this file make a copy of it in lib/spree/core and modify it.
1111
12- # set up some basic filters for use with products
12+ # Each filter has two parts:
1313 #
14- # Each filter has two parts
15- # * a parametrized named scope which expects a list of labels
16- # * an object which describes/defines the filter
14+ # * a parametrized named scope which expects a list of labels
15+ # * an object which describes/defines the filter
1716 #
18- # The filter description has three components
19- # * a name, for displaying on pages
20- # * a named scope which will 'execute' the filter
21- # * a mapping of presentation labels to the relevant condition (in the context of the named scope)
22- # * an optional list of labels and values (for use with object selection - see taxons examples below)
17+ # The filter description has the following components:
2318 #
24- # The named scopes here have a suffix '_any', following Ransack's convention for a
25- # scope which returns results which match any of the inputs. This is purely a convention,
26- # but might be a useful reminder.
19+ # * a name for displaying on pages
20+ # * a named scope which filters the products
21+ # * a mapping of presentation labels to the relevant condition (in the
22+ # context of the named scope)
23+ # * an optional list of labels and values (for use with object selection -
24+ # see taxons examples below)
2725 #
28- # When creating a form, the name of the checkbox group for a filter F should be
29- # the name of F's scope with [] appended, eg "price_range_any[]", and for
30- # each label you should have a checkbox with the label as its value. On submission,
31- # Rails will send the action a hash containing (among other things) an array named
26+ # The named scopes here have a suffix '_any', following Ransack's convention
27+ # for a scope which returns results which match any of the inputs. This is
28+ # purely a convention, but might be a useful reminder.
29+ #
30+ # When creating a form, the name of the checkbox group for a filter F should
31+ # be the name of F's scope with [] appended, e.g. "price_range_any[]", and
32+ # for each label you should have a checkbox with the label as its value. On
33+ # submission, Rails will send the action a hash containing an array named
3234 # after the scope whose values are the active labels.
3335 #
34- # Ransack will then convert this array to a call to the named scope with the array
35- # contents, and the named scope will build a query with the disjunction of the conditions
36- # relating to the labels, all relative to the scope's context.
36+ # Ransack will then convert this array to a call to the named scope with the
37+ # array contents, and the named scope will build a query with the
38+ # disjunction of the conditions relating to the labels, all relative to the
39+ # scope's context.
3740 #
38- # The details of how/when filters are used is a detail for specific models (eg products
39- # or taxons), eg see the taxon model/controller.
40-
41- # See specific filters below for concrete examples.
41+ # The details of how/when filters are used is a detail for specific models.
42+ # For example, see the Taxon model/controller. See specific filters below
43+ # for concrete examples.
4244 module ProductFilters
43- # Example: filtering by price
44- # The named scope just maps incoming labels onto their conditions, and builds the conjunction
45- # 'price' is in the base scope's context (ie, "select foo from products where ...") so
46- # we can access the field right away
47- # The filter identifies which scope to use, then sets the conditions for each price range
45+ # Example: Filtering by price
4846 #
49- # If user checks off three different price ranges then the argument passed to
50- # below scope would be something like ["$10 - $15", "$15 - $18", "$18 - $20"]
47+ # The named scope just maps incoming labels onto their conditions, and
48+ # builds the conjunction 'price' is in the base scope's context (e.g.
49+ # "select foo from products where ...") so we can access the field right
50+ # away. The filter identifies which scope to use, then sets the
51+ # conditions for each price range.
5152 #
53+ # If user checks off three different price ranges then the argument passed
54+ # to below scope would be something like ["$10 - $15", "$15 - $18", "$18 -
55+ # $20"].
5256 Spree ::Product . add_search_scope :price_range_any do |*opts |
5357 conds = opts . map { |element | Spree ::Core ::ProductFilters . price_filter [ :conds ] [ element ] } . reject ( &:nil? )
5458 scope = conds . shift
@@ -78,18 +82,21 @@ def self.price_filter
7882 }
7983 end
8084
81- # Example: filtering by possible brands
85+ # Example: Filtering by possible brands
8286 #
83- # First, we define the scope. Two interesting points here: (a) we run our conditions
84- # in the scope where the info for the 'brand' property has been loaded; and (b)
85- # because we may want to filter by other properties too, we give this part of the
86- # query a unique name (which must be used in the associated conditions too).
87+ # First, we define the scope. Two interesting points here:
8788 #
88- # Secondly, the filter. Instead of a static list of values, we pull out all existing
89- # brands from the db, and then build conditions which test for string equality on
90- # the (uniquely named) field "p_brand.value". There's also a test for brand info
91- # being blank: note that this relies on with_property doing a left outer join
92- # rather than an inner join.
89+ # * we run our conditions in the scope where the info for the 'brand'
90+ # property has been loaded; and
91+ # * because we may want to filter by other properties too, we give this
92+ # part of the query a unique name (which must be used in the
93+ # associated conditions too).
94+ #
95+ # Second, instead of a static list of values, we pull out all existing
96+ # brands from the database. Then we build conditions which test for string
97+ # equality on the (uniquely named) field "p_brand.value". There's also a
98+ # test for brand info being blank. Note that this relies on
99+ # `with_property` doing a left outer join rather than an inner join.
93100 Spree ::Product . add_search_scope :brand_any do |*opts |
94101 conds = opts . map { |value | ProductFilters . brand_filter [ :conds ] [ value ] } . reject ( &:nil? )
95102 scope = conds . shift
@@ -112,25 +119,27 @@ def self.brand_filter
112119 }
113120 end
114121
115- # Example: a parameterized filter
116- # The filter above may show brands which aren't applicable to the current taxon,
117- # so this one only shows the brands that are relevant to a particular taxon and
118- # its descendants.
122+ # Example: A parameterized filter
123+ #
124+ # The filter above may show brands which aren't applicable to the current
125+ # taxon, so this one only shows the brands that are relevant to a
126+ # particular taxon and its descendants.
119127 #
120- # We don't have to give a new scope since the conditions here are a subset of the
121- # more general filter, so decoding will still work - as long as the filters on a
122- # page all have unique names (ie, you can't use the two brand filters together
123- # if they use the same scope). To be safe, the code uses a copy of the scope.
128+ # We don't need to give a new scope since the conditions here are a subset
129+ # of the more general filter, so decoding will still work as long as the
130+ # filters on a page all have unique names (i.e. you can't use the two
131+ # brand filters together if they use the same scope). To be safe, the code
132+ # uses a copy of the scope.
124133 #
125- # HOWEVER: what happens if we want a more precise scope? we can't pass
126- # parametrized scope names to Ransack, only atomic names, so couldn 't ask
127- # for taxon T's customized filter to be used. BUT: we can arrange for the form
128- # to pass back a hash instead of an array, where the key acts as the ( taxon)
129- # parameter and value is its label array, and then get a modified named scope
130- # to get its conditions from a particular filter.
134+ # However, if we want a more precise scope, we can't pass parametrized
135+ # scope names to Ransack, only atomic names. We can 't ask for taxon T's
136+ # customized filter to be used, but we can arrange for the form to pass
137+ # back a hash instead of an array where the key acts as the taxon
138+ # parameter and value is its label array, and then get a modified named
139+ # scope to get its conditions from a particular filter.
131140 #
132- # The brand-finding code can be simplified if a few more named scopes were added to
133- # the product properties model.
141+ # The brand-finding code could be simplified if a few more named scopes
142+ # were added to the product properties model.
134143 Spree ::Product . add_search_scope :selective_brand_any do |*opts |
135144 Spree ::Product . brand_any ( *opts )
136145 end
0 commit comments