My Money Problem
By: Jonelle Noelani Yacapin
Tags: Javascript Tips, Ruby on Rails, JavaScript, Rails, Serializers

Money

I’m making a single page application (SPA) with a Ruby on Rails as an API backend and HTML/CSS/JavaScript for the frontend. The wine resource has an attribute of price. What datatype should I use to have 19.00 (with the 2 zeros after the decimal) passed to the front end where I can just prepend a $ sign and walk away?

Float

Initially, I thought to use a float data type for my price attribute since it allows for decimals. But, when I set my price to be 50.00 in the seeds.rb file it converts it to 50.0 and drops the second 0.

That price looks pretty sus

After doing some research, I discovered float is the worst data type for money because it doesn’t compute (add, subtract, multiply etc.) in the same way we expect numbers to

Decimal

An overwhelming amount of sources recommend using the decimal data type because it allows for the decimal (go figure) and it’s more accurate with computations.

The precision is for the number of digits allowed in the number and scale is the number of digits to follow the decimal point.

With a precision of 5, I figure none of my wines are going to have a price higher than $999.99.

Sounds perfect!

But, when I bring it into my JavaScript frontend, the 50.00 that I had in my seeds.rb file gets converted to 50.0.

sigh… I had such high hopes.

In the backend, I decide to check what the price output is in the rails console (type “rails c” in the terminal) by inputing Wine.last.price .

It returns… 0.25e2

What’s going on here? The actual price in the seeds.rb file is 25.00.

So, I guess the decimal data type is going to convert 25.00 into 0.25e2. Fine by me as long as the program understands what’s going on.

But why won’t it leave the 2 zeros intact when I bring it to the frontend?

To dust this under the rug, I used a “edit” functionality I built in JavaScript to change the price from 25.0 to 24.99 and it leaves all the numbers intact.

Why fret over this?

Since I’m already building a lot of code in JavaScript for my frontend, I’d rather the prices be set in the backend so I can just call them without having to do additional configuration in the front end.

The most configuration I wanted to do was add a ‘$’ in front.

div4.innerText = `Price: $${wine.price}`

Thinking ahead, I wanted to be prepared for this project to grow and possibly have the price attribute in a couple places where I would maybe have to do some sort of math.

It didn’t quite get to that point but, it ain’t over till it’s over, right?

Money-Rails Gem

Onward with the money quest I found this neat gem.

Returned back to my migrations…

class CreateWines < ActiveRecord::Migration[6.0] def change create_table :wines do |t| t.string :name t.string :varietal t.string :wine_type t.string :country t.string :image_url t.monetize :price, precision: 5, scale: 2 t.timestamps end end end

… which creates this in my schema.rb …

create_table "wines", force: :cascade do |t| t.string "name" t.string "varietal" t.string "wine_type" t.string "country" t.string "image_url" t.integer "price_cents", default: 0, null: false t.string "price_currency", default: "USD", null: false t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false end

(Notice now there’s a “price_cents” integer column and “price_currency” string column)

… then add one more thing to my Wine model …

class Wine < ApplicationRecord has_many :reviews, :dependent => :destroy has_many :users, through: :reviews monetize :price_cents, as: "price" end

Alright, all this work and setup. Moment of truth. I checked my api in JSON format.

"id": 1, "name": "Buena Vista", "varietal": "Cabernet Sauvignon", "wine_type": "red", "country": "USA", "image_url": "https://images.vivino.com/thumbs/f7tR4MRISRWWdrXFoGzG_w_pb_x600.png", "price_cents": 5000, "price_currency": "USD", "created_at": "2020-10-23T05:01:00.008Z", "updated_at": "2020-10-23T05:01:00.008Z"

😭I’ve strayed farther from my goal. I think when I called for a price of wine in the front end it would appear as “USD 5000”.

Note: I’m new to coding and I’m sure this cool money gem could work for my purposes with some helper methods but I’m going to have to figure that out some other time. I have less than a week to finish this project for my coding bootcamp program.

After all that, I reverted back to the decimal type and when I came across a wine priced at $25.0 in my app, I would use the Edit button I created to “fix” it to something like $24.99.😏