rating 0.8.0 → 0.9.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 +4 -4
- data/CHANGELOG.md +12 -0
- data/README.md +2 -2
- data/lib/generators/rating/install_generator.rb +1 -1
- data/lib/generators/rating/templates/db/migrate/create_rate_table.rb +6 -2
- data/lib/generators/rating/templates/db/migrate/create_rating_table.rb +4 -1
- data/lib/rating/config.rb +2 -2
- data/lib/rating/models/rating/extension.rb +1 -1
- data/lib/rating/models/rating/rate.rb +1 -1
- data/lib/rating/models/rating/rating.rb +2 -2
- data/lib/rating/version.rb +1 -1
- data/spec/config/rate_table_spec.rb +10 -6
- data/spec/config/rating_table_spec.rb +10 -6
- data/spec/config/validations_spec.rb +24 -18
- data/spec/factories/rating/rate.rb +1 -1
- data/spec/factories/rating/rating.rb +4 -4
- data/spec/models/extension/order_by_rating_spec.rb +15 -15
- data/spec/models/extension/rated_question_spec.rb +10 -8
- data/spec/models/extension/rated_spec.rb +7 -5
- data/spec/models/extension/rates_spec.rb +7 -5
- data/spec/models/rate/create_spec.rb +131 -129
- data/spec/models/rate/rate_for_spec.rb +49 -47
- data/spec/models/rate_spec.rb +1 -1
- data/spec/models/rating/averager_data_spec.rb +3 -3
- data/spec/models/rating/values_data_spec.rb +6 -6
- data/spec/support/db/migrate/add_extra_fields_on_rating_rates_table.rb +0 -2
- data/spec/support/db/migrate/create_rates_table.rb +19 -0
- data/spec/support/db/migrate/create_rating_table.rb +20 -0
- data/spec/support/migrate.rb +6 -6
- metadata +23 -12
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 11fafaaddcc1f4568cfd1412930a42a06aa0467bfa6e68a74d1bd3214f24aa87
|
4
|
+
data.tar.gz: d1dc1822b99b9a928e6bdceabcdd00bed081d08498e7189b1169ce323b3f720d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0a636e5f8b60c69b98384343ffa3ddb5023f020d07716917e2e1fe5a5292c8e2c4a28056755a01bae4978365f4b73a8f5e98fb9169f03e0b9825b44a0b6a6fd3
|
7
|
+
data.tar.gz: '09713cd4fd3a48b8433a3482c791eb380231b1a2edec2016d8a909bb3f7b8abbb0020c08d3fe5b68418840f9a017459d40e65672bda38aeb6ffbea6100cc9178'
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,15 @@
|
|
1
|
+
## v0.9.0
|
2
|
+
|
3
|
+
### News
|
4
|
+
|
5
|
+
- Order index keys of template the same way Rails does the query;
|
6
|
+
- Limits the `_type` columns to avoid overflow bytes in DBs like MySQL < 5.7.
|
7
|
+
|
8
|
+
### Updates
|
9
|
+
|
10
|
+
- Update Rails to 2.6.5;
|
11
|
+
- Update Activerecord to the last version;
|
12
|
+
|
1
13
|
## v0.8.0
|
2
14
|
|
3
15
|
### News
|
data/README.md
CHANGED
@@ -410,6 +410,6 @@ author.rate resource, 3
|
|
410
410
|
|
411
411
|
Now the `sum` will be `6` and the `total` will be `3` because all rating will be calculated into just one rating record ignoring the `scopeable` object. The rating record is always saved on the record with `scopeable` as `nil`.
|
412
412
|
|
413
|
-
|
413
|
+
### References
|
414
414
|
|
415
|
-
|
415
|
+
- [Evan Miller](http://www.evanmiller.org/ranking-items-with-star-ratings.html)
|
@@ -7,12 +7,16 @@ class CreateRateTable < ActiveRecord::Migration[5.0]
|
|
7
7
|
|
8
8
|
t.references :author, index: true, null: false, polymorphic: true
|
9
9
|
t.references :resource, index: true, null: false, polymorphic: true
|
10
|
-
t.references :scopeable, index: true, null: 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
|
-
|
15
|
+
change_column :rating_rates, :author_type, :string, limit: 10
|
16
|
+
change_column :rating_rates, :resource_type, :string, limit: 10
|
17
|
+
change_column :rating_rates, :scopeable_type, :string, limit: 10
|
18
|
+
|
19
|
+
add_index :rating_rates, %i[author_type author_id resource_type resource_id scopeable_type scopeable_id],
|
16
20
|
name: :index_rating_rates_on_author_and_resource_and_scopeable,
|
17
21
|
unique: true
|
18
22
|
end
|
@@ -14,7 +14,10 @@ class CreateRatingTable < ActiveRecord::Migration[5.0]
|
|
14
14
|
t.timestamps null: false
|
15
15
|
end
|
16
16
|
|
17
|
-
|
17
|
+
change_column :rating_ratings, :resource_type, :string, limit: 10
|
18
|
+
change_column :rating_ratings, :scopeable_type, :string, limit: 10
|
19
|
+
|
20
|
+
add_index :rating_ratings, %i[resource_type resource_id scopeable_type scopeable_id],
|
18
21
|
name: :index_rating_rating_on_resource_and_scopeable,
|
19
22
|
unique: true
|
20
23
|
end
|
data/lib/rating/config.rb
CHANGED
@@ -29,8 +29,8 @@ module Rating
|
|
29
29
|
{
|
30
30
|
rate: {
|
31
31
|
case_sensitive: config.dig('validations', 'rate', 'case_sensitive') || false,
|
32
|
-
scope: config.dig('validations', 'rate', 'scope') || default_scope
|
33
|
-
}
|
32
|
+
scope: config.dig('validations', 'rate', 'scope') || default_scope,
|
33
|
+
},
|
34
34
|
}.deep_stringify_keys
|
35
35
|
end
|
36
36
|
end
|
@@ -73,7 +73,7 @@ module Rating
|
|
73
73
|
class_name: '::Rating::Rate',
|
74
74
|
dependent: :destroy
|
75
75
|
|
76
|
-
scope :order_by_rating,
|
76
|
+
scope :order_by_rating, lambda { |column = :estimate, direction = :desc, scope: nil|
|
77
77
|
includes(:rating_records)
|
78
78
|
.where(Rating.table_name => { scopeable_id: scope&.id, scopeable_type: scope&.class&.base_class&.name })
|
79
79
|
.order("#{Rating.table_name}.#{column} #{direction}")
|
@@ -16,7 +16,7 @@ module Rating
|
|
16
16
|
|
17
17
|
validates :author_id, uniqueness: {
|
18
18
|
case_sensitive: ::Rating::Config.validations['rate']['case_sensitive'],
|
19
|
-
scope: ::Rating::Config.validations['rate']['scope'].map(&:to_sym)
|
19
|
+
scope: ::Rating::Config.validations['rate']['scope'].map(&:to_sym),
|
20
20
|
}
|
21
21
|
|
22
22
|
def self.create(author:, extra_scopes:, metadata:, resource:, scopeable: nil, value:)
|
@@ -13,7 +13,7 @@ module Rating
|
|
13
13
|
|
14
14
|
validates :resource_id, uniqueness: {
|
15
15
|
case_sensitive: false,
|
16
|
-
scope: %i[resource_type scopeable_id scopeable_type]
|
16
|
+
scope: %i[resource_type scopeable_id scopeable_type],
|
17
17
|
}
|
18
18
|
|
19
19
|
class << self
|
@@ -43,7 +43,7 @@ module Rating
|
|
43
43
|
average: values.rating_avg,
|
44
44
|
estimate: estimate(averager, values),
|
45
45
|
sum: values.rating_sum,
|
46
|
-
total: values.rating_count
|
46
|
+
total: values.rating_count,
|
47
47
|
}
|
48
48
|
end
|
49
49
|
|
data/lib/rating/version.rb
CHANGED
@@ -3,11 +3,15 @@
|
|
3
3
|
require 'rails_helper'
|
4
4
|
|
5
5
|
RSpec.describe Rating::Config, '.rate_table' do
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if ENV['CONFIG_ENABLED'] != 'true'
|
7
|
+
context 'when rating.yml does not exist' do
|
8
|
+
it { expect(subject.rate_table).to eq 'rating_rates' }
|
9
|
+
end
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
if ENV['CONFIG_ENABLED'] == 'true'
|
13
|
+
context 'when rating.yml exists' do
|
14
|
+
it { expect(subject.rate_table).to eq 'reviews' }
|
15
|
+
end
|
16
|
+
end
|
13
17
|
end
|
@@ -3,11 +3,15 @@
|
|
3
3
|
require 'rails_helper'
|
4
4
|
|
5
5
|
RSpec.describe Rating::Config, '.rating_table' do
|
6
|
-
|
7
|
-
|
8
|
-
|
6
|
+
if ENV['CONFIG_ENABLED'] != 'true'
|
7
|
+
context 'when rating.yml does not exist' do
|
8
|
+
it { expect(subject.rating_table).to eq 'rating_ratings' }
|
9
|
+
end
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
-
|
12
|
+
if ENV['CONFIG_ENABLED'] == 'true'
|
13
|
+
context 'when rating.yml exists' do
|
14
|
+
it { expect(subject.rating_table).to eq 'review_ratings' }
|
15
|
+
end
|
16
|
+
end
|
13
17
|
end
|
@@ -3,25 +3,31 @@
|
|
3
3
|
require 'rails_helper'
|
4
4
|
|
5
5
|
RSpec.describe Rating::Config, '.validations' do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
6
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] != 'true'
|
7
|
+
context 'when rating.yml does not exist' do
|
8
|
+
it do
|
9
|
+
expect(subject.validations).to eq({
|
10
|
+
rate: {
|
11
|
+
case_sensitive: false,
|
12
|
+
scope: %w[author_type resource_id resource_type scopeable_id scopeable_type],
|
13
|
+
},
|
14
|
+
}.deep_stringify_keys
|
15
|
+
)
|
16
|
+
end
|
14
17
|
end
|
15
|
-
end
|
18
|
+
end
|
16
19
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
21
|
+
context 'when rating.yml exists' do
|
22
|
+
it do
|
23
|
+
expect(subject.validations).to eq({
|
24
|
+
rate: {
|
25
|
+
case_sensitive: false,
|
26
|
+
scope: %w[author_type resource_id resource_type scopeable_id scopeable_type scope_1 scope_2],
|
27
|
+
},
|
28
|
+
}.deep_stringify_keys
|
29
|
+
)
|
30
|
+
end
|
25
31
|
end
|
26
|
-
end
|
32
|
+
end
|
27
33
|
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
FactoryBot.define do
|
4
4
|
factory :rating_rating, class: Rating::Rating do
|
5
|
-
average 100
|
6
|
-
estimate 100
|
7
|
-
sum 100
|
8
|
-
total 1
|
5
|
+
average { 100 }
|
6
|
+
estimate { 100 }
|
7
|
+
sum { 100 }
|
8
|
+
total { 1 }
|
9
9
|
|
10
10
|
association :resource, factory: :article, strategy: :build
|
11
11
|
end
|
@@ -11,7 +11,7 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
11
11
|
expect(Article.order_by_rating).to eq [
|
12
12
|
article_1,
|
13
13
|
article_2,
|
14
|
-
article_3
|
14
|
+
article_3,
|
15
15
|
]
|
16
16
|
end
|
17
17
|
end
|
@@ -22,14 +22,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
22
22
|
expect(Article.order_by_rating(:average, :asc)).to eq [
|
23
23
|
article_3,
|
24
24
|
article_2,
|
25
|
-
article_1
|
25
|
+
article_1,
|
26
26
|
]
|
27
27
|
end
|
28
28
|
|
29
29
|
context 'with scope' do
|
30
30
|
it 'works' do
|
31
31
|
expect(Article.order_by_rating(:average, :asc, scope: category)).to eq [
|
32
|
-
article_1
|
32
|
+
article_1,
|
33
33
|
]
|
34
34
|
end
|
35
35
|
end
|
@@ -40,14 +40,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
40
40
|
expect(Article.order_by_rating(:average, :desc)).to eq [
|
41
41
|
article_1,
|
42
42
|
article_2,
|
43
|
-
article_3
|
43
|
+
article_3,
|
44
44
|
]
|
45
45
|
end
|
46
46
|
|
47
47
|
context 'with scope' do
|
48
48
|
it 'works' do
|
49
49
|
expect(Article.order_by_rating(:average, :desc, scope: category)).to eq [
|
50
|
-
article_1
|
50
|
+
article_1,
|
51
51
|
]
|
52
52
|
end
|
53
53
|
end
|
@@ -60,14 +60,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
60
60
|
expect(Article.order_by_rating(:estimate, :asc)).to eq [
|
61
61
|
article_3,
|
62
62
|
article_2,
|
63
|
-
article_1
|
63
|
+
article_1,
|
64
64
|
]
|
65
65
|
end
|
66
66
|
|
67
67
|
context 'with scope' do
|
68
68
|
it 'works' do
|
69
69
|
expect(Article.order_by_rating(:estimate, :asc, scope: category)).to eq [
|
70
|
-
article_1
|
70
|
+
article_1,
|
71
71
|
]
|
72
72
|
end
|
73
73
|
end
|
@@ -78,14 +78,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
78
78
|
expect(Article.order_by_rating(:estimate, :desc)).to eq [
|
79
79
|
article_1,
|
80
80
|
article_2,
|
81
|
-
article_3
|
81
|
+
article_3,
|
82
82
|
]
|
83
83
|
end
|
84
84
|
|
85
85
|
context 'with scope' do
|
86
86
|
it 'works' do
|
87
87
|
expect(Article.order_by_rating(:estimate, :desc, scope: category)).to eq [
|
88
|
-
article_1
|
88
|
+
article_1,
|
89
89
|
]
|
90
90
|
end
|
91
91
|
end
|
@@ -98,14 +98,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
98
98
|
expect(Article.order_by_rating(:sum, :asc)).to eq [
|
99
99
|
article_3,
|
100
100
|
article_2,
|
101
|
-
article_1
|
101
|
+
article_1,
|
102
102
|
]
|
103
103
|
end
|
104
104
|
|
105
105
|
context 'with scope' do
|
106
106
|
it 'works' do
|
107
107
|
expect(Article.order_by_rating(:sum, :asc, scope: category)).to eq [
|
108
|
-
article_1
|
108
|
+
article_1,
|
109
109
|
]
|
110
110
|
end
|
111
111
|
end
|
@@ -116,14 +116,14 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
116
116
|
expect(Article.order_by_rating(:sum, :desc)).to eq [
|
117
117
|
article_1,
|
118
118
|
article_2,
|
119
|
-
article_3
|
119
|
+
article_3,
|
120
120
|
]
|
121
121
|
end
|
122
122
|
|
123
123
|
context 'with scope' do
|
124
124
|
it 'works' do
|
125
125
|
expect(Article.order_by_rating(:sum, :desc, scope: category)).to eq [
|
126
|
-
article_1
|
126
|
+
article_1,
|
127
127
|
]
|
128
128
|
end
|
129
129
|
end
|
@@ -142,7 +142,7 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
142
142
|
context 'with scope' do
|
143
143
|
it 'works' do
|
144
144
|
expect(Article.order_by_rating(:total, :asc, scope: category)).to eq [
|
145
|
-
article_1
|
145
|
+
article_1,
|
146
146
|
]
|
147
147
|
end
|
148
148
|
end
|
@@ -159,7 +159,7 @@ RSpec.describe Rating::Extension, ':order_by_rating' do
|
|
159
159
|
context 'with scope' do
|
160
160
|
it 'works' do
|
161
161
|
expect(Article.order_by_rating(:total, :desc, scope: category)).to eq [
|
162
|
-
article_1
|
162
|
+
article_1,
|
163
163
|
]
|
164
164
|
end
|
165
165
|
end
|
@@ -32,15 +32,17 @@ RSpec.describe Rating::Extension, ':rated?' do
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
36
|
+
context 'with extra scopes' do
|
37
|
+
before { author.rate resource, 1, extra_scopes: { scope_1: 'scope_1' } }
|
37
38
|
|
38
|
-
|
39
|
-
|
40
|
-
|
39
|
+
context 'when has no rate for the given resource with given extra scopes' do
|
40
|
+
specify { expect(author.rated?(resource, extra_scopes: { scope_1: 'missing' })).to eq false }
|
41
|
+
end
|
41
42
|
|
42
|
-
|
43
|
-
|
43
|
+
context 'when has rate for the given resource with given extra scopes' do
|
44
|
+
specify { expect(author.rated?(resource, extra_scopes: { scope_1: 'scope_1' })).to eq true }
|
45
|
+
end
|
44
46
|
end
|
45
|
-
end
|
47
|
+
end
|
46
48
|
end
|
@@ -38,11 +38,13 @@ RSpec.describe Rating::Extension, ':rated' do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
42
|
+
context 'with extra scopes' do
|
43
|
+
let!(:extra_scopes_rate) { author_1.rate article_1, 1, extra_scopes: { scope_1: 'scope_1' } }
|
43
44
|
|
44
|
-
|
45
|
-
|
45
|
+
it 'returns records considering the extra scopes' do
|
46
|
+
expect(author_1.rated(extra_scopes: { scope_1: 'scope_1' })).to eq [extra_scopes_rate]
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
49
|
+
end
|
48
50
|
end
|
@@ -38,11 +38,13 @@ RSpec.describe Rating::Extension, ':rates' do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
|
42
|
-
|
41
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
42
|
+
context 'with extra scopes' do
|
43
|
+
let!(:extra_scopes_rate) { author_1.rate article_1, 1, extra_scopes: { scope_1: 'scope_1' } }
|
43
44
|
|
44
|
-
|
45
|
-
|
45
|
+
it 'returns records considering the extra scopes' do
|
46
|
+
expect(article_1.rates(extra_scopes: { scope_1: 'scope_1' })).to eq [extra_scopes_rate]
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
49
|
+
end
|
48
50
|
end
|
@@ -194,51 +194,11 @@ RSpec.describe Rating::Rate, ':create' do
|
|
194
194
|
end
|
195
195
|
end
|
196
196
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
it 'creates a rate entry' do
|
201
|
-
described_class.create(
|
202
|
-
author: author,
|
203
|
-
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
204
|
-
metadata: {},
|
205
|
-
resource: article,
|
206
|
-
scopeable: category,
|
207
|
-
value: 1
|
208
|
-
)
|
209
|
-
|
210
|
-
rate = described_class.last
|
197
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
198
|
+
context 'with extra scopes' do
|
199
|
+
let!(:category) { create :category }
|
211
200
|
|
212
|
-
|
213
|
-
expect(rate.resource).to eq article
|
214
|
-
expect(rate.scope_1).to eq 'scope_1'
|
215
|
-
expect(rate.scope_2).to eq 'scope_2'
|
216
|
-
expect(rate.scopeable).to eq category
|
217
|
-
expect(rate.value).to eq 1
|
218
|
-
end
|
219
|
-
|
220
|
-
it 'creates a rating entry' do
|
221
|
-
described_class.create(
|
222
|
-
author: author,
|
223
|
-
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
224
|
-
metadata: {},
|
225
|
-
resource: article,
|
226
|
-
scopeable: category,
|
227
|
-
value: 1
|
228
|
-
)
|
229
|
-
|
230
|
-
rating = Rating::Rating.last
|
231
|
-
|
232
|
-
expect(rating.average).to eq 1
|
233
|
-
expect(rating.estimate).to eq 1
|
234
|
-
expect(rating.resource).to eq article
|
235
|
-
expect(rating.scopeable).to eq category
|
236
|
-
expect(rating.sum).to eq 1
|
237
|
-
expect(rating.total).to eq 1
|
238
|
-
end
|
239
|
-
|
240
|
-
context 'when rate already exists' do
|
241
|
-
before do
|
201
|
+
it 'creates a rate entry' do
|
242
202
|
described_class.create(
|
243
203
|
author: author,
|
244
204
|
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
@@ -247,116 +207,158 @@ RSpec.describe Rating::Rate, ':create' do
|
|
247
207
|
scopeable: category,
|
248
208
|
value: 1
|
249
209
|
)
|
250
|
-
end
|
251
|
-
|
252
|
-
it 'updates the rate entry' do
|
253
|
-
described_class.create(
|
254
|
-
author: author,
|
255
|
-
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
256
|
-
metadata: {},
|
257
|
-
resource: article,
|
258
|
-
scopeable: category,
|
259
|
-
value: 2
|
260
|
-
)
|
261
|
-
|
262
|
-
rates = described_class.all
|
263
210
|
|
264
|
-
|
265
|
-
|
266
|
-
rate = rates[0]
|
211
|
+
rate = described_class.last
|
267
212
|
|
268
213
|
expect(rate.author).to eq author
|
269
214
|
expect(rate.resource).to eq article
|
270
215
|
expect(rate.scope_1).to eq 'scope_1'
|
271
216
|
expect(rate.scope_2).to eq 'scope_2'
|
272
217
|
expect(rate.scopeable).to eq category
|
273
|
-
expect(rate.value).to eq
|
218
|
+
expect(rate.value).to eq 1
|
274
219
|
end
|
275
220
|
|
276
|
-
it '
|
221
|
+
it 'creates a rating entry' do
|
277
222
|
described_class.create(
|
278
223
|
author: author,
|
279
224
|
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
280
225
|
metadata: {},
|
281
226
|
resource: article,
|
282
227
|
scopeable: category,
|
283
|
-
value:
|
228
|
+
value: 1
|
284
229
|
)
|
285
230
|
|
286
|
-
|
287
|
-
|
288
|
-
expect(ratings.size).to eq 1
|
289
|
-
|
290
|
-
rating = ratings[0]
|
231
|
+
rating = Rating::Rating.last
|
291
232
|
|
292
|
-
expect(rating.average).to eq
|
293
|
-
expect(rating.estimate).to eq
|
233
|
+
expect(rating.average).to eq 1
|
234
|
+
expect(rating.estimate).to eq 1
|
294
235
|
expect(rating.resource).to eq article
|
295
236
|
expect(rating.scopeable).to eq category
|
296
|
-
expect(rating.sum).to eq
|
237
|
+
expect(rating.sum).to eq 1
|
297
238
|
expect(rating.total).to eq 1
|
298
239
|
end
|
299
|
-
end
|
300
|
-
|
301
|
-
context 'when rate already exists but with at least one extra scope different' do
|
302
|
-
before do
|
303
|
-
described_class.create(
|
304
|
-
author: author,
|
305
|
-
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
306
|
-
metadata: {},
|
307
|
-
resource: article,
|
308
|
-
scopeable: category,
|
309
|
-
value: 1
|
310
|
-
)
|
311
|
-
|
312
|
-
described_class.create(
|
313
|
-
author: author,
|
314
|
-
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_missing' },
|
315
|
-
metadata: {},
|
316
|
-
resource: article,
|
317
|
-
scopeable: category,
|
318
|
-
value: 2
|
319
|
-
)
|
320
|
-
end
|
321
|
-
|
322
|
-
it 'creates a new rate entry' do
|
323
|
-
rates = described_class.all
|
324
|
-
|
325
|
-
expect(rates.size).to eq 2
|
326
|
-
|
327
|
-
rate = rates[0]
|
328
240
|
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
241
|
+
context 'when rate already exists' do
|
242
|
+
before do
|
243
|
+
described_class.create(
|
244
|
+
author: author,
|
245
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
246
|
+
metadata: {},
|
247
|
+
resource: article,
|
248
|
+
scopeable: category,
|
249
|
+
value: 1
|
250
|
+
)
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'updates the rate entry' do
|
254
|
+
described_class.create(
|
255
|
+
author: author,
|
256
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
257
|
+
metadata: {},
|
258
|
+
resource: article,
|
259
|
+
scopeable: category,
|
260
|
+
value: 2
|
261
|
+
)
|
262
|
+
|
263
|
+
rates = described_class.all
|
264
|
+
|
265
|
+
expect(rates.size).to eq 1
|
266
|
+
|
267
|
+
rate = rates[0]
|
268
|
+
|
269
|
+
expect(rate.author).to eq author
|
270
|
+
expect(rate.resource).to eq article
|
271
|
+
expect(rate.scope_1).to eq 'scope_1'
|
272
|
+
expect(rate.scope_2).to eq 'scope_2'
|
273
|
+
expect(rate.scopeable).to eq category
|
274
|
+
expect(rate.value).to eq 2
|
275
|
+
end
|
276
|
+
|
277
|
+
it 'updates the unique rating entry' do
|
278
|
+
described_class.create(
|
279
|
+
author: author,
|
280
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
281
|
+
metadata: {},
|
282
|
+
resource: article,
|
283
|
+
scopeable: category,
|
284
|
+
value: 2
|
285
|
+
)
|
286
|
+
|
287
|
+
ratings = Rating::Rating.all
|
288
|
+
|
289
|
+
expect(ratings.size).to eq 1
|
290
|
+
|
291
|
+
rating = ratings[0]
|
292
|
+
|
293
|
+
expect(rating.average).to eq 2
|
294
|
+
expect(rating.estimate).to eq 2
|
295
|
+
expect(rating.resource).to eq article
|
296
|
+
expect(rating.scopeable).to eq category
|
297
|
+
expect(rating.sum).to eq 2
|
298
|
+
expect(rating.total).to eq 1
|
299
|
+
end
|
344
300
|
end
|
345
301
|
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
302
|
+
context 'when rate already exists but with at least one extra scope different' do
|
303
|
+
before do
|
304
|
+
described_class.create(
|
305
|
+
author: author,
|
306
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
307
|
+
metadata: {},
|
308
|
+
resource: article,
|
309
|
+
scopeable: category,
|
310
|
+
value: 1
|
311
|
+
)
|
312
|
+
|
313
|
+
described_class.create(
|
314
|
+
author: author,
|
315
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_missing' },
|
316
|
+
metadata: {},
|
317
|
+
resource: article,
|
318
|
+
scopeable: category,
|
319
|
+
value: 2
|
320
|
+
)
|
321
|
+
end
|
322
|
+
|
323
|
+
it 'creates a new rate entry' do
|
324
|
+
rates = described_class.all
|
325
|
+
|
326
|
+
expect(rates.size).to eq 2
|
327
|
+
|
328
|
+
rate = rates[0]
|
329
|
+
|
330
|
+
expect(rate.author).to eq author
|
331
|
+
expect(rate.resource).to eq article
|
332
|
+
expect(rate.scope_1).to eq 'scope_1'
|
333
|
+
expect(rate.scope_2).to eq 'scope_2'
|
334
|
+
expect(rate.scopeable).to eq category
|
335
|
+
expect(rate.value).to eq 1
|
336
|
+
|
337
|
+
rate = rates[1]
|
338
|
+
|
339
|
+
expect(rate.author).to eq author
|
340
|
+
expect(rate.resource).to eq article
|
341
|
+
expect(rate.scope_1).to eq 'scope_1'
|
342
|
+
expect(rate.scope_2).to eq 'scope_missing'
|
343
|
+
expect(rate.scopeable).to eq category
|
344
|
+
expect(rate.value).to eq 2
|
345
|
+
end
|
346
|
+
|
347
|
+
it 'updates the unique rating entry' do
|
348
|
+
ratings = Rating::Rating.all
|
349
|
+
|
350
|
+
expect(ratings.size).to eq 1
|
351
|
+
|
352
|
+
rating = ratings[0]
|
353
|
+
|
354
|
+
expect(rating.average).to eq 1.5
|
355
|
+
expect(rating.estimate).to eq 1.5
|
356
|
+
expect(rating.resource).to eq article
|
357
|
+
expect(rating.scopeable).to eq category
|
358
|
+
expect(rating.sum).to eq 3
|
359
|
+
expect(rating.total).to eq 2
|
360
|
+
end
|
359
361
|
end
|
360
362
|
end
|
361
|
-
end
|
363
|
+
end
|
362
364
|
end
|
@@ -51,55 +51,57 @@ RSpec.describe Rating::Rate, ':rate_for' do
|
|
51
51
|
end
|
52
52
|
end
|
53
53
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
54
|
+
if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
55
|
+
context 'with extra scopes' do
|
56
|
+
let!(:category) { create :category }
|
57
|
+
|
58
|
+
context 'when matches all attributes including the extra scopes' do
|
59
|
+
let!(:record) do
|
60
|
+
described_class.create(
|
61
|
+
author: author,
|
62
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
63
|
+
metadata: {},
|
64
|
+
resource: article,
|
65
|
+
scopeable: category,
|
66
|
+
value: 1
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
it 'returns the record' do
|
71
|
+
result = described_class.rate_for(
|
72
|
+
author: author,
|
73
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
74
|
+
resource: article,
|
75
|
+
scopeable: category
|
76
|
+
)
|
77
|
+
|
78
|
+
expect(result).to eq record
|
79
|
+
end
|
78
80
|
end
|
79
|
-
end
|
80
81
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
82
|
+
context 'when matches all attributes but at least one extra scopes' do
|
83
|
+
before do
|
84
|
+
described_class.create(
|
85
|
+
author: author,
|
86
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_2' },
|
87
|
+
metadata: {},
|
88
|
+
resource: article,
|
89
|
+
scopeable: category,
|
90
|
+
value: 1
|
91
|
+
)
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'does not return the record' do
|
95
|
+
result = described_class.rate_for(
|
96
|
+
author: author,
|
97
|
+
extra_scopes: { scope_1: 'scope_1', scope_2: 'scope_missing' },
|
98
|
+
resource: article,
|
99
|
+
scopeable: category
|
100
|
+
)
|
101
|
+
|
102
|
+
expect(result).to eq nil
|
103
|
+
end
|
102
104
|
end
|
103
105
|
end
|
104
|
-
end
|
106
|
+
end
|
105
107
|
end
|
data/spec/models/rate_spec.rb
CHANGED
@@ -16,7 +16,7 @@ RSpec.describe Rating::Rate do
|
|
16
16
|
it { is_expected.to validate_presence_of :value }
|
17
17
|
|
18
18
|
it do
|
19
|
-
|
19
|
+
expect(subject).to validate_numericality_of(:value).is_less_than_or_equal_to(100).is_less_than_or_equal_to 100
|
20
20
|
end
|
21
21
|
|
22
22
|
it do
|
@@ -10,7 +10,7 @@ RSpec.describe Rating::Rating, ':averager_data' do
|
|
10
10
|
subject(:result) { described_class.averager_data article_1, nil }
|
11
11
|
|
12
12
|
it 'returns the values average of given resource type' do
|
13
|
-
expect(result.as_json['rating_avg']).to eq 30.5
|
13
|
+
expect(result.as_json['rating_avg'].to_f.to_s).to eq '30.5'
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'returns the average of number of records for the given resource type' do
|
@@ -22,11 +22,11 @@ RSpec.describe Rating::Rating, ':averager_data' do
|
|
22
22
|
subject(:result) { described_class.averager_data article_1, category }
|
23
23
|
|
24
24
|
it 'returns the values average of given resource type' do
|
25
|
-
expect(result.as_json['rating_avg']).to eq 1.5
|
25
|
+
expect(result.as_json['rating_avg'].to_f.to_s).to eq '1.5'
|
26
26
|
end
|
27
27
|
|
28
28
|
it 'returns the average of number of records for the given resource type' do
|
29
|
-
expect(result.as_json['count_avg']).to eq 2
|
29
|
+
expect(result.as_json['count_avg'].to_f.to_s).to eq '2.0'
|
30
30
|
end
|
31
31
|
end
|
32
32
|
end
|
@@ -10,15 +10,15 @@ RSpec.describe Rating::Rating, ':values_data' do
|
|
10
10
|
subject(:result) { described_class.values_data article_1, nil }
|
11
11
|
|
12
12
|
it 'returns the average of value for a resource' do
|
13
|
-
expect(result.as_json['rating_avg']).to eq 50.5
|
13
|
+
expect(result.as_json['rating_avg'].to_f.to_s).to eq '50.5'
|
14
14
|
end
|
15
15
|
|
16
16
|
it 'returns the sum of values for a resource' do
|
17
|
-
expect(result.as_json['rating_sum']).to eq 101
|
17
|
+
expect(result.as_json['rating_sum'].to_f.to_s).to eq '101.0'
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'returns the count of votes for a resource' do
|
21
|
-
expect(result.as_json['rating_count']).to eq 2
|
21
|
+
expect(result.as_json['rating_count'].to_f.to_s).to eq '2.0'
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -26,15 +26,15 @@ RSpec.describe Rating::Rating, ':values_data' do
|
|
26
26
|
subject(:result) { described_class.values_data article_1, category }
|
27
27
|
|
28
28
|
it 'returns the average of value for a resource' do
|
29
|
-
expect(result.as_json['rating_avg']).to eq 1.5
|
29
|
+
expect(result.as_json['rating_avg'].to_f.to_s).to eq '1.5'
|
30
30
|
end
|
31
31
|
|
32
32
|
it 'returns the sum of values for a resource' do
|
33
|
-
expect(result.as_json['rating_sum']).to eq 3
|
33
|
+
expect(result.as_json['rating_sum'].to_f.to_s).to eq '3.0'
|
34
34
|
end
|
35
35
|
|
36
36
|
it 'returns the count of votes for a resource' do
|
37
|
-
expect(result.as_json['rating_count']).to eq 2
|
37
|
+
expect(result.as_json['rating_count'].to_f.to_s).to eq '2.0'
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -4,7 +4,5 @@ class AddExtraScopesOnRatingRatesTable < ActiveRecord::Migration[5.0]
|
|
4
4
|
def change
|
5
5
|
add_column :rating_rates, :scope_1, :string
|
6
6
|
add_column :rating_rates, :scope_2, :string
|
7
|
-
|
8
|
-
remove_index :rating_rates, %i[author_id author_type resource_id resource_type scopeable_id scopeable_type]
|
9
7
|
end
|
10
8
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateRateTable < ActiveRecord::Migration[5.0]
|
4
|
+
def change
|
5
|
+
create_table :rating_rates do |t|
|
6
|
+
t.decimal :value, default: 0, precision: 25, scale: 16
|
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
|
11
|
+
|
12
|
+
t.timestamps null: false
|
13
|
+
end
|
14
|
+
|
15
|
+
change_column :rating_rates, :author_type, :string, limit: 10
|
16
|
+
change_column :rating_rates, :resource_type, :string, limit: 10
|
17
|
+
change_column :rating_rates, :scopeable_type, :string, limit: 10
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateRatingTable < ActiveRecord::Migration[5.0]
|
4
|
+
def change
|
5
|
+
create_table :rating_ratings do |t|
|
6
|
+
t.decimal :average, default: 0, mull: false, precision: 25, scale: 16
|
7
|
+
t.decimal :estimate, default: 0, mull: false, precision: 25, scale: 16
|
8
|
+
t.integer :sum, default: 0, mull: false
|
9
|
+
t.integer :total, default: 0, mull: false
|
10
|
+
|
11
|
+
t.references :resource, index: true, null: false, polymorphic: true
|
12
|
+
t.references :scopeable, index: true, null: true, polymorphic: true
|
13
|
+
|
14
|
+
t.timestamps null: false
|
15
|
+
end
|
16
|
+
|
17
|
+
change_column :rating_ratings, :resource_type, :string, limit: 10
|
18
|
+
change_column :rating_ratings, :scopeable_type, :string, limit: 10
|
19
|
+
end
|
20
|
+
end
|
data/spec/support/migrate.rb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require File.expand_path('../../lib/generators/rating/templates/db/migrate/create_rating_table.rb', __dir__)
|
4
|
-
require File.expand_path('../../lib/generators/rating/templates/db/migrate/create_rate_table.rb', __dir__)
|
5
|
-
|
6
3
|
Dir[File.expand_path('db/migrate/*.rb', __dir__)].each { |file| require file }
|
7
4
|
|
5
|
+
CreateRateTable.new.change
|
6
|
+
CreateRatingTable.new.change
|
7
|
+
|
8
8
|
CreateArticlesTable.new.change
|
9
9
|
CreateAuthorsTable.new.change
|
10
10
|
|
@@ -12,9 +12,9 @@ CreateGlobalsTable.new.change
|
|
12
12
|
CreateCategoriesTable.new.change
|
13
13
|
|
14
14
|
CreateCommentsTable.new.change
|
15
|
-
|
16
|
-
CreateRatingTable.new.change
|
15
|
+
|
17
16
|
CreateReviewRatingsTable.new.change
|
18
17
|
CreateReviewsTable.new.change
|
18
|
+
|
19
19
|
AddCommentOnRatingRatesTable.new.change
|
20
|
-
AddExtraScopesOnRatingRatesTable.new.change
|
20
|
+
AddExtraScopesOnRatingRatesTable.new.change if ENV['CONFIG_ENABLED_WITH_EXTRA_SCOPES'] == 'true'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rating
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Washington Botelho
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2019-10-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|
@@ -16,20 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
-
- - "<"
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '6'
|
19
|
+
version: '0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
24
|
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version: '
|
30
|
-
- - "<"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '6'
|
26
|
+
version: '0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: database_cleaner
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -100,6 +94,20 @@ dependencies:
|
|
100
94
|
- - ">="
|
101
95
|
- !ruby/object:Gem::Version
|
102
96
|
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: rubocop-performance
|
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'
|
103
111
|
- !ruby/object:Gem::Dependency
|
104
112
|
name: rubocop-rspec
|
105
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -187,6 +195,8 @@ files:
|
|
187
195
|
- spec/support/db/migrate/create_categories_table.rb
|
188
196
|
- spec/support/db/migrate/create_comments_table.rb
|
189
197
|
- spec/support/db/migrate/create_globals_table.rb
|
198
|
+
- spec/support/db/migrate/create_rates_table.rb
|
199
|
+
- spec/support/db/migrate/create_rating_table.rb
|
190
200
|
- spec/support/db/migrate/create_review_ratings_table.rb
|
191
201
|
- spec/support/db/migrate/create_reviews_table.rb
|
192
202
|
- spec/support/factory_bot.rb
|
@@ -219,8 +229,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
229
|
- !ruby/object:Gem::Version
|
220
230
|
version: '0'
|
221
231
|
requirements: []
|
222
|
-
|
223
|
-
rubygems_version: 2.7.3
|
232
|
+
rubygems_version: 3.0.6
|
224
233
|
signing_key:
|
225
234
|
specification_version: 4
|
226
235
|
summary: A true Bayesian rating system with scope and cache enabled.
|
@@ -264,11 +273,13 @@ test_files:
|
|
264
273
|
- spec/support/db/migrate/create_authors_table.rb
|
265
274
|
- spec/support/db/migrate/create_review_ratings_table.rb
|
266
275
|
- spec/support/db/migrate/create_articles_table.rb
|
276
|
+
- spec/support/db/migrate/create_rating_table.rb
|
267
277
|
- spec/support/db/migrate/add_comment_on_rating_rates_table.rb
|
268
278
|
- spec/support/db/migrate/add_extra_fields_on_rating_rates_table.rb
|
269
279
|
- spec/support/db/migrate/create_reviews_table.rb
|
270
280
|
- spec/support/db/migrate/create_comments_table.rb
|
271
281
|
- spec/support/db/migrate/create_globals_table.rb
|
282
|
+
- spec/support/db/migrate/create_rates_table.rb
|
272
283
|
- spec/support/database_cleaner.rb
|
273
284
|
- spec/support/shared_context/with_database_records.rb
|
274
285
|
- spec/factories/article.rb
|