Skip to content

Commit

Permalink
Merge pull request #2 from fortytools/development
Browse files Browse the repository at this point in the history
merged ordered facet
  • Loading branch information
axelerator committed Jun 2, 2014
2 parents 0e2fc0b + 9f12e14 commit a8c6df5
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 25 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,25 @@ Use the search object to display further narrowing options to the user
= link_to genre.name, filter.add(genre).path
%span.count= "(#{facet_value.count})"
```
## API

### Base class

To create a custom search subclass `FortyFacets::FacetSearch`.

```ruby
class MySearch
model 'MyActiveRecordModel' # replace this with an class name from your models folder
end
```

### Available declaration methods
| keyword | options | |
|---------|---------------|-------------------------------------------------------------------------------------------------------------------------|
| text | prefix:true | creates a filter to limit search result to entities containing the filter value in the given field |
| facet | | creates a facetted filter on the specified model attribute (attribute or belongs_to) |
| range | | creates a range filter (param format 'FROM - TO') limiting result to entities with values in that range |
| orders | | takes a hash mapping a label to an argument that the active record `order` method can be called with to sort the result |

## FAQ

Expand Down
10 changes: 5 additions & 5 deletions lib/forty_facets/facet_search.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,11 @@ def range(model_field, opts = {})
end

def facet(model_field, opts = {})
definitions << BelongsToFilterDefinition.new(self, model_field, opts)
end

def facet_attr(model_field, opts = {})
definitions << AttributeFilterDefinition.new(self, model_field, opts)
if self.root_scope.reflect_on_association(model_field)
definitions << BelongsToFilterDefinition.new(self, model_field, opts)
else
definitions << AttributeFilterDefinition.new(self, model_field, opts)
end
end

def orders(name_and_order_options)
Expand Down
28 changes: 24 additions & 4 deletions lib/forty_facets/filter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ def name
filter_definition.options[:name] || filter_definition.model_field
end

def values
@values ||= Array.wrap(value).sort.uniq
end

def empty?
value.nil? || value == '' || value == []
end
Expand All @@ -24,5 +20,29 @@ def without
search_instance.class.new_unwrapped(new_params)
end
end

# Base class for filter with multiple values and grouped facet values
class FacetFilter < Filter
def values
@values ||= Array.wrap(value).sort.uniq
end

protected

def order_facet!(facet)
order_accessor = filter_definition.options[:order]
if order_accessor
if order_accessor.is_a?(Proc)
facet.sort_by!{|facet_value| order_accessor.call(facet_value.entity) }
else
facet.sort_by!{|facet_value| facet_value.entity.send(order_accessor) }
end
else
facet.sort_by!{|facet_value| -facet_value.count }
end
facet
end

end
end

6 changes: 4 additions & 2 deletions lib/forty_facets/filter/attribute_filter_definition.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module FortyFacets
class AttributeFilterDefinition < FilterDefinition
class AttributeFilter < Filter
class AttributeFilter < FacetFilter
def selected
entity = search_instance.class.root_class
column = entity.columns_hash[filter_definition.model_field.to_s]
Expand All @@ -15,10 +15,12 @@ def build_scope
def facet
my_column = filter_definition.model_field
counts = without.result.reorder('').select("#{my_column} AS facet_value, count(#{my_column}) as occurrences").group(my_column)
counts.map do |c|
facet = counts.map do |c|
is_selected = selected.include?(c.facet_value)
FacetValue.new(c.facet_value, c.occurrences, is_selected)
end

order_facet!(facet)
end

def remove(value)
Expand Down
15 changes: 2 additions & 13 deletions lib/forty_facets/filter/belongs_to_filter_definition.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module FortyFacets
class BelongsToFilterDefinition < FilterDefinition
class FacetFilter < Filter
class BelonsToFilter < FacetFilter
def association
filter_definition.search.root_class.reflect_on_association(filter_definition.model_field)
end
Expand Down Expand Up @@ -48,21 +48,10 @@ def add(entity)
search_instance.class.new_unwrapped(new_params)
end

private

def order_facet!(facet)
order_accessor = filter_definition.options[:order]
if order_accessor
facet.sort_by!{|facet_value| facet_value.entity.send(order_accessor) }
else
facet.sort_by!{|facet_value| -facet_value.count }
end
facet
end
end

def build_filter(search_instance, param_value)
FacetFilter.new(self, search_instance, param_value)
BelonsToFilter.new(self, search_instance, param_value)
end

end
Expand Down
8 changes: 7 additions & 1 deletion test/smoke_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MovieSearch < FortyFacets::FacetSearch

text :title, name: 'Title'
facet :studio, name: 'Studio'
facet_attr :year
facet :year, order: Proc.new {|year| -year}
range :price, name: 'Price'
end

Expand Down Expand Up @@ -116,4 +116,10 @@ def test_belongs_to_filter
assert_equal movies_with_studio.size, first_facet_value.count
end

def test_sort_by_proc
blank_search = MovieSearch.new
facet_entities = blank_search.filter(:year).facet.map(&:entity)
assert_equal Movie.all.map(&:year).sort.uniq.reverse, facet_entities
end

end

0 comments on commit a8c6df5

Please sign in to comment.