iam working on RoR code, i want to know how to find two digit precision for the numbers
a = 0.7
b = 5
thanks
Always your standard
a = "%.2f" % 0.2
b = "%.2f" % 5
0.20
5.00
Outputs strings though, so you may need ("%.2f" % 0.2).to_i or cast later (a.to_i).
number_with_precision. If you're looking to express them as currency, use number_to_currency.
If you're looking to store those numbers and their precision in the database you should set up decimal fields.
add_column :table_name, :column_name, :decimal, :precision => 5, :scale => 2
Options for a decimal field:
:precision : maximum number of digits in a value
:scale : number of digits after the decimal place
With a decimal field you will never need the helper methods to limit the precision after the decimal place.
Related
I just realized my column type needs to be decimal instead of integer
Can i make the change directly in my seeds.rb or there's something else i should do?
Also how do i do this if i intend to add a letter after the decimal?
Example: 2.0L, 2.5L, 5.7L, etc.
If you want to store a letter in your DB, that column type can't be a decimal or integer. A string field would be more appropriate for your case. I'll assume your main question is regarding decimals though.
If you do want to change a column type in the DB, you're supposed to do it using Migrations. From terminal, in your app directory, run: bin/rails g migration changeFieldNameFromIntegerToDecimal.
This will generate a migration file with a timestamp in the filename, in which there is a change method telling rails how you want to change the database. In that change method, put:
def change
change_column :table_name, :column_name, :decimal, precision: :8, scale: :2
end
the precision and scale options do the follwing (from the above link):
precision: Defines the precision for the decimal fields, representing the total number of digits in the number.
scale: Defines the scale for the decimal fields, representing the number of digits after the decimal point.
If you want to convert it to a string, then the migration file would contain:
def change
change_column :table_name, :column_name, :string
end
Finally run bin/rails db:migrate from the terminal in your app directory to execute the migration.
This will change the column type to decimal. To know about the scale and precision check out this Stackoverflow question https://stackoverflow.com/a/2377176/12297707 or the docs https://edgeguides.rubyonrails.org/active_record_migrations.html#column-modifiers
change_column :table_name, :column_name, :decimal, :precision => 8, :scale => 2, :default => 0
I am using simple_form_for for my form template which is not storing decimal numbers into my database table. When I submit the form, it throws away the precision.
Here is what I have:
my schema.rb
create_table "coupons", force: true do |t|
t.decimal "amount", precision: 10, scale: 0
end
new.html.slim
.panel-body.padded
= simple_form_for #coupon, :url => admin_coupons_path do |f|
.form-group
= f.input :amount, as: :string, input_html: { value: number_with_precision(f.object.amount, precision: 8) }, required: true
database image
Am confused as to what else I can do to make that work. Any help will be appreciated.
The missing piece to the puzzle is the precision of the decimal within the database. By default, the code above will create a decimal field in MySQL with 10 digits, all of which are to the left of the decimal point. In other words, saving 15.37 to your model will show 15.37 within the app, but when you save it, it’ll become 15 both in the data store and when you reload it.
The way around this is to specify the precision and the scale in your migration. So correct it with a followup migration:
change_column :table_name_in_plural, :column_name, :decimal, :precision => 10, :scale => 2
In this case, we’ve set the total number of digits (the precision) to 10, with 2 decimal places (the scale.) Note that you can pick your sizes as per your needs – MySQL docs give some guidelines to the storage requirements for different combinations.
Also, when picking your precision and scale, be aware that the scale (max decimal places) can’t be greater than the precisions (total digits.) That might seem obvious when written here, but without those translations in parentheses, it’s easy to get lazy and make the two values the same, which would leave you with a number that has to be less than 1.0, since all the space will be allocated to the right of the decimal place.
Reference: Here
I need to create a column of type double in my database, I understand that in ruby there is no double type and that to simulate this type of value I have to use :scale and :precision
How can i solve this?
You can specify the precision and scale in your migration.
class AddCostToBookings < ActiveRecord::Migration
def change
add_column :bookings, :cost, :decimal, precision: 10, scale: 2
end
end
Precision defines the precision for the decimal fields, representing
the total number of digits in the number.
Scale defines the scale for the decimal fields, representing the number of digits after the decimal point.
I have a pieces model in my rails app, and each piece has a decimal called :price. I want to validate that this price is two decimal places, greater than 0, and is less than a million dollars. I have looked at numerous sources on Stack overflow, and whenever I type a decimal for these validations, for example, 4.99 , the price becomes 4.990000000000000213162820728030055761. This has happened for all the validations I have looked up. Is this because I need to specify my precision for the decimal in my database? How can I fix this?
My current validation:
validates :price, :presence => true, :format => { :with => /\A(\$)?(\d+)(\.|,)?\d{0,2}?\z/ }
Thanks guys!
I dont know which database you are using but you can define precision in your migration like this,
add_column :pieces, :price, :decimal, precision: 8, scale: 2
It will give you a total of 8 digits, with 2 after the decimal point.
About the validation,
If you want that the :price should always have two decimal place (i.e: 4.99) you can try this,
validates :price, presence: true, format: { with: /\A\d+(?:\.\d{2})?\z/ }, numericality: { greater_than: 0, less_than: 1000000 }
If you want that the :price should have at most two decimal or less (i.e: 4, 4.9, 4.99) you can try this,
validates :price, presence: true, format: { with: /\A\d+(?:\.\d{0,2})?\z/ }, numericality: { greater_than: 0, less_than: 1000000 }
Or if you dont want to validate precision and just want to round up the precision before you save it to the database you can use round_with_precision.
You should set it on the database. For example in a migration:
add_column :products, :price, :decimal, precision: 5, scale: 2
Precision is the number of digits in a number. Scale is the number of
digits to the right of the decimal point in a number. For example, the
number 123.45 has a precision of 5 and a scale of 2. In SQL Server,
the default maximum precision of numeric and decimal data types is 38.
https://msdn.microsoft.com/en-us/library/ms190476.aspx
If you're seeing that your values are having additional numbers tacked on, what's likely happening is that your column is set as a floating-point type. If you're working with dollar values do not use floating-point numbers. M. Karim's answer is fine otherwise.
I have a rails model using postgres, with a height_value column, which is set as a decimal.
I want to store values without the trailing zeros, but I am thinking this is not possible with a decimal column type?
If it's not possible to store them this way, what is the best approach to trim off the trailing zeros in my model to make them always display properly. Should I change the column, is there a precision that would do what I want?
so if height_value:
28.5 => 28.5
28.0 => 28
19.75 => 19.75
19.00 => 19
Schema
create_table "buildings", force: true do |t|
t.decimal "height_value"
end
define a read method in your model like this.The value returned will be a string
def height_value
"%g" % read_attribute(:height_value)
end
if you want the method to return a number then
def height_value
val = read_attribute(:height_value)
if val == val.to_i
val.to_i
else
val
end
end
The value stored will be decimal but the value returned from database will satisfy the requirements