Ruby 从哈希创建方法

发布于 2024-10-21 10:36:02 字数 698 浏览 5 评论 0原文

我有以下代码,用于将哈希集合转换为我的类上的方法(有点像活动记录)。我遇到的问题是我的设置器无法工作。我对 Ruby 还很陌生,并且相信我已经改变了一些。

class TheClass
  def initialize
    @properties = {"my hash"}
    self.extend @properties.to_methods
  end
end

class Hash
  def to_methods
    hash = self
    Module.new do
      hash.each_pair do |key, value|
        define_method key do
          value
        end
        define_method("#{key}=") do |val|
          instance_variable_set("@#{key}", val)
        end
      end
    end
  end
end

这些方法已创建,我可以在课堂上阅读它们,但设置它们不起作用。

myClass = TheClass.new
item = myClass.property # will work.
myClass.property = item # this is what is currently not working.

I have the following code I am using to turn a hash collection into methods on my classes (somewhat like active record). The problem I am having is that my setter is not working. I am still quite new to Ruby and believe I've gotten myself turned around a bit.

class TheClass
  def initialize
    @properties = {"my hash"}
    self.extend @properties.to_methods
  end
end

class Hash
  def to_methods
    hash = self
    Module.new do
      hash.each_pair do |key, value|
        define_method key do
          value
        end
        define_method("#{key}=") do |val|
          instance_variable_set("@#{key}", val)
        end
      end
    end
  end
end

The methods are created and I can read them on my class but setting them does not work.

myClass = TheClass.new
item = myClass.property # will work.
myClass.property = item # this is what is currently not working.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

微暖i 2024-10-28 10:36:02

如果您的目标是设置动态属性,那么您可以使用 OpenStruct。

require 'ostruct'

person = OpenStruct.new
person.name = "Jennifer Tilly"
person.age = 52

puts person.name     
# => "Jennifer Tilly"
puts person.phone_number 
# => nil

它甚至内置支持从哈希创建它们

hash = { :name => "Earth", :population => 6_902_312_042 }
planet = OpenStruct.new(hash)

If your goal is to set dynamic properties then you could use OpenStruct.

require 'ostruct'

person = OpenStruct.new
person.name = "Jennifer Tilly"
person.age = 52

puts person.name     
# => "Jennifer Tilly"
puts person.phone_number 
# => nil

It even has built-in support to create them from a hash

hash = { :name => "Earth", :population => 6_902_312_042 }
planet = OpenStruct.new(hash)
深陷 2024-10-28 10:36:02

您的 getter 方法始终返回原始哈希中的值。设置实例变量不会改变这一点;您需要使 getter 引用实例变量。类似于:

hash.each_pair do |key, value|
  define_method key do
    instance_variable_get("@#{key}")
  end
  # ... define the setter as before
end

并且您还需要在开始时设置实例变量,例如通过放入

@properties.each_pair do |key,val|
  instance_variable_set("@#{key}",val)
end

初始化方法。

注意:我不保证这是最好的方法;我不是 Ruby 专家。但它确实有效。

Your getter method always returns the value in the original hash. Setting the instance variable won't change that; you need to make the getter refer to the instance variable. Something like:

hash.each_pair do |key, value|
  define_method key do
    instance_variable_get("@#{key}")
  end
  # ... define the setter as before
end

And you also need to set the instance variables at the start, say by putting

@properties.each_pair do |key,val|
  instance_variable_set("@#{key}",val)
end

in the initialize method.

Note: I do not guarantee that this is the best way to do it; I am not a Ruby expert. But it does work.

格子衫的從容 2024-10-28 10:36:02

它对我来说工作得很好(当然,在修复了代码中明显的语法错误之后):

myClass.instance_variable_get(:@property) # => nil
myClass.property = 42
myClass.instance_variable_get(:@property) # => 42

请注意,在 Ruby 中,实例变量始终是私有的,并且您永远不会为它们定义 getter,因此您实际上无法从外部查看它们(除了通过反射),但这并不意味着您的代码不起作用,它只意味着您看不到它的工作原理。

It works just fine for me (after fixing the obvious syntax errors in your code, of course):

myClass.instance_variable_get(:@property) # => nil
myClass.property = 42
myClass.instance_variable_get(:@property) # => 42

Note that in Ruby instance variables are always private and you never define a getter for them, so you cannot actually look at them from the outside (other than via reflection), but that doesn't mean that your code doesn't work, it only means that you cannot see that it works.

甩你一脸翔 2024-10-28 10:36:02

这基本上就是我对 method_missing 的建议。我对这两种途径都不太熟悉,无法说出为什么或为什么不使用它,这就是我在上面问的原因。本质上,这将为您自动生成属性:

def method_missing sym, *args
   name = sym.to_s
   aname = name.sub("=","")

   self.class.module_eval do 
      attr_accessor aname
   end
  send name, args.first unless aname == name
end

This is essentially what I was suggesting with method_missing. I'm not familiar enough with either route to say why or why not to use it which is why I asked above. Essentially this will auto-generate properties for you:

def method_missing sym, *args
   name = sym.to_s
   aname = name.sub("=","")

   self.class.module_eval do 
      attr_accessor aname
   end
  send name, args.first unless aname == name
end
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文