Ruby method returns nil, problem with self reference
I have defined a method called ccy which takes in a number num
, determines the currency (an attribute of the parent Record model) and returns the number multiplied by a conversion factor. Self, in this case, refers to a Setting, which has a number of attributes of its own and belongs to Record. The method is defined in the Setting model below:
开发者_高级运维class Setting < ActiveRecord::Base
belongs_to :record
def ccy(num)
self.record.currency == "USD" ? ( num * 1 ) :
self.record.currency == "GBP" ? ( num * 0.616181 ) :
self.record.currency == "EUR" ? ( num * 0.70618 ) :
self.record.currency == "CAD" ? ( num * 0.97415 ) : nil
end
end
This doesn't work, however, because after doing some tests I've discovered that self.record.currency
is nil. So, when I try to do something like self.ccy(100)
in a rails application, for example, I get the following error:
You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.*
or this, if I'm doing using some sort of operator on the nil element:
TypeError: nil can't be coerced into Fixnum
I've looked around online for a bit and I can't seem to figure out exactly how to fix this. Help appreciated!
Maybe you have a scope problem? In
def ccy(num)
self ...
The self there is referring to an instance of Setting (@setting).
It also seems that this method should be in your Record model. Also, you might consider using a hash for your conversion:
class Setting < ActiveRecord::Base
belongs_to :record
delegate :convert_currecy, :to => :record
end
class Record < ActiveRecord::Base
CURRENCY_CONVERSION_FACTOR =
{
"USD" => 1,
"GBP" => 0.616181
}
def convert_currency(num)
CURRENCY_CONVERSION_FACTOR[currency] * num
end
In addition to @monocle's excellent refactoring suggestion:
You might want to make sure that when you're saving the Record, there's a default currency value set.
Something like:
validates_presence_of :currency
before_save :default_currency
def default_currency
self.currency = "GBP" unless self.currency.present? #Woo Anglophilia!
end
You might also have a/n (potentially implicit) :include_blank => true
in your currency selector such that you're getting these empty values stored in the db.
精彩评论