forty_facets 0.1.9.0 → 0.2.1

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
  SHA256:
3
- metadata.gz: ad48e8c4f2338a87b29236fd94806a15f82da882ab7c754407cdb1795f608d15
4
- data.tar.gz: e19407ae762c613e784f8ebfb9e802d4398aa38520ef3b942016d50926cf70ca
3
+ metadata.gz: b199beee6e5f6cb3ce5024427b3d21b3458c2f8b94e362e02132d30bf89e0b56
4
+ data.tar.gz: 8e4f12b0498ecd4f307b916615f32d1f22602757484f396bdac9e6545ea62a53
5
5
  SHA512:
6
- metadata.gz: 9165e142d34aac61ce38eaac7efa70db5172496494e48082b5a9882345ba113850f2bda7ff066c2d7df76557555e59acf0b7286dd6f1e5d6b1e4d2eeb4473ee1
7
- data.tar.gz: 005ef2414ddcadcf8c53d176f887386c17de905cf6f27a2ca03b9b90f5b326020cfce26fb062475ffdddf62c6f1a30e4ab79924f36c474fd47e308042a2d9ca7
6
+ metadata.gz: 297c5f1d5dcef25897f877e9af20bf35af4e4642dc73c145ac42c6e3de2b1cfb6a504f70f46221853f32b38fbca0bbe66315f0fb06a9f40861b200a75c92b513
7
+ data.tar.gz: b484abb4c5ee26c000cdc97da161a515a73f3321d2191b8ff45961962c2f01c7f4dd50b38b266023c83bd9dbc627c1f7b240db0ae881297e7a97c5ae436cc37d
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.1
1
+ 3.1.2
data/CHANGELOG ADDED
@@ -0,0 +1,12 @@
1
+ # CHANGELOG
2
+
3
+ ## 0.2.1
4
+
5
+ - added "ORDER" to Range query to fix integration with Postgres
6
+
7
+ ## 0.2
8
+
9
+ - introduction of CHANGELOG
10
+ - upgraded to Ruby 3.1
11
+ - upgraded to ActiveRecrd/Rails 7
12
+ - 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,27 +1,39 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FortyFacets
2
4
  class RangeFilterDefinition < FilterDefinition
3
5
  class RangeFilter < Filter
6
+ RANGE_REGEX = /(\d*) - (\d*)/
7
+
4
8
  def build_scope
5
- return Proc.new { |base| base } if empty?
9
+ return proc { |base| base } if empty?
6
10
 
7
- Proc.new do |base|
8
- base.joins(definition.joins)
9
- .where("#{definition.qualified_column_name} >= ? AND #{definition.qualified_column_name} <= ? ", min_value, max_value )
11
+ proc do |base|
12
+ scope = base.joins(definition.joins)
13
+ scope = scope.where("#{definition.qualified_column_name} >= ?", min_value) if min_value.present?
14
+ scope = scope.where("#{definition.qualified_column_name} <= ?", max_value) if max_value.present?
15
+ scope
10
16
  end
11
17
  end
12
18
 
13
19
  def min_value
14
- return nil if empty?
15
- value.split(' - ').first
20
+ min, _max = range_values
21
+ min
16
22
  end
17
23
 
18
24
  def max_value
19
- return nil if empty?
20
- value.split(' - ').last
25
+ _min, max = range_values
26
+ max
21
27
  end
22
28
 
23
29
  def absolute_interval
24
- @abosultes ||= without.result.reorder('').select("min(#{definition.qualified_column_name}) AS min, max(#{definition.qualified_column_name}) as max").first
30
+ @abosultes ||=
31
+ without
32
+ .result
33
+ .reorder('')
34
+ .select("min(#{definition.qualified_column_name}) AS min, max(#{definition.qualified_column_name}) as max")
35
+ .order("min(#{definition.qualified_column_name})")
36
+ .first
25
37
  end
26
38
 
27
39
  def absolute_min
@@ -32,6 +44,11 @@ module FortyFacets
32
44
  absolute_interval.max
33
45
  end
34
46
 
47
+ private
48
+
49
+ def range_values
50
+ value&.match(RANGE_REGEX)&.captures
51
+ end
35
52
  end
36
53
 
37
54
  def build_filter(search_instance, value)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module FortyFacets
2
- VERSION = "0.1.9.0"
4
+ VERSION = '0.2.1'
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.9.0
4
+ version: 0.2.1
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-12-11 00:00:00.000000000 Z
11
+ date: 2022-06-10 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: