Follow @learnvim for more Vim tips and tricks!
I recently published an article on Vimspector (Debugging in Vim with Vimspector). There I covered different ways to run Vimspector for various Javascript environments. If you're a Rails developer like me, you may ask, "I'm sold on Vimspector, but how can I run it in Rails?"
To be frank, there are not a lot of resources online on how to accomplish this. After tinkering for a few days, I found a few setups that work on a basic Rails application.
I am not claiming that this is the foolproof way to debug any Rails application. There are rooms for improvement and exploration. But for starting out, this is sufficient.
This article assumes that you have had some experience with Vimspector. At minimum, you need to know how to step into, step over, and step out of breakpoints. You also need to know how to launch and restart Vimspector. If you don't, please read my previous article first.
Create a Basic Rails App
I am a huge fan of practical learning. I believe you'll get far more mileage if you actually do the steps as you are reading this article. So for the sake of hands-on approach, let's create a brand new Rails app. Don't worry, it should take less than 5 min.
Create a new Rails app:
rails new hello
Create a controller:
rails generate controller Says hello
Let's go to the controller and write up some codes. Inside ./app/controllers/says_controller.rb
, modify the hello
action:
class SaysController < ApplicationController
def hello
@time = DateTime.now
@greetings = "Greetings"
end
end
Modify the hello.html.erb
file:
<h1>Says#hello</h1>
<p><= @greetings %></p>
<p>It is now <= @time %></p>
Excellent! Let's quickly test if the Rails app is running properly.
rails s
Visit http://localhost:3000/says/hello. You should also see the values of the @greetings
and @time
instance variables.
Adding Important Gems
Vimspector isn't a debugger. It's a "middle-man" that talks to a debugger. Vimspector provides a standard protocol to communicate with different debuggers. With Vimspector, you can communicate the same way with a Node debugger, Python debugger, Go debugger, etc.
For Vimspector to work with Ruby, you need to install a Ruby debugger. We will use ruby-debug-ide.
In addition, you also need to install debase
(source). Add these two in your gemfile (in a real project, you probably want to put them inside the group :development, :test do ...
block)
gem 'ruby-debug-ide'
gem 'debase'
Vimspector JSON
Create a .vimspector.json
at the Rails project root. Inside it:
{
"configurations": {
"rails": {
"adapter": "cust_vscode-ruby",
"default": true,
"configuration": {
"name": "Debug Rails server",
"type": "Ruby",
"request": "launch",
"cwd": "${workspaceRoot}",
"pathToBundler": "/Users/iggy/.rbenv/shims/bundle",
"pathToRDebugIDE": "/Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2",
"program": "${workspaceRoot}/bin/rails",
"args": [
"server"
]
}
}
}
}
Note that you have to update pathToRDebugIDE
and pathToBundler
with your own paths. I'll explain below.
Bundler, Debugger, and Adapter
There are three things that you need to provide Vimspector with:
- The path to bundler.
- The path to the debugger.
- Which adapter to use.
To get the path for pathToBundler
, run:
which bundler
In my case, it returns /User/iggy/.rbenv/shims/bundle
. Use whatever path your machine uses.
Assuming you have installed the ruby-debug-ide gem via your Rails' Gemfile, to get the pathToRDebugIDE
path, run:
bundle show ruby-debug-ide
In my case, it returns /Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2
. Use whatever path you see.
Finally, recall that Vimspector requires a special adapter for each language / environment you use (in my previous article, I installed adapters - also known as "gadgets" - for node and chrome). Since we're debugging a Ruby framework, we need a Ruby adapter.
Adding a Ruby Adapter
If you look at the Vimspector config file above, you'll see:
"adapter": "cust_vscode-ruby",
Unfortunately, Ruby is not in one of the supported languages in the Vimspector page (darn it!). Don't worry, if you dig the Vimspector repo deep enough, you will find instructions on how to "install" a Ruby gadget there.
Here's the page with information for languages not officially mentioned in the README. If you scroll down, you'll find an instruction for Ruby.
Follow the instruction on the introduction section
- Inside the Vimspector directory (in my case, it is in
~/.vim/plugged/vimspector/gadgets/custom/cust_vscode-ruby.json
- yours could be in a different directory depending on what plugin manager you use), add a custom json file for your language. - Run
./install_gadget.py --upgrade
. Vimspector should install some files fromvscode-ruby
.
Phew! We are done with the preliminary setup.
If you're still curious what just happened, here are a few pages to read:
Program and Args
Let's take another look at a section inside the Vimspector config file:
"program": "${workspaceRoot}/bin/rails",
"args": [
"server"
]
Recall from the previous article, program
is the program that Vimspector will run when you tell it to launch something and args
is the argument that gets passed to program
.
When running a rails app, you would (usually) run bin/rails server
. The config does exactly that.
Running the Vimspector
Now we are ready to run Vimspector. Our config is set to launch
, so do not run rails s
from the terminal. We will run it from the debugger.
Go to the says_controller.rb
and add a breakpoint on @time
:
class SaysController < ApplicationController
def hello
@time = DateTime.now # add a breakpoint here
@greetings = "Greetings"
end
end
Excellent. Now here comes the moment of truth - let's launch Vimspector!
Wait a few seconds, you should see on the Console
window that Vimspector is launching a Rails app.
Now, visit http://localhost:3000/says/hello. The app should pause.
Check your Vimspector. You should see it paused at the breakpoint.
If this is what you see, congratulations! You've successfully launched a Rails debugger - from Vim!
From there, you can step into, step over, and step out of different lines of code.
Attach Vs Launch
There are two ways you can run Vimspector: attach and launch. The former attaches the debugger into an already running process. The latter launches a process from the debugger.
The Rails example above is an example of launch, as it launches a Rails process directly from the debugger. Theoretically, you should be able to perform either attach or launch.
Attaching a Debugger to a Rails Server
You've seen how to launch a Rails app from Vimspector. Let's see how you can attach Vimspector to a Rails process.
First, modify our .vimspector.json
file:
{
"configurations": {
"rails": {
"adapter": "cust_vscode-ruby",
"default": true,
"configuration": {
"name": "Debug Rails server",
"type": "Ruby",
"request": "attach",
"cwd": "${workspaceRoot}",
"remoteHost": "0.0.0.0",
"remotePort": "1234",
"pathToBundler": "/Users/iggy/.rbenv/shims/bundle",
"pathToRDebugIDE": "/Users/iggy/.rbenv/versions/2.6.6/lib/ruby/gems/2.6.0/gems/ruby-debug-ide-0.7.2"
}
}
}
}
Here are the changes:
request
is nowattach
.- We added
remoteHost
andremotePort
. - We removed
"programs"
and"args"
(they are unnecessary for attach).
The remoteHost
and remotePort
are the IP address and port number that we will be running the debugger on. The host is set to 0.0.0.0
and the port is set to 1234
. These numbers will make sense in a little bit.
Once your vimspector.json
file is configured, let's run the app. Instead of running the regular bin/rails s
, run:
rdebug-ide --host 0.0.0.0 --port 1234 --dispatcher-port 1234 -- bin/rails s
This will launch the ruby-debug-ide
program installed earlier. Note the host and port numbers: we are running the debugger on host 0.0.0.0
and port 1234
in addition to running the rails server.
Next, add the breakpoints inside the says_controller.rb
file, then launch Vimspector. Since we are running Vimspector on attach mode, it won't launch a Rails server this time. Head to the page related to this controller: http://localhost:3000/says/hello. Watch your Vimspector pauses at the breakpoint(s).
Sweet chocolate pancake! Super cool, isn't it? Well, this also concludes this article.
Conclusion
Congratulations! You've successfully debugged a Rails app. You are one step closer from becoming a supreme master developer.
There is still much to explore about Vimspector and Rails applications. There are different settings, environments, and configs that I don't mention in this article. Experiment. Share this article. Let me know how you do things differently.
In the end, I hope that this article has given you a good place to start. Happy Vimming!