Ruby:你能确定一个对象是否有一个方法被调用吗



我甚至不确定我问的问题是否正确。我可能错误地处理了这个问题,但基本上我在这里遇到了这种情况:

obj = get_user(params)
obj.profile => {:name => "John D", :age => 40, :sex => "male"} #Has to be of class Hash
obj.profile.name => "John D"
obj.profile[:name] => "John D"
obj.profile.job => nil

所以,基本上,我必须满足所有这些条件,我甚至不确定如何实现这一点(我今天刚刚学习Ruby)。

注意访问内部变量的点符号,否则我只会让profile是一个符号散列。所以我尝试了两种方法,它们只会让我达到

方法1:使配置文件成为OpenStruct

因此,这允许我使用点符号访问姓名、年龄和性别,如果密钥不存在,它会自动返回nil,但是obj.profile的类型是OpenStruct,而不是Hash

方法2:使配置文件成为自己的类

有了这个,我将它们设置为实例变量,如果它们不存在,我可以使用method_missing返回nil。但是,我再次遇到obj.profile不是正确的类型/类的问题

我有什么东西不见了吗?有没有办法区分

obj.profile
obj.profile.name

在getter函数中,并返回散列或其他?

我可以更改我的自定义类为配置文件返回的内容吗,这样它就会返回一个Hash?

我甚至尝试过在get函数中检查obj.profileargs和**kwargs,但它们似乎都没有帮助,或者如果我调用obj.profiletsomething

,它们都不会填充

如果它绝对必须是Hash:

require 'pp'
module JSHash
  refine Hash do
    def method_missing(name, *args, &block)
      if !args.empty? || block
        super(name, *args, &block)
      else
        self[name]
      end
    end
  end
end
using JSHash
profile = {:name => "John D", :age => 40, :sex => "male"}
pp profile.name    # "John D"
pp profile[:name]  # "John D"
pp profile.job     # nil
pp profile.class   # Hash

但最好不要成为Hash,除非它绝对需要:

require 'pp'
class Profile < Hash
  def initialize(hash)
    self.merge!(hash)
  end
  def method_missing(name, *args, &block)
    if !args.empty? || block
      super(name, *args, &block)
    else
      self[name]
    end
  end
end
profile = Profile.new({:name => "John D", :age => 40, :sex => "male"})
pp profile.name
pp profile[:name]
pp profile.job

只需几个哈希键,就可以轻松地定义singleton方法,如:

def define_getters(hash)
  hash.instance_eval do
    def name
      get_val(__method__)
    end
    def job
      get_val(__method__)
    end
    def get_val(key)
      self[key.to_sym]
    end
  end
end
profile = person.profile #=> {name: "John Doe", age: 40, gender: "M"}
define_getters(profile)
person.profile.name #=> "John Doe"
person.profile.job #=> nil

也反映了变化的值(如果你想知道的话):

person.profile[:name] = "Ralph Lauren"
person.profile.name #=> "Ralph Lauren"

使用这种方法,您不必重写method_missing、创建从Hash继承的新类,也不必对Hash类进行猴子补丁。

但是,为了能够通过方法调用访问未知密钥并返回nil而不是错误,必须涉及method_missing

这个Hash覆盖将完成您想要做的事情。您所需要做的就是将它包含在您已经加载的一个类文件中。

class Hash
  def method_missing(*args)
    if args.size == 1  
      self[args[0].to_sym]
    else
      self[args[0][0..-2].to_sym] = args[1] # last char is chopped because the equal sign is included in the string, print out args[0] to see for yourself
    end
  end
end

请参阅以下IRB输出进行确认:

1.9.3-p194 :001 > test_hash = {test: "testing"}
 => {:test=>"testing"} 
1.9.3-p194 :002 > test_hash.test
 => "testing" 
1.9.3-p194 :003 > test_hash[:test]
 => "testing" 
1.9.3-p194 :004 > test_hash.should_return_nil
 => nil 
1.9.3-p194 :005 > test_hash.test = "hello"
 => "hello" 
1.9.3-p194 :006 > test_hash[:test]
 => "hello" 
1.9.3-p194 :007 > test_hash[:test] = "success"
 => "success" 
1.9.3-p194 :008 > test_hash.test
 => "success" 
1.9.3-p194 :009 > test_hash.some_new_key = "some value"
 => "some value" 
1.9.3-p194 :011 > test_hash[:some_new_key]
 => "some value" 

相关内容

  • 没有找到相关文章

最新更新