forty_facets 0.1.8.9 → 0.2

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
  SHA256:
3
- metadata.gz: ce24e462cc7ee4e339d052120807239c0e4406faa14c2be784ae41548bcbc18a
4
- data.tar.gz: ab5d0fa8bf95ca88d5071ae74084bf56c3baae9c4a9af40dbd10fd5bf6f29132
3
+ metadata.gz: 145715b5814badb1b542b7eac19af6683c1c624e55aeeb4cd65a3f7e69d84d1a
4
+ data.tar.gz: bfc630bf7222be66578beca4923982e7172343fdf08f7b932819eb73f7072e7e
5
5
  SHA512:
6
- metadata.gz: 3e49b4403a1be6a802f1f9e492ca8753a64ee0d1bc5f39b1c254880b3f75baf7e52448cc81e7f530c37e59a6a5c9e5067fcb537bbe9a7b99fd0f7753c96c90b3
7
- data.tar.gz: 585d41f4b4b55c09c8af4a51ac755951174c67e528187910e025d001fa147d2e3dd3752c1e2856d04f66c50ac6c09a7fba888363d2d5b2f456003fb0fb3265db
6
+ metadata.gz: 216b8f57082cd4d8b820484d089e47cde6e97ac21be0f9dd7761db01a150b30d110888d9826d617b6f9b8612880e446b5ffe86f0fddbdb7dddabe500d188d6c2
7
+ data.tar.gz: e635009e28fb7ec381295405d402f7026e9a3ca49eead6cd8541a93eea586734333eb9e60982e98fdd052869d4451fc32705d6045c328400cf3e3d7f8f07965c
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 3.1.2
data/CHANGELOG ADDED
@@ -0,0 +1,8 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.2
4
+
5
+ - introduction of CHANGELOG
6
+ - upgraded to Ruby 3.1
7
+ - upgraded to ActiveRecrd/Rails 7
8
+ - merged #27
data/forty_facets.gemspec CHANGED
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_development_dependency "bundler", "~> 1.5"
21
+ spec.add_development_dependency "bundler"
22
22
  spec.add_development_dependency "rake"
23
23
  spec.add_development_dependency "minitest"
24
24
  spec.add_development_dependency "sqlite3"
25
25
  spec.add_development_dependency "coveralls"
26
- spec.add_development_dependency "activerecord", "~> 5.0"
26
+ spec.add_development_dependency "activerecord", "~> 7.0"
27
27
  spec.add_development_dependency "byebug" # travis doenst like byebug
28
28
  end
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FortyFacets
2
4
  class FacetFilterDefinition < FilterDefinition
3
-
4
5
  class FacetFilter < Filter
5
6
  def values
6
7
  @values ||= Array.wrap(value).sort.uniq
@@ -12,12 +13,12 @@ module FortyFacets
12
13
  order_accessor = definition.options[:order]
13
14
  if order_accessor
14
15
  if order_accessor.is_a?(Proc)
15
- facet.sort_by!{|facet_value| order_accessor.call(facet_value.entity) }
16
+ facet.sort_by! { |facet_value| order_accessor.call(facet_value.entity) }
16
17
  else
17
- facet.sort_by!{|facet_value| facet_value.entity.send(order_accessor) }
18
+ facet.sort_by! { |facet_value| facet_value.entity.send(order_accessor) }
18
19
  end
19
20
  else
20
- facet.sort_by!{|facet_value| -facet_value.count }
21
+ facet.sort_by! { |facet_value| -facet_value.count }
21
22
  end
22
23
  facet
23
24
  end
@@ -25,7 +26,7 @@ module FortyFacets
25
26
 
26
27
  class AssociationFacetFilter < FacetFilter
27
28
  def selected
28
- @selected ||= definition.association.klass.find(Array.wrap(values).reject(&:blank?))
29
+ @selected ||= definition.association.klass.unscoped.find(Array.wrap(values).reject(&:blank?))
29
30
  end
30
31
 
31
32
  def remove(entity)
@@ -49,12 +50,14 @@ module FortyFacets
49
50
  def selected
50
51
  entity = definition.origin_class
51
52
  column = entity.columns_hash[definition.attribute.to_s]
