Working with Ruby
Hi, I am Jan. This is my old Ruby blog. I still post about Ruby, but I now do it on idiosyncratic-ruby.com. You should also install Irbtools to improve your IRB.

♥ .railsrc / rails console snippets

13 Rails-specific hints for your rails 3 console.

.railsrc – how to load it?

The .railsrc file should only be loaded in Rails enviroments. Put the following snippet into your ~/.irbrc or use the lastest irbtools:

 1
2
3
4
5
6
7
8
railsrc_path = File.expand_path('~/.railsrc')
if ( ENV['RAILS_ENV'] || defined? Rails ) && File.exist?( railsrc_path )
  begin
    load railsrc_path
  rescue Exception
    warn "Could not load: #{ railsrc_path }" # because of $!.message
  end
end

ActiveRecord’s SQL queries

This one is the most common (and helpful) rails console tweak. It shows the SQL queries Rails is doing:

 1
2
ActiveRecord::Base.logger     = Logger.new STDOUT
ActiveRecord::Base.clear_reloadable_connections!

ActionController logger

The ActionController logger functions in the same way like the ActiveRecord logger above: It displays its actions within the console:

 1
ActionController::Base.logger = Logger.new STDOUT

By the way, You can do controller requests using the app object.

Named routes

You can access your app’s named route urls in from the console:

 1
2
include Rails.application.routes.url_helpers
default_url_options[:host] = Rails.application.class.parent_name.downcase

ActionView helpers

You can use ActionView’s (including your own) helpers using the helper object. You can even include them directly to your global console namespace.

 1
2
3
4
5
6
7
8
9
10
11
12
13
#include ActionView::Helpers           # All Rails helpers
include ApplicationController._helpers # Your own helpers
#
# unfortunately that breaks some functionality (e.g. the named route helpers above)
#  so, look at actionpack/lib/action_view/helpers.rb and choose the helpers you need
#  (and which don't break anything), e.g.
include ActionView::Helpers::DebugHelper
include ActionView::Helpers::NumberHelper
include ActionView::Helpers::RawOutputHelper
include ActionView::Helpers::SanitizeHelper
include ActionView::Helpers::TagHelper
include ActionView::Helpers::TextHelper
include ActionView::Helpers::TranslationHelper

Some nice route table views

Get table views for your routes (requires hirb):

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# hirb view for a route
class Hirb::Helpers::Route < Hirb::Helpers::AutoTable
  def self.render(output, options = {})
    super( output.requirements.map{ |k,v|
      [k, v.inspect]
    }, options.merge({
      :headers     => [output.name || '', "#{ output.verb || 'ANY' } #{ output.path }"],
      :unicode     => true,
      :description => nil,
    }) )
  end
end
Hirb.add_view ActionDispatch::Routing::Route, :class => Hirb::Helpers::Route

# short and long route list
def routes(long_output = false)
  if long_output
    Rails.application.routes.routes.each{ |e|
      puts Hirb::Helpers::Route.render(e)
    }
    true
  else
    Hirb::Console.render_output Rails.application.routes.routes.map{|e|
      [e.name || '', e.verb || 'ANY', e.path]
    },{
      :class   => Hirb::Helpers::AutoTable,
      :headers => %w<name verb path>,
    }
  end
end

# get a specific route via index or name
def route(index_or_name)
  route = case index_or_name
  when Integer
    Rails.application.routes.routes[ index_or_name ]
  when Symbol # named route
    Rails.application.routes.named_routes.get index_or_name
  end
end

# access to routeset for easy recognize / generate
def r
  ActionController::Routing::Routes
end

Rails prompt

Isn’t it nice to see the current project+environment in your prompt: rails_app(dev)> ? You need to add this:

ripl version:

 1
2
3
4
5
6
7
module Ripl::RailsPrompt
  def prompt
    @prompt = "#{ Rails.application.class.parent_name.downcase }(#{ Rails.env[0...3] })> "
    super
  end
end
Ripl::Shell.include Ripl::RailsPrompt

irb version:

 1
2
3
4
5
6
7
8
9
10
11
12
app_name = Rails.application.class.parent_name.downcase
app_env  = Rails.env[0...3]
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:RAILS] = {
  :PROMPT_I => "#{ app_name }(#{ app_env })> ",
  :PROMPT_N => "#{ app_name }(#{ app_env })| ",
  :PROMPT_C => "#{ app_name }(#{ app_env })| ",
  :PROMPT_S => "#{ app_name }(#{ app_env })%l ",
  :RETURN => "=> %s\n",
  :AUTO_INDENT => true,
}
IRB.conf[:PROMPT_MODE] = :RAILS

Per project histories

I also like to have a unique console history for each of my rails projects (in a .console_history file):

ripl version:

 1
Ripl.config[:history] = File.join Dir.pwd, '.console_history'

