Forum: Ruby Undefined method `-' for nil

Posted by Joz Private (joza)
on 2012-10-08 22:13
Hi guys.

So I've hit a brick wall with a simple piece of code and hope someone
here can shed some light on what's going wrong ...

***************************************************
developer_object_array.each do |dev|
    if dev.is_solvent? == false
      then puts("#{dev.name} is bankrupt.")
        dev.bankrupt = true
        bank_object_array.each do |bank|
          bank.moves_loans(amount)
    else puts("#{dev.name} is not bankrupt.")
    end
  end
*********************************************************

I have the above piece of code in a class. Inside this class I create
and array of Bank and Developer objects. When the code gets to
bank.move_loans
I get an "undefined method `-' for nil:NilClass (NoMethodError" error.

The move_loans method is defined in the Bank class just does some basic
subtraction on the value passed to it.

I've no idea what the error is, as I've torn through every piece of code
in the classes and can't see anything wrong.

Any ideas would be great!! Thanks!
Posted by Sam Duncan (Guest)
on 2012-10-08 22:18
(Received via mailing list)
On 10/09/2012 09:13 AM, Joz Private wrote:
>          bank_object_array.each do |bank|
>
> The move_loans method is defined in the Bank class just does some basic
> subtraction on the value passed to it.
>
> I've no idea what the error is, as I've torn through every piece of code
> in the classes and can't see anything wrong.
>
> Any ideas would be great!! Thanks!
>
Really need to see what the developer objects and bank objects look
like, and how/ where the bank_object_array gets populated.

Sam
Posted by Joz Private (joza)
on 2012-10-08 22:35
class Developer
  attr_accessor :name, :networth, :loans, :banks_loaned_from, :bankrupt

  def initialize(name, networth, loans, banks_loaned_from, bankrupt)
  @name, @networth, @loans, @banks_loaned_from, @bankrupt = name, 
networth, loans, banks_loaned_from, bankrupt
  end

  def is_solvent?
    if networth >= owes_amount
      then true
    else  false
    end
  end

        def owes_amount
    total_loans = 0
    loans_array = loans.split(',')
    loans_array.each { |item| total_loans += item.to_f }
    total_loans
  end

  def owes_bank(bank)
    loans_array = loans.split(',')
    banks_array = banks_loaned_from.split(',')
    banks_array.each do |item|
      if bank == item
        then i = banks_array.index(item)
        loans_array[i].to_f
      else
        puts("No such bank - check name.")
      end
    end
  end

end
**************************************************************************
**************************************************************************
class Bank
  attr_accessor :name, :amount_of_deposits, :amount_of_loans

  def initialize(name, amount_of_deposits, amount_of_loans)
    @name, @amount_of_deposits, @amount_of_loans, = name, 
amount_of_deposits, amount_of_loans
  end

  def moves_loans(amount)
    amount_of_loans -= amount
    amount_of_deposits += (amount*0.5)
  end

  def bank_is_solvent?
    if amount_of_deposits >= amount_of_loans
      true
    else
      false
    end
  end

end
**************************************************************************
**************************************************************************
require_relative '.\Bank.rb'
require_relative '.\Developers.rb'

class Bankrupter

  # creating the developers
  L = Developer.new("L", 650000, "1500000, 500000, 1000000, 300000", 
"AIB,BOI,Ulster,Anglo", false)
  M = Developer.new("M", 2100000, "1400000, 2000000", "AIB,Anglo", 
false)
  R = Developer.new("R", 900000, "500000, 700000, 1000000, 1200000", 
"AIB,BOI,RSB,Anglo", false)
  MF = Developer.new("MF", 1200000, "400000, 2000000, 8000000", 
"AIB,Ulster,Anglo", false)
  MN = Developer.new("MN", 3000000, "100000, 300000", "BOI,RSB", false)

  # creating the banks
  AIB = Bank.new("AIB", 450, 3000000, 500000, false)
  Anglo = Bank.new("Anglo", 520, 5000000, 12000000, false)
  BOI = Bank.new("BOI", 600, 2500000, 2500000, false)
  RBS = Bank.new("RBS", 530, 2800000, 1700000, false)
  Ulster = Bank.new("Ulster", 580, 2000000, 1500000, false)


  developer_object_array = [ L, M, R, MF, MN]
  bank_object_array = [ AIB, Anglo, BOI, RBS, Ulster ]

  #Now, test if they are solvent or bankrupt, and then the knock-on 
effects for the banks ...

  developer_object_array.each do |dev|
    if dev.is_solvent? == false
      then puts("#{dev.name} is bankrupt.")
        dev.bankrupt = true
        bank_object_array.each do |bank|
          bank.moves_loans
        end
    else puts("#{dev.name} is not bankrupt.")
    end
  end

