1

以下代码有效:

class String
  def color(code)
    "\e[#{code}m#{self}\e[0m"
  end
end

puts "Anything".color(93)

我希望能够做到:

puts "Anything".red

通过捕获red作为字符串,然后将其提供给 case-block,如下所示:

class String
  case **?WHAT?**       
  when "red" then color(91)
  else color(0)
  end
end

但它不起作用。有没有聪明的方法来做到这一点?如何获取方法名称并在案例块中使用它?

4

2 回答 2

2

我认为您正在寻找method_missing,我在下面提出了一个解决方案。这非常适合学习,但如果您正在处理生产代码库String,您可能不想打补丁!method_missing

class String
  def color(code)
    "\e[#{code}m#{self}\e[0m"
  end

  private

  def method_missing(name, *args)
    return send(:color, 91) if name == :red
    send(:color, 0)
  end
end

p "Anything".red # => "\e[91mAnything\e[0m" 
p "Anything".color(93) # => "\e[93mAnything\e[0m"
p "Anything".magenta # => "\e[0mAnything\e[0m"

这是解决问题的另一种方法define_method

class String
  def self.color_mapping
    {
      red: 91,
      blue: 100
    }
  end

  def color(code)
    "\e[#{code}m#{self}\e[0m"
  end

  color_mapping.each do |c, v|
    define_method(c) do
      color(v)
    end
  end

  def method_missing(name, *args)
    send(:color, 0)
  end
end
于 2015-07-26T22:50:02.753 回答
0

谢谢你的努力。我根据您的最后一段代码找到了一个解决方案,并在这里和那里提出了一些问题:

class String
  def color(code)
    "\e[#{code}m#{self}\e[0m"
  end

  colors = { black: 30, red: 31, green: 32, orange: 33, blue: 34, purple: 35, cyan: 36, gray: 37, white: 97,
             lgray: 90, lred: 91, lgreen: 92, yellow: 93, lblue: 94, lpurple: 95, lcyan: 96 }
  colors.each {|name, value| define_method(name) do; color(value); end; }

end

如您所见,我没有抓住方法的名称,而是使用散列通过“define_method”创建定义。与使用案例块相比,它的代码要小得多并且易于阅读。:D

人们告诉我使用模块而不是修补核心类,但我认为可以供个人使用。

于 2015-07-27T12:25:58.187 回答