Puts or Rails.logger.info?

When creating Ruby to be executed interactively, you might want to ensure that you see the output on the console.

However, rubocop will flag the use of puts in Rails files unless you disable the rule like this:

      # rubocop:disable Rails/Output
      puts(*args)
      # rubocop:enable Rails/Output

If you use Rails.logger.info, then your output gets buried in the log file if run during development. When running a command interactively, you typically want the important output to go to the console.

One way to get all logs to redirect to the console during development is to use this Rake task

# https://stackoverflow.com/a/13649373
desc <<~DESC.strip_heredoc
  Switch logger to stdout

  Example:
    rake to_stdout other_task
DESC
task to_stdout: [:environment] do
  Rails.logger = ActiveSupport::TaggedLogging.new(Logger.new($stdout))
end

But this is too blunt. You might want some logs like the SQL logs to go to log/development.log.

Solution – Custom log method

On Heroku, there’s no need to redirect logs since the RAILS_ENV is “production” and all logs go to stdout. So it’s better to keep the log level.

But outside of Heroku, it’s best to use warn as that’s the standard used by Rake

  def self.on_heroku?
    ENV['HEROKU_APP_NAME'].present?
  end

  # For rake tasks where Rails.logger might not be available, and so that
  # messages from the Rake task either go to level WARN
  def self.log(*args)
    msg = if block_given?
      [yield]
    else
      args
    end
    # On Heroku, there's no need to redirect logs since the RAILS_ENV is "production"
    # and all logs go to stdout. So it's better to keep the log level.
    # But outside of Heroku, it's best to use `warn` as that's the standard used by `Rake`
    if Rails.logger && on_heroku?
      # Warn level to highlight messages
      Rails.logger.warn(*msg)
    else
      # Same as what rake/file_utils_ext rake_output_message does
      warn(*msg)
    end
  end

With this utility method, you can use Utils.log(*args) instead of puts and Rails.logger.info.

What’s does this accomplish?

  1. No need to clutter the code by disabling the RuboCop rule.
  2. When running on Heroku, logs can be filtered for warn to find the important messages.
  3. When running at the command line, the important messages show on the console.