52
- values.map{|v| entity.connection.type_cast(v, column)}
53
+ type = entity.connection.lookup_cast_type_from_column(column)
54
+ values.map { |value| type.serialize(value) }
53
55
  end
54
56
 
55
57
  def build_scope
56
- return Proc.new { |base| base } if empty?
57
- Proc.new do |base|
58
+ return proc { |base| base } if empty?
59
+
60
+ proc do |base|
58
61
  base.joins(definition.joins).where(definition.qualified_column_name => value)
59
62
  end
60
63
  end
@@ -90,8 +93,9 @@ module FortyFacets
90
93
 
91
94
  class BelongsToFilter < AssociationFacetFilter
92
95
  def build_scope
93
- return Proc.new { |base| base } if empty?
94
- Proc.new do |base|
96
+ return proc { |base| base } if empty?
97
+
98
+ proc do |base|
95
99
  base.joins(definition.joins).where(definition.qualified_column_name => values)
96
100
  end
97
101
  end
@@ -101,7 +105,7 @@ module FortyFacets
101
105
  query = "#{my_column} AS foreign_id, count(#{my_column}) AS occurrences"
102
106
  counts = without.result(skip_ordering: true).distinct.joins(definition.joins).select(query).group(my_column)
103
107
  counts.includes_values = []
104
- entities_by_id = definition.association.klass.find(counts.map(&:foreign_id)).group_by(&:id)
108
+ entities_by_id = definition.association.klass.unscoped.find(counts.map(&:foreign_id)).group_by(&:id)
105
109
 
106
110
  facet = counts.map do |count|
107
111
  facet_entity = entities_by_id[count.foreign_id].first
@@ -115,8 +119,9 @@ module FortyFacets
115
119
 
116
120
  class HasManyFilter < AssociationFacetFilter
117
121
  def build_scope
118
- return Proc.new { |base| base } if empty?
119
- Proc.new do |base|
122
+ return proc { |base| base } if empty?
123
+
124
+ proc do |base|
120
125
  base_table = definition.origin_class.table_name
121
126
 
122
127
  primary_key_column = "#{base_table}.#{definition.origin_class.primary_key}"
@@ -130,15 +135,15 @@ module FortyFacets
130
135
  def facet
131
136
  base_table = definition.search.root_class.table_name
132
137
  join_name = [definition.association.name.to_s, base_table.to_s].sort.join('_')
133
- foreign_id_col = definition.association.name.to_s.singularize + '_id'
134
- my_column = join_name + '.' + foreign_id_col
138
+ foreign_id_col = "#{definition.association.name.to_s.singularize}_id"
139
+ my_column = "#{join_name}.#{foreign_id_col}"
135
140
  counts = without.result(skip_ordering: true)
136
- .distinct
137
- .joins(definition.joins)
138
- .select("#{my_column} as foreign_id, count(#{my_column}) as occurrences")
139
- .group(my_column)
141
+ .distinct
142
+ .joins(definition.joins)
143
+ .select("#{my_column} as foreign_id, count(#{my_column}) as occurrences")
144
+ .group(my_column)
140
145
  counts.includes_values = []
141
- entities_by_id = definition.association.klass.find(counts.map(&:foreign_id)).group_by(&:id)
146
+ entities_by_id = definition.association.klass.unscoped.find(counts.map(&:foreign_id)).group_by(&:id)
142
147
 
143
148
  facet = counts.map do |count|
144
149
  facet_entity = entities_by_id[count.foreign_id].first
@@ -152,11 +157,12 @@ module FortyFacets
152
157
 
153
158
  def build_filter(search_instance, param_value)
154
159
  if association
155
- if association.macro == :belongs_to
160
+ case association.macro
161
+ when :belongs_to
156
162
  BelongsToFilter.new(self, search_instance, param_value)
157
- elsif association.macro == :has_many
163
+ when :has_many
158
164
  HasManyFilter.new(self, search_instance, param_value)
159
- elsif association.macro == :has_and_belongs_to_many
165
+ when :has_and_belongs_to_many
160
166
  HasManyFilter.new(self, search_instance, param_value)
161
167
  else
162
168
  raise "Unsupported association type: #{association.macro}"
