Проблема в том, что WheelStore
выполняет процедурную работу для Wheel
. Вам нужен правильный класс Колеса.
class Wheel
attr_reader :rim, :tire
def initialize(rim:, tire:)
@rim = rim
@tire = tire
end
def diameter
rim + (tire * 2)
end
end
Тогда wheelify
уходит. Вместо этого используйте Wheel.new
напрямую. Инициализируйте только с соответствующими объектами колеса. Это более гибко и эффективно. Вместо того, чтобы сначала преобразовывать данные из исходного формата в формат Array of Arrays, а затем снова в пары ключ / значение, их нужно преобразовать только один раз в пары ключ / значение.
class WheelStore
attr_reader :wheels
def initialize(wheels: [])
@wheels = wheels
end
def diameters
wheels.map { |wheel| wheel.diameter }
end
end
datum = [["rim1", "tire1"], ["rim2", "tire2"]]
wheel_store1 = WheelStore.new(
wheels: datum.map { |data| Wheel.new(rim: data[0], tire: data[1]) }
)
datum = [
{ rim: "rim1", tire: "tire1" },
{ rim: "rim2", tire: "tire2" }
]
wheel_store2 = WheelStore.new(
wheels: datum.map { |data| Wheel.new(**data) }
)
Если у вас есть укажите c форматы данных, которые вы обычно превращаете в Wheels, тогда вы должны создать классовый метод для работы с ними.
class Wheel
class << self
def new_from_array(wheel_data)
new(rim: wheel_data[0], tire: wheel_data[1])
end
end
end
datum = [["rim1", "tire1"], ["rim2", "tire2"]]
ws = WheelStore.new(
wheels: datum.map { |data| Wheel.new_from_array(data) }
)
Если импорт Wheels становится достаточно сложным, вы можете написать WheelImporter.
Возможно, вы предполагаете, что Struct будет более эффективным, чем именованный класс, но в Ruby это не так. Это почти точно так же с точки зрения производительности.
2.6.5 :001 > Wheel = Struct.new :rim, :tire, keyword_init: true
=> Wheel(keyword_init: true)
2.6.5 :002 > Wheel.class
=> Class
#best
def diameters
wheels.map { diameter }
end
2.7 добавлено Нумерованные параметры .
wheels.map { _1.diameter }
До версии 2.7 вы должны объявить аргументы.
Вы можете обойти это с помощью instance_eval
и создать свои собственные неявные версии методов Enumerable. Это превращает каждый элемент в тему блока, self
.
module Enumerable
def implied_map(&block)
map { |a| a.instance_eval(&block) }
end
end
[1,2,3].implied_map { to_s } # ["1", "2", "3"]
[1,2,3].implied_map { self.to_s } # same
... но не делайте этого. instance_eval
полезно для записи DSL . Но создание собственных версий стандартных методов означает, что вы создаете свой собственный небольшой отросток Ruby, который другие люди должны будут изучить.