1---
2title: Ruby
3description: "Configure Ruby language support in Zed, including language servers, formatting, and debugging."
4---
5
6# Ruby
7
8Ruby support is available through the [Ruby extension](https://github.com/zed-extensions/ruby).
9
10- Tree-sitters:
11 - [tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby)
12 - [tree-sitter-embedded-template](https://github.com/tree-sitter/tree-sitter-embedded-template)
13- Language Servers:
14 - [ruby-lsp](https://github.com/Shopify/ruby-lsp)
15 - [solargraph](https://github.com/castwide/solargraph)
16 - [rubocop](https://github.com/rubocop/rubocop)
17 - [Herb](https://herb-tools.dev)
18- Debug Adapter: [`rdbg`](https://github.com/ruby/debug)
19
20The Ruby extension also provides support for ERB files.
21
22## Language Servers
23
24There are multiple language servers available for Ruby. Zed supports the two following:
25
26- [solargraph](https://github.com/castwide/solargraph)
27- [ruby-lsp](https://github.com/Shopify/ruby-lsp)
28
29They 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.
30
31In addition to these two language servers, Zed also supports:
32
33- [rubocop](https://github.com/rubocop/rubocop) which is a static code analyzer and linter for Ruby. Under the hood, it's also used by Zed as a language server, but its functionality is complimentary to that of solargraph and ruby-lsp.
34- [sorbet](https://sorbet.org/) which is a static type checker for Ruby with a custom gradual type system.
35- [steep](https://github.com/soutaro/steep) which is a static type checker for Ruby that uses Ruby Signature (RBS).
36- [Herb](https://herb-tools.dev) which is a language server for ERB files.
37
38When 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.
39
40## Configuring a language server
41
42The [Ruby extension](https://github.com/zed-extensions/ruby) offers both `solargraph` and `ruby-lsp` language server support.
43
44### Language Server Activation
45
46For all supported Ruby language servers (`solargraph`, `ruby-lsp`, `rubocop`, `sorbet`, and `steep`), the Ruby extension follows this activation sequence:
47
481. If the language server is found in your project's `Gemfile`, it will be used through `bundle exec`.
492. If not found in the `Gemfile`, the Ruby extension will look for the executable in your system `PATH`.
503. If the language server is not found in either location, the Ruby extension will automatically install it as a global gem (note: this will not install to your current Ruby gemset).
51
52You can skip step 1 and force using the system executable by setting `use_bundler` to `false` in your settings:
53
54```json [settings]
55{
56 "lsp": {
57 "<SERVER_NAME>": {
58 "settings": {
59 "use_bundler": false
60 }
61 }
62 }
63}
64```
65
66### Using `solargraph`
67
68`solargraph` is enabled by default in the Ruby extension.
69
70### Using `ruby-lsp`
71
72Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
73
74```json [settings]
75{
76 "languages": {
77 "Ruby": {
78 "language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."]
79 },
80 // Enable herb and ruby-lsp for *.html.erb files
81 "HTML+ERB": {
82 "language_servers": ["herb", "ruby-lsp", "..."]
83 },
84 // Enable ruby-lsp for *.js.erb files
85 "JS+ERB": {
86 "language_servers": ["ruby-lsp", "..."]
87 },
88 // Enable ruby-lsp for *.yaml.erb files
89 "YAML+ERB": {
90 "language_servers": ["ruby-lsp", "..."]
91 }
92 }
93}
94```
95
96That disables `solargraph` and `rubocop` and uses `ruby-lsp`.
97
98### Using `rubocop`
99
100The Ruby extension also provides support for `rubocop` language server for offense detection and autocorrection.
101
102Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
103
104```json [settings]
105{
106 "languages": {
107 "Ruby": {
108 "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
109 }
110 }
111}
112```
113
114Or, conversely, you can disable `ruby-lsp` and enable `solargraph` and `rubocop`:
115
116```json [settings]
117{
118 "languages": {
119 "Ruby": {
120 "language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
121 }
122 }
123}
124```
125
126## Setting up `solargraph`
127
128Solargraph has formatting and diagnostics disabled by default. We can tell Zed to enable them by adding the following to your `settings.json`:
129
130```json [settings]
131{
132 "lsp": {
133 "solargraph": {
134 "initialization_options": {
135 "diagnostics": true,
136 "formatting": true
137 }
138 }
139 }
140}
141```
142
143### Configuration
144
145Solargraph 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](https://solargraph.org/guides/configuration).
146
147## Setting up `ruby-lsp`
148
149You can pass Ruby LSP configuration to `initialization_options`, e.g.
150
151```json [settings]
152{
153 "languages": {
154 "Ruby": {
155 "language_servers": ["ruby-lsp", "!solargraph", "..."]
156 }
157 },
158 "lsp": {
159 "ruby-lsp": {
160 "initialization_options": {
161 "enabledFeatures": {
162 // "someFeature": false
163 }
164 }
165 }
166 }
167}
168```
169
170For full configuration options, see the [Ruby LSP website](https://shopify.github.io/ruby-lsp/editors.html).
171
172LSP `settings` and `initialization_options` can also be project-specific. For example to use [standardrb/standard](https://github.com/standardrb/standard) as a formatter and linter for a particular project, add this to a `.zed/settings.json` inside your project repo:
173
174```json [settings]
175{
176 "lsp": {
177 "ruby-lsp": {
178 "initialization_options": {
179 "formatter": "standard",
180 "linters": ["standard"]
181 }
182 }
183 }
184}
185```
186
187## Setting up `rubocop` LSP
188
189Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your `settings.json`:
190
191```json [settings]
192{
193 "languages": {
194 "Ruby": {
195 // Use ruby-lsp as the primary language server and rubocop as the secondary.
196 "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
197 }
198 },
199 "lsp": {
200 "rubocop": {
201 "initialization_options": {
202 "safeAutocorrect": false
203 }
204 },
205 "ruby-lsp": {
206 "initialization_options": {
207 "enabledFeatures": {
208 "diagnostics": false
209 }
210 }
211 }
212 }
213}
214```
215
216## Setting up Sorbet
217
218[Sorbet](https://sorbet.org/) is a popular static type checker for Ruby that includes a language server.
219
220To 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.
221
222Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
223
224```json [settings]
225{
226 "languages": {
227 "Ruby": {
228 "language_servers": [
229 "ruby-lsp",
230 "sorbet",
231 "!rubocop",
232 "!solargraph",
233 "..."
234 ]
235 }
236 }
237}
238```
239
240For all aspects of installing Sorbet, setting it up in your project, and configuring its behavior, please refer to the [official Sorbet documentation](https://sorbet.org/docs/overview).
241
242## Setting up Steep
243
244[Steep](https://github.com/soutaro/steep) is a static type checker for Ruby that uses RBS files to define types.
245
246To 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.
247
248Configure language servers in Settings ({#kb zed::OpenSettings}) under Languages > Ruby, or add to your settings file:
249
250```json [settings]
251{
252 "languages": {
253 "Ruby": {
254 "language_servers": [
255 "ruby-lsp",
256 "steep",
257 "!solargraph",
258 "!rubocop",
259 "..."
260 ]
261 }
262 }
263}
264```
265
266## Setting up Herb
267
268`Herb` is enabled by default for the `HTML+ERB` language.
269
270## Using the Tailwind CSS Language Server with Ruby
271
272To get all the features (autocomplete, linting, etc.) from the [Tailwind CSS language server](https://github.com/tailwindlabs/tailwindcss-intellisense/tree/HEAD/packages/tailwindcss-language-server#readme) 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`:
273
274```json [settings]
275{
276 "lsp": {
277 "tailwindcss-language-server": {
278 "settings": {
279 "experimental": {
280 "classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
281 }
282 }
283 }
284 }
285}
286```
287
288With 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:
289
290```rb
291# Ruby file:
292def method
293 div(class: "pl-2 <completion here>") do
294 p(class: "mt-2 <completion here>") { "Hello World" }
295 end
296end
297
298# ERB file:
299<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
300<a href="/hello" class="pl-2 <completion here>">Hello</a>
301```
302
303## Running tests
304
305To 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.
306
307### Minitest with Rails
308
309```json [tasks]
310[
311 {
312 "label": "test $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
313 "command": "bin/rails",
314 "args": [
315 "test",
316 "$ZED_RELATIVE_FILE",
317 "-n",
318 "\"$ZED_CUSTOM_RUBY_TEST_NAME\""
319 ],
320 "cwd": "$ZED_WORKTREE_ROOT",
321 "tags": ["ruby-test"]
322 }
323]
324```
325
326### Minitest
327
328Plain minitest does not support running tests by line number, only by name, so we need to use `$ZED_CUSTOM_RUBY_TEST_NAME` instead:
329
330```json [tasks]
331[
332 {
333 "label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_CUSTOM_RUBY_TEST_NAME/",
334 "command": "bundle",
335 "args": [
336 "exec",
337 "ruby",
338 "-Itest",
339 "$ZED_RELATIVE_FILE",
340 "-n",
341 "\"$ZED_CUSTOM_RUBY_TEST_NAME\""
342 ],
343 "cwd": "$ZED_WORKTREE_ROOT",
344 "tags": ["ruby-test"]
345 }
346]
347```
348
349### RSpec
350
351```json [tasks]
352[
353 {
354 "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
355 "command": "bundle",
356 "args": ["exec", "rspec", "\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
357 "cwd": "$ZED_WORKTREE_ROOT",
358 "tags": ["ruby-test"]
359 }
360]
361```
362
363Similar task syntax can be used for other test frameworks such as `quickdraw` or `tldr`.
364
365## Debugging
366
367The 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`](https://github.com/ruby/debug) gem. The extension uses the [same activation logic](#language-server-activation) as the language servers.
368
369### Examples
370
371#### Debug a Ruby script
372
373```json [debug]
374[
375 {
376 "label": "Debug current file",
377 "adapter": "rdbg",
378 "request": "launch",
379 "script": "$ZED_FILE",
380 "cwd": "$ZED_WORKTREE_ROOT"
381 }
382]
383```
384
385#### Debug Rails server
386
387```json [debug]
388[
389 {
390 "label": "Debug Rails server",
391 "adapter": "rdbg",
392 "request": "launch",
393 "command": "./bin/rails",
394 "args": ["server"],
395 "cwd": "$ZED_WORKTREE_ROOT",
396 "env": {
397 "RUBY_DEBUG_OPEN": "true"
398 }
399 }
400]
401```
402
403## Formatters
404
405### `erb-formatter`
406
407To format ERB templates, you can use the `erb-formatter` formatter. This formatter uses the [`erb-formatter`](https://rubygems.org/gems/erb-formatter) gem to format ERB templates.
408
409Configure formatting in Settings ({#kb zed::OpenSettings}) under Languages > HTML+ERB, or add to your settings file:
410
411```json [settings]
412{
413 "languages": {
414 "HTML+ERB": {
415 "formatter": {
416 "external": {
417 "command": "erb-formatter",
418 "arguments": ["--stdin-filename", "{buffer_path}"]
419 }
420 }
421 }
422 }
423}
424```