rating 1.0.0 → 2.0.0

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: 2d43b5a545fab38d39feb7a46f4d081c4408dd2281f00478996bf989a4f3682d
4
- data.tar.gz: cfc83ae954ea334ecf0a7cf44b16594d0fd8a3c0fe48cc75034bb662cd555fa7
3
+ metadata.gz: 58836d050bdbccc7ed3cd471a8eebfe5bf3b6e16f3cfe6b5514b5e7ee724d59f
4
+ data.tar.gz: 5b92166c762349531174a1a04a2784eb826f7f5a37d12d9f607a464482aae0b6
5
5
  SHA512:
6
- metadata.gz: 6a393e04ede36dd77e88023c8ed134e359ad2ead75a96a07e483d46f99fe9ec0c83c9303143dc3fd545902064f8e711c8665de1293259561bec7afd1293ce091
7
- data.tar.gz: 89e4096c7c2e43b7771e2af9680f8a3fca8753831fc7c4c5685f9fd676fd2694bde65cdbcf816f70150486dd5282141938ecd700ec79d2f9a231b6aadf97eabd
6
+ metadata.gz: 3a3a39af0d990559f576a8a65e04f1d528bf89dd739e50b8127b43c3ec06b659e8cd2e62458337b903c6855fa6edad45ded96d5be94f67e5f5860d9904a5ae45
7
+ data.tar.gz: dacdd84b9eaed47bdc1ceec1eceae4218f2ad5bb26c6b2f0ad81f4bf58ee3764d04b4317b8073f1211c00d7ee33bd525a5d3716362d74b5db8001907389aa501
data/CHANGELOG.md CHANGED
@@ -1,11 +1,54 @@
1
- ## v1.0.0
1
+ ## v2.0.0
2
+
3
+ ### Break Changes
4
+
5
+ - Ruby 3.0, and 3.1 and 3.2 are no longer supported. The minimum Ruby version is now 3.3;
6
+ - The `estimate` field is now computed via Evan Miller's lower bound of the confidence interval
7
+ (https://www.evanmiller.org/ranking-items-with-star-ratings.html) instead of the previous weighted
8
+ Bayesian average. The new formula uses the full vote distribution (not just the mean), so it ranks
9
+ consistent ratings above polarized ones with the same mean, and items with few votes below items
10
+ with many votes;
11
+ - The `estimate` and `average` columns increased from `DECIMAL(11, 2)` to `DECIMAL(12, 8)`. Existing
12
+ apps must run a manual upgrade migration:
13
+
14
+ ```ruby
15
+ class UpgradeRatingPrecision < ActiveRecord::Migration[7.0]
16
+ def change
17
+ change_column :rating_ratings, :average, :decimal, precision: 12, scale: 8, default: 0, null: false
18
+ change_column :rating_ratings, :estimate, :decimal, precision: 12, scale: 8, default: 0, null: false
19
+ end
20
+ end
21
+ ```
22
+
23
+ After running the migration, the new `estimate` values will be populated on the next vote per
24
+ resource. To force a recalculation now, iterate over your rated resources and call `Rating::Rating.update_rating(resource, scope)`;
25
+ - The `.round(2)` previously applied to `estimate` and `average` is removed. Values are stored at
26
+ full column precision. Round at the view layer if needed for display;
27
+ - The `Rating::Rate#value` validation changed from `1..100` to `1..Rating::Config.rating_levels`
28
+ (default 5) and now requires an integer. If your app uses a different scale, configure
29
+ `rating_levels` (see below);
30
+ - New configuration: `Rating::Config.rating_levels` (default `5`) defines the maximum value of your
31
+ rating scale. `Rating::Config.rating_z_score` (default `1.96`, i.e. 95% confidence) tunes how
32
+ aggressively low-confidence items are penalized in the estimate.
33
+
34
+ ### Bug Fixes
35
+
36
+ - Fixes #8: `PG::NumericValueOutOfRange` overflow that occurred when a `resource_type` accumulated
37
+ 1000+ rates. The new formula does not compute the `total_count / distinct_count` ratio that
38
+ caused the overflow.
2
39
 
3
- ### Break Change
40
+ ### Updates
4
41
 
5
- - The attributes `estimate` and `average` now is rounded by two decimal numbers;
42
+ - Fixes a typo in the migration generator template (`mull: false` `null: false`);
43
+ - The `mysql2` and `pg` gems are no longer transitive dev dependencies of the gem. Contributors
44
+ install only the adapter they need via the Gemfile groups (`bundle install --without mysql` or
45
+ `--without postgres`).
6
46
 
7
- ### Updates
47
+ ## v1.0.0
48
+
49
+ ### Break Changes
8
50
 
51
+ - The attributes `estimate` and `average` now is rounded by two decimal numbers;
9
52
  - The method `order_by_rating` now receives a hash parameter to avoid scope and so support Ruby 3.2;
10
53
 
11
54
  ## v0.12.0
data/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # Rating
2
2
 
3
- [![CI](https://github.com/wbotelhos/rating/workflows/CI/badge.svg)](https://github.com/wbotelhos/rating/actions)
3
+ [![Tests](https://github.com/wbotelhos/rating/workflows/Tests/badge.svg)](https://github.com/wbotelhos/rating/actions)
4
4
  [![Gem Version](https://badge.fury.io/rb/rating.svg)](https://badge.fury.io/rb/rating)
5
5
  [![Maintainability](https://api.codeclimate.com/v1/badges/cc5efe8b06bc1d5e9e8a/maintainability)](https://codeclimate.com/github/wbotelhos/rating/maintainability)
6
- [![codecov](https://codecov.io/gh/wbotelhos/rating/branch/master/graph/badge.svg?token=QJSHUOULEG)](https://codecov.io/gh/wbotelhos/rating)
6
+ [![Coverage](https://codecov.io/gh/wbotelhos/rating/branch/master/graph/badge.svg?token=QJSHUOULEG)](https://codecov.io/gh/wbotelhos/rating)
7
7
  [![Sponsor](https://img.shields.io/badge/sponsor-%3C3-green)](https://github.com/sponsors/wbotelhos)
8
8
 
9
- A true Bayesian rating system with scope and cache enabled.
9
+ A confidence-based rating system with scope and cache enabled.
10
10
 
11
11
  ## JS Rating?
12
12
 
@@ -14,35 +14,42 @@ This is **Raty**: https://github.com/wbotelhos/raty :star2:
14
14
 
15
15
  ## Description
16
16
 
17
- Rating uses the know as "True Bayesian Estimate" inspired on [IMDb rating](http://www.imdb.com/help/show_leaf?votestopfaq) with the following formula:
17
+ Rating computes the `estimate` field using the **lower bound of the confidence interval** described
18
+ by Evan Miller in [Ranking Items With Star Ratings](https://www.evanmiller.org/ranking-items-with-star-ratings.html).
19
+
20
+ The formula uses the full distribution of votes — not just the mean — so it considers both the
21
+ average rating and the confidence we have in that average:
18
22
 
19
23
  ```
20
- (WR) = (v ÷ (v + m)) × R + (m ÷ (v + m)) × C
24
+ estimate = mean z × √(variance / (N + K + 1))
21
25
  ```
22
26
 
23
- **IMDb Implementation:**
24
-
25
- `WR`: weighted rating
26
-
27
- `R`: average for the movie (mean) = (Rating)
27
+ Where:
28
28
 
29
- `v`: number of votes for the movie = (votes)
29
+ - `mean` and `variance` are computed over the smoothed vote distribution (Laplace prior of 1 vote per level);
30
+ - `N` is the total number of votes for the resource;
31
+ - `K` is the number of rating levels (e.g. 5 for a 1–5 star scale);
32
+ - `z` is the normal distribution quantile (1.96 for 95% confidence).
30
33
 
31
- `m`: minimum votes required to be listed in the Top 250
34
+ In practice, this means:
32
35
 
33
- `C`: the mean vote across the whole report
36
+ - An item with consistent votes (e.g. all 4-stars) ranks **above** an item with the same mean but polarized votes (half 1-stars, half 5-stars), because the latter has higher variance and thus more uncertainty;
37
+ - An item with 3 five-star votes ranks **below** an item with 200 votes averaging 4.7 stars, because the term `√(variance / (N + K + 1))` shrinks as `N` grows.
34
38
 
35
- **Rating Implementation:**
39
+ This is the same family of approach used by sites like Amazon and IMDb to avoid items with very few votes dominating top-rated lists.
36
40
 
37
- `WR`: weighted rating
41
+ ### Configuration
38
42
 
39
- `R`: average for the resource
43
+ You can tune the formula via `Rating::Config`:
40
44
 
41
- `v`: number of votes for the resource
45
+ - `rating_levels` (default `5`): the maximum value of your rating scale. Vote `value` must be an integer between `1` and `rating_levels`. Set this in `config/rating.yml`:
42
46
 
43
- `m`: average of the number of votes
47
+ ```yaml
48
+ rating:
49
+ rating_levels: 10
50
+ ```
44
51
 
45
- `C`: the average rating based on all resources
52
+ - `rating_z_score` (default `1.96`): controls confidence level. Use `2.576` for 99% confidence (more conservative, penalizes low-vote items harder), `1.645` for 90% confidence (more permissive).
46
53
 
47
54
  ## Install
48
55
 
@@ -101,7 +108,7 @@ It will return a `Rating` object that keeps:
101
108
 
102
109
  `average`: the normal mean of votes;
103
110
 
104
- `estimate`: the true Bayesian estimate mean value (you should use this over average);
111
+ `estimate`: the lower bound (95% confidence) of the rating, based on the vote distribution. Use this for ranking — it penalizes both polarized distributions and items with few votes;
105
112
 
106
113
  `sum`: the sum of votes for this resource;
107
114
 
@@ -296,7 +303,7 @@ article.rates_records
296
303
  ### As
297
304
 
298
305
  If you have a model that will only be able to rate but not to receive a rate, configure it as `author`.
299
- An author model still can be rated, but won't genarate a Rating record with all values as zero to warm up the cache.
306
+ An author model still can be rated, but won't generate a Rating record with all values as zero to warm up the cache.
300
307
 
301
308
  ```ruby
302
309
  rating as: :author
@@ -5,15 +5,15 @@ class CreateRateTable < ActiveRecord::Migration[5.0]
5
5
  create_table :rating_rates do |t|
6
6
  t.decimal :value, default: 0, precision: 11, scale: 2
7
7
 
8
- t.references :author, index: true, null: false, polymorphic: true
9
- t.references :resource, index: true, null: false, polymorphic: true
10
- t.references :scopeable, index: true, null: true, polymorphic: true
8
+ t.references :author, index: true, null: false, polymorphic: true
9
+ t.references :resource, index: true, null: false, polymorphic: true
10
+ t.references :scopeable, index: true, null: true, polymorphic: true
11
11
 
12
12
  t.timestamps null: false
13
13
  end
14
14
 
15
- change_column :rating_rates, :author_type, :string, limit: 10
16
- change_column :rating_rates, :resource_type, :string, limit: 10
15
+ change_column :rating_rates, :author_type, :string, limit: 10
16
+ change_column :rating_rates, :resource_type, :string, limit: 10
17
17
  change_column :rating_rates, :scopeable_type, :string, limit: 10
18
18
 
19
19
  add_index :rating_rates, %i[author_type author_id resource_type resource_id scopeable_type scopeable_id],
@@ -3,18 +3,18 @@
3
3
  class CreateRatingTable < ActiveRecord::Migration[5.0]
4
4
  def change
5
5
  create_table :rating_ratings do |t|
6
- t.decimal :average, default: 0, mull: false, precision: 11, scale: 2
7
- t.decimal :estimate, default: 0, mull: false, precision: 11, scale: 2
8
- t.integer :sum, default: 0, mull: false
9
- t.integer :total, default: 0, mull: false
6
+ t.decimal :average, default: 0, null: false, precision: 12, scale: 8
7
+ t.decimal :estimate, default: 0, null: false, precision: 12, scale: 8
8
+ t.integer :sum, default: 0, null: false
9
+ t.integer :total, default: 0, null: false
10
10
 
11
- t.references :resource, index: true, null: false, polymorphic: true
12
- t.references :scopeable, index: true, null: true, polymorphic: true
11
+ t.references :resource, index: true, null: false, polymorphic: true
12
+ t.references :scopeable, index: true, null: true, polymorphic: true
13
13
 
14
14
  t.timestamps null: false
15
15
  end
16
16
 
17
- change_column :rating_ratings, :resource_type, :string, limit: 10
17
+ change_column :rating_ratings, :resource_type, :string, limit: 10
18
18
  change_column :rating_ratings, :scopeable_type, :string, limit: 10
19
19
 
20
20
  add_index :rating_ratings, %i[resource_type resource_id scopeable_type scopeable_id],
data/lib/rating/config.rb CHANGED
@@ -8,9 +8,7 @@ module Rating
8
8
  @config ||= begin
9
9
  file_path = File.expand_path('config/rating.yml')
10
10
 
11
- return {} unless File.exist?(file_path)
12
-
13
- YAML.safe_load(File.read(file_path))['rating']
11
+ File.exist?(file_path) ? YAML.safe_load_file(file_path)['rating'] : {}
14
12
  end
15
13
  end
16
14
 
@@ -22,6 +20,14 @@ module Rating
22
20
  @rating_table ||= config[__method__.to_s] || 'rating_ratings'
23
21
  end
24
22
 
23
+ def rating_levels
24
+ @rating_levels ||= config[__method__.to_s] || 5
25
+ end
26
+
27
+ def rating_z_score
28
+ @rating_z_score ||= config[__method__.to_s] || 1.96
29
+ end
30
+
25
31
  def validations
26
32
  @validations ||= begin
27
33
  default_scope = %w[author_type resource_id resource_type scopeable_id scopeable_type]
@@ -7,21 +7,21 @@ module Rating
7
7
  included do
8
8
  def rate(resource, value, author: self, extra_scopes: {}, metadata: {}, scope: nil)
9
9
  Rate.create(
10
- author: author,
11
- extra_scopes: extra_scopes,
12
- metadata: metadata,
13
- resource: resource,
10
+ author:,
11
+ extra_scopes:,
12
+ metadata:,
13
+ resource:,
14
14
  scopeable: scope,
15
- value: value
15
+ value:
16
16
  )
17
17
  end
18
18
 
19
19
  def rate_for(resource, extra_scopes: {}, scope: nil)
20
- Rate.rate_for author: self, extra_scopes: extra_scopes, resource: resource, scopeable: scope
20
+ Rate.rate_for author: self, extra_scopes:, resource:, scopeable: scope
21
21
  end
22
22
 
23
23
  def rated?(resource, extra_scopes: {}, scope: nil)
24
- Rate.exists?(extra_scopes.merge(author: self, resource: resource, scopeable: scope))
24
+ Rate.exists?(extra_scopes.merge(author: self, resource:, scopeable: scope))
25
25
  end
26
26
 
27
27
  def rates(extra_scopes: {}, scope: nil)
@@ -76,9 +76,10 @@ module Rating
76
76
  column = opts.fetch(:column, :estimate)
77
77
  direction = opts.fetch(:direction, :desc)
78
78
  scope = opts[:scope]
79
+ base_class = scope&.class&.base_class
79
80
 
80
81
  includes(:rating_records)
81
- .where(Rating.table_name => { scopeable_id: scope&.id, scopeable_type: scope&.class&.base_class&.name })
82
+ .where(Rating.table_name => { scopeable_id: scope&.id, scopeable_type: base_class&.name })
82
83
  .order("#{Rating.table_name}.#{column} #{direction}")
83
84
  }
84
85
 
@@ -3,16 +3,21 @@
3
3
  module Rating
4
4
  class Rate < ActiveRecord::Base
5
5
  self.table_name_prefix = 'rating_'
6
- self.table_name = ::Rating::Config.rate_table
6
+ self.table_name = ::Rating::Config.rate_table
7
7
 
8
8
  after_save :update_rating
9
9
 
10
- belongs_to :author, polymorphic: true
11
- belongs_to :resource, polymorphic: true
10
+ belongs_to :author, polymorphic: true
11
+ belongs_to :resource, polymorphic: true
12
12
  belongs_to :scopeable, polymorphic: true
13
13
 
14
- validates :author, :resource, :value, presence: true
15
- validates :value, numericality: { greater_than_or_equal_to: 1, less_than_or_equal_to: 100 }
14
+ validates :value, presence: true
15
+
16
+ validates :value, numericality: {
17
+ only_integer: true,
18
+ greater_than_or_equal_to: 1,
19
+ less_than_or_equal_to: ::Rating::Config.rating_levels,
20
+ }
16
21
 
17
22
  validates :author_id, uniqueness: {
18
23
  case_sensitive: ::Rating::Config.validations['rate']['case_sensitive'],
@@ -20,8 +25,8 @@ module Rating
20
25
  }
21
26
 
22
27
  def self.create(author:, extra_scopes:, metadata:, resource:, value:, scopeable: nil)
23
- attributes = { author: author, resource: resource, scopeable: scopeable }.merge(extra_scopes)
24
- record = find_or_initialize_by(attributes)
28
+ attributes = { author:, resource:, scopeable: }.merge(extra_scopes)
29
+ record = find_or_initialize_by(attributes)
25
30
 
26
31
  metadata.each { |k, v| record[k] = v } if metadata.present?
27
32
 
@@ -32,7 +37,7 @@ module Rating
32
37
  end
33
38
 
34
39
  def self.rate_for(author:, resource:, extra_scopes: {}, scopeable: nil)
35
- find_by extra_scopes.merge(author: author, resource: resource, scopeable: scopeable)
40
+ find_by extra_scopes.merge(author:, resource:, scopeable:)
36
41
  end
37
42
 
38
43
  private
@@ -3,12 +3,12 @@
3
3
  module Rating
4
4
  class Rating < ActiveRecord::Base
5
5
  self.table_name_prefix = 'rating_'
6
- self.table_name = ::Rating::Config.rating_table
6
+ self.table_name = ::Rating::Config.rating_table
7
7
 
8
- belongs_to :resource, polymorphic: true
8
+ belongs_to :resource, polymorphic: true
9
9
  belongs_to :scopeable, polymorphic: true
10
10
 
11
- validates :average, :estimate, :resource, :sum, :total, presence: true
11
+ validates :average, :estimate, :sum, :total, presence: true
12
12
  validates :average, :estimate, :sum, :total, numericality: true
13
13
 
14
14
  validates :resource_id, uniqueness: {
@@ -17,34 +17,35 @@ module Rating
17
17
  }
18
18
 
19
19
  class << self
20
- def averager_data(resource, scopeable)
21
- total_count = how_many_resource_received_votes_sql(distinct: false, resource: resource, scopeable: scopeable)
22
- distinct_count = how_many_resource_received_votes_sql(distinct: true, resource: resource, scopeable: scopeable)
23
- values = { resource_type: resource.class.base_class.name }
24
-
25
- values[:scopeable_type] = scopeable.class.base_class.name unless scopeable.nil?
26
-
20
+ def histogram_data(resource, scopeable)
27
21
  sql = %(
28
22
  SELECT
29
- (CAST(#{total_count} AS DECIMAL(17, 14)) / #{distinct_count}) count_avg,
30
- COALESCE(AVG(value), 0) rating_avg
23
+ value,
24
+ COUNT(1) AS rating_count
31
25
  FROM #{rate_table_name}
32
26
  WHERE
33
- resource_type = :resource_type
34
- #{scope_type_query(resource, scopeable)}
27
+ resource_type = ?
28
+ AND resource_id = ?
29
+ #{scope_type_and_id_query(resource, scopeable)}
35
30
  #{scope_where_query(resource)}
31
+ GROUP BY value
36
32
  ).squish
37
33
 
38
- execute_sql [sql, values]
34
+ values = [sql, resource.class.base_class.name, resource.id]
35
+ values += [scopeable.class.base_class.name, scopeable.id] unless scopeable.nil? || unscoped_rating?(resource)
36
+
37
+ Rate.find_by_sql(values).to_h do |row|
38
+ [row.value.to_i, row.rating_count.to_i]
39
+ end
39
40
  end
40
41
 
41
42
  def data(resource, scopeable)
42
- averager = averager_data(resource, scopeable)
43
- values = values_data(resource, scopeable)
43
+ histogram = histogram_data(resource, scopeable)
44
+ values = values_data(resource, scopeable)
44
45
 
45
46
  {
46
- average: values.rating_avg.round(2),
47
- estimate: estimate(averager, values).round(2),
47
+ average: values.rating_avg,
48
+ estimate: miller_lower_bound(histogram),
48
49
  sum: values.rating_sum,
49
50
  total: values.rating_count,
50
51
  }
@@ -64,22 +65,22 @@ module Rating
64
65
  #{scope_where_query(resource)}
65
66
  ).squish
66
67
 
67
- values = [sql, resource.class.base_class.name, resource.id]
68
+ values = [sql, resource.class.base_class.name, resource.id]
68
69
  values += [scopeable.class.base_class.name, scopeable.id] unless scopeable.nil? || unscoped_rating?(resource)
69
70
 
70
71
  execute_sql values
71
72
  end
72
73
 
73
74
  def update_rating(resource, scopeable)
74
- attributes = { resource: resource }
75
+ attributes = { resource: }
75
76
  attributes[:scopeable] = unscoped_rating?(resource) ? nil : scopeable
76
77
 
77
78
  record = find_or_initialize_by(attributes)
78
79
  result = data(resource, scopeable)
79
80
 
80
- record.average = result[:average]
81
- record.sum = result[:sum]
82
- record.total = result[:total]
81
+ record.average = result[:average]
82
+ record.sum = result[:sum]
83
+ record.total = result[:total]
83
84
  record.estimate = result[:estimate]
84
85
 
85
86
  record.save
@@ -87,14 +88,24 @@ module Rating
87
88
 
88
89
  private
89
90
 
90
- def estimate(averager, values)
91
- resource_type_rating_avg = averager.rating_avg
92
- count_avg = averager.count_avg
93
- resource_rating_avg = values.rating_avg
94
- resource_rating_count = values.rating_count.to_f
91
+ def miller_lower_bound(histogram)
92
+ rating_levels = ::Rating::Config.rating_levels
93
+ z_score = ::Rating::Config.rating_z_score
94
+ total_votes = (1..rating_levels).sum { |level| histogram.fetch(level, 0) }
95
+
96
+ return BigDecimal('0') if total_votes.zero?
97
+
98
+ denominator = total_votes + rating_levels
99
+
100
+ smoothed_mean = (1..rating_levels).sum do |level|
101
+ level * (histogram.fetch(level, 0) + 1).to_d / denominator
102
+ end
103
+
104
+ smoothed_variance = (1..rating_levels).sum do |level|
105
+ (level**2) * (histogram.fetch(level, 0) + 1).to_d / denominator
106
+ end - (smoothed_mean**2)
95
107
 
96
- ((resource_rating_count / (resource_rating_count + count_avg)) * resource_rating_avg) +
97
- ((count_avg / (resource_rating_count + count_avg)) * resource_type_rating_avg)
108
+ smoothed_mean - (z_score.to_d * (smoothed_variance / (denominator + 1)).sqrt(16))
98
109
  end
99
110
 
100
111
  def execute_sql(sql)
@@ -105,29 +116,10 @@ module Rating
105
116
  resource.rating_options[:unscoped_rating]
106
117
  end
107
118
 
108
- def how_many_resource_received_votes_sql(distinct:, resource:, scopeable:)
109
- count = distinct ? 'COUNT(DISTINCT resource_id)' : 'COUNT(1)'
110
-
111
- %((
112
- SELECT GREATEST(#{count}, 1)
113
- FROM #{rate_table_name}
114
- WHERE
115
- resource_type = :resource_type
116
- #{scope_type_query(resource, scopeable)}
117
- #{scope_where_query(resource)}
118
- ))
119
- end
120
-
121
119
  def rate_table_name
122
120
  @rate_table_name ||= Rate.table_name
123
121
  end
124
122
 
125
- def scope_type_query(resource, scopeable)
126
- return '' if unscoped_rating?(resource)
127
-
128
- scopeable.nil? ? 'AND scopeable_type is NULL' : 'AND scopeable_type = :scopeable_type'
129
- end
130
-
131
123
  def scope_type_and_id_query(resource, scopeable)
132
124
  return '' if unscoped_rating?(resource)
133
125
  return 'AND scopeable_type is NULL AND scopeable_id is NULL' if scopeable.nil?
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Rating
4
- VERSION = '1.0.0'
4
+ VERSION = '2.0.0'
5
5
  end
metadata CHANGED
@@ -1,14 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rating
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Washington Botelho
8
- autorequire:
9
8
  bindir: bin
10
9
  cert_chain: []
11
- date: 2023-03-04 00:00:00.000000000 Z
10
+ date: 1980-01-02 00:00:00.000000000 Z
12
11
  dependencies:
13
12
  - !ruby/object:Gem::Dependency
14
13
  name: activerecord
@@ -24,161 +23,7 @@ dependencies:
24
23
  - - ">="
25
24
  - !ruby/object:Gem::Version
26
25
  version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: codecov
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: '0'
34
- type: :development
35
- prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - ">="
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: database_cleaner
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - ">="
46
- - !ruby/object:Gem::Version
47
- version: '0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - ">="
53
- - !ruby/object:Gem::Version
54
- version: '0'
55
- - !ruby/object:Gem::Dependency
56
- name: factory_bot_rails
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">="
60
- - !ruby/object:Gem::Version
61
- version: '0'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- version: '0'
69
- - !ruby/object:Gem::Dependency
70
- name: mysql2
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: pg
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: pry-byebug
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - ">="
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - ">="
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: rspec-rails
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - ">="
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - ">="
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
- - !ruby/object:Gem::Dependency
126
- name: rubocop-performance
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - ">="
130
- - !ruby/object:Gem::Version
131
- version: '0'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - ">="
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: rubocop-rails
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ">="
144
- - !ruby/object:Gem::Version
145
- version: '0'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - ">="
151
- - !ruby/object:Gem::Version
152
- version: '0'
153
- - !ruby/object:Gem::Dependency
154
- name: rubocop-rspec
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - ">="
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
- prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - ">="
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: shoulda-matchers
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - ">="
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - ">="
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
- description: A true Bayesian rating system with scope and cache enabled.
26
+ description: A confidence-based rating system with scope and cache enabled.
182
27
  email: wbotelhos@gmail.com
183
28
  executables: []
184
29
  extensions: []
@@ -204,7 +49,6 @@ licenses:
204
49
  - MIT
205
50
  metadata:
206
51
  rubygems_mfa_required: 'true'
207
- post_install_message:
208
52
  rdoc_options: []
209
53
  require_paths:
210
54
  - lib
@@ -212,15 +56,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
212
56
  requirements:
213
57
  - - ">="
214
58
  - !ruby/object:Gem::Version
215
- version: '0'
59
+ version: '3.3'
216
60
  required_rubygems_version: !ruby/object:Gem::Requirement
217
61
  requirements:
218
62
  - - ">="
219
63
  - !ruby/object:Gem::Version
220
64
  version: '0'
221
65
  requirements: []
222
- rubygems_version: 3.4.6
223
- signing_key:
66
+ rubygems_version: 3.6.9
224
67
  specification_version: 4
225
68
  summary: A true Bayesian rating system with scope and cache enabled.
226
69
  test_files: []