Как сделать объект со значением по умолчанию, если он не передан в класс? - PullRequest
1 голос
/ 23 февраля 2020

Я пытаюсь создать объект в классе Produto со значением по умолчанию "Geral", когда нет входных данных для переменной категории, но у меня возникли проблемы с пониманием, что не так с этой задачей, я я искал более углубленный класс об объектно-ориентированном, но не получил ни малейшего представления о том, что я должен изменить, чтобы он работал, мне очень жаль, если это глупый вопрос.

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

rspe c 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)>'


Ответы [ 2 ]

1 голос
/ 23 февраля 2020

Если вы попытаетесь дословно запустить код в определении класса Produto, вы заметите вывод

warning: circular argument reference - categoria

Это первая подсказка. Также вы заметите, что Categoria#nome - это метод экземпляра. Это означает, что вам придется иметь дело с экземпляром этого класса, чтобы успешно выполнить этот вызов метода.

Попробуйте изменить параметры инициализатора Produto, чтобы убедиться, что вы по умолчанию задаете ему экземпляр Categoria (вместо categoria, которое, если вы не передадите значение, будет nil). Например:

class Categoria
  ...
  def initialize(nome: 'Sem nome', categoria: Categoria.new , preco: '0', estoque: '0')
    @nome = nome
    @preco = preco
    @categoria = categoria
    @estoque = estoque
  end
  ...
end

После внесения этого изменения вы должны увидеть, что (в пределах вашего тестового блока) produto.categoria.nome возвращает "Geral".

1 голос
/ 23 февраля 2020

Краткий ответ: Вам нужно изменить

def initialize(nome: 'Sem nome', categoria: categoria , preco: '0', estoque: '0')
  @nome = nome
  @preco = preco
  @categoria = categoria
  @estoque = estoque
end

на

def initialize(nome: 'Sem nome', categoria: categoria , preco: '0', estoque: '0')
  @nome = nome
  @preco = preco
  @categoria = categoria || Categoria.new
  @estoque = estoque
end

Длинный ответ: Проблема в том, что attr_accessor :categoria совпадает с

def categoria
  @categoria
end

def categoria=(val)
  @categoria = val
end

это означает, что когда вы не устанавливаете categoria в Produto.new, требуется @categoria, что равно nil.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...