Code . Art . Web

Notes on Software Craftsmanship, Architecture Design and the Art of Building beautiful abstractions,
primary focus being on Web centric platforms and technologies.

Configuring Emacs as a productive development environment for Rails development.

02 Feb 2014

Updates

  • The default keybindings have been updated based on the feedback from Asok, the author of the awesmoe projectile-rails package.

This post outlines some of the Emacs extensions (open source, of course) which can significantly ease the life of a Rails developer. While Rails is, by design, quite a productive framework, having the dev environment properly setup can multiply developer efficiency by an order of magnitude. Although almost all of this information is available online elsewhere, I nevertheless wanted to summarize my explorations in form of a basic guide to easily configure extensions I have found to be useful, during the course of my Rails projects. While the primary audience is a forgetful me from the future, I hope developers new to Rails or Emacs (or both) will find this helpful to get up and running with Emacs and Rails, without having to wade through reams of documentation right upfront. I have tried my best to link the appropriate authoritative resources, which may be helpful for people looking forward to customizing and extending the setup.

While the setup below has been tested only in Linux Elementary, it should work for other Posix environments as well. Please ensure that you have got atleast Emacs 24 and can download packages through package.el. If you are not familiar with package management in emacs Bozhidar Batsov has presented a great introduction. Adding the following snippet to your ~/.emacs should provide access to marmalade and melpa package archives:

(require 'package)
(add-to-list 'package-archives 
    '("marmalade" .
      "http://marmalade-repo.org/packages/"))
