How do I initialize a primitive, and add to it? - ruby-on-rails

I'm trying to initialize a variable as a float and then add to it in a times loop. Here's my code:
amt = 0.0
5.times do
amt = amt + ("%.2f" % (item.price * 0.05))
end
Here's the error:
String can't be coerced into Float
EDIT:
I've changed the 1.times do. I had adapted my code so that it would be more readable, the 1.times wasn't in my actual code.

Firstly, try not to use floats for money - what you'll need to do in this case is use BigDecimal - floating point math is not accurate.
To use BigDecimal, require 'bigdecimal' in your application.rb
Then, what you want is:
amt = BigDecimal.new("0")
1.times do
price = BigDecimal.new(item.price.to_s)
factor = BigDecimal.new("0.05")
amt += (price * factor).round(2)
end
amt

Yeah sorry everyone. I am new to Ruby so I didn't know that this was the problem, but the "%.2f" was causing the problem. (Although irrelevant to this question, what this does is convert the amount into two decimal precision.) Stupid mistake!

Related

Is an integer variable not numeric in Ruby?

I have user_waiting period saved as an integer in my DB. I am trying to use it in the below code, but I keep getting the error "Expected Numeric." I am very new to Ruby, and my understanding was that an integer would be numeric. Am I incorrect in this understanding?
if #pto_management.waiting_period.nil?
#pto_management.accrual_begin_date = current_user.start_date
else
#pto_management.accrual_begin_date = current_user.start_date +
#pto_management.user_waiting_period
end
Perhaps explicitly convert it to an int?
if #pto_management.waiting_period.nil?
#pto_management.accrual_begin_date = current_user.start_date
else
#pto_management.accrual_begin_date = current_user.start_date +
#pto_management.user_waiting_period.to_i # <-- HERE
end

How can I divide two table fields?

This is in my model:
before_save :set_pay_this
def set_pay_this
self.pay_this = "#{self.amount} / #{self.divisor}"
end
end
But what gets saved as "pay this" is the "amount" entry, so no division is being done. Is it my syntax or what else should I post to ask my question properly?
"#{self.amount} / #{self.divisor}" is a string. If amount was 5 and divisor was 2 you'd end up with "5 / 2" the string, not the mathematical equation. You want this:
self.pay_this = self.amount / self.divisor
Or maybe this if you care about the cents and amount and divisor are integers.
self.pay_this = self.amount.to_f / self.divisor

Ruby get arrays of dates based on given period

I have question is there maybe a fine simple solution to this task:
I have first_date = "2011-02-02" , last_date = "2013-01-20" and period = 90 (days).
I need to get arrays with two elements for example:
[first_date, first_date + period] ... [some_date, last_date].
I will make it with some kind of a loop but maybe there is some nice fancy way to do this :D.
Date has a step method:
require 'date'
first_date = Date.parse("2011-02-02")
last_date = Date.parse("2013-02-20")
period = 90
p first_date.step(last_date-period, period).map{|d| [d, d+period]}
#or
p first_date.step(last_date, period).map.each_cons(2).to_a
require 'pp'
require 'date'
first_date=Date.parse "2011-02-02"
last_date=Date.parse "2013-01-20"
period = 90
periods = []
current = first_date
last = current + period
while(last < last_date ) do
periods << [current, last]
current = last
last = current + period
end
if periods[-1][1] != last_date
periods << [periods[-1][1], last_date]
end
p periods
I am assuming that the last period must end on last_date regardless of its length, as your question implies.

Simple calculation causes syntax error in Ruby

