ruby-on-rails - 在 Ruby 1.9 中使用 instance_eval 进行常量查找

标签 ruby-on-rails ruby ruby-on-rails-3 ruby-1.9 ruby-1.9.2

短小精悍

在 Ruby 1.9 中运行这段代码:

FOO = "global constant"

class Something
  FOO = "success!"

  def self.handle &block
    self.new.instance_eval &block
  end
end

class Other
  FOO = "wrong constant"

  def self.handle
    Something.handle{FOO}
  end
end

puts Something.handle{FOO}
puts Other.handle

我得到“成功!”和“错误的常数”。我怎样才能让两个电话都打印“成功!”?这不是为了好玩而设计的练习——我不会为此浪费人们的时间。我遇到了一个现实世界的问题,我已将其缩减为可以证明该问题的最简单示例。继续阅读“为什么”。

更详尽的解释

调用 Something.handle{FOO} 工作正常。 Ruby 使用 Something 类中给出的 FOO 定义。但是,如果我尝试从另一个类以相同的方式调用它,它会为我提供那个类的 FOO 定义。

我认为 Ruby 1.9 中更严格的常量查找的想法是为了避免这样的问题。 instance_eval 应该使用其接收者的范围(在本例中为 self.new),而不是调用 block 的范围。它适用于实例变量之类的东西,但不适用于常量。这不是优先级问题 - 删除“全局”和“错误”常量,ruby 仍然无法找到剩余的正确常量。

我遇到的现实问题是我有一个包含多个类的模块。我有一个方法可以接受一个 block ,并在模块的上下文中运行该 block 。在该 block 内,我希望能够通过短名称引用这些类(就像我可以在模块本身的任何地方一样),而不必在模块名称前添加。

这很痛苦:

ThirdPartyApis::MyAnswerSite.connection question.id, answer.id do |question_id, answer_id|
  question = ThirdPartyApis::MyAnswerSite::Question.find question_id
  answer = ThirdPartyApis::MyAnswerSite::Answer.find answer_id

  ThirdPartyApis::MyAnswerSite::Solution.new question, answer
end

这很愉快:

ThirdPartyApis::MyAnswerSite.connection question.id, answer.id do |question_id, answer_id|
  question = Question.find question_id
  answer = Answer.find answer_id

  Solution.new question, answer
end

总结

这就是冗长的解释。请不要提供不能解决我的问题的解决方法。我很欣赏探索其他途径的愿望,但我的问题很简单:只能以打印“成功!”的方式修改 Something 类。最后两次?那是测试用例,任何符合这个的解决方案都是我接受的答案,它的作者是我本周的个人英雄。请!

最佳答案

我使用 sourcify gem(gem install sourcify)让它工作:

require 'sourcify'
FOO = "global constant"

class Something
  FOO = "success!"

  def self.handle &block
    (self.new.instance_eval(block.to_source)).call
  end

end

class Other
  FOO = "wrong constant"

  def self.handle
    Something.handle{FOO}
  end
end

puts Something.handle{FOO}
=> success!
puts Other.handle
=> success!

编辑:糟糕,您也可以看到我在何处使用绑定(bind),删除了该代码。

关于ruby-on-rails - 在 Ruby 1.9 中使用 instance_eval 进行常量查找,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4892726/

相关文章:

ruby-on-rails - 有没有可以比较或解析多种语言的工具?

ruby-on-rails - 在 8000 万行表上索引 UUID

ruby - 检查 s3 存储桶中是否存在文件夹

javascript - jQuery Remotipart 发送 [object Object] 到服务器

ruby-on-rails - 使用网络服务时缓存

ruby-on-rails - Geocoder Gem - Ruby On Rails

ruby-on-rails-3 - 在测试环境中设置 default_url_options 似乎不起作用

ruby-on-rails - Ruby on Rails Ransack 日期时间到日期搜索

jquery - 如何增加tinymce Iframe的高度?

ruby-on-rails - Rails 选择表单标签 - 如何添加默认的 "All"选项?