Ruby 直接将结构传递给具有匹配关键字参数的方法

Ruby 直接将结构传递给具有匹配关键字参数的方法,ruby,Ruby,正如标题所示,我试图通过关键字参数将结构传递给方法。由于ruby通常非常简洁,所以我希望有一种不那么冗长的方法来实现我目前所拥有的 这是我正在一起工作的班级 等级车轮商店 属性读取器:轮子 def初始化数据:[] @wheels=wheelify数据 终止 def直径 车轮.map{|车轮|直径轮辋:车轮.轮辋,轮胎:车轮.轮胎} 终止 私有的 def直径轮辋:,轮胎: 轮辋+轮胎*2 终止 Wheel=Struct.new:rim,:tire,关键字_init:true def轮转数据 dat

正如标题所示,我试图通过关键字参数将结构传递给方法。由于ruby通常非常简洁,所以我希望有一种不那么冗长的方法来实现我目前所拥有的

这是我正在一起工作的班级

等级车轮商店 属性读取器:轮子 def初始化数据:[] @wheels=wheelify数据 终止 def直径 车轮.map{|车轮|直径轮辋:车轮.轮辋,轮胎:车轮.轮胎} 终止 私有的 def直径轮辋:,轮胎: 轮辋+轮胎*2 终止 Wheel=Struct.new:rim,:tire,关键字_init:true def轮转数据 data.map{| item | Wheel.new rim:item[0],tire:item[1]} 终止 终止 放置WheelStore.newdata:[[10,2],[3,2]]直径 问题在于直径法,该法要求轮辋和轮胎。我希望调用方能够将wheel传递给diameter方法,这是一个实现rim&tire的wheel结构

冗长的 def直径 车轮.map{|车轮|直径轮辋:车轮.轮辋,轮胎:车轮.轮胎} 终止 较好的 def直径 wheels.map{| wheel | diameter wheel} 终止 最好的 def直径 wheels.map{diameter} 终止 我很好奇,这仅仅是一种语言结构,为什么我们不能实现这个方法的最后两个版本

作为参考,我做了很多Javascript开发,我在这里尝试的与Javascript的非常相似

问题是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。仅使用正确的控制盘对象初始化。这是更加灵活和有效的。与先将数据从原始格式转换为数组格式,然后再转换为键/值对不同,它只需转换一次键/值对

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) }
)
如果您有一些特定的数据格式,这些格式通常会转换为Wheel,那么您可以创建一个Wheel类方法来处理它们

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) }
)
2.7增加

在2.7之前,必须声明参数

您可以使用并创建自己的可枚举方法的隐式版本来解决这个问题。这会将每个元素变成块的主体,self

…但不要那样做。实例评估对写作很有用。但是,制作自己版本的标准方法意味着你正在创建自己的Ruby,其他人需要学习。

问题是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。仅使用正确的控制盘对象初始化。这是更加灵活和有效的。与先将数据从原始格式转换为数组格式,然后再转换为键/值对不同,它只需转换一次键/值对

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) }
)
如果您有一些特定的数据格式,这些格式通常会转换为Wheel,那么您可以创建一个Wheel类方法来处理它们

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) }
)
2.7增加

在2.7之前,必须声明参数

您可以使用并创建自己的可枚举方法的隐式版本来解决这个问题。这会将每个元素变成块的主体,self


…但不要那样做。实例评估对写作很有用。但是,创建自己版本的标准方法意味着您正在创建自己的Ruby,其他人需要学习。

Ruby 2.7有隐式块参数:wheels.map{u 1.diameter}。或者在2.7中添加了一个好的旧符号来进行转换:wheels.map&:diameter。谢谢你的推荐信。这个答案是无价的。这是Sandi Metz在《Ruby中的实用面向对象设计》一书中的一个示例问题,我想澄清一些语法结构。不幸的是,我无法轻松找到这些资源。再次感谢您。Ruby 2.7有隐式块参数:wheels.map{u 1.diameter}。或者在2.7中添加了一个好的旧符号来进行转换:wheels.map&:diameter。谢谢你的推荐信。这个答案是无价的。这是Sandi Metz在《Ruby中的实用面向对象设计》一书中的一个示例问题,我想澄清一些语法结构。不幸的是,我无法轻松找到这些资源。再次非常感谢你。
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