Ruby Best Practices and Tips from Ruby experts | Toptal®

3 min read Original article ↗

Ruby has some great gems for coloring output prints to terminal, but sometimes you just need to print a couple of times and don’t want to add another gem just for that.

For example, instead of:

puts "\e[31mThis is red!\e[0m"
puts "\e[32mThis is green!\e[0m"

you could just create the format separated on variables, using %s placeholder (printf format):

red = "\e[31m%s\e[0m"
green = "\e[32m%s\e[0m"

Then use the % operator for readable formatting:

puts red % 'Red Again!'
puts green % 'Green Again!'
puts 'Mixed %s with %s!' % [red % 'red', green % 'green']

Let’s take a look at another example:

a = 2
b = 3
sum = a + b
format = '%s + %s = %s'
puts format % [red % a, red % b, green % sum]

This example is much more readable then the following code:

puts "\e[31m#{a}\e[0m + \e[31m#{b}\e[0m = \e[32m#{sum}\e[0m"

This can be used in a simple and unobtrusive way, and in a single place, like a log method:

class MyClass
  def log(message, level)
    red = "\e[31m%s\e[0m"
    green = "\e[32m%s\e[0m"

    puts "%s: %s" % [red % level, green % message]
  end
end

If you want to use this method globally, you can monkey patch String class:

class String
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end
end

and then use them anywhere in the code:

puts "Red again!".red
puts "Green again!".green
puts "Mixed %s with %s!" % ["red".red, "green".green]

Let’s reuse the same example we used before, but now with the new syntax:

a = 2
b = 3
format = "%s + %s = %s"
puts format % [a.to_s.red, b.to_s.red, (a + b).to_s.green]

A more polite variation of monkey patching would be by using a module:

module ConsoleColors
  def red
    "\e[31m#{self}\e[0m"
  end

  def green
    "\e[32m#{self}\e[0m"
  end
end

String.include ConsoleColors

If you still want to use it globally but don’t want to monkey patch String, you can use the following code variation:

class Color
  # constants
  RED = "\e[31m%s\e[0m"
  GREEN = "\e[32m%s\e[0m"

  # or methods
  def self.red(s)
    "\e[31m#{s}\e[0m"
  end

  def self.green(s)
    "\e[32m#{s}\e[0m"
  end
end

puts Color::RED % 'reddish'
puts Color::GREEN % 'greenish'

puts Color.red 'reddish method'
puts Color.green 'greenish method'

In the end, you could use Ruby 2.0 refinements to limit the scope of the change:

module ConsoleColorsStringRefinement
  refine String do
    def red
      "\e[31m#{self}\e[0m"
    end

    def green
      "\e[32m#{self}\e[0m"
    end
  end
end

class MyLogClass
  using ConsoleColorsStringRefinement

  def log(message, level)
    puts "%s: %s" % [level.to_s.red, message.to_s.green]
  end
end

MyLogClass.new.log('My Message', 'DEBUG') # DEBUG: My Message