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 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