ruby - 如何实现getter setter方法来更改动态方法中的键值?
问题描述
读取一个 csv 格式的文件,并以文件名动态构造一个新的类。所以如果csv是persons.csv,ruby类应该是person,如果是places.csv,ruby类应该是places还创建用于读取和显示“csv”文件中的每个值以及csv文件第一行中的值的方法将作为函数的名称。构造一个对象数组并将每个对象与 csv 文件的行相关联。例如 csv 文件的内容可以是 name,age,city Chris,23,NYC Matt,23,SFO
我已经找到了解决这个问题的方法,并且代码可以有效地解决这个问题,我只在更新正在访问的新键值时遇到问题。我还想更新如下值:
p k.call 'name'
p k.call 'age'
p k.call 'city'
k.name = 'XYZ' # updating new key values
k.age = 25 # updating new key values
p k.call 'name'
p k.call 'age'
我在运行时收到错误:
undefined method `name' for #<Input:0x00007fb6c20d75c0>
有人可以建议,在这种情况下实现getter setter方法的正确方法是什么?
require 'csv'
class ReadCsv
attr_accessor :arr
def initialize(source_name)
@klass = Class.new
class_name = File.basename(source_name, ".csv").capitalize
Object.const_set(class_name, @klass)
csv_read(source_name)
method_def
end
def csv_read(source_name)
@arr = CSV.read(source_name).transpose
end
def method_def
@klass_obj = @klass.new
arr.each { |method_name, *a| @klass_obj.define_singleton_method(method_name.to_s) { a } }
end
def universal_attr_accessor(entity, attr_name) #change added
definition_method_name = "define_#{entity.is_a?(Object) ? 'singleton_' : ''}method".to_sym
entity.send(definition_method_name, "#{attr_name}=".to_sym) do |value|
instance_variable_set("@#{attr_name}", value)
end
entity.send(definition_method_name, attr_name.to_sym) do
instance_variable_get("@#{attr_name}")
end
end
def call(method_name)
@klass_obj.send(method_name)
universal_attr_accessor(@klass_obj, method_name)
end
end
k = ReadCsv.new('Input.csv')
p k.call 'name'
p k.call 'age'
p k.call 'city' . # until here code works just fine
k.name = 'XYZ' # I am not able to assign new key value for this dynamic method called at runtime.
k.age = 25
p k.call 'name'
p k.call 'age'
预期结果 :
k = ReadCsv.new('Input.csv')
p k.call 'name' # ['Chris','Matt']
p k.call 'age' # [23,23]
p k.call 'city' . # ['NYC','SFO']
k.name = 'XYZ'
k.age = 25
p k.call 'name' # ['Chris','Matt','XYZ']
p k.call 'age' # [23,23,25]
解决方案
根据@Amadan 的评论,这是您要实现的目标的准系统解决方案。它使用OpenStruct
而不是自定义类。
persons =
CSV.parse(<<~ROWS, headers: true, header_converters: :symbol)
name,department,salary
Bob,Engineering,1000
Jane,Sales,2000
John,Management,5000
ROWS
persons =
persons.map(&:to_h).map(&OpenStruct.method(:new))
导致:
#⇒ [#<OpenStruct name="Bob", department="Engineering", salary="1000">,
# #<OpenStruct name="Jane", department="Sales", salary="2000">,
# #<OpenStruct name="John", department="Management", salary="5000">]
和:
persons.first.name
#⇒ "Bob"
persons.first.name = "Mary"
#⇒ "Mary"
persons.first.name
#⇒ "Mary"
推荐阅读
- typescript - 打字稿既不是,也不是,但不是两个属性
- c# - AppBarToggleButton 第三状态的 UWP 编辑样式
- sql - 如何在 ORDER BY 和 LIMIT 之后获得一列的总和?
- android - 如何以编程方式在 Android 中将 .mid 转换为 .wav 文件?
- javascript - 本地存储错误,纠正的最佳方法?
- arduino - 从 Arduino IDE 上传 ESP8266 失败
- python - 如何为嵌套分类变量设置 x_range 或缩放级别以解决重叠问题
- postgresql - 添加复合主键时,我得到列“my_column”包含空值
- html - 如何让我的 Favicon 在 WordPress 自定义主题中显示?
- wordpress - 本地主机上的 docker - wordpress cron 的问题 - 无法连接到 local.domain 端口 80:连接被拒绝