@@ -1,23 +1,27 @@
1
1
  module FortyFacets
2
2
  class RangeFilterDefinition < FilterDefinition
3
3
  class RangeFilter < Filter
4
+ RANGE_REGEX = /(\d*) - (\d*)/.freeze
5
+
4
6
  def build_scope
5
7
  return Proc.new { |base| base } if empty?
6
8
 
7
9
  Proc.new do |base|
8
- base.joins(definition.joins)
9
- .where("#{definition.qualified_column_name} >= ? AND #{definition.qualified_column_name} <= ? ", min_value, max_value )
10
+ scope = base.joins(definition.joins)
11
+ scope = scope.where("#{definition.qualified_column_name} >= ?", min_value) if min_value.present?
12
+ scope = scope.where("#{definition.qualified_column_name} <= ?", max_value) if max_value.present?
13
+ scope
10
14
  end
11
15
  end
12
16
 
13
17
  def min_value
14
- return nil if empty?
15
- value.split(' - ').first
18
+ min, _max = range_values
19
+ min
16
20
  end
17
21
 
18
22
  def max_value
19
- return nil if empty?
20
- value.split(' - ').last
23
+ _min, max = range_values
24
+ max
21
25
  end
22
26
 
23
27
  def absolute_interval
@@ -32,6 +36,11 @@ module FortyFacets
32
36
  absolute_interval.max
33
37
  end
34
38
 
39
+ private
40
+
41
+ def range_values
42
+ value&.match(RANGE_REGEX)&.captures
43
+ end
35
44
  end
36
45
 
37
46
  def build_filter(search_instance, value)
@@ -2,7 +2,7 @@ module FortyFacets
2
2
  class ScopeFilterDefinition < FilterDefinition
3
3
  class ScopeFilter < Filter
4
4
  def active?
5
- definition.options[:pass_value] ? value.present? : '1'
5
+ definition.options[:pass_value] ? value.present? : value == '1'
6
6
  end
7
7
 
8
8
  def selected
@@ -28,7 +28,7 @@ module FortyFacets
28
28
  search_instance.class.new_unwrapped(new_params, search_instance.root)
29
29
  end
30
30
 
31
- def add(value = nil)
31
+ def add(value = '1')
32
32
  new_params = search_instance.params || {}
33
33
  new_params[definition.request_param] = value
34
34
  search_instance.class.new_unwrapped(new_params, search_instance.root)
@@ -38,7 +38,5 @@ module FortyFacets
38
38
  def build_filter(search_instance, value)
39
39
  ScopeFilter.new(self, search_instance, value)
40
40
  end
41
-
42
41
  end
43
42
  end
44
-
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FortyFacets
2
- VERSION = "0.1.8.9"
4
+ VERSION = '0.2'
3
5
  end
data/test/fixtures.rb CHANGED
@@ -14,6 +14,7 @@ ActiveRecord::Schema.define do
14
14
  t.string :status
15
15
  t.string :name
16
16
  t.string :description
17
+ t.datetime :deleted_at
17
18
  end
18
19
 
19
20
  create_table :producers do |t|
@@ -79,10 +80,13 @@ end
79
80
  class Studio < ActiveRecord::Base
80
81
  belongs_to :country
81
82
  has_and_belongs_to_many :producers
83
+
84
+ default_scope ->{ where(deleted_at: nil) }
85
+ scope :with_deleted, ->{ unscope(where: :deleted_at) }
82
86
  end
83
87
 
84
88
  class Movie < ActiveRecord::Base
85
- belongs_to :studio
89
+ belongs_to :studio, ->{ with_deleted }
86
90
  has_and_belongs_to_many :genres
87
91
  has_and_belongs_to_many :actors
88
92
  has_and_belongs_to_many :writers
data/test/smoke_test.rb CHANGED
@@ -1,46 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'coveralls'
2
4
  Coveralls.wear!
3
5
 
4
- require "minitest/autorun"
6
+ require 'minitest/autorun'
7
+ require 'test_helper'
5
8
  require 'logger'
6
- #require 'byebug'# travis doenst like byebug
9
+ # require 'byebug'# travis doenst like byebug
7
10
  require_relative '../lib/forty_facets'
