Как извлечь и отсортировать переменные экземпляра одного класса, которые хранятся в массиве внутри переменной экземпляра в другом классе, используя ruby? - PullRequest
0 голосов
/ 22 апреля 2020

Узнавая больше о Ruby, я в настоящее время сталкиваюсь со стеной. Я пытаюсь извлечь и отсортировать значение переменной экземпляра одного класса, которая хранится в массиве внутри переменной экземпляра в другом классе. Кажется, я могу получить только экземпляр самого класса, а не указанные c переменные экземпляра внутри класса.

Ниже приведены два класса.

product .rb

class Product
  attr_reader :name,
              :price

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

catalogue.rb

class Catalogue
  attr_reader :contents

  def initialize
    @contents = []
  end

  def cheapest
    @contents.product.first
  end

  def <<(product)
    @contents << product
  end
end

Следующий тест подтверждает, что я неправильно извлекаю и сортирую @name или @price для экземпляра Product, который хранится в @contents в экземпляре Catalogue.

catalogue_test.rb

gem 'minitest', '~> 5.2'                                                             
require 'minitest/autorun'                                                           
require 'minitest/pride'  
require 'catalogue'
require 'product'

class CatalogueTest < Minitest::Test                                                 
  def test_cheapest_of_one                                                           
    catalogue = Catalogue.new                                                        
    catalogue << Product.new('scissors', 8)                                          
    assert_equal 'scissors', catalogue.cheapest                                      
  end                                                                          
end

Вот ошибка :

Failure:
CatalogueTest#test_cheapest_of_one [catalogue_test.rb:16]:
--- expected
+++ actual
@@ -1 +1 @@
-"scissors"
+[#<Product:0xXXXXXX @name="scissors", @price=8>]

В идеале я хотел бы иметь возможность извлекать и сортировать товар по цене в нескольких случаях. Я понимаю, что мне нужно будет и дальше расширять существующий код, чтобы обеспечить получение самого дешевого (когда в массиве более одного объекта), но я просто пытался начать с функции basi c для доступа к элементам в it.

До сих пор я пробовал несколько различных методов, таких как sort и first, однако я не могу go выйти за пределы вышеприведенного вывода [#<Product:0xXXXXXX @name="scissors", @price=8>] и углубиться в переменные экземпляра. 10

Что мне нужно добавить к catalogue.rb, чтобы сделать test_cheapest_of_one за catalogue_test.rb проход?

Ответы [ 2 ]

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

В вашем вопросе вы спрашиваете:

Что мне нужно добавить к catalogue.rb, чтобы сделать test_cheapest_of_one за catalogue_test.rb проход?

Но это неправильный вопрос! Как я упоминал в моем комментарии выше , ваша проблема в том, что в вашем тесте вы проверяете, равно ли Product равен String, что может никогда не будет true, потому что Продукт никогда не будет равным строке. Product будет равняться только Product, а String - только String.

Итак, проблема в с вашим тестом , а не с рабочим кодом.

Если бы вы изменили свой производственный код, вам пришлось бы изменить метод cheapest, чтобы вернуть имя самого дешевого продукта. Но это неправильно . Он должен вернуть самый дешевый продукт . Это не поможет вам, если вернет имя, потому что вы ничего не можете сделать с этим именем. Вы не можете распечатать, сколько стоит самый дешевый продукт, например, потому что вы не знаете, какой продукт самый дешевый, вы знаете только, как он называется.

Правильное решение - изменить тест, поэтому что он проверяет, что верный продукт возвращается, а не имя:

def test_cheapest_of_one
  catalogue = Catalogue.new
  scissors  = Product.new('scissors', 8)
  catalogue << scissors

  assert_equal scissors, catalogue.cheapest
end
1 голос
/ 22 апреля 2020

Я думаю, что ваш тест будет работать со следующим определением метода:

def cheapest
  @contents.sort_by(&:price).reverse.first.name
end

или альтернативно

def cheapest
  @contents.sort_by { |product| produce.price * -1 }.first.name
end

В настоящее время вы пытаетесь вызвать @contents.product, который на самом деле вызывает Array # product - не то, что вы хотите.

...