【问题标题】:Ruby create methods from a hashRuby 从哈希创建方法
【发布时间】:2011-03-11 13:35:15
【问题描述】:

我有以下代码用于将哈希集合转换为我的类上的方法(有点像活动记录)。我遇到的问题是我的二传手不工作。我对 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.

【问题讨论】:

  • 好奇你为什么会选择这条路线而不是method_missing?
  • 我不太明白。 method_missing 只会提醒我没有方法。我希望能够像上面的代码一样设置属性,问题是它不起作用。
  • 使用method_missing,您实际上会将调用捕获到一个不存在的方法,然后根据方法名称和参数实现您的功能。
  • 该方法存在,我没有收到错误,它只是从未真正设置属性。我不想捕获错误。我要设置属性。
  • 谢谢乔纳斯,我认为很明显这是一个占位符。感谢您的关心。

标签: ruby dynamic-method


【解决方案1】:

如果您的目标是设置动态属性,那么您可以使用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)

【讨论】:

    【解决方案2】:

    您的 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 专家。但它确实有效。

    【讨论】:

      【解决方案3】:

      它对我来说很好用(当然是在修复代码中明显的语法错误之后):

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

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

      【讨论】:

        【解决方案4】:

        这基本上就是我对 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
        

        【讨论】:

        • method_missing 会破坏继承层次结构。
        • @cbz 你能不能再含糊一点,举个例子?
        猜你喜欢
        • 2015-03-01
        • 2021-02-03
        • 1970-01-01
        • 2016-01-27
        • 2016-10-06
        • 2022-01-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多