forty_facets 0.0.14 → 0.1.0

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: 45710d05be44d2f782e28be3b437560bd1719854
4
- data.tar.gz: d26a2f029858f02ac4f2420843330119f715cbe7
3
+ metadata.gz: 2775c3dbeacb02d6a306671c1f46306f03baaa7c
4
+ data.tar.gz: 007b804dc78ebe61b1aff29a41f276f2986d62ed
5
5
  SHA512:
6
- metadata.gz: 84d1706a3e43d31733b6cc3d47eb10e6e07b1e4b259f37e1430d682e0ef8ed629752f52b160d01cebac6d34e5124599d7ab0a919a48f031ce8205738a087ada2
7
- data.tar.gz: 999adefbe1effdfebf2035c0e417f7e8707adcdd44f7e9cec294d8d4e0638d969be3063295935e953242a3190829ca09e925af8e924816cdbb9252dd4b8bb25d
6
+ metadata.gz: 86d860f3463b9c264010489f2520cf4ac8e216f7f2cfe94ba0e1a5839439e1d799275ccc88281636e5b6a1f0911f26744a826e0a9ca93929eb6c0fb68082800b
7
+ data.tar.gz: 51c6d45ef8c18c8185d142baac5cbb7bccc1cd54888fb2453f7157d9559657b86d151fc72b5da83bf0cb708c456f2691a593b66210b8e63b2f39392a9507489f
data/forty_facets.gemspec CHANGED
@@ -24,5 +24,5 @@ Gem::Specification.new do |spec|
24
24
  spec.add_development_dependency "sqlite3"
25
25
  spec.add_development_dependency "coveralls"
26
26
  spec.add_development_dependency "activerecord", "= 4.1.0"
27
- # spec.add_development_dependency "byebug" # travis doenst like byebug
27
+ #spec.add_development_dependency "byebug" # travis doenst like byebug
28
28
  end
@@ -40,6 +40,10 @@ module FortyFacets
40
40
  definitions << FacetFilterDefinition.new(self, path, opts)
41
41
  end
42
42
 
43
+ def sql_facet(queries, opts = {})
44
+ definitions << SqlFacetFilterDefinition.new(self, queries, opts)
45
+ end
46
+
43
47
  def orders(name_and_order_options)
44
48
  @order_definitions = name_and_order_options.to_a.inject([]) {|ods, no| ods << OrderDefinition.new(no.first, no.last)}
45
49
  end
@@ -0,0 +1,94 @@
1
+ module FortyFacets
2
+ class SqlFacetFilterDefinition < FilterDefinition
3
+ attr_reader(:queries)
4
+
5
+ def initialize(search, queries, opts)
6
+ @search = search
7
+ @queries = queries
8
+ @path = Array(opts[:path]) if opts[:path].present?
9
+ @path ||= @queries.keys
10
+ @options = opts
11
+ end
12
+
13
+ def request_param
14
+ path.join("-")
15
+ end
16
+
17
+ def build_filter(search_instance, param_value)
18
+ ScopeFacetFilter.new(self, search_instance, param_value)
19
+ end
20
+
21
+ class ScopeFacetFilter < Filter
22
+ def values
23
+ @values ||= Array.wrap(value).sort.uniq
24
+ end
25
+
26
+ def build_scope
27
+ return Proc.new { |base| base } if empty?
28
+
29
+ Proc.new do |base|
30
+ # intersection of values and definition queries
31
+ base.where(selected_queries.values.map do |query|
32
+ "(#{query})"
33
+ end.join(" OR "))
34
+ end
35
+ end
36
+
37
+ def selected
38
+ values
39
+ end
40
+
41
+ def remove(value)
42
+ new_params = search_instance.params || {}
43
+ old_values = new_params[definition.request_param]
44
+ old_values.delete(value.to_s)
45
+ new_params.delete(definition.request_param) if old_values.empty?
46
+ search_instance.class.new_unwrapped(new_params, search_instance.root)
47
+ end
48
+
49
+ def add(value)
50
+ new_params = search_instance.params || {}
51
+ old_values = new_params[definition.request_param] ||= []
52
+ old_values << value.to_s
53
+ search_instance.class.new_unwrapped(new_params, search_instance.root)
54
+ end
55
+
56
+ def facet
57
+ query = definition.queries.map do |key, sql_query|
58
+ "(#{sql_query}) as #{key}"
59
+ end.join(", ")
60
+ query += ", count(*) as occurrences"
61
+
62
+ counts = without.result.reorder("")
63
+ .select(query)
64
+ .group(definition.queries.keys)
65
+ counts.includes_values = []
66
+
67
+ result = {}
68
+
69
+ counts.map do |count|
70
+ definition.queries.each do |key, _|
71
+ result[key] ||= 0
72
+ if [1, "1", true].include?(count[key])
73
+ result[key] += count.occurrences
74
+ end
75
+ end
76
+ end
77
+
78
+ result.map do |key, count|
79
+ key = key.to_sym
80
+ is_selected = selected_queries.keys.include?(key)
81
+ FacetValue.new(key, count, is_selected)
82
+ end
83
+ end
84
+
85
+ private
86
+
87
+ def selected_queries
88
+ @selected_queries ||= definition.queries.select do |key, _|
89
+ values.map(&:to_sym).include? key
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -1,3 +1,3 @@
1
1
  module FortyFacets
