Reputation: 127
I'm trying to make an object within the class Produto with a default value of "Geral" when there's no input for the variable categoria, but I'm having some trouble understanding what is wrong with this challenge, I've been searching for a more in depth class about object oriented but got no clues about what I should change for it to work, I'm really sorry if it's a dumb question.
categoria.rb
require 'produto'
class Categoria
attr_accessor :nome
def initialize(nome: 'Geral')
@nome = nome
end
end
class Produto
attr_accessor :nome, :categoria, :preco, :estoque
def initialize(nome: 'Sem nome', categoria: categoria , preco: '0', estoque: '0')
@nome = nome
@preco = preco
@categoria = categoria
@estoque = estoque
end
def adiciona_estoque(quantidade)
@estoque += quantidade
end
def remove_estoque(quantidade)
@estoque -= quantidade
end
end
spec.rb
it "deveria criar um objeto de categoria Geral por padrão" do
nome = 'Teclado'
preco = 100
estoque = 3
produto = Produto.new(nome: nome, preco: preco, estoque: estoque)
expect(produto.nome).to eq 'Teclado'
expect(produto.categoria.nome).to eq 'Geral'
expect(produto.preco).to eq 100
expect(produto.estoque).to eq 3
end
rspec output
Produto deveria criar um objeto de categoria Geral por padrão
Failure/Error: expect(produto.categoria.nome).to eq 'Geral'
NoMethodError:
undefined method `nome' for nil:NilClass
# ./spec/1_produto_spec.rb:25:in `block (2 levels) in <top (required)>'
Upvotes: 2
Views: 792
Reputation: 158
If you try to run the code verbatim in your class definition of Produto
you'll notice the output
warning: circular argument reference - categoria
This is the first clue. Also, you'll notice that Categoria#nome
is an instance method. That means you'll have to be dealing with an instance of that class to successfully make that method call.
Try modifying your Produto
initializer parameters to make sure you are actually defaulting to giving it an instance of Categoria
(instead of categoria
which, unless you pass in a value, will be nil
). For example:
class Categoria
...
def initialize(nome: 'Sem nome', categoria: Categoria.new , preco: '0', estoque: '0')
@nome = nome
@preco = preco
@categoria = categoria
@estoque = estoque
end
...
end
After making that change, you should see that (within your test block) produto.categoria.nome
returns "Geral".
Upvotes: 1
Reputation: 4440
Short answer: You need to change
def initialize(nome: 'Sem nome', categoria: categoria , preco: '0', estoque: '0')
@nome = nome
@preco = preco
@categoria = categoria
@estoque = estoque
end
to
def initialize(nome: 'Sem nome', categoria: categoria , preco: '0', estoque: '0')
@nome = nome
@preco = preco
@categoria = categoria || Categoria.new
@estoque = estoque
end
Long answer:
Problem that attr_accessor :categoria
is the same as
def categoria
@categoria
end
def categoria=(val)
@categoria = val
end
it mean that when you not setting categoria
in Produto.new
it takes @categoria
that is equal to nil
.
Upvotes: 1