forty_facets 0.0.12 → 0.0.13
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +2 -1
- data/lib/forty_facets/facet_search.rb +13 -3
- data/lib/forty_facets/filter/facet_filter_definition.rb +20 -3
- data/lib/forty_facets/order_definition.rb +16 -1
- data/lib/forty_facets/version.rb +1 -1
- data/test/smoke_test.rb +6 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac056d5510aee76abee5c3eb5f277b3c8ff2c366
|
4
|
+
data.tar.gz: 55eb83dcb730ba5bbccd72b39bbc78eb2277c584
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f55aa94c15b85cef3f8450b21f53fa3597942969c6d9c1585e05e46c3ff9645d120114eba9b7b52ddd0bdac309420a9c69c53d4f98062f120f1427ed69c05c86
|
7
|
+
data.tar.gz: 7c62c3913a5f53c7bc5de3f0dc68338b96176821396adc26b83798989ff8f80eb2a80fea3153be199c76ea926a92b46e86705ffc2af76a70a55da0811b490181
|
data/README.md
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
[![Build Status](https://travis-ci.org/fortytools/forty_facets.svg)](https://travis-ci.org/fortytools/forty_facets)
|
2
2
|
[![Coverage Status](https://coveralls.io/repos/fortytools/forty_facets/badge.png?branch=master)](https://coveralls.io/r/fortytools/forty_facets?branch=master)
|
3
3
|
[![Code Climate](https://codeclimate.com/github/fortytools/forty_facets.png)](https://codeclimate.com/github/fortytools/forty_facets)
|
4
|
+
[![forty_facets API Documentation](https://www.omniref.com/ruby/gems/forty_facets.png)](https://www.omniref.com/ruby/gems/forty_facets)
|
4
5
|
|
5
6
|
# FortyFacets
|
6
7
|
|
7
8
|
FortyFacets lets you easily build explorative search interfaces based on fields of your ActiveRecord models.
|
8
9
|
|
9
|
-
![demo](demo.gif)
|
10
|
+
![demo](https://raw.githubusercontent.com/fortytools/forty_facets/master/demo.gif)
|
10
11
|
|
11
12
|
See it implemented in a [example rails application](https://github.com/fortytools/forty_facets_demo) or
|
12
13
|
try a [working demo](http://forty-facets-demo.herokuapp.com/ "Testinstallation on heroku")!
|
@@ -12,7 +12,8 @@ module FortyFacets
|
|
12
12
|
#
|
13
13
|
# orders 'Title' => :title,
|
14
14
|
# 'price, cheap first' => "price asc",
|
15
|
-
# 'price, expensive first' => {price: :desc, title: :desc}
|
15
|
+
# 'price, expensive first' => {price: :desc, title: :desc},
|
16
|
+
# 'Title, reverse' => {order: "title desc", default: true}
|
16
17
|
#
|
17
18
|
# end
|
18
19
|
class FacetSearch
|
@@ -78,6 +79,11 @@ module FortyFacets
|
|
78
79
|
orders << definition.build(self, params[:order])
|
79
80
|
end
|
80
81
|
|
82
|
+
unless @orders.find(&:active)
|
83
|
+
default_order = @orders.find {|o| o.definition.default}
|
84
|
+
default_order.active = true if default_order
|
85
|
+
end
|
86
|
+
|
81
87
|
@root = root
|
82
88
|
end
|
83
89
|
|
@@ -100,7 +106,7 @@ module FortyFacets
|
|
100
106
|
filter.build_scope.call(previous)
|
101
107
|
end
|
102
108
|
query = query.order(order.definition.clause) if order
|
103
|
-
query
|
109
|
+
query
|
104
110
|
end
|
105
111
|
|
106
112
|
def wrapped_params
|
@@ -117,7 +123,7 @@ module FortyFacets
|
|
117
123
|
end
|
118
124
|
|
119
125
|
def path
|
120
|
-
|
126
|
+
'?' + wrapped_params.to_param
|
121
127
|
end
|
122
128
|
|
123
129
|
def unfiltered?
|
@@ -128,6 +134,10 @@ module FortyFacets
|
|
128
134
|
@root || self.class.root_scope
|
129
135
|
end
|
130
136
|
|
137
|
+
def change_root new_root
|
138
|
+
@root = new_root
|
139
|
+
end
|
140
|
+
|
131
141
|
private
|
132
142
|
|
133
143
|
def request_to_search_params(request_params)
|
@@ -54,13 +54,21 @@ module FortyFacets
|
|
54
54
|
|
55
55
|
def build_scope
|
56
56
|
return Proc.new { |base| base } if empty?
|
57
|
-
Proc.new
|
57
|
+
Proc.new do |base|
|
58
|
+
result = base.joins(definition.joins).where(definition.qualified_column_name => value)
|
59
|
+
if definition.joins
|
60
|
+
result = result.distinct
|
61
|
+
end
|
62
|
+
|
63
|
+
result
|
64
|
+
end
|
58
65
|
end
|
59
66
|
|
60
67
|
def facet
|
61
68
|
my_column = definition.qualified_column_name
|
62
69
|
query = "#{my_column} AS facet_value, count(#{my_column}) AS occurrences"
|
63
70
|
counts = without.result.reorder('').joins(definition.joins).select(query).group(my_column)
|
71
|
+
counts.includes_values = []
|
64
72
|
facet = counts.map do |c|
|
65
73
|
is_selected = selected.include?(c.facet_value)
|
66
74
|
FacetValue.new(c.facet_value, c.occurrences, is_selected)
|
@@ -89,13 +97,21 @@ module FortyFacets
|
|
89
97
|
class BelongsToFilter < AssociationFacetFilter
|
90
98
|
def build_scope
|
91
99
|
return Proc.new { |base| base } if empty?
|
92
|
-
Proc.new
|
100
|
+
Proc.new do |base|
|
101
|
+
result = base.joins(definition.joins).where(definition.qualified_column_name => values)
|
102
|
+
if definition.joins
|
103
|
+
result = result.distinct
|
104
|
+
end
|
105
|
+
|
106
|
+
result
|
107
|
+
end
|
93
108
|
end
|
94
109
|
|
95
110
|
def facet
|
96
111
|
my_column = definition.qualified_column_name
|
97
112
|
query = "#{my_column} AS foreign_id, count(#{my_column}) AS occurrences"
|
98
113
|
counts = without.result.reorder('').joins(definition.joins).select(query).group(my_column)
|
114
|
+
counts.includes_values = []
|
99
115
|
entities_by_id = definition.association.klass.find(counts.map(&:foreign_id)).group_by(&:id)
|
100
116
|
|
101
117
|
facet = counts.map do |count|
|
@@ -120,7 +136,7 @@ module FortyFacets
|
|
120
136
|
subquery = base.joins(definition.joins).select(primary_key_column)
|
121
137
|
.where("#{join_name}.#{definition.association.foreign_key}" => values).uniq
|
122
138
|
|
123
|
-
base.joins(definition.joins).where(primary_key_column => subquery.select(primary_key_column)).
|
139
|
+
base.joins(definition.joins).where(primary_key_column => subquery.select(primary_key_column)).distinct
|
124
140
|
end
|
125
141
|
end
|
126
142
|
|
@@ -134,6 +150,7 @@ module FortyFacets
|
|
134
150
|
.joins(definition.joins)
|
135
151
|
.select("#{my_column} as foreign_id, count(#{my_column}) as occurrences")
|
136
152
|
.group(my_column)
|
153
|
+
counts.includes_values = []
|
137
154
|
entities_by_id = definition.association.klass.find(counts.map(&:foreign_id)).group_by(&:id)
|
138
155
|
|
139
156
|
facet = counts.map do |count|
|
@@ -1,6 +1,21 @@
|
|
1
1
|
module FortyFacets
|
2
2
|
# Stores the parameters of a order criteria for a search.
|
3
|
-
OrderDefinition
|
3
|
+
class OrderDefinition
|
4
|
+
attr(:title, :clause, :default)
|
5
|
+
|
6
|
+
def initialize title, clause
|
7
|
+
@title = title
|
8
|
+
@clause = clause
|
9
|
+
@default = false
|
10
|
+
|
11
|
+
if clause.is_a? Hash
|
12
|
+
if clause[:order] && clause[:default]
|
13
|
+
@clause = clause[:order]
|
14
|
+
@default = clause[:default]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
4
19
|
def build(search, order_param)
|
5
20
|
Order.new(search, self, order_param == title.to_s)
|
6
21
|
end
|
data/lib/forty_facets/version.rb
CHANGED
data/test/smoke_test.rb
CHANGED
@@ -213,4 +213,10 @@ class SmokeTest < Minitest::Test
|
|
213
213
|
|
214
214
|
end
|
215
215
|
|
216
|
+
def test_includes_does_not_blow_up
|
217
|
+
selected_genre = Genre.first
|
218
|
+
search = MovieSearch.new({}, Movie.all.includes(:studio)).filter(:genres).add(selected_genre)
|
219
|
+
search.filter(:studio).facet.reject(&:selected).to_a
|
220
|
+
end
|
221
|
+
|
216
222
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forty_facets
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.13
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Axel Tetzlaff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|