(add-to-list 'package-archives
    '("melpa" . "http://melpa.milkbox.net/packages/") t)
(package-initialize)

Syntax Checking

While the ruby-mode bundled with Emacs works well with syntax highlighting, it does not automatically handle syntax checking. Luckily we have flymake, which is a generic on the fly syntax checking system. We can install flymake-ruby which facilitates syntax checking for ruby through our package manager. Just hit M-x package-install and type in flymake-ruby.

Once flymake-ruby is installed, we just have to hook it up with the ruby-mode.

(require 'flymake-ruby)
(add-hook 'ruby-mode-hook 'flymake-ruby-load)

And voila, no syntax errors go unnoticed ever again:

Emacs flymake screenshot

Sane indentation

The default indentation system attempts to align the arguments of a function with the opening bracket vertically.

function_call (arg1,
               arg2);

While this is subjective, but if you, like me, find this behaviour erratic - the following will make emacs indent code inside parenthesis similar to elsewhere.

(setq ruby-deep-indent-paren nil)

Ruby shell inside emacs

inf-ruby provides a REPL buffer connected to a Ruby subprocess. It is available through the package manager. Once installed you would probably want to bind it to a convenient shortcut. The following would bind it to C-c r r.

(global-set-key (kbd "C-c r r") 'inf-ruby)

Integration with RVM

If you use RVM for managing ruby versions, you would want to use rvm.el. Once installed you will just have to call rvm-activate-corresponding-ruby and rvm.el will automatically pick up your ruby version and gemset from .rvmrc file.

The following will bind the aforementioned command to C-c r a

(global-set-key (kbd "C-c r a") 'rvm-activate-corresponding-ruby)

rvm.el

It seamlessly integrates with inf-ruby so if you invoke inf-ruby after the previous step, you will get the version of ruby and gemset you expect.

Project management with projectile

So far the steps had nothing to do with Rails and were equally useful for vanilla ruby projects. However for managing large Rails applications some basic project management facilities might come in handy.

While there are a plethora of project management utilities for emacs, One that is particularly simple and easy to install is projectile. It is available through the package manager. Once installed it can be configured as a global mode as follows:

(projectile-global-mode)

or it can be hooked into particular modes:

(add-hook 'ruby-mode-hook 'projectile-on)

I would also strongly recommend using the ido-mode which, among other things, provides various enhancements to make navigation between files and buffers easy. The default behaviour of C-x C-f and C-x C-b are changed to a more interactive version, which shows a list of matched options while typing right inside the minibuffer. flx-ido is an extension which further enhances the matching capabilities of ido to perform fuzzy matching (a-la sublime text) which can be a great productivity boost, particularly if you are a bit sloppy with keyboard. ido is built into emacs and flx-ido is available through package manager.

flx-ido-mode activates the ido mode augmenting with flexible matching.

You may want to use following snippet to display ido completions vertically instead of horizontally, as is the default behaviour.

 ;; Display ido results vertically, rather than horizontally
  (setq ido-decorations (quote ("\n-> " "" "\n   " "\n   ..." "[" "]" " [No match]" " [Matched]" " [Not readable]" " [Too big]" " [Confirm]")))
  (defun ido-disable-line-truncation () (set (make-local-variable 'truncate-lines) nil))
  (add-hook 'ido-minibuffer-setup-hook 'ido-disable-line-truncation)
  (defun ido-define-keys () ;; C-n/p is more intuitive in vertical layout
    (define-key ido-completion-map (kbd "C-n") 'ido-next-match)
    (define-key ido-completion-map (kbd "C-p") 'ido-prev-match))
  (add-hook 'ido-setup-hook 'ido-define-keys)

Emacs ido vertical completions

Projectile integrates with ido and uses it as its indexing method. For projectile to recognize the project root, you just have to drop an empty .projectile file there. Once that is done, you can simply perform a fuzzy search for files using C-c C-p f and directories using C-c C-p d

Projectile find file Projectile find dir

Projectile Rails builds upon projectile to provide project management facilities specifically tailored for Rails applications. It is available through package manager and can be hooked up with projectile using :

(add-hook 'projectile-mode-hook 'projectile-rails-on)

Projectile Rails adds a large number of keybindings to ease navigation across files in a rails project, running rake tasks, invoking console etc. Following is the list of commands and associated bindings taken from the home page of projectile rails.

Command Keybinding Description
projectile-rails-find-model C-c r m Find a model using projectile-completion-system.
projectile-rails-find-current-model C-c r M Go to a model connected with the current resource.
projectile-rails-find-controller C-c r c Find a controller using projectile-completion-system.
projectile-rails-find-current-controller C-c r C Go to a controller connected with the current resource.
projectile-rails-find-view C-c r v Find a template or partial using projectile-completion-system.
projectile-rails-find-current-view C-c r V Go to a view connected with the current resource.
projectile-rails-find-helper C-c r h Find a helper using projectile-completion-system.
projectile-rails-find-current-helper C-c r H Go to a helper connected with the current resource.
projectile-rails-find-lib C-c r l Find a lib using projectile-completion-system.
projectile-rails-find-feature C-c r f Find a feature using projectile-completion-system.
projectile-rails-find-spec C-c r p Find a spec using projectile-completion-system.
projectile-rails-find-current-spec C-c r P Go to a spec connected with the current resource.
projectile-rails-find-migration C-c r n Find a migration using projectile-completion-system.
projectile-rails-find-current-migration C-c r N Go to a migration connected with the current resource.
projectile-rails-find-javascript C-c r j Find a javascript using projectile-completion-system.
projectile-rails-find-stylesheet C-c r s Find a stylesheet using projectile-completion-system.
projectile-rails-find-log C-c r o Find a log file and enable auto-revert-tail-mode in its buffer.
projectile-rails-find-initializer C-c r i Find an initializer file using projectile-completions-system.
projectile-rails-find-environment C-c r e Find an environment file using projectile-completions-system.
projectile-rails-find-locale C-c r a Find a locale file using projectile-completions-system.
projectile-rails-find-mailer C-c r @ Find a mailer file using projectile-completions-system.
projectile-rails-find-layout C-c r y Find a layout file using projectile-completions-system.
projectile-rails-console C-c r ! c, C-c r r Run rails console command in inf-ruby buffer.
projectile-rails-server C-c r ! s, C-c r R Run rails server.
projectile-rails-rake C-c r ! r Select a rake task to run using projectile-completion-system.
projectile-rails-generate C-c r ! g Run rails generate command.
projectile-rails-extract-region C-c r x Extract the selected region to a partial.
projectile-rails-goto-file-at-point C-c r RET, C-c r g f Go to a file at point. Depending on the context that might be a constant, template or partial, or a gem.
projectile-rails-goto-gemfile C-c r g g Go to Gemfile file.
projectile-rails-goto-routes C-c r g r Go to config/routes.rb file.
projectile-rails-goto-schema C-c r g d Go to db/schema.rb file.
projectile-rails-goto-spec-helper C-c r g l Go to spec/spec_helper.rb file.

Note that rails console uses inf-ruby, so integration with rvm is smooth and effortless.

Projectile Rails console

Intelligent Code navigation and Completion with Robe

Robe is a code assistance tool that uses a Ruby REPL subprocess with your application or gem code loaded, to provide information about loaded classes and modules, and where each method is defined.

Robe is available via package manager. Once installed it can be hooked into ruby mode.

(require 'robe)
(add-hook 'ruby-mode-hook 'robe-mode)

If you are using rvm you may want to instruct robe to auto-trigger rvm-activate-corresponding-ruby.

(defadvice inf-ruby-console-auto (before activate-rvm-for-robe activate)
  (rvm-activate-corresponding-ruby))

robe-jump bound by default to M-. can be used to jump to definitions of various classes and methods. While it is not ideal, in most of the scenarios, the expected entry is present in the first few suggestions.

For intelligent completion robe can be integrated with company mode. Company mode is a modern and modular completion system for emacs which accepts a multitude of pluggable back-ends and front-ends to provide rich completions on the fly. Robe provides a backend to the completion in form of company-robe. This can be configured as follows :

(global-company-mode t)
(push 'company-robe company-backends)

Now all you have to do is hit robe-start when you navigate into your project. After that at any point if you trigger company-robe you should be greeted with an intellisense like method definitions.

Completion will start automatically after you type a few letters. Use M-n, M-p, <tab> and <return> to complete. Search through the completions with C-s, C-r and C-o. Even the documentations are available right from the editor (Press F1 at any menu entry).

Emacs robe completions

One of the caveats is that robe requires pry and pry-doc to be in Gemfile. This is a problem when working with third party projects and I don't have a workaround for that yet.

Also Ruby being a dynamic language which strives to push the limits on flexibility, perfect completion is simply not possible. Many of known caveats are listed here and some are being actively being worked upon. But nevertheless, I have found the setup to be quite useful for day to day development and hope you do too.

I hope that this quick detour into the world of emacs-extensions has motivated you to atleast try out Emacs. How far you go down the rabbit hole is of-course for you to decide. As always, any criticism, suggestions and comments are welcome.

comments powered by Disqus