Sunday, June 15, 2008

IRB/Console tweaks

Today ill explain how you can tweak your irb and rails console. First you'll need an irb configuration file called '.irbrc' which should be placed in your home directory. You'll need to create one if it doesn't already exist. Now you can add the following.

#Load the readline module.
IRB.conf[:USE_READLINE] = true

#Remove the annoying irb(main):001:0 and replace with >>
IRB.conf[:PROMPT_MODE] = :SIMPLE

#Always nice to have auto indentation
IRB.conf[:AUTO_INDENT] = true

#History configuration
IRB.conf[:SAVE_HISTORY] = 100
IRB.conf[:HISTORY_FILE] = "#{ENV['HOME']}/.irb-save-history"

#Load modules if not already loaded
IRB.conf[:LOAD_MODULES] = [] unless IRB.conf.key?(:LOAD_MODULES)
unless IRB.conf[:LOAD_MODULES].include?('irb/completion')
IRB.conf[:LOAD_MODULES] << 'irb/completion' #Autocompletion of keywords
IRB.conf[:LOAD_MODULES] << 'irb/ext/save-history' #Persist history across sessions
end

The comments should be pretty much self-explanatory. By fat the most useful feature has to be the auto-completion of keywords. So now you can just hit tab tab to display all methods of on an object.

The next biggest feature has to be the persistence of the history across sessions. Anything that helps me save a few repetitious keystrokes is a big gain in my book.

Since console is just basically irb on steroids you will have all this functionality there too!

You can also add rails/console configurations here. Just make sure you are in the right environment before trying anything rails specific so irb doesnt blow up.

if ENV['RAILS_ENV']
#do something rails specific
end


A good way to separate out your rails specific configurations is to include it in another file and just load it from .irbrc This idea and the following are slight modifications of the snack recipes from the great book Advanced Rails Recipes (Authors of the recipe are at errtheblog.com). You'll need to create a file called .railsrc in your home directory.

if ENV['RAILS_ENV']
load "#{ENV['HOME']}/.railsrc"
end


One helpful method I like to have in .railsrc is the ability to turn on and off ActiveRecord logging to the console to help analyze/debug my sql.

#Enable ActiveRecord logging
def loud_logger(enable = true)
logger = (enable == true ? Logger.new(STDOUT) : nil)
ActiveRecord::Base.logger = logger
ActiveRecord::Base.clear_active_connections!
end


Now you can easily turn on and off your ActiveRecord logging.

>> SomeModel.first
=> # < SomeModel id: 1.. >
>> loud_logger
>> SomeModel.first
SomeModel Load (0.000442) SELECT * FROM some_models LIMIT 1
>> loud_logger false
>> SomeModel.first
=> # < SomeModel id: 1.. >

Tuesday, June 3, 2008

MySQL NULL sort order

Say we have an application that keeps track of tasks that need to be completed.

A task will have a name, description and an optional expiration date.

A possible schema could look something like the following.

create_table :tasks do |t|
t.column :name, :string, :null => false
t.column :description, :text
t.column :expiration, :datetime
end


Now lets try to display all Tasks ordering by their expiration. We will just display the expiration for the sake of brevity.

>> puts Tasks.all(:order => 'expiration ASC').map(&:expiration)
nil
nil
nil
Fri June 4th 00:00:00
Sat June 5th 00:00:00


The problem here is that by default null values appear at the top of the list. How can we display this list in ASC order but null values at the bottom of the list? After scouring around for awhile I finally came across a solution. It turns out that MySQL has a way to control the sorting of NULL values by adding a '-' before the field.

>> puts Tasks.all(:order => '-expiration DESC').map(&:expiration)
Fri June 4th 00:00:00
Sat June 5th 00:00:00
nil
nil
nil


Now we can list all Tasks ordered by their expiration date with NULL values at the bottom.