gpt4 book ai didi

ruby - 使用可重用代码创建 Ruby 构建器对象

转载 作者:行者123 更新时间:2023-12-04 07:51:39 25 4
gpt4 key购买 nike

我正在努力创建一些 Ruby 构建器对象,并思考如何重用 Ruby 的一些魔法来将构建器的逻辑简化为单个类/模块。自从我上次与该语言共舞以来已经有 10 年了,所以有点生疏。
例如,我有这个构建器:

class Person
PROPERTIES = [:name, :age]
attr_accessor(*PROPERTIES)

def initialize(**kwargs)
kwargs.each do |k, v|
self.send("#{k}=", v) if self.respond_to?(k)
end
end

def build
output = {}
PROPERTIES.each do |prop|
if self.respond_to?(prop) and !self.send(prop).nil?
value = self.send(prop)
# if value itself is a builder, evalute it
output[prop] = value.respond_to?(:build) ? value.build : value
end
end

output
end

def method_missing(m, *args, &block)
if m.to_s.start_with?("set_")
mm = m.to_s.gsub("set_", "")
if PROPERTIES.include?(mm.to_sym)
self.send("#{mm}=", *args)
return self
end
end
end
end

可以这样使用:
Person.new(name: "Joe").set_age(30).build
# => {name: "Joe", age: 30}
我希望能够将所有内容重构为一个类和/或模块,以便我可以创建多个这样的构建器,这些构建器只需要定义属性并继承或包含其余部分(并可能相互扩展)。
class BuilderBase
# define all/most relevant methods here for initialization,
# builder attributes and object construction
end

module BuilderHelper
# possibly throw some of the methods here for better scope access
end

class Person < BuilderBase
include BuilderHelper

PROPERTIES = [:name, :age, :email, :address]
attr_accessor(*PROPERTIES)
end

# Person.new(name: "Joe").set_age(30).set_email("joe@mail.com").set_address("NYC").build

class Server < BuilderBase
include BuilderHelper

PROPERTIES = [:cpu, :memory, :disk_space]
attr_accessor(*PROPERTIES)
end

# Server.new.set_cpu("i9").set_memory("32GB").set_disk_space("1TB").build
我已经能够做到这一点:
class BuilderBase
def initialize(**kwargs)
kwargs.each do |k, v|
self.send("#{k}=", v) if self.respond_to?(k)
end
end
end

class Person < BuilderBase
PROPERTIES = [:name, :age]
attr_accessor(*PROPERTIES)

def build
...
end

def method_missing(m, *args, &block)
...
end
end
试图提取 method_missingbuild进入基类或模块不断向我抛出错误,例如:
NameError: uninitialized constant BuilderHelper::PROPERTIES

OR

NameError: uninitialized constant BuilderBase::PROPERTIES
本质上,父类和 mixin 都不能访问子类的属性。对于父级来说,这是有道理的,但不确定为什么 mixin 无法读取它所包含的类中的值。这是 Ruby,我确信有一些我错过的神奇方法可以做到这一点。
帮助表示赞赏 - 谢谢!

最佳答案

我将您的 sample 减少到所需的部分并提出:

module Mixin
def say_mixin
puts "Mixin: Value defined in #{self.class::VALUE}"
end
end

class Parent
def say_parent
puts "Parent: Value defined in #{self.class::VALUE}"
end
end

class Child < Parent
include Mixin

VALUE = "CHILD"
end


child = Child.new
child.say_mixin
child.say_parent

这就是您可以从父/包含类访问子类/包含类中的常量的方式。
但我不明白你为什么要首先拥有整个 Builder 的东西。 OpenStruct 不适用于您的情况吗?

关于ruby - 使用可重用代码创建 Ruby 构建器对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66938530/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com