I had started to write this for a Rake task, where I wanted the option of both logging to the console versus the file. Suppose for sake of this argument that you don’t want the same thing to go to both places. (If you did, then the answer for that is at the bottom). Suppose you had the following, and then realized that you wanted to add a method called error. But that’s just too much duplicated code!
def warn(message = nil, &block)
  if @console_mode
    if message.nil? && block_given?
        message = yield
    end
    puts "WARNING: #{message}"
  else
    Rails.logger.warn(message, &block)
  end
end
def info(message = nil, &block)
  if @console_mode
    if message.nil? && block_given?
      message = yield
    end
    puts message
  else
    Rails.logger.info(message, &block)
  end
end
Here’s the solution. I encourage you to try to develop this on your own.
There’s a few key tricks:
- Read up a little on what class_evaldoes in Ruby.
- Pass in the FILEandLINE + 1so you get a stack trace.
- Understand how and when to escape the #when doing string interpolation. Take a look at the lineputs "#{severity}: \#{message}". Do you see how the\#{message}needs to get quoted? Try with and without this this\.
- Consider that the class_eval is really taking a STRING, so you need to consider when you need to put an actual string in quotes. Especially see the call below to Rails.logger.sendwhere the#{severity.downcase}is quoted.
 %w(INFO WARN ERROR).each do |severity|
    class_eval <<-EOT, __FILE__, __LINE__ + 1
      def #{severity.downcase}(message = nil, &block) # def info(message = nil, &block)
        if @console_mode
          if message.nil? && block_given?
              message = yield
          end
          puts "#{severity}: \#{message}"
        else
          Rails.logger.send("#{severity.downcase}", message, &block)
        end
      end
    EOT
  end
Incidentally, if you want to just change the logger to STDOUT for a rake task, you can call:
Rails.logger = Logger.new(STDOUT)
However, that ends up logging all your queries to STDOUT as well, which might swamp the messages you want to see.