forty_facets 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +9 -1
- data/forty_facets.gemspec +1 -1
- data/lib/forty_facets/facet_search.rb +93 -10
- data/lib/forty_facets/version.rb +1 -1
- metadata +2 -3
- data/demo.gif +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e439d4f05f7a8bfe44665eec3bed14cf9d323e2
|
4
|
+
data.tar.gz: c2c5a838fe3489158e5a88947e30cedfe68472b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 35018e26f1a6a037cf48d9e48d5df2fcd4df016758b4a5f91314b5f1b7ae6d36c5c91e6bd85d4f372417447fca70545469be79c2f6b8ff74aa94309eecf2d273
|
7
|
+
data.tar.gz: 337b7d8da1cfb036564bb03b1e997e0fd4de8d705d3efab261ec5bd5cc657f21f62a8c0a6f3b0c54b86f377644c35b0e8435ef0dfd7c4ed31555911965306989
|
data/README.md
CHANGED
@@ -4,6 +4,8 @@ FortyFacets lets you easily build explorative search interfaces based on fields
|
|
4
4
|
|
5
5
|

|
6
6
|
|
7
|
+
Try a [working demo](http://forty-facets-demo.herokuapp.com/ "Testinstallation on heroku")!
|
8
|
+
|
7
9
|
It offers a simple API to create an interactive UI to browse your data by iteratively adding
|
8
10
|
filter values.
|
9
11
|
|
@@ -88,9 +90,15 @@ Use the search object to display further narrowing options to the user
|
|
88
90
|
%span.count= "(#{facet_value.count})"
|
89
91
|
```
|
90
92
|
|
93
|
+
## FAQ
|
94
|
+
|
95
|
+
### Can I create filter for `has_many` associations ?
|
96
|
+
|
97
|
+
No. At the moment only objects directly related via a `belongs_to` can be used as filter.
|
98
|
+
|
91
99
|
## Contributing
|
92
100
|
|
93
|
-
1. Fork it ( http://github.com
|
101
|
+
1. Fork it ( http://github.com/fortytools/forty_facets/fork )
|
94
102
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
95
103
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
96
104
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/forty_facets.gemspec
CHANGED
@@ -13,7 +13,7 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.homepage = "https://github.com/fortytools/forty_facets"
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
16
|
-
spec.files = `git ls-files -z`.split("\x0")
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject{|f| f == 'demo.gif'}
|
17
17
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
@@ -1,6 +1,7 @@
|
|
1
1
|
module FortyFacets
|
2
2
|
class FacetSearch
|
3
|
-
attr_reader :filters
|
3
|
+
attr_reader :filters, :orders
|
4
|
+
|
4
5
|
|
5
6
|
FieldDefinition = Struct.new(:search, :model_field, :options) do
|
6
7
|
def request_param
|
@@ -27,6 +28,42 @@ module FortyFacets
|
|
27
28
|
end
|
28
29
|
end
|
29
30
|
|
31
|
+
class RangeField < FieldDefinition
|
32
|
+
class RangeFilter < Filter
|
33
|
+
def build_scope
|
34
|
+
return Proc.new { |base| base } if empty?
|
35
|
+
Proc.new { |base| base.where("#{field_definition.model_field} >= ? AND #{field_definition.model_field} <= ? ", min_value, max_value ) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def min_value
|
39
|
+
return nil if empty?
|
40
|
+
value.split(' - ').first
|
41
|
+
end
|
42
|
+
|
43
|
+
def max_value
|
44
|
+
return nil if empty?
|
45
|
+
value.split(' - ').last
|
46
|
+
end
|
47
|
+
|
48
|
+
def absolute_interval
|
49
|
+
@abosultes ||= without.result.select("min(#{field_definition.model_field}) as min, max(#{field_definition.model_field}) as max").first
|
50
|
+
end
|
51
|
+
|
52
|
+
def absolute_min
|
53
|
+
absolute_interval.min
|
54
|
+
end
|
55
|
+
|
56
|
+
def absolute_max
|
57
|
+
absolute_interval.max
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def build_filter(search_instance, value)
|
63
|
+
RangeFilter.new(self, search_instance, value)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
30
67
|
class TextField < FieldDefinition
|
31
68
|
class TextFilter < Filter
|
32
69
|
def build_scope
|
@@ -42,10 +79,6 @@ module FortyFacets
|
|
42
79
|
"%#{term}%"
|
43
80
|
end
|
44
81
|
end
|
45
|
-
|
46
|
-
def display_value
|
47
|
-
value
|
48
|
-
end
|
49
82
|
end
|
50
83
|
|
51
84
|
def build_filter(search_instance, value)
|
@@ -137,10 +170,40 @@ module FortyFacets
|
|
137
170
|
definitions << TextField.new(self, model_field, opts)
|
138
171
|
end
|
139
172
|
|
173
|
+
def range(model_field, opts = {})
|
174
|
+
definitions << RangeField.new(self, model_field, opts)
|
175
|
+
end
|
176
|
+
|
140
177
|
def facet(model_field, opts = {})
|
141
178
|
definitions << FacetField.new(self, model_field, opts)
|
142
179
|
end
|
143
180
|
|
181
|
+
OrderDefinition = Struct.new(:title, :clause) do
|
182
|
+
def build(search, order_param)
|
183
|
+
Order.new(search, self, order_param == title.to_s)
|
184
|
+
end
|
185
|
+
|
186
|
+
def request_value
|
187
|
+
title
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
Order = Struct.new(:search, :definition, :active) do
|
192
|
+
def title
|
193
|
+
definition.title
|
194
|
+
end
|
195
|
+
|
196
|
+
def by
|
197
|
+
new_params = search.params || {}
|
198
|
+
new_params[:order] = definition.request_value
|
199
|
+
search.class.new_unwrapped(new_params)
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def orders(name_and_order_options)
|
204
|
+
@order_definitions = name_and_order_options.to_a.inject([]) {|ods, no| ods << OrderDefinition.new(no.first, no.last)}
|
205
|
+
end
|
206
|
+
|
144
207
|
def definitions
|
145
208
|
@definitions ||= []
|
146
209
|
end
|
@@ -161,6 +224,10 @@ module FortyFacets
|
|
161
224
|
def request_param_name
|
162
225
|
@request_param_name ||= 'search'
|
163
226
|
end
|
227
|
+
|
228
|
+
def order_definitions
|
229
|
+
@order_definitions
|
230
|
+
end
|
164
231
|
end
|
165
232
|
|
166
233
|
def initialize(request_params)
|
@@ -169,9 +236,14 @@ module FortyFacets
|
|
169
236
|
else
|
170
237
|
{}
|
171
238
|
end
|
172
|
-
@filters = self.class.definitions.inject([]) do |
|
173
|
-
|
239
|
+
@filters = self.class.definitions.inject([]) do |filters, definition|
|
240
|
+
filters << definition.build_filter(self, params[definition.request_param])
|
174
241
|
end
|
242
|
+
|
243
|
+
@orders = self.class.order_definitions.inject([]) do |orders, definition|
|
244
|
+
orders << definition.build(self, params[:order])
|
245
|
+
end
|
246
|
+
|
175
247
|
end
|
176
248
|
|
177
249
|
def self.new_unwrapped(params)
|
@@ -179,13 +251,21 @@ module FortyFacets
|
|
179
251
|
end
|
180
252
|
|
181
253
|
def filter(filter_name)
|
182
|
-
@filters.find { |f| f.field_definition.model_field == filter_name }
|
254
|
+
filter = @filters.find { |f| f.field_definition.model_field == filter_name }
|
255
|
+
raise "unknown filter #{filter_name}" unless filter
|
256
|
+
filter
|
257
|
+
end
|
258
|
+
|
259
|
+
def order
|
260
|
+
@orders.find(&:active)
|
183
261
|
end
|
184
262
|
|
185
263
|
def result
|
186
|
-
@filters.inject(self.class.root_scope) do |previous, filter|
|
264
|
+
query = @filters.inject(self.class.root_scope) do |previous, filter|
|
187
265
|
filter.build_scope.call(previous)
|
188
266
|
end
|
267
|
+
query = query.order(order.definition.clause) if order
|
268
|
+
query
|
189
269
|
end
|
190
270
|
|
191
271
|
def wrapped_params
|
@@ -193,10 +273,12 @@ module FortyFacets
|
|
193
273
|
end
|
194
274
|
|
195
275
|
def params
|
196
|
-
@filters.inject({}) do |sum, filter|
|
276
|
+
params = @filters.inject({}) do |sum, filter|
|
197
277
|
sum[filter.field_definition.request_param] = filter.value.dup unless filter.empty?
|
198
278
|
sum
|
199
279
|
end
|
280
|
+
params[:order] = order.definition.request_value if order
|
281
|
+
params
|
200
282
|
end
|
201
283
|
|
202
284
|
def path
|
@@ -208,3 +290,4 @@ module FortyFacets
|
|
208
290
|
end
|
209
291
|
end
|
210
292
|
end
|
293
|
+
|
data/lib/forty_facets/version.rb
CHANGED
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.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Axel Tetzlaff
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-05-
|
11
|
+
date: 2014-05-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -51,7 +51,6 @@ files:
|
|
51
51
|
- LICENSE.txt
|
52
52
|
- README.md
|
53
53
|
- Rakefile
|
54
|
-
- demo.gif
|
55
54
|
- forty_facets.gemspec
|
56
55
|
- lib/forty_facets.rb
|
57
56
|
- lib/forty_facets/facet_search.rb
|
data/demo.gif
DELETED
Binary file
|