irb version:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
history_file = File.join Dir.pwd, '.console_history'
if !IRB.conf[:PROMPT][:RVM]
  IRB.conf[:HISTORY_FILE] = history_file
else # RVM workaround, code from ~/.rvm/scripts/irbrc.rb
  # NOTE: messes up your ~/.irb-history
  # consider editing the rvm script directly
  if File.exists?(history_file)
    lines = IO.readlines(history_file).collect { |line| line.chomp }
    Readline::HISTORY.clear
    Readline::HISTORY.push(*lines)
  end

  Kernel::at_exit do
    maxhistsize = IRB.conf[:SAVE_HISTORY] || 100
    history_file = File.join Dir.pwd, ".console_history"
    lines = Readline::HISTORY.to_a.reverse.uniq.reverse
    lines = lines[-maxhistsize, maxhistsize] if lines.compact.length > maxhistsize
    File::open(history_file, "w+") { |io| io.puts lines.join("\n") }
  end
end

SQL helper method

Plain SQL:

 1
2
3
def sql(query)
  ActiveRecord::Base.connection.select_all(query)
end

Model#find helper methods

Instead of User.find.. you can do user... Without arguments it only returns the model class. Based on this snippet.

 1
2
3
4
5
6
7
8
9
10
11
12
13
Dir.glob( File.join(Dir.pwd, *%w<app models ** *.rb>) ).map { |file_name|
  table_name = File.basename(file_name).split('.')[0..-2].join
  Object.instance_eval do
    define_method(table_name) do |*args|
      table_class = table_name.camelize.constantize
      if args.empty?
        table_class
      else
        table_class.send(:find, *args)
      end
    end
  end
}

Edit records with vim

console_update is similar to interactive_editor, but offers more options:

 1
2
3
4
5
6
7
8
9
# # #
# edit records with vim, emacs...
# class Url
#   can_console_update
# end
# Url.first.console_update
# see https://github.com/cldwalker/console_update
require 'console_update'
# ConsoleUpdate.editor = 'vim' # not necessary if env var $EDITOR is set

Misc DB helper methods

I bundle them in a db object:

 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
module DatabaseHelpers
  extend self

  def tables
    Hirb::Console.render_output ActiveRecord::Base.connection.tables.map{|e|[e]},{
      :class   => Hirb::Helpers::AutoTable,
      :headers => %w<tables>,
    }
    true
  end

  def table(which)
    Hirb::Console.render_output ActiveRecord::Base.connection.columns(which).map{ |e|
      [e.name, e.type, e.sql_type, e.limit, e.default, e.scale, e.precision, e.primary, e.null]
    },{
      :class   => Hirb::Helpers::AutoTable,
      :headers => %w<name type sql_type limit default scale precision primary null>,
    }
    true
  end

  def counts
    Hirb::Console.render_output ActiveRecord::Base.connection.tables.map{|e|
      [e, ActiveRecord::Base.connection.select_value("SELECT COUNT(*) FROM #{e}")]
    },{
      :class   => Hirb::Helpers::AutoTable,
      :headers => %w<table count>,
    }
    true
  end

  # ...
end
def db; DatabaseHelpers; end

Authlogic

Initialize Session:

 1
2
3
4
if defined? Authlogic
  Authlogic::Session::Base.controller =
      Authlogic::ControllerAdapters::RailsAdapter.new(self)
end

Putting it all together

gist

Have another nice helper? Post it in the comments ;)

Creative Commons License

iain | March 31, 2011

Nice list! But you'll still need to add all the gems you use in your projects Gemfile, right? If not, how do you get around bundler? If so, which gems do you use, so I know which ones to add.

J-_-L | March 31, 2011

Yes, currently, you have to add them to your Gemfile. I only use hirb and console_update in this post. If you want to use ripl, you will have to also add it and its plugins.

kronn | April 01, 2011

Nicely done, sir. I will definitly try it (can't promise to keep it, though).

For the "Gemfile problem": I use a group :development, which contains capistrano and capistrano-ext anyway. During deployment, this group is not installed by default. If you don't want to enforce anything on your co-workers machines, you can do this:

group :development do
gem 'ripl' if Gem.available?('ripl')
end

iain | April 01, 2011

@kronn Wouldn't that mess up your Gemfile.lock? Everybody will create a different version of that file, depending on what they have installed.

jeremy | April 04, 2011

I'm always down for some new dotfile trickery. Thanks for these!
I found this helper a few years ago: https://gist.github.com/524652 (shows usage and sample output below gist code)
It prints out all of the "interesting" methods of an object and how many args it takes, and namespace/scope.

nilclass | August 17, 2011

I'm wondering about this part:
if ( ENV['RAILS_ENV'] || defined? Rails )
In which case would ENV['RAILS_ENV'] be set, but Rails not defined? I guess this can lead to unexpected errors, when you have RAILS_ENV always set to some default in your shell.