Undefined method `+' for nil:Nilclass - Ruby error

Asked

Viewed 2,436 times

1

I have the following Ruby codes in three different files. Follow them:

Rb program.

require_relative "product"
require_relative "store"

cd = Product.new("CD",20.5)
pinico = Product.new("Pinico",30.6)

store = [cd,pinico]
test = Store.new(store)
puts test

product.Rb

class Product
  attr_accessor :name, :price

  def initialize(name,price)
    @name = name
    @price = price
  end

  def to_s
    "name: #{@name} - price: #{@price}"
  end
end

store.Rb

class Store
  attr_accessor :product, :total

  def initialize(product)
    @product = product
  end

  total = 0
  def to_s
    product.each do |product|
      puts product.price
      total += product.price
    end
    "Soma total dos produtos: #{@total}"
  end
end

From the store.Rb file, I would like to sum up the total value of the products and return them to the program.Rb file, where I build the class. When I run the same file on the terminal, it returns me the following error:

/home/cabox/workspace/test/store.rb:12:in `block in to_s': undefined method `+' for nil:NilClass (NoMethodError)
        from /home/cabox/workspace/test/store.rb:10:in `each'
        from /home/cabox/workspace/test/store.rb:10:in `to_s'
        from programa.rb:9:in `puts'
        from programa.rb:9:in `puts'
        from programa.rb:9:in `<main>'

I would like to know how I should proceed to remedy the error.

1 answer

1


In your class store.Rb the variable total is defined outside the method def to_s, soon it becomes inaccessible for instance methods.

The correct code for it would be the following:

class Store
  attr_accessor :products

  def initialize(products)
    @products = products
  end

  def to_s
    total = 0
    products.each do |product|
      total += product.price
    end

    "Soma total dos produtos: #{total}"
  end
end

Note that I

  1. corrected the variable name @product for @products,
  2. removed the instance variable @total and used a temporary within the scope of to_s
  3. removed the puts that was inside the .each.

If you use Ruby > 2.4 you want to further improve your code you can leave the def to_s as follows:

def to_s
  "Soma total dos produtos: #{@products.sum(&:price)}"
end

See the method documentation Array#sum. And the use of &:price is an abbreviation when the block is of the type @products.sum { |product| product.price }.

For versions < 2.4 vc you can use @products.map(&:price).reduce(&:+)

Gives a quick search on the internet about the scope of variables in Ruby (I found this one), helps a lot who is starting and is very simple. Good luck :)

  • 1

    Just what I needed! I’m new to Ruby and I end up having doubts about it. The link you informed me helped me a lot to understand more about it. Thank you very much for all the help and attention! :)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.