DEV Community

Igor Irianto
Igor Irianto

Posted on

Debugging a Rails App in Vim With Vimspector

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


Enter fullscreen mode Exit fullscreen mode

Create a controller:



rails generate controller Says hello


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

Modify the hello.html.erb file:



<h1>Says#hello</h1>
<p><%= @greetings %></p>
<p>It is now <%= @time %></p>


Enter fullscreen mode Exit fullscreen mode

Excellent! Let's quickly test if the Rails app is running properly.



rails s


Enter fullscreen mode Exit fullscreen mode

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'


Enter fullscreen mode Exit fullscreen mode

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"
          ]
      }
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

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:

  1. The path to bundler.
  2. The path to the debugger.
  3. Which adapter to use.

To get the path for pathToBundler, run:



which bundler


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

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",


Enter fullscreen mode Exit fullscreen mode

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

  1. 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.
  2. Run ./install_gadget.py --upgrade. Vimspector should install some files from vscode-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"
]


Enter fullscreen mode Exit fullscreen mode

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


Enter fullscreen mode Exit fullscreen mode

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.

Rails Vimspector Launch

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"
      }
    }
  }
}


Enter fullscreen mode Exit fullscreen mode

Here are the changes:

  • request is now attach.
  • We added remoteHost and remotePort.
  • 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


Enter fullscreen mode Exit fullscreen mode

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).

Rails Vimspector Attach

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!

Top comments (0)