ruby.md

  1# Ruby
  2
  3Ruby support is available through the [Ruby extension](https://github.com/zed-extensions/ruby).
  4
  5- Tree-sitters:
  6  - [tree-sitter-ruby](https://github.com/tree-sitter/tree-sitter-ruby)
  7  - [tree-sitter-embedded-template](https://github.com/tree-sitter/tree-sitter-embedded-template)
  8- Language Servers:
  9  - [ruby-lsp](https://github.com/Shopify/ruby-lsp)
 10  - [solargraph](https://github.com/castwide/solargraph)
 11  - [rubocop](https://github.com/rubocop/rubocop)
 12
 13The Ruby extension also provides support for ERB files.
 14
 15## Language Servers
 16
 17There are multiple language servers available for Ruby. Zed supports the two following:
 18
 19- [solargraph](https://github.com/castwide/solargraph)
 20- [ruby-lsp](https://github.com/Shopify/ruby-lsp)
 21
 22They 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.
 23
 24In addition to these two language servers, Zed also supports [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.
 25
 26When configuring a language server, it helps to open the LSP Logs window using the 'debug: open language server logs' command. You can then choose the corresponding language instance to see any logged information.
 27
 28## Configuring a language server
 29
 30The [Ruby extension](https://github.com/zed-extensions/ruby) offers both `solargraph` and `ruby-lsp` language server support.
 31
 32### Using `solargraph`
 33
 34`solargraph` is enabled by default in the Ruby extension.
 35
 36### Using `ruby-lsp`
 37
 38To switch to `ruby-lsp`, add the following to your `settings.json`:
 39
 40```json
 41{
 42  "languages": {
 43    "Ruby": {
 44      "language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."]
 45    }
 46  }
 47}
 48```
 49
 50That disables `solargraph` and `rubocop` and enables `ruby-lsp`.
 51
 52### Using `rubocop`
 53
 54The Ruby extension also provides support for `rubocop` language server for offense detection and autocorrection.
 55
 56To enable it, add the following to your `settings.json`:
 57
 58```json
 59{
 60  "languages": {
 61    "Ruby": {
 62      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
 63    }
 64  }
 65}
 66```
 67
 68Or, conversely, you can disable `ruby-lsp` and enable `solargraph` and `rubocop` by adding the following to your `settings.json`:
 69
 70```json
 71{
 72  "languages": {
 73    "Ruby": {
 74      "language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
 75    }
 76  }
 77}
 78```
 79
 80## Setting up `solargraph`
 81
 82Zed currently doesn't install Solargraph automatically. To use Solargraph, you need to install the gem. Zed just looks for an executable called `solargraph` on your `PATH`.
 83
 84You can install the gem manually with the following command:
 85
 86```sh
 87gem install solargraph
 88```
 89
 90Alternatively, if your project uses Bundler, you can add the Solargraph gem to your `Gemfile`:
 91
 92```rb
 93gem 'solargraph', group: :development
 94```
 95
 96Solargraph has formatting and diagnostics disabled by default. We can tell Zed to enable them by adding the following to your `settings.json`:
 97
 98```json
 99{
100  "lsp": {
101    "solargraph": {
102      "initialization_options": {
103        "diagnostics": true,
104        "formatting": true
105      }
106    }
107  }
108}
109```
110
111By default, Solargraph uses `bundle exec` to run in the context of the bundle. To disable that, you can use the `use_bundler` configuration option:
112
113```json
114{
115  "lsp": {
116    "solargraph": {
117      "settings": {
118        "use_bundler": false
119      }
120    }
121  }
122}
123```
124
125### Configuration
126
127Solargraph 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).
128
129## Setting up `ruby-lsp`
130
131Zed currently doesn't install Ruby LSP automatically. To use Ruby LSP, you need to install the gem. Zed just looks for an executable called `ruby-lsp` on your `PATH`.
132
133You can install the gem manually with the following command:
134
135```sh
136gem install ruby-lsp
137```
138
139Ruby LSP uses pull-based diagnostics which Zed doesn't support yet. We can tell Zed to disable it by adding the following to your `settings.json`:
140
141```json
142{
143  "languages": {
144    "Ruby": {
145      "language_servers": ["ruby-lsp", "!solargraph", "..."]
146    }
147  },
148  "lsp": {
149    "ruby-lsp": {
150      "initialization_options": {
151        "enabledFeatures": {
152          // This disables diagnostics
153          "diagnostics": false
154        }
155      }
156    }
157  }
158}
159```
160
161LSP `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:
162
163```json
164{
165  "lsp": {
166    "ruby-lsp": {
167      "initialization_options": {
168        "formatter": "standard",
169        "linters": ["standard"]
170      }
171    }
172  }
173}
174```
175
176By default, Ruby LSP does not use `bundle exec` to run in the context of the bundle. To enable that, you can use the `use_bundler` configuration option:
177
178```json
179{
180  "lsp": {
181    "ruby-lsp": {
182      "settings": {
183        "use_bundler": true
184      }
185    }
186  }
187}
188```
189
190## Setting up `rubocop` LSP
191
192Zed currently doesn't install `rubocop` automatically. To use `rubocop`, you need to install the gem. Zed just looks for an executable called `rubocop` on your `PATH`.
193
194You can install the gem manually with the following command:
195
196```sh
197gem install rubocop
198```
199
200Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your `settings.json`:
201
202```json
203{
204  "languages": {
205    "Ruby": {
206      // Use ruby-lsp as the primary language server and rubocop as the secondary.
207      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
208    }
209  },
210  "lsp": {
211    "rubocop": {
212      "initialization_options": {
213        "safeAutocorrect": false
214      }
215    },
216    "ruby-lsp": {
217      "initialization_options": {
218        "enabledFeatures": {
219          "diagnostics": false
220        }
221      }
222    }
223  }
224}
225```
226
227By default, `rubocop` uses `bundle exec` to run in the context of the bundle. To disable that, you can use the `use_bundler` configuration option:
228
229```json
230{
231  "lsp": {
232    "rubocop": {
233      "settings": {
234        "use_bundler": false
235      }
236    }
237  }
238}
239```
240
241## Using the Tailwind CSS Language Server with Ruby
242
243It's possible to use the [Tailwind CSS Language Server](https://github.com/tailwindlabs/tailwindcss-intellisense/tree/HEAD/packages/tailwindcss-language-server#readme) in Ruby and ERB files.
244
245In order to do that, you need to configure the language server so that it knows about where to look for CSS classes in Ruby/ERB files by adding the following to your `settings.json`:
246
247```json
248{
249  "languages": {
250    "Ruby": {
251      "language_servers": ["tailwindcss-language-server", "..."]
252    }
253  },
254  "lsp": {
255    "tailwindcss-language-server": {
256      "settings": {
257        "includeLanguages": {
258          "erb": "html",
259          "ruby": "html"
260        },
261        "experimental": {
262          "classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
263        }
264      }
265    }
266  }
267}
268```
269
270With 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:
271
272```rb
273# Ruby file:
274def method
275  div(class: "pl-2 <completion here>") do
276    p(class: "mt-2 <completion here>") { "Hello World" }
277  end
278end
279
280# ERB file:
281<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
282<a href="/hello" class="pl-2 <completion here>">Hello</a>
283```
284
285## Running tests
286
287To 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.
288
289### Minitest with Rails
290
291```json
292[
293  {
294    "label": "test $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
295    "command": "bin/rails test $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
296    "tags": ["ruby-test"]
297  }
298]
299```
300
301Note: We can't use `args` here because of the way quotes are handled.
302
303### Minitest
304
305Plain minitest does not support running tests by line number, only by name, so we need to use `$ZED_SYMBOL` instead:
306
307```json
308[
309  {
310    "label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
311    "command": "bundle exec ruby",
312    "args": ["-Itest", "$ZED_RELATIVE_FILE", "-n /$ZED_SYMBOL/"],
313    "tags": ["ruby-test"]
314  }
315]
316```
317
318### RSpec
319
320```json
321[
322  {
323    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
324    "command": "bundle exec rspec",
325    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
326    "tags": ["ruby-test"]
327  }
328]
329```
330
331### quickdraw
332
333```json
334[
335  {
336    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
337    "command": "bundle exec qt",
338    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
339    "tags": ["ruby-test"]
340  }
341]
342```
343
344### tldr
345
346```json
347[
348  {
349    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
350    "command": "bundle exec tldr",
351    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
352    "tags": ["ruby-test"]
353  }
354]
355```