使对象method_missing的行为类似于method_missing类

时间:2013-05-23 09:03:20

标签: ruby-on-rails ruby oop metaprogramming

我创建了一个类,我有一些不变的哈希值。我想键入Myclass.myhash.hashkey并显示哈希的值。现在我已经用method_missing创建了一个类似的行为,但我必须初始化该对象,所以我称它为Myclass.new.myhash.hashkey并且它可以工作。到目前为止,这是我的代码:

class Myclass
  def initialize
    @attributes = []
  end

  def method_missing(name, *args)
    @attributes << name
    if @attributes.length == 2
      eval("#{@attributes.first.upcase}[:#{@attributes.last.downcase}]")
    else
      self
    end
  end

  MYHASH = {
    id: 1,
    description: "A nice hash",
    hashkey: "hash key"
  }
end

如果没有初始化而没有new,我怎么能这样做,所以每次都不会创建MyClass的对象?

更新 第一个问题是由toro2k解释但我不知道是否使用它我可以有我的第二个问题的行为......

问题2 我的课程中有很多opentructs,如何动态地将它们定义为类方法,而不是每次都添加类似的东西:

  def self.myhash
    MYHASH
  end   

2 个答案:

答案 0 :(得分:2)

您可以使用OpenStruct对象而不是Hash

class MyClass
  MYHASH = OpenStruct.new(id: 1, 
                          description: 'A nice Ostruct', 
                          hashkey: 'hash key')
  def self.myhash
    MYHASH
  end      
end

MyClass.myhash.id # => 1
MyClass.myhash.description # => "A nice Ostruct"
MyClass.myhash.foo # => nil

更新您可以使用类实例变量替换常量:

class MyClass
  def self.myhash
    @myhash ||= OpenStruct(id: ...)
  end
end

MyClass.myhash.id

或者您可以使用类变量和cattr_reader

class MyClass
  cattr_reader :myhash
  @@myhash = OpenStruct(id: ...)
end

MyClass.myhash.id

或者你可以摆脱myhash方法并直接访问常量:

class MyClass
  MYHASH = OpenStruct(id: ...)
end

MyClass::MYHASH.id

答案 1 :(得分:1)

我终于找到了第二个问题的解决方案:

  class << self
    Myclass.constants.each do |constant|
      define_method(constant.to_s.downcase) do
        eval("#{constant}")
      end
    end
  end

在我定义了所有的openstruct变量之后,我只需要在类的末尾添加它。