8
11
 
9
- #silence_warnings do
12
+ # silence_warnings do
10
13
  require_relative 'fixtures'
11
- #end
14
+ # end
12
15
 
13
16
  class MovieSearch < FortyFacets::FacetSearch
14
17
  model 'Movie'
15
18
 
16
19
  text :title, name: 'Title'
17
20
  facet :studio, name: 'Studio'
18
- facet :year, order: Proc.new {|year| -year}
21
+ facet :year, order: proc { |year| -year }
19
22
  facet :genres, name: 'Genre'
20
23
  facet :actors, name: 'Actor'
21
24
  range :price, name: 'Price'
22
25
  facet :writers, name: 'Writer'
23
- facet [:studio, :country], name: 'Country'
24
- facet [:studio, :status], name: 'Studio status'
25
- facet [:studio, :producers], name: 'Producers'
26
+ facet %i[studio country], name: 'Country'
27
+ facet %i[studio status], name: 'Studio status'
28
+ facet %i[studio producers], name: 'Producers'
26
29
  sql_facet({ uschis: "studios.name = 'Uschi'", non_uschis: "studios.name != 'USCHI'" },
27
- { name: "Uschis", path: [:studio, :uschis], joins: [:studio] })
28
- sql_facet({ classic: "year <= 1980", non_classic: "year > 1980" },
29
- { name: "Classic", path: :classic })
30
- sql_facet({ classic: "year <= 1980", non_classic: "year > 1980" },
31
- { name: "Classic" })
32
- text [:studio, :description], name: 'Studio Description'
30
+ { name: 'Uschis', path: %i[studio uschis], joins: [:studio] })
31
+ sql_facet({ classic: 'year <= 1980', non_classic: 'year > 1980' },
32
+ { name: 'Classic', path: :classic })
33
+ sql_facet({ classic: 'year <= 1980', non_classic: 'year > 1980' },
34
+ { name: 'Classic' })
35
+ text %i[studio description], name: 'Studio Description'
33
36
  scope :classics, name: 'Name classics'
34
37
  scope :year_lte, name: 'Year less than or equal', pass_value: true
35
38
  custom :needs_complex_filtering
36
39
  end
37
40
 
38
41
  class SmokeTest < Minitest::Test
39
-
40
42
  def test_sql_facet_with_belongs_to
41
- search = MovieSearch.new({'studio-uschis' => {}})
43
+ search = MovieSearch.new({ 'studio-uschis' => {} })
42
44
  assert_equal Movie.count, search.result.size
43
- assert_equal search.filter([:studio, :uschis]).facet, [FortyFacets::FacetValue.new(:uschis, 0, false), FortyFacets::FacetValue.new(:non_uschis, 40, false)]
45
+ assert_equal search.filter(%i[studio uschis]).facet,
46
+ [FortyFacets::FacetValue.new(:uschis, 0, false), FortyFacets::FacetValue.new(:non_uschis, 40, false)]
44
47
  end
45
48
 
46
49
  def test_it_finds_all_movies
@@ -49,57 +52,57 @@ class SmokeTest < Minitest::Test
49
52
  end
50
53
 
51
54
  def test_scope_filter
52
- search = MovieSearch.new("search" => {})
55
+ search = MovieSearch.new('search' => {})
53
56
  assert_equal 40, search.result.size
54
57
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
55
58
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
56
59
 
57
- search = MovieSearch.new("search" => { "classic" => "classic" })
60
+ search = MovieSearch.new('search' => { 'classic' => 'classic' })
58
61
  assert_equal 6, search.result.size
59
62
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
60
63
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
61
64
 
62
- search = MovieSearch.new("search" => { "classic" => "non_classic" })
65
+ search = MovieSearch.new('search' => { 'classic' => 'non_classic' })
63
66
  assert_equal 34, search.result.size
64
67
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
65
68
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
66
69
 
67
- search = MovieSearch.new("search" => { "classic" => ["non_classic", "classic"] })
70
+ search = MovieSearch.new('search' => { 'classic' => %w[non_classic classic] })
68
71
  assert_equal 40, search.result.size
69
72
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
70
73
  assert search.filter(:classic).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