I have a simple financial app in Ruby that can keep track of a user's expenses and generate reports based on them.
Expenses belong to different categories, which affects how much of each expenses is taxes.
In my code to generate a report on expenses, I have this piece:
tax_totals = [0] * 13
totals = [0] * 13
expenses.each do |expense|
tax_ratio = tax_rate/(1+tax_rate)
category = Category.find(expense.category_id).first
tax_ratio *= category.tax_rate.to_f / 100
if !expense.rate_id.nil?
subcategory = Rate.where("id = ?", expense.rate_id).first
tax_ratio *= subcategory.tax_rate.to_f
end
tax_totals[expense.transaction_date.to_date.month] +=
(expense.amount * tax_ratio)
totals[expense.transaction_date.to_date.month] += expense.amount
end
I keep getting a syntax error on the line tax_ratio = tax_rate/(1+tax_rate):
syntax error, unexpected '(', expecting keyword_end
If I remove that line, the error moves to tax_ratio *= category.tax_rate.to_f / 100 line:
syntax error, unexpected tINTEGER, expecting keyword_end
and I have NO IDEA, where this is coming from. I don't see anything wrong with the code at all. I have very similar code in multiple functions each doing the calculations slightly differently. But only this one is an issue.
Maybe it's the lack of caffeine. Is there something wrong with this code? Could there be something else in the file causing this? How can I proceed with debugging?
Cheers!
EDIT: I figured it out. Ruby noob mistake. See answer below.
As written above, this is valid Ruby. I was able to get your code into a method and call it. See below:
require 'active_support/all'
require 'rspec'
class Category
def self.find(category_id)
[new]
end
def tax_rate
0.5
end
end
class Rate
def self.where(*args)
[new]
end
def tax_rate
0.5
end
end
def ratio(expenses, tax_rate)
tax_totals = [0] * 13
totals = [0] * 13
expenses.each do |expense|
tax_ratio = tax_rate/(1+tax_rate)
category = Category.find(expense.category_id).first
tax_ratio *= category.tax_rate.to_f / 100
if !expense.rate_id.nil?
subcategory = Rate.where("id = ?", expense.rate_id).first
tax_ratio *= subcategory.tax_rate.to_f
end
tax_totals[expense.transaction_date.to_date.month] +=
(expense.amount * tax_ratio)
totals[expense.transaction_date.to_date.month] += expense.amount
end
end
describe "#ratio" do
let(:expense) do
double("expense", category_id: 5, rate_id: 6, transaction_date: 5.days.ago, amount: 5)
end
let(:expenses) { [expense] }
let(:tax_rate) { 0.25 }
it "should run" do
ratio(expenses, tax_rate)
end
end
I am new to Ruby and Rails and to me this was the weirdest thing ever.
The error was coming from such an innocent looking line that I didn't even bother to include it in my original question.
tax_rate was a variable that was getting passed to the method. It's stored in a DB as an integer, so I needed to convert it to a decimal point. This was the more complete code:
tax_rate = tax_rate.to_f /100
tax_totals = [0] * 13
totals = [0] * 13
expenses.each do |expense|
tax_ratio = tax_rate/(1+tax_rate)
category = Category.find(expense.category_id).first
tax_ratio *= category.tax_rate.to_f / 100
if !expense.rate_id.nil?
subcategory = Rate.where("id = ?", expense.rate_id).first
tax_ratio *= subcategory.tax_rate.to_f
end
tax_totals[expense.transaction_date.to_date.month] +=
(expense.amount * tax_ratio)
totals[expense.transaction_date.to_date.month] += expense.amount
end
And that first line is what Ruby doesn't like and I still don't know why. But you can't put myVar /100 it has to be myVar / 100 or even myVar/ 100 but there absolutely needs to be a space between / and the number.

LocalJumpError (Ruby on Rails)

I have searched/Googled around but I'm struggling with the following problem.
I am building a Rails 2.3.2 application and one of the requirements is to calculate the median of an array of results. I am using code for calculating the median from the Ruby Cookbook but keep running in to a problem with receiving an error 'LocalJumpError - no block given' when I attempt to find the median of an array where there are an odd number of members.
The example code in my view is as follows:
<%= survey_response.median([6,4,5,4,4,2]) %>
Then in survey_response.rb model the methods are as follows:
def mean(array)
array.inject(array.inject(0) { |sum, x| sum += x } / array.size.to_f)
end
def median(array,already_sorted=false)
return nil if array.empty?
array = array.sort unless already_sorted
m_pos = array.size / 2
return array.size % 2 == 1 ? array[m_pos] : mean(array[m_pos-1..m_pos])
end
The error is caused when the median method refers back to the mean method to get the media of an odd total of items in the array. I just can't figure out why I get that error or indeed how to fix it - so I'd hugely appreciate any help/guidance/laughing anybody could offer me!
Thanks
Simon
Lis looks like it's due to you using a fractional index into the array. Try replacing:
m_pos = array.size / 2
with:
m_pos = (array.size / 2).ceil
Also, try changing your mean function to this:
def mean(array)
array.inject(0) { |sum, x| sum += x } / array.size.to_f
end
That mean method looks horribly botched. Try this:
def mean(array)
a.inject(0) { |sum,x| sum += x } / a.size.to_f
end
Better code:
def mean(array)
array.inject { |sum, n| sum + n } / array.length.to_f
end
def median(array)
return nil if array.empty?
array.sort!
middle = array.length / 2
(array.length % 2 == 1) ? array[middle] : mean([array[middle-1], array[middle]])
end
puts median([5,11,12,4,8,21]) # => 9.5

Resources