Emacs and Ruby on Rails
The EmacsWiki collects som resources related to customizing Emacs for developing in Ruby on Rails.
I like a simple setup mainly based on built-in tools.
Project Management
The built-in project management functions are rather handy, so I typically use:
M-x project-project-find-file
Alternatives include Projectile and Projectile Rails.
Syntax Checking and Linting
Syntax checking and linting:
M-x flycheck-mode
Alternative: M-x rubocop-mode
.
Auto completion (company mode)
I don’t use auto-completion often, short of the occasional dabbrev
expand
every once in a while.
There are three options:
- Hippie/Dabbrev, available in Emacs (and language agnostic).
- Company mode
- Autocomplete, which integrates with LSP and Robe, but it is a bit invasive for my tastes. For instance, it auto-completes directories in the shell, even if I do not want to. (I should probably spend some time customizing it to my liking)
Navigating Code
There are various options to display the file and project hierarchy (Speedback, SrSpeedbar, Treemacs, …), which allows you to interactively choose files.
Projectile-Rails also has various functions to easily jump from one file to another file of the same object (e.g., from the model to the controller).
I do not use them, though. Never got used to them.
Finding Definitions
To jump between function usage and definition, there are four options:
- Use the project search facilities (they do a grep, though)
- Use tags tables and the
xref
functions - Use
robe
- Use a Language Server Protocol (LSP) implementation
XREF
Build the XREF table using Emacs built-in tools:
find . -name *.rb | etags -
In alternative to etags
one can use ripper-tags
:
gem install ripper-tags ripper-tags --tag-file TAGS
Then:
M-.
,M-x xref-find-definitions
M-?
,M-x xref-find-references
M-x xref-query-replace-in-results
M-x tags-query-replace RET regexp RET replacement RET
See Find Identifier References for more details. The XREF table has to be manually updated on file changes.
Robe
The limitation of static syntax checking (and, therefore of tags tables) is that it can’t find methods defined with meta-programming.
This limitation is overcome by robe, which uses an inferior shell and pry to analyze code. You simply need to:
M-x robe-start
Language Server Protocols
From the Microsoft website on Language Server Protocol:
A Language Server is meant to provide the language-specific smarts and communicate with development tools over a protocol that enables inter-process communication. The idea behind the Language Server Protocol (LSP) is to standardize the protocol for how such servers and development tools communicate.
Emacs implements Language Server Protocols. The least invasive approach is that of eglot. (In alternative you can use LSP Mode, but it tweaks the interface quite a bit, making more useful or more bloated, according to the point of view.)
To use it with Ruby (on Rails), install and add to the project the solargraph and, for better Rails support, solargraph-rails and tell solargraph about it:
cat .solargraph.yml plugins: - solargraph-rails
Then:
M-x eglot
Running Ruby
Chruby
(require 'chruby nil t) (if (featurep 'chruby) (chruby "ruby-3.1.4"))
Yet another RI browser:
(require 'yari nil t)
Inferior Superior Ruby Shell
Run an inferior Ruby shell with M-x inf-ruby
and M-x inf-ruby-console-auto
:
(require 'inf-ruby nil t) (autoload 'inf-ruby-minor-mode "inf-ruby" "Run an inferior Ruby process" t) (add-hook 'ruby-mode-hook 'inf-ruby-minor-mode) (defalias 'inferior-ruby-shell 'inf-ruby) (if (featurep 'inf-ruby) (progn (define-key ruby-mode-map (kbd "C-c C-l") 'ruby-send-line) (define-key ruby-mode-map (kbd "C-c C-r") 'ruby-send-region) (define-key ruby-mode-map (kbd "C-c C-b") 'ruby-send-buffer)))
Version Control
Two options:
- The built-in version control features, which I use quite often.
Use it with
C-x v ..
. For instanceC-x v d
,C-x v =
- Magit, which has a slightly more efficient workflow