71
74
  end
72
75
 
73
76
  def test_scope_filter_without_path
74
- search = MovieSearch.new("search" => {})
77
+ search = MovieSearch.new('search' => {})
75
78
  assert_equal 40, search.result.size
76
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
77
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
79
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
80
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
78
81
 
79
- search = MovieSearch.new("search" => { "classic-non_classic" => "classic" })
82
+ search = MovieSearch.new('search' => { 'classic-non_classic' => 'classic' })
80
83
  assert_equal 6, search.result.size
81
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
82
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
84
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
85
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, false)
83
86
 
84
- search = MovieSearch.new("search" => { "classic-non_classic" => "non_classic" })
87
+ search = MovieSearch.new('search' => { 'classic-non_classic' => 'non_classic' })
85
88
  assert_equal 34, search.result.size
86
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
87
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
89
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, false)
90
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
88
91
 
89
- search = MovieSearch.new("search" => { "classic-non_classic" => ["non_classic", "classic"] })
92
+ search = MovieSearch.new('search' => { 'classic-non_classic' => %w[non_classic classic] })
90
93
  assert_equal 40, search.result.size
91
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
92
- assert search.filter([:classic, :non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
94
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:classic, 6, true)
95
+ assert search.filter(%i[classic non_classic]).facet.include? FortyFacets::FacetValue.new(:non_classic, 34, true)
93
96
  end
94
97
 
95
98
  def test_text_filter
96
- search = MovieSearch.new({'search' => { 'title' => 'ipsum' }})
99
+ search = MovieSearch.new({ 'search' => { 'title' => 'ipsum' } })
97
100
  assert_equal 1, search.result.size
98
101
  assert_equal 'ipsum', search.result.first.title
99
102
  end
100
103
 
101
104
  def test_year_filter
102
- search = MovieSearch.new({'search' => { 'year' => '2011' }})
105
+ search = MovieSearch.new({ 'search' => { 'year' => '2011' } })
103
106
  assert_equal [2011], search.result.map(&:year).uniq
104
107
 
105
108
  facet = search.filter(:year).facet
@@ -107,34 +110,43 @@ class SmokeTest < Minitest::Test
107
110
  end
108
111
 
109
112
  def test_range_filter
110
- search = MovieSearch.new({'search' => {'price' => '0 - 20'}})
113
+ search = MovieSearch.new({ 'search' => { 'price' => '0 - 20' } })
111
114
  assert_equal Movie.count, search.result.size
112
115
 
113
- search = MovieSearch.new({'search' => {'price' => '0 - 10'}})
114
- assert_equal Movie.all.reject{|m| m.price > 10}.size, search.result.size
116
+ search = MovieSearch.new({ 'search' => { 'price' => '5 - 10' } })
117
+ assert_equal Movie.where('price >= ? AND price <= ?', 5, 10).count, search.result.size
118
+
119
+ search = MovieSearch.new({ 'search' => { 'price' => '5 - ' } })
120
+ assert_equal Movie.where('price >= ?', 5).count, search.result.size
121
+
122
+ search = MovieSearch.new({ 'search' => { 'price' => ' - 5' } })
123
+ assert_equal Movie.where('price <= ?', 5).count, search.result.size
124
+
125
+ search = MovieSearch.new({ 'search' => { 'price' => '' } })
126
+ assert_equal Movie.count, search.result.size
115
127
  end
116
128
 
117
129
  def test_text_filter_via_belongs_to
118
130
  description = Studio.first.description
119
- search = MovieSearch.new({'search' => { 'studio-description' => description }})
131
+ search = MovieSearch.new({ 'search' => { 'studio-description' => description } })
120
132
 
121
- assert_equal Movie.all.reject{|m| m.studio.description != description}.size, search.result.size
133
+ assert_equal Movie.all.select { |m| m.studio.description == description }.size, search.result.size
122
134
  assert_equal description, search.result.first.studio.description
123
135
  end
124
136
 
125
137
  def test_country_filter
126
- search = MovieSearch.new('search' => { 'studio-country' => Country.first.id.to_s})
127
- assert_equal [Country.first], search.result.map{|m| m.studio.country}.uniq
138
+ search = MovieSearch.new('search' => { 'studio-country' => Country.first.id.to_s })
139
+ assert_equal [Country.first], search.result.map { |m| m.studio.country }.uniq
128
140
  assert_equal Movie.count / 2, search.result.count
129
141
 
130
- search = MovieSearch.new('search' => { 'studio-country' => Country.last.id.to_s})
131
- assert_equal [Country.last], search.result.map{|m| m.studio.country}.uniq
142
+ search = MovieSearch.new('search' => { 'studio-country' => Country.last.id.to_s })
143
+ assert_equal [Country.last], search.result.map { |m| m.studio.country }.uniq
132
144
  assert_equal Movie.count / 2, search.result.count
133
145
  end
134
146
 
135
147
  def test_selected_country_filter
136
- search = MovieSearch.new('search' => { 'studio-country' => Country.first.id.to_s})
137
- filter = search.filter([:studio, :country])
148
+ search = MovieSearch.new('search' => { 'studio-country' => Country.first.id.to_s })
149
+ filter = search.filter(%i[studio country])
138
150
  assert_equal FortyFacets::FacetFilterDefinition::BelongsToFilter, filter.class
139
151
  assert_equal [Country.first], filter.selected
140
152
 
@@ -142,17 +154,16 @@ class SmokeTest < Minitest::Test
142
154
  end
143
155
 
144
156
  def test_studio_status_filter
145
- search = MovieSearch.new('search' => { 'studio-status' => 'active'})
146
- assert_equal ['active'], search.result.map{|m| m.studio.status}.uniq
157
+ search = MovieSearch.new('search' => { 'studio-status' => 'active' })
158
+ assert_equal ['active'], search.result.map { |m| m.studio.status }.uniq
147
159
  assert_equal Movie.count / 2, search.result.count
148
160
 
149
- filter = search.filter([:studio, :status])
161
+ filter = search.filter(%i[studio status])
150
162
  assert_equal ['active'], filter.selected
151
163
  end
152
164
 
153
165
  def test_year_add_remove_filter
154
-
155
- search = MovieSearch.new()
166
+ search = MovieSearch.new
156
167
 
157
168
  search = search.filter(:year).add(2010)
158
169
  assert_equal Movie.where(year: 2010).count, search.result.count
@@ -165,7 +176,7 @@ class SmokeTest < Minitest::Test
165
176
  end
166
177
 
167
178
  def test_selected_year_filter
168
- search = MovieSearch.new()
179
+ search = MovieSearch.new
169
180
 
170
181
  search = search.filter(:year).add(2010)
171
182
  assert_equal [2010], search.filter(:year).selected
@@ -174,9 +185,9 @@ class SmokeTest < Minitest::Test
174
185
  assert_equal [2010, 2011], search.filter(:year).selected
175
186
 
176
187
  facet = search.filter(:year).facet
177
- assert facet.find{|fv| fv.entity == 2010}.selected
178
- assert facet.find{|fv| fv.entity == 2011}.selected
179
- assert !facet.find{|fv| fv.entity == 2012}.selected
188
+ assert facet.find { |fv| fv.entity == 2010 }.selected
189
+ assert facet.find { |fv| fv.entity == 2011 }.selected
190
+ assert !facet.find { |fv| fv.entity == 2012 }.selected
180
191
  end
181
192
 
182
193
  def test_belongs_to_filter
@@ -185,13 +196,27 @@ class SmokeTest < Minitest::Test
185
196
  studio = first_facet_value.entity
186
197
  assert_kind_of Studio, studio
187
198
 
188
- movies_with_studio = Movie.where(studio: studio)
199
+ movies_with_studio = Movie.where(studio:)
189
200
  search_with_studio = blank_search.filter(:studio).add(studio)
190
201
 
191
202
  assert_equal movies_with_studio.size, search_with_studio.result.size
192
203
  assert_equal movies_with_studio.size, first_facet_value.count
193
204
  end
194
205
 
206
+ def test_belongs_to_filter_with_default_scope
207
+ wrap_in_db_transaction do
208
+ deleted_studio = Studio.create!(name: 'Deleted studio', status: 'active')
209
+ Movie.create!(studio: deleted_studio)
210
+ deleted_studio.update!(deleted_at: Time.now)
211
+
212
+ blank_search = MovieSearch.new
213
+
214
+ assert_equal(
215
+ 5, blank_search.filter(:studio).facet.length
216
+ )
217
+ end
218
+ end
219
+
195
220
  def test_sort_by_proc
196
221
  blank_search = MovieSearch.new
197
222
  facet_entities = blank_search.filter(:year).facet.map(&:entity)
@@ -201,7 +226,7 @@ class SmokeTest < Minitest::Test
201
226
  def test_has_many
202
227
  blank_search = MovieSearch.new
203
228
  genre = Genre.first
204
- expected = Movie.order(:id).select{|m| m.genres.include?(genre)}
229
+ expected = Movie.order(:id).select { |m| m.genres.include?(genre) }
205
230
  assert blank_search.filter(:genres).is_a?(FortyFacets::FacetFilterDefinition::HasManyFilter)
206
231
  search = blank_search.filter(:genres).add(genre)
207
232
  actual = search.result
@@ -212,9 +237,9 @@ class SmokeTest < Minitest::Test
212
237
  def test_hast_many_via_belongs_to
213
238
  blank_search = MovieSearch.new
214
239
  producer = Producer.first
215
- expected = Movie.order(:id).select{|m| m.studio.producers.include? producer}
216
- assert blank_search.filter([:studio, :producers]).is_a?(FortyFacets::FacetFilterDefinition::HasManyFilter)
217
- search = blank_search.filter([:studio, :producers]).add(producer)
240
+ expected = Movie.order(:id).select { |m| m.studio.producers.include? producer }
241
+ assert blank_search.filter(%i[studio producers]).is_a?(FortyFacets::FacetFilterDefinition::HasManyFilter)
242
+ search = blank_search.filter(%i[studio producers]).add(producer)
218
243
  actual = search.result
219
244
 
220
245
  assert_equal expected.size, actual.size
@@ -223,7 +248,7 @@ class SmokeTest < Minitest::Test
223
248
  def test_has_many_writers
224
249
  blank_search = MovieSearch.new
225
250
  writer = Writer.first
226
- expected = Movie.order(:id).select{|m| m.writers.include?(writer)}
251
+ expected = Movie.order(:id).select { |m| m.writers.include?(writer) }
227
252
  assert blank_search.filter(:writers).is_a?(FortyFacets::FacetFilterDefinition::HasManyFilter)
228
253
  search = blank_search.filter(:writers).add(writer)
229
254
  actual = search.result
@@ -236,8 +261,8 @@ class SmokeTest < Minitest::Test
236
261
  genre = Genre.first
237
262
  actor = Actor.first
238
263
  expected = Movie.order(:id)
239
- .select{|m| m.genres.include?(genre)}
240
- .select{|m| m.actors.include?(actor)}
264
+ .select { |m| m.genres.include?(genre) }
265
+ .select { |m| m.actors.include?(actor) }
241
266
  assert blank_search.filter(:genres).is_a?(FortyFacets::FacetFilterDefinition::HasManyFilter)
242
267
  search_with_genre = blank_search.filter(:genres).add(genre)
243
268
  search_with_genre_and_actor = search_with_genre.filter(:actors).add(actor)
@@ -252,11 +277,11 @@ class SmokeTest < Minitest::Test
252
277
 
253
278
  search.filter(:writers).facet.each do |facet_value|
254
279
  writer = facet_value.entity
255
- expected = Movie.order(:id).select{|m| m.writers.include?(writer)}.count
256
- assert_equal expected, facet_value.count, "The amount of movies for a writer should match the number indicated in the facet"
280
+ expected = Movie.order(:id).select { |m| m.writers.include?(writer) }.count
281
+ assert_equal expected, facet_value.count,
282
+ 'The amount of movies for a writer should match the number indicated in the facet'
257
283
  assert_equal writer.id == selected_writer.id, facet_value.selected
258
284
  end
259
-
260
285
  end
261
286
 
262
287
  def test_has_many_facet_values_genres
@@ -265,11 +290,11 @@ class SmokeTest < Minitest::Test
265
290
 
266
291
  search.filter(:genres).facet.each do |facet_value|
267
292
  genre = facet_value.entity
268
- expected = Movie.order(:id).select{|m| m.genres.include?(genre)}.count
269
- assert_equal expected, facet_value.count, "The amount of movies for a genre should match the number indicated in the facet"
293
+ expected = Movie.order(:id).select { |m| m.genres.include?(genre) }.count
294
+ assert_equal expected, facet_value.count,
295
+ 'The amount of movies for a genre should match the number indicated in the facet'
270
296
  assert_equal genre.id == selected_genre.id, facet_value.selected
271
297
  end
272
-
273
298
  end
274
299
 
275
300
  def test_includes_does_not_blow_up
@@ -278,14 +303,15 @@ class SmokeTest < Minitest::Test
278
303
  search.filter(:studio).facet.reject(&:selected).to_a
279
304
  end
280
305
 
281
- def test_scope_filter
282
- search_with_scope = MovieSearch.new().filter(:classics).add('1')
306
+ def test_activating_scope_filter
307
+ search_with_scope = MovieSearch.new.filter(:classics).add('1')
283
308
  assert search_with_scope.result.count < Movie.count, 'Activating the scope should yield a smaller set of movies'
284
309
  end
285
310
 
286
311
  def test_scope_filter_with_params
287
- search_with_scope = MovieSearch.new().filter(:year_lte).add(1980)
288
- assert search_with_scope.result.count < Movie.count, 'Activating the scope with filter should yield a smaller set of movies'
312
+ search_with_scope = MovieSearch.new.filter(:year_lte).add(1980)
313
+ assert search_with_scope.result.count < Movie.count,
314
+ 'Activating the scope with filter should yield a smaller set of movies'
289
315
  end
290
316
 
291
317
  def test_custom_filter
@@ -294,5 +320,4 @@ class SmokeTest < Minitest::Test
294
320
 
295
321
  assert_equal 'foo', new_search.filter(:needs_complex_filtering).value
296
322
  end
297
-
298
323
  end
data/test/test_helper.rb CHANGED
@@ -0,0 +1,8 @@
1
+ class Minitest::Test
2
+ def wrap_in_db_transaction(&block)
3
+ ActiveRecord::Base.transaction do
4
+ yield
5
+ raise ActiveRecord::Rollback
6
+ end
7
+ end
8
+ end
metadata CHANGED
@@ -1,29 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forty_facets
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8.9
4
+ version: '0.2'
5
5
  platform: ruby
6
6
  authors:
7
7
  - Axel Tetzlaff
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-11-19 00:00:00.000000000 Z
11
+ date: 2022-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: '1.5'
19
+ version: '0'
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: '1.5'
26
+ version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rake
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -86,14 +86,14 @@ dependencies:
86
86
  requirements:
87
87
  - - "~>"
88
88
  - !ruby/object:Gem::Version
89
- version: '5.0'
89
+ version: '7.0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
94
  - - "~>"
95
95
  - !ruby/object:Gem::Version
96
- version: '5.0'
96
+ version: '7.0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: byebug
99
99
  requirement: !ruby/object:Gem::Requirement
@@ -121,6 +121,7 @@ files:
121
121
  - ".ruby-gemset"
122
122
  - ".ruby-version"
123
123
  - ".travis.yml"
124
+ - CHANGELOG
124
125
  - Gemfile
125
126
  - LICENSE.txt
126
127
  - README.md
@@ -146,7 +147,7 @@ homepage: https://github.com/fortytools/forty_facets
146
147
  licenses:
147
148
  - MIT
148
149
  metadata: {}
149
- post_install_message:
150
+ post_install_message:
150
151
  rdoc_options: []
151
152
  require_paths:
152
153
  - lib
@@ -161,9 +162,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
161
162
  - !ruby/object:Gem::Version
162
163
  version: '0'
163
164
  requirements: []
164
- rubyforge_project:
165
- rubygems_version: 2.7.6
166
- signing_key:
165
+ rubygems_version: 3.3.7
166
+ signing_key:
167
167
  specification_version: 4
168
168
  summary: Library for building facet searches for active_record models
169
169
  test_files: