docs/src/languages/ruby.md
Ruby support is available through the Ruby extension.
rdbgThe Ruby extension also provides support for ERB files.
There are multiple language servers available for Ruby. Zed supports the two following:
They both have an overlapping feature set of autocomplete, diagnostics, code actions, etc. and it's up to you to decide which one you want to use. Note that you can't use both at the same time.
In addition to these two language servers, Zed also supports:
When configuring a language server, it helps to open the LSP Logs window using the 'dev: Open Language Server Logs' command. You can then choose the corresponding language instance to see any logged information.
The Ruby extension offers both solargraph and ruby-lsp language server support.
For all supported Ruby language servers (solargraph, ruby-lsp, rubocop, sorbet, and steep), the Ruby extension follows this activation sequence:
Gemfile, it will be used through bundle exec.Gemfile, the Ruby extension will look for the executable in your system PATH.You can skip step 1 and force using the system executable by setting use_bundler to false in your settings:
{
"lsp": {
"<SERVER_NAME>": {
"settings": {
"use_bundler": false
}
}
}
}
solargraphsolargraph is enabled by default in the Ruby extension.
ruby-lspConfigure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
{
"languages": {
"Ruby": {
"language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."]
},
// Enable herb and ruby-lsp for *.html.erb files
"HTML+ERB": {
"language_servers": ["herb", "ruby-lsp", "..."]
},
// Enable ruby-lsp for *.js.erb files
"JS+ERB": {
"language_servers": ["ruby-lsp", "..."]
},
// Enable ruby-lsp for *.yaml.erb files
"YAML+ERB": {
"language_servers": ["ruby-lsp", "..."]
}
}
}
That disables solargraph and rubocop and uses ruby-lsp.
rubocopThe Ruby extension also provides support for rubocop language server for offense detection and autocorrection.
Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
{
"languages": {
"Ruby": {
"language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
}
}
}
Or, conversely, you can disable ruby-lsp and enable solargraph and rubocop:
{
"languages": {
"Ruby": {
"language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
}
}
}
solargraphSolargraph has formatting and diagnostics disabled by default. We can tell Zed to enable them by adding the following to your settings.json:
{
"lsp": {
"solargraph": {
"initialization_options": {
"diagnostics": true,
"formatting": true
}
}
}
}
Solargraph reads its configuration from a file called .solargraph.yml in the root of your project. For more information about this file, see the Solargraph configuration documentation.
ruby-lspYou can pass Ruby LSP configuration to initialization_options, e.g.
{
"languages": {
"Ruby": {
"language_servers": ["ruby-lsp", "!solargraph", "..."]
}
},
"lsp": {
"ruby-lsp": {
"initialization_options": {
"enabledFeatures": {
// "someFeature": false
}
}
}
}
}
For full configuration options, see the Ruby LSP website.
LSP settings and initialization_options can also be project-specific. For example to use standardrb/standard as a formatter and linter for a particular project, add this to a .zed/settings.json inside your project repo:
{
"lsp": {
"ruby-lsp": {
"initialization_options": {
"formatter": "standard",
"linters": ["standard"]
}
}
}
}
rubocop LSPRubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your settings.json:
{
"languages": {
"Ruby": {
// Use ruby-lsp as the primary language server and rubocop as the secondary.
"language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
}
},
"lsp": {
"rubocop": {
"initialization_options": {
"safeAutocorrect": false
}
},
"ruby-lsp": {
"initialization_options": {
"enabledFeatures": {
"diagnostics": false
}
}
}
}
}
Sorbet is a popular static type checker for Ruby that includes a language server.
To enable Sorbet, add \"sorbet\" to the language_servers list for Ruby. You may want to disable other language servers if Sorbet is intended to be your primary LSP, or if you plan to use it alongside another LSP for specific features like type checking.
Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
{
"languages": {
"Ruby": {
"language_servers": [
"ruby-lsp",
"sorbet",
"!rubocop",
"!solargraph",
"..."
]
}
}
}
For all aspects of installing Sorbet, setting it up in your project, and configuring its behavior, please refer to the official Sorbet documentation.
Steep is a static type checker for Ruby that uses RBS files to define types.
To enable Steep, add \"steep\" to the language_servers list for Ruby. You may need to adjust the order or disable other LSPs depending on your desired setup.
Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
{
"languages": {
"Ruby": {
"language_servers": [
"ruby-lsp",
"steep",
"!solargraph",
"!rubocop",
"..."
]
}
}
}
Herb is enabled by default for the HTML+ERB language.
To get all the features (autocomplete, linting, etc.) from the Tailwind CSS language server in Ruby/ERB files, you need to configure the language server so that it knows about where to look for CSS classes by adding the following to your settings.json:
{
"lsp": {
"tailwindcss-language-server": {
"settings": {
"experimental": {
"classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
}
}
}
}
}
With these settings, you will get completions for Tailwind CSS classes in HTML attributes inside ERB files and inside Ruby/ERB strings that are coming after a class: key. Examples:
# Ruby file:
def method
div(class: "pl-2 <completion here>") do
p(class: "mt-2 <completion here>") { "Hello World" }
end
end
# ERB file:
<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
<a href="/hello" class="pl-2 <completion here>">Hello</a>
To run tests in your Ruby project, you can set up custom tasks in your local .zed/tasks.json configuration file. These tasks can be defined to work with different test frameworks like Minitest, RSpec, quickdraw, and tldr. Below are some examples of how to set up these tasks to run your tests from within your editor.
[
{
"label": "test $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
"command": "bin/rails",
"args": [
"test",
"$ZED_RELATIVE_FILE",
"-n",
"\"$ZED_CUSTOM_RUBY_TEST_NAME\""
],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
Plain minitest does not support running tests by line number, only by name, so we need to use $ZED_CUSTOM_RUBY_TEST_NAME instead:
[
{
"label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
"command": "bundle",
"args": [
"exec",
"ruby",
"-Itest",
"$ZED_RELATIVE_FILE",
"-n",
"\"$ZED_CUSTOM_RUBY_TEST_NAME\""
],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
[
{
"label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
"command": "bundle",
"args": ["exec", "rspec", "\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
"cwd": "$ZED_WORKTREE_ROOT",
"tags": ["ruby-test"]
}
]
Similar task syntax can be used for other test frameworks such as quickdraw or tldr.
The Ruby extension provides a debug adapter for debugging Ruby code. Zed's name for the adapter (in the UI and debug.json) is rdbg, and under the hood, it uses the debug gem. The extension uses the same activation logic as the language servers.
[
{
"label": "Debug current file",
"adapter": "rdbg",
"request": "launch",
"script": "$ZED_FILE",
"cwd": "$ZED_WORKTREE_ROOT"
}
]
[
{
"label": "Debug Rails server",
"adapter": "rdbg",
"request": "launch",
"command": "./bin/rails",
"args": ["server"],
"cwd": "$ZED_WORKTREE_ROOT",
"env": {
"RUBY_DEBUG_OPEN": "true"
}
}
]
erb-formatterTo format ERB templates, you can use the erb-formatter formatter. This formatter uses the erb-formatter gem to format ERB templates.
Configure formatting in Settings ({#kb zed::OpenSettings}) under Languages > HTML+ERB, or add to your settings file:
{
"languages": {
"HTML+ERB": {
"formatter": {
"external": {
"command": "erb-formatter",
"arguments": ["--stdin-filename", "{buffer_path}"]
}
}
}
}
}