ruby - 有没有办法在 block 内重新定义方法?

标签 ruby

假设我想puts大量大写的字符串,但为了简洁起见,我想写puts(string)而不是每次都 puts(string.upcase)

有没有办法让我像这样重新定义puts 仅在一个 block 内

# This will puts as normal
puts "abc"
# => abc

# This will puts an upcased string, but it's too verbose
puts "abc".upcase
# => ABC

# I want to do something like this, which will override the puts method for code run within the block
def always_upcase_strings(&block)
  def puts(string)
    super(string.upcase)
  end
end

always_upcase_strings do 
  puts "abc"
  puts "def"
  puts "ghi"
end
puts "xyz"
# => ABC
# => DEF
# => GHI
# => xyz

上面的示例经过简化 - 在我的例子中,我没有使用 puts,而是我自己编写的方法。

最佳答案

关于second thoughts ,这是一个更好的答案:

def always_upcase_strings(&block)
  anon_class = Class.new do
    def puts(str)
      super(str.upcase)
    end
  end
  anon_class.new.instance_eval(&block)
end

always_upcase_strings do
  puts "abc" #=> "ABC"
  puts "def" #=> "DEF"
  puts "ghi" #=> "GHI"
end

puts "xyz"   #=> "xyz"

这个creates具有所需方法覆盖的临时类(匿名,因为它不需要名称)。

然后,在此类实例的上下文中调用生成的 block 。

除了比我的“重新定义-取消定义-重新定义方法”解决方案更容易混淆之外,这种方法还有一个额外的优点,即它是线程安全的。因此,例如,如果在调用该方法时运行并行测试,您不会得到奇怪的行为。

...但我仍然坚持我最初的说法,即在 block 内重新定义方法是非常令人惊讶的行为。同事可能不会喜欢你选择这种设计模式(除非它是以有限的方式完成的,并且有充分的理由!)

关于ruby - 有没有办法在 block 内重新定义方法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55928251/

相关文章:

ruby - 无法安装rmagick

用于麦克风和扬声器的 ruby gem

ruby-on-rails - 如何将 Rails 环境变量放入 apple-app-site-association 文件中以获得通用链接?

arrays - 如何在 ruby​​ 中分割单行输入并将其存储为不同的变量和不同的数据类型(即整数/字符串/数组)

Ruby::如何使用 Mechanize 搜索隐藏元素

ruby-on-rails - 在 Rails 中获取 CSV 文件

ruby - 如何使用 `gsub` 将多个子字符串替换为相同的字符串

ruby - 给定参数的 rspec 模拟返回

ruby-on-rails - Rails Time Zone : Setting Time. zone not Changing Time.current

ruby-on-rails - Kaminari 和 unscoped