Sigh.

[1] hollandaise_party »  blank_string = String.new
=> ""
[2] hollandaise_party »  price = blank_string.to_d
=> 0.0
[3] hollandaise_party »  price.present?
=> true
[4] hollandaise_party »  price = ''
=> ""
[5] hollandaise_party »  price.present?
=> false

Although I'm not sure what I expected to happen - when trying to figure out why

validates :price, presence: true

was failing when I did not put a value into the input box on my form, turns out the above example is why.

I try not to rely on front end form validations all that much, and build out ActiveRecord validators first. And during the inital stages of testing, I couldn't figure out why that particular validation was failing when I didn't put anything in the input boxes.

Looking into further (I'm bad at source browsing) it looks to be doing something similar to Ruby's to_f method (even though I can't confirm it in the Rails/Rails repo).
If there is not a valid number at the start of str, 0.0 is returned.

So now we know if a blank string is passed to price.to_d method we're going to get 0.0. Well we could just do a check to see if it's blank? price.to_d if price.present? which would technically work. But let's say a user passed in text to our input boxes, instead of an Integer. At that point, the previous example is going to fail.

[6] hollandaise_party »  price = "loltext"
=> "loltext"
[7] hollandaise_party »  price.present?
=> true
[8] hollandaise_party »  price.to_d
=> 0.0

Balls.

There were a few ideas floating around on StackOverflow on how to deal with this - most people opted for regex. However, a more clever solution which I think works better than regex was this:

def is_a_number?(value)
  true if Float(value) rescue false
end

Which works for just about nearly any value you pass to it.

[9] hollandaise_party »  Float('-1000.00')
=> -1000.0
[10] hollandaise_party »  Float('1000')
=> 1000.0

The only thing I found an issue with was if a comma was included in the value.

[11] hollandaise_party »  Float('1,000.00')
ArgumentError: invalid value for Float(): "1,000.00"
from (pry):11:in `Float'

Easy enough solution for that, just .tr (source) the string and remove the comma, then pass that number to the Float(value). The whole method that I ended up using looks like this.

def is_a_number?(value)
  number = value.tr(',','')
  true if Float(number) rescue false
end

Now! Back to our validations! Should look something like this.

price.to_d if is_a_number?(price)

Shazam.
If there is a better way to do this let me know!