yokmp
yokmp

Reputation: 155

Get the method name

The following code works:

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

puts "Anything".color(93)

I want to be able to do:

puts "Anything".red

by catching the red as a string, and then giving it to a case-block as follows:

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

but it doesn't work. Is there a smart way to do this? How can I get the method name and use it in a case block?

Upvotes: 1

Views: 313

Answers (2)

yokmp
yokmp

Reputation: 155

Thanks for your effort. I've found a Solution based on your last code piece and a bit of asking here and there:

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

As you can see, I didn't catch the method's name but used a hash to create definitions via 'define_method'. Its much smaller code and nice to read than using case-blocks. :D

People told me to use a Module instead of patching core classes but for personal use its ok I think.

Upvotes: 0

Powers
Powers

Reputation: 19308

I think you're looking for method_missing and I've presented a solution below. This is great for learning, but you probably don't want to monkey patch String with method_missing if you're working on a production codebase!

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"

Here is another way to solve the problem with 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

Upvotes: 2

Related Questions