end
Posted by Prog Rammer (proggrammer)
on 2012-10-08 22:35
Go into the function: bank.moves_loans
and for each '-' operation check operand, I am 100 % sure that one of 
the operand becomes NIL at some point.

Looking at your question, I would like to give an explicit answer, which 
is not expected here:

for each statement involving '-' viz:
a=b-c
replace it by:
if b==nil or c==nil
  puts "My 100% is proved, here is the error"
else
  a=b-c
end
Posted by Joz Private (joza)
on 2012-10-08 22:37
Don't mind the extra fields in the Bank object creation, they're not 
supposed to be there
Posted by Sam Duncan (Guest)
on 2012-10-08 22:47
(Received via mailing list)
On 10/09/2012 09:35 AM, Joz Private wrote:
>        then true
>
>      end
> amount_of_deposits, amount_of_loans
>      else
> class Bankrupter
>    MN = Developer.new("MN", 3000000, "100000, 300000", "BOI,RSB", false)
>    bank_object_array = [ AIB, Anglo, BOI, RBS, Ulster ]
>          end
>      else puts("#{dev.name} is not bankrupt.")
>      end
>    end
>
> end
>
Well for a start, Bank#moves_loans method takes an 'amount' argument
which you don't appear to be passing. I wouldn't be assigning your bank
and developer instances to constants either (variable names starting
with upper case letters are implicitly constants in Ruby). Also, the
constructor for the Bank object takes 3 values, however you are passing
them 5?

Sam
Posted by Joz Private (joza)
on 2012-10-08 23:22
Sam Duncan wrote in post #1079016:
> On 10/09/2012 09:35 AM, Joz Private wrote:
>>        then true
>>
>>      end
>> amount_of_deposits, amount_of_loans
>>      else
>> class Bankrupter
>>    MN = Developer.new("MN", 3000000, "100000, 300000", "BOI,RSB", false)
>>    bank_object_array = [ AIB, Anglo, BOI, RBS, Ulster ]
>>          end
>>      else puts("#{dev.name} is not bankrupt.")
>>      end
>>    end
>>
>> end
>>
> Well for a start, Bank#moves_loans method takes an 'amount' argument
> which you don't appear to be passing. I wouldn't be assigning your bank
> and developer instances to constants either (variable names starting
> with upper case letters are implicitly constants in Ruby). Also, the
> constructor for the Bank object takes 3 values, however you are passing
> them 5?
>

My bad, I just copied the code wrong .... assuming I have all that fixed
...

I've stumbled on this:

The move_loans method works if I use this code below as I get the
output:

def move_loans
     puts(amount_of_loans - amount)
end

But if I replace the body with what I really want, it throws the error:

def moves_loans
     amount_of_loans = amount_of_loans - amount
end

It seems to be THAT body right there that's throwing the error...what's
going on??!!


> Sam
Posted by Sam Duncan (Guest)
on 2012-10-08 23:31
(Received via mailing list)
On 10/09/2012 10:22 AM, Joz Private wrote:
>>>           end
>> constructor for the Bank object takes 3 values, however you are passing
> def move_loans
> going on??!!
>
>
>> Sam
It is very confusing what the code actually looks like. Do you think you
could put the whole lot up as a gist on github or some other pastebin
type bizzo? It is not clear where the 'amount' value comes from in that
method now for a start =]

Sam
Posted by Joz Private (joza)
on 2012-10-08 23:34
Sam Duncan wrote in post #1079021:
> On 10/09/2012 10:22 AM, Joz Private wrote:
>>>>           end
>>> constructor for the Bank object takes 3 values, however you are passing
>> def move_loans
>> going on??!!
>>
>>
>>> Sam
> It is very confusing what the code actually looks like. Do you think you
> could put the whole lot up as a gist on github or some other pastebin
> type bizzo? It is not clear where the 'amount' value comes from in that
> method now for a start =]
>
> Sam

Sorry, I really messed up copying the code :p

The amount gets passed as in:

bank.moves_loans(dev.owes_bank(bank.name))

^^^That's what should be in Bankrupter class above!
Posted by "Jesús Gabriel y Galán" <jgabrielygalan@gmail.com> (Guest)
on 2012-10-09 09:58
(Received via mailing list)
On Mon, Oct 8, 2012 at 11:22 PM, Joz Private <lists@ruby-forum.com> 
wrote:

> def moves_loans
>      amount_of_loans = amount_of_loans - amount
> end

Here amount_of_loans is understoos as a local variable, since you have
an assigment, so the amount_of_loans at the right hand side gets
evaluated to nil. I guess you want the instance variable, so:

def moves_loans
  @amount_of_loans = @amount_of_loans - amount
end

or

def moves_loans
  @amount_of_loans -= amount
end

Jesus.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.