Open fluffyx opened 4 years ago
Hi @fluffyx looks like your database field has a precision less (17/14) than the necessary (numeric field overflow). You should use a precision like the migration:
t.decimal :value, default: 0, precision: 25, scale: 16
I'm getting this error with a fresh instalation ActiveRecord::ValueTooLong Exception: PG::StringDataRightTruncation: ERROR: value too long for type character varying(10) Maybe related, how can i fix it?
I could have sworn the field was set up correctly, but maybe not.
After further troubleshooting, I found it occurred when more than 999 entries were in the table. I switched to ratyrate before @wbotelhos responded and that gem met my needs with some small customization.
Curious, does the migration trick work for you?
Good luck!
Yes, I don't have your same error. About my error, it's just increase the string fields limits in the migrations, from 10 to 20. Greetings
Hi @jeferbc ,
varying(10)
is too short to keep the precision needed.
@fluffyx I believe your problem is the same, just increase the precision. I use Postgres too and it is ok.
I don't know this gem, but I can see that is about build the Raty presentation. This gem is about make the hard and fair "average" calculation. Just check this goals.
Hi there, I got the same issue exactly although the schema was (25, 16) already. Any suggestions?
ActiveRecord::RangeError
PG::NumericValueOutOfRange: ERROR: numeric field overflow
DETAIL: A field with precision 17, scale 14 must round to an absolute value less than 10^3.
PG::NumericValueOutOfRange
ERROR: numeric field overflow
DETAIL: A field with precision 17, scale 14 must round to an absolute value less than 10^3.
# db/schema.rb
create_table "rating_rates", id: :serial, force: :cascade do |t|
t.decimal "value", precision: 25, scale: 16, default: "0.0"
t.string "author_type", limit: 10, null: false
t.integer "author_id", null: false
t.string "resource_type", limit: 50, null: false
t.integer "resource_id", null: false
t.string "scopeable_type", limit: 50
t.integer "scopeable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "comment"
t.index ["author_type", "author_id", "resource_type", "resource_id", "scopeable_type", "scopeable_id"], name: "index_rating_rates_on_author_and_resource_and_scopeable", unique: true
t.index ["author_type", "author_id"], name: "index_rating_rates_on_author_type_and_author_id"
t.index ["resource_type", "resource_id"], name: "index_rating_rates_on_resource_type_and_resource_id"
t.index ["scopeable_type", "scopeable_id"], name: "index_rating_rates_on_scopeable_type_and_scopeable_id"
end
create_table "rating_ratings", id: :serial, force: :cascade do |t|
t.decimal "average", precision: 25, scale: 16, default: "0.0"
t.decimal "estimate", precision: 25, scale: 16, default: "0.0"
t.integer "sum", default: 0
t.integer "total", default: 0
t.string "resource_type", limit: 50, null: false
t.integer "resource_id", null: false
t.string "scopeable_type", limit: 50
t.integer "scopeable_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["resource_type", "resource_id", "scopeable_type", "scopeable_id"], name: "index_rating_rating_on_resource_and_scopeable", unique: true
t.index ["resource_type", "resource_id"], name: "index_rating_ratings_on_resource_type_and_resource_id"
t.index ["scopeable_type", "scopeable_id"], name: "index_rating_ratings_on_scopeable_type_and_scopeable_id"
end
Hi, @fongfan999 .
Do you have the number for us try to emulate the error? I'm trying to imagine the problem and maybe it could be the SQL returning a very large precision number that does not fit well in the DB constraint.
Hi @wbotelhos
I'm sorry, I'm not sure what number you expected?
Rating::Rating.averager_data(User.first, nil).rating_avg.to_s
=> "4.9469469469469469"
@fongfan999 I checked the code and maybe I found a possible bug, but not using the number you provided.
Your number will be fit like this:
The value: 4.9469469469469469 Total number: 17 Precision: 1 (on the left side of the dot (.)) Scale: 16 (on the right side of the dot (.))
Rating uses a migration like this:
t.decimal :value, default: 0, precision: 25, scale: 16
So you can fit a number like this:
The value: 123456789.1234567812345678 (9+16) Total number: 25 (9+16) Precision: 9 (on the left side of the dot (.)) Scale: 16 (on the right side of the dot (.))
In a place where you can have (9+16) you should be allowed to fit yours (1+16)
How to debug it?
The place the code generates the result is here via SQL where we have:
(CAST(#{total_count} AS DECIMAL(17, 14)) / #{distinct_count}) count_avg
Using your app value, like I asked for an example we have:
SELECT (CAST(4.9469469469469469 AS DECIMAL(17, 14)) / 2) count_avg
-- 2.4734734734734750
The result 2.4734734734734750
is (1.16) and should work.
The possible bug
Maybe the problem is around the distinct_count
division because when we divide by a number like 3
the scale can grow:
SELECT (CAST(4.9469469469469469 AS DECIMAL(17, 14)) / 3) count_avg
-- 1.6489823156489833
See that the division is outside the CAST
so we're not forcing the "precision.scale". Now let's force it:
SELECT CAST(4.9469469469469469 / 3 AS DECIMAL(17, 14)) count_avg
-- 1.64898231564898
We have a difference here of 2 numbers on the scale:
1.6489823156489833
1.64898231564898
It still should not be a problem since default cast is DECIMAL(17, 14)
being less than what migration expect precision: 25, scale: 16
. The two extra numbers here would become scale equal to 16 that is covered by migration.
But it's almost impossible predict all possible rating values and so the result of the division that can increase more than only two numbers. So I think the distinct_count
should be included on the CAST
to make sure the precision and scale and we should increase the precision like the actual migration not the old 17.14 value.
Just rephrasing, after a conversation with Peter we changed the final rounding to 2 decimals so it should not a problem anymore. Since the round was done on the Ruby side, not the SQL side we still can make the correction in the SQL and leave the round as it is. A future feature could be an adapter to change the final round based in a configuration so people can decide keeps the 25.16 or round it just change the config and the migration.
@wbotelhos Thank you so much for taking a look, so how do we resolve the issue? by upgrade the gem to the latest version?
@fongfan999 I believe that the last version won't be buggy since the return is just 2 decimals. Are you using the last version?
@wbotelhos I upgraded to the latest version, which is 1.0.0
but the error was still there.
Then I downgraded to this commit: e8582b792ca66d03a1ff76d088254a794030b71b, it worked. Anyway, thank you for you help.
I'm now getting this error when trying to rate any object of a specific class. No code changes occurred; seems something is messed up in the database.
Is there a way to rebuild the cache or something?
ActiveRecord::RangeError (PG::NumericValueOutOfRange) ERROR: numeric field overflow DETAIL: A field with precision 17, scale 14 must round to an absolute value less than 10^3.