Alias - Quickness in the Ruby Console
This post introduces Alias, a gem for configuring and managing aliases. Whether you need to alias a method, class, constant or a string of Ruby code, your fingers will thank you.
Motivation
If you’re like me, when you type something enough times, you tend to alias it. Sure, completion exists in your ruby shell but it doesn’t consistently give you fewer keystrokes than an alias. Take for example some aliases I have in my .irbrc for Rails:
AB = ActiveRecord::Base
class ActiveRecord::Base; class << self; alias_method :[], :find; end; end
class ActiveRecord::Base; alias_method :ua, :update_attribute; end
With these aliases, finding and updating on models are down to 2-3 keystrokes for the method. Naturally, for each of these aliases I made sure that I wasn’t overriding existing constants and methods. Note that each of the above aliases are different alias types i.e. a constant alias, class method alias and instance method alias.
So if you end up aliasing more than a couple of times, the above code and checking for conflicts tends to get old and repetitive. Wouldn’t it just be easier to have a config file from which to read and create aliases? This is what Alias does! Simply create aliases in irb, save them and configure your irb to load your created aliases next time around.
Install
To install Alias:
gem install alias
Using Alias
The Basics
To see Alias in action, let’s start by creating the above Rails aliases:
bash> script/console >> require 'alias' => true # Import alias methods >> extend Alias::Console => main # First let's see what ruby code Alias generates to create an alias. >> create_aliases :class_method, {"ActiveRecord::Base"=>{'find'=>'[]'}}, :pretend=>true class ::ActiveRecord::Base; class << self; alias_method :[], :find; end; end => true # Create the above class method alias >> create_aliases :class_method, "ActiveRecord::Base"=>{'find'=>'[]'} => true # Create the above constant alias >> create_aliases :constant, "ActiveRecord::Base"=>"AB" => true # Verify that it worked >> AB => ActiveRecord::Base # If we try to create the constant alias again, Alias prevents us and warns us >> create_aliases :constant, "ActiveRecord::Base"=>"AB" Constant 'AB' not created since it already exists => false # We can force Alias to override a method, class or constant that already exists >> create_aliases :constant, {"ActiveRecord::Base"=>"AB"}, :force=>true => true # Create the above instance method alias >> create_aliases :instance_method, "ActiveRecord::Base"=>{"update_attribute"=>'ua'} => true # By default aliases are saved to config/alias.yml in rails or ~/.alias.yml if not. >> save_aliases Saved created aliases to config/alias.yml. => true
As you can see, create_aliases()
takes an alias type and a hash of aliases. Note that each alias type has its own format for interpreting the hash. Now to see what Alias saved in config/alias.yml :
:aliases: :constant: ActiveRecord::Base: AB :instance_method: ActiveRecord::Base: update_attribute: ua :class_method: ActiveRecord::Base: find: "[]"
Since Alias is all about typing less, why not alias away it’s primary commands for future use?:
# You can pass the first few unique letters of an alias type and Alias will pick the right type # :in => :instance_method >> create_aliases :in, "Alias::Console"=>{"save_aliases"=>"sa", "create_aliases"=>"ca"} => true # Saving these aliases naturally adds to the ones already saved >> sa Saved created aliases to config/alias.yml. => true
Update: It’s important to point out that you don’t have to create aliases from the console. You can always open up an Alias config file and just edit it directly. However, those changes won’t instantly effect your current console. You’d have to restart or call Alias.create()
within the console.
Delegating with Alias
Alias’ code generation ability extends beyond just creating aliases. With the alias type :any_to_instance_method, Alias can delegate an instance method to call any string of ruby code which ends with a method call. Ch-what? Take for example two handy methods for interacting with your Rails’ routes: ActionController::Routing::Routes.generate and ActionController::Routing::Routes.recognize_path. Sure, we could type that all out each time we want to use it in irb. Or we could just configure Alias to create these aliases:
# Create a module which will hold our aliases >> module RouteCommands; end => nil # :any is a shortcut for :any_to_instance_method # Let's see what Alias generates for these aliases: >> ca :any, {"RouteCommands"=>{"ActionController::Routing::Routes.generate"=>"generate", "ActionController::Routing::Routes.recognize_path"=>"recognize_path"}}, :pretend=>true module ::RouteCommands; def recognize_path(*args, &block); ActionController::Routing::Routes.recognize_path(*args, &block); end; end module ::RouteCommands; def generate(*args, &block); ActionController::Routing::Routes.generate(*args, &block); end; end => true # Looks good, let's create them >> ca :any, "RouteCommands"=>{"ActionController::Routing::Routes.generate"=>"generate", "ActionController::Routing::Routes.recognize_path"=>"recognize_path"} => true # Import the aliases/commands we've created >> extend RouteCommands => main # Save these aliases >> sa Saved created aliases to config/alias.yml. => true # Play with your new commands: generate and recognize_path >> generate :controller=>"tags" => "/tags"
Alias in Your Irbrc
To setup your script/console to load the aliases we’ve created, drop this at the end of your config/environment.rb (or .irbrc outside of Rails):
# Ensures the code is called only by script/console
if $0 == 'irb'
# For the route commands. Should exist before we start aliasing to it.
module ::RouteCommands; end
extend ::RouteCommands
require 'alias'
# create the aliases
Alias.create
end
Next time you start up script/console, the above aliases are automatically created!
Searching Aliases
Since created aliases are stored as arrays of hashes, it’s quite easy to search them:
# Using Hirb's tables for special effects. Not an Alias dependency. >> require 'hirb'; extend Hirb::Console => main # List all the aliases and pipe them through Hirb's table() for formatting. >> table search_aliases, :fields=>[:name,:alias,:class,:type,:any_method] +--------------------+----------------+--------------------+------------------------+--------------------------------------------------+ | name | alias | class | type | any_method | +--------------------+----------------+--------------------+------------------------+--------------------------------------------------+ | find | [] | ActiveRecord::Base | class_method | | | ActiveRecord::Base | AB | | constant | | | update_attribute | ua | ActiveRecord::Base | instance_method | | | create_aliases | ca | Alias::Console | instance_method | | | save_aliases | sa | Alias::Console | instance_method | | | | recognize_path | RouteCommands | any_to_instance_method | ActionController::Routing::Routes.recognize_path | | | generate | RouteCommands | any_to_instance_method | ActionController::Routing::Routes.generate | +--------------------+----------------+--------------------+------------------------+--------------------------------------------------+ 7 rows in set => true # We can search the aliases by a particular alias field with a search hash >> table search_aliases :class=>'Alias::' +-------+----------------+----------------+-----------------+ | alias | class | name | type | +-------+----------------+----------------+-----------------+ | ca | Alias::Console | create_aliases | instance_method | | sa | Alias::Console | save_aliases | instance_method | +-------+----------------+----------------+-----------------+ 2 rows in set => true
Create Your Own Alias Types
So what if you didn’t like the above formats for creating aliases or perhaps have your own clever alias type? No prob. It’s easy to create your own alias type with an Alias::Creator subclass. For example, here’s all 10 lines needed to create constant aliases:
class Alias::Creators::ConstantCreator < Alias::Creator
map {|config| config.map {|k,v| {:name=>k, :alias=>v}} }
valid :alias, :unless=>:constant, :optional=>true
valid :name, :if=>:constant
generate do |aliases|
aliases.map {|e| "::#{e[:alias]} = ::#{e[:name]}"}.join("\n")
end
end
As you can see Alias::Creator
provides three methods for creating an alias type:
map()
: Maps the hash from a config file or console input into an array of alias hashes.valid()
: Defines a validation that each alias hash must pass.generate()
: Given the array of alias hashes, generates the string of ruby code to be evaled for alias creation.
Of the above example, the only thing I think may be unclear are the valid()
calls. Let’s recall the hash we used above for creating constants: {"ActiveRecord::Base"=>"AB"}
. ActiveRecord::Base
is the :name key and is valid :if
it’s a constant. AB
is the :alias key and should be valid :unless
it’s already a constant.
Having understood how a creator works, you can make your own now by subclassing Alias::Creator
and putting it in the Alias::Creators
namespace.
Finito
As you’ve seen, Alias is a handy tool for creating, managing and searching aliases. Although I’ve shown it mostly in the context of Rails, it’s just as useful in irb or any Ruby console program that wants to provide aliasing. For more about Alias, hit up the homepage, the docs or my config files.