2
- VERSION = "0.0.14"
2
+ VERSION = "0.1.0"
3
3
  end
data/lib/forty_facets.rb CHANGED
@@ -10,4 +10,5 @@ require "forty_facets/filter_definition"
10
10
  require "forty_facets/filter/range_filter_definition"
11
11
  require "forty_facets/filter/text_filter_definition"
12
12
  require "forty_facets/filter/facet_filter_definition"
13
+ require "forty_facets/filter/sql_facet_filter_definition"
13
14
  require "forty_facets/facet_search"
data/test/fixtures.rb CHANGED
@@ -86,6 +86,9 @@ class Movie < ActiveRecord::Base
86
86
  has_and_belongs_to_many :genres
87
87
  has_and_belongs_to_many :actors
88
88
  has_and_belongs_to_many :writers
89
+
90
+ scope :classics, -> { where("year <= ?", 1980) }
91
+ scope :non_classics, -> { where("year > ?", 1980) }
89
92
  end
90
93
 
91
94
  LOREM = %w{Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren}
@@ -133,7 +136,8 @@ end
133
136
 
134
137
  rand = Random.new
135
138
  LOREM.each_with_index do |title, index|
136
- m = Movie.create!(title: title, studio: studios[index % studios.length], price: rand.rand(20.0), year: (index%3 + 2010) )
139
+ m = Movie.create!(title: title, studio: studios[index % studios.length],
140
+ price: rand.rand(20.0), year: (index + 1975))
137
141
  3.times do
138
142
  actor = actors[rand(actors.length)]
139
143
  unless m.actors.include? actor
data/test/smoke_test.rb CHANGED
@@ -23,6 +23,10 @@ class MovieSearch < FortyFacets::FacetSearch
23
23
  facet [:studio, :country], name: 'Country'
24
24
  facet [:studio, :status], name: 'Studio status'
25
25
  facet [:studio, :producers], name: 'Producers'
26
+ sql_facet({ classic: "year <= 1980", non_classic: "year > 1980" },
27
+ { name: "Classic", path: :classic })
28
+ sql_facet({ classic: "year <= 1980", non_classic: "year > 1980" },
29
+ { name: "Classic" })
26
30
  text [:studio, :description], name: 'Studio Description'
27
31
  end
28
32
 
@@ -33,6 +37,50 @@ class SmokeTest < Minitest::Test
33
37
  assert_equal Movie.all.size, search.result.size
34
38
  end
35
39
 
40
+ def test_scope_filter
41
+ search = MovieSearch.new("search" => {})
42
+ assert_equal 40, search.result.size
43
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
44
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
45
+
46
+ search = MovieSearch.new("search" => { "classic" => "classic" })
47
+ assert_equal 6, search.result.size
48
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
49
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
50
+
51
+ search = MovieSearch.new("search" => { "classic" => "non_classic" })
52
+ assert_equal 34, search.result.size
53
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
54
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
55
+
56
+ search = MovieSearch.new("search" => { "classic" => ["non_classic", "classic"] })
57
+ assert_equal 40, search.result.size
58
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
59
+ assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
60
+ end
61
+
62
+ def test_scope_filter_without_path
63
+ search = MovieSearch.new("search" => {})
64
+ assert_equal 40, search.result.size
65
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
66
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
67
+
68
+ search = MovieSearch.new("search" => { "classic-non_classic" => "classic" })
69
+ assert_equal 6, search.result.size
70
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
71
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
72
+
73
+ search = MovieSearch.new("search" => { "classic-non_classic" => "non_classic" })
74
+ assert_equal 34, search.result.size
75
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
76
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
77
+
78
+ search = MovieSearch.new("search" => { "classic-non_classic" => ["non_classic", "classic"] })
79
+ assert_equal 40, search.result.size
80
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
81
+ assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
82
+ end
83
+
36
84
  def test_text_filter
37
85
  search = MovieSearch.new({'search' => { 'title' => 'ipsum' }})
38
86
  assert_equal 1, search.result.size
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.14
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Axel Tetzlaff
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-27 00:00:00.000000000 Z
11
+ date: 2015-03-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -117,6 +117,7 @@ files:
117
117
  - lib/forty_facets/filter.rb
118
118
  - lib/forty_facets/filter/facet_filter_definition.rb
119
119
  - lib/forty_facets/filter/range_filter_definition.rb
120
+ - lib/forty_facets/filter/sql_facet_filter_definition.rb
120
121
  - lib/forty_facets/filter/text_filter_definition.rb
121
122
  - lib/forty_facets/filter_definition.rb
122
123
  - lib/forty_facets/order.rb