【问题标题】:Convert symbol into an object将符号转换为对象
【发布时间】:2016-05-19 10:03:36
【问题描述】:

我的方法需要一个参数。我更喜欢避免像这样直接传递对象:

def print_error(Loggers::MyLogger.new, error)
  ...
end

相反,我想像这样传递一个符号:

def print_error(:my_logger, error)
  ...
end

有没有一种优雅的方法可以将:my_logger 符号转换为MyLogger 实例?还是我必须为此建立一个工厂机制?

【问题讨论】:

  • 您使用什么逻辑“将Symbol 转换为对象”?
  • @JörgWMittag 抱歉,我不确定我是否理解这个问题。你想知道我在方法中请求对象的原因吗?

标签: ruby


【解决方案1】:

在 Rails 中,有一个帮助器为 constantize 准备好了:

:my_logger.to_s.camelize.constantize
#⇒ MyLogger

在 Ruby 中,可以使用Module#const_get

klazz = :my_logger.to_s.gsub(/(\A|_)(.)/) { |m| m[-1].upcase }
const_get(klazz) if const_defined?(klazz)
#⇒ MyLogger

【讨论】:

  • Kernel 中查找常量而不是Object 或当前范围或Logger 模块的原因是什么?
  • @JörgWMittag 没有理由,我只是为了清楚起见。如果你觉得它搞砸了,我会删除它。
  • 您应该删除 Rails 部分。 OP 要求使用非 Rails 解决方案(无论如何它都不起作用)。
  • @Stefan 究竟是什么不起作用?我认为Inflector可能会用在非rails项目中,看看它是如何实现的,是一个很好的参考。
  • 谢谢 mudasobwa,它可以工作 :-)(至少 Ruby 方法是这样做的,我不使用 rails 我无法测试constantize)。
【解决方案2】:

首先,我们将:my_logger 转换为字符串“MyLogger”(参考:Converting string from snake_case to CamelCase in Ruby):

camel_str = :my_logger.to_s.camelize  

然后我们使用带有类名的字符串来创建对象(参考:How do I create a class instance from a string name in ruby?):

obj = Object.const_get(camel_str)

所以把所有东西放在一起:

camel_str = :my_logger.to_s.camelize  
obj = Object.const_get(camel_str)

【讨论】:

  • NoMethodError: undefined method 'camelize' for "my_logger":String
  • camelize 在 Rails 中,对不起,我以为你在用它。
  • 感谢 Pholochtairze。遗憾的是,正如我提到的,我没有使用 Rails,所以 camelize 不起作用。
【解决方案3】:

好吧,如果是将一个符号转换成它对应的类(如果存在的话!),那么这个呢:

class Symbol
  def to_ob
    eval(self.to_s)
  end
end

:String.to_ob        #=>String

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-12-09
    • 2011-10-05
    • 2012-10-24
    • 2015-11-01
    • 2016-11-05
    • 2020-09-02
    • 2016-09-26
    相关资源
    最近更新 更多