forty_facets 0.0.1 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ffffd6ffbdfc630f50719b17036d4442aa08a900
4
- data.tar.gz: d2e5c895e6c2ad6f422bca70935a0569d98801f3
3
+ metadata.gz: 3e439d4f05f7a8bfe44665eec3bed14cf9d323e2
4
+ data.tar.gz: c2c5a838fe3489158e5a88947e30cedfe68472b0
5
5
  SHA512:
6
- metadata.gz: 1b863db6fb54e3d392cf23e220bd2513f581a077fee1ad448780d390e54e8f9f443719757f01e136b73a76ee4d1d07c0b10f5fa6c1e868af32a14fba81a17446
7
- data.tar.gz: 09b7f942ae6584790fd6a578af19e2a2046d6bc7dde1753bda80dbc33e40403e5740eaa7dc6587d0c17addb862d7b06dc335a6487f21ca78d2c4bd80859e0d41
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
  ![demo](demo.gif)
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/<my-github-username>/forty_facets/fork )
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 |sum, definition|
173
- sum << definition.build_filter(self, params[definition.request_param])
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
+
@@ -1,3 +1,3 @@
1
1
  module FortyFacets
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.3"
3
3
  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.1
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-15 00:00:00.000000000 Z
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