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 'dev: 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### Language Server Activation
 33
 34For all Ruby language servers (`solargraph`, `ruby-lsp`, and `rubocop`), the Ruby extension follows this activation sequence:
 35
 361. If the language server is found in your project's `Gemfile`, it will be used through `bundle exec`.
 372. If not found in the `Gemfile`, the Ruby extension will look for the executable in your system `PATH`.
 383. 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).
 39
 40You can skip step 1 and force using the system executable by setting `use_bundler` to `false` in your settings:
 41
 42```jsonc
 43{
 44  "lsp": {
 45    "<SERVER_NAME>": {
 46      "settings": {
 47        "use_bundler": false,
 48      },
 49    },
 50  },
 51}
 52```
 53
 54### Using `solargraph`
 55
 56`solargraph` is enabled by default in the Ruby extension.
 57
 58### Using `ruby-lsp`
 59
 60To switch to `ruby-lsp`, add the following to your `settings.json`:
 61
 62```json
 63{
 64  "languages": {
 65    "Ruby": {
 66      "language_servers": ["ruby-lsp", "!solargraph", "!rubocop", "..."]
 67    }
 68  }
 69}
 70```
 71
 72That disables `solargraph` and `rubocop` and enables `ruby-lsp`.
 73
 74### Using `rubocop`
 75
 76The Ruby extension also provides support for `rubocop` language server for offense detection and autocorrection.
 77
 78To enable it, add the following to your `settings.json`:
 79
 80```json
 81{
 82  "languages": {
 83    "Ruby": {
 84      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
 85    }
 86  }
 87}
 88```
 89
 90Or, conversely, you can disable `ruby-lsp` and enable `solargraph` and `rubocop` by adding the following to your `settings.json`:
 91
 92```json
 93{
 94  "languages": {
 95    "Ruby": {
 96      "language_servers": ["solargraph", "rubocop", "!ruby-lsp", "..."]
 97    }
 98  }
 99}
100```
101
102## Setting up `solargraph`
103
104Solargraph has formatting and diagnostics disabled by default. We can tell Zed to enable them by adding the following to your `settings.json`:
105
106```json
107{
108  "lsp": {
109    "solargraph": {
110      "initialization_options": {
111        "diagnostics": true,
112        "formatting": true
113      }
114    }
115  }
116}
117```
118
119### Configuration
120
121Solargraph 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).
122
123## Setting up `ruby-lsp`
124
125Ruby 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`:
126
127```json
128{
129  "languages": {
130    "Ruby": {
131      "language_servers": ["ruby-lsp", "!solargraph", "..."]
132    }
133  },
134  "lsp": {
135    "ruby-lsp": {
136      "initialization_options": {
137        "enabledFeatures": {
138          // This disables diagnostics
139          "diagnostics": false
140        }
141      }
142    }
143  }
144}
145```
146
147LSP `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:
148
149```json
150{
151  "lsp": {
152    "ruby-lsp": {
153      "initialization_options": {
154        "formatter": "standard",
155        "linters": ["standard"]
156      }
157    }
158  }
159}
160```
161
162## Setting up `rubocop` LSP
163
164Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your `settings.json`:
165
166```json
167{
168  "languages": {
169    "Ruby": {
170      // Use ruby-lsp as the primary language server and rubocop as the secondary.
171      "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
172    }
173  },
174  "lsp": {
175    "rubocop": {
176      "initialization_options": {
177        "safeAutocorrect": false
178      }
179    },
180    "ruby-lsp": {
181      "initialization_options": {
182        "enabledFeatures": {
183          "diagnostics": false
184        }
185      }
186    }
187  }
188}
189```
190
191## Using the Tailwind CSS Language Server with Ruby
192
193It'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.
194
195In 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`:
196
197```json
198{
199  "languages": {
200    "Ruby": {
201      "language_servers": ["tailwindcss-language-server", "..."]
202    }
203  },
204  "lsp": {
205    "tailwindcss-language-server": {
206      "settings": {
207        "includeLanguages": {
208          "erb": "html",
209          "ruby": "html"
210        },
211        "experimental": {
212          "classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
213        }
214      }
215    }
216  }
217}
218```
219
220With 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:
221
222```rb
223# Ruby file:
224def method
225  div(class: "pl-2 <completion here>") do
226    p(class: "mt-2 <completion here>") { "Hello World" }
227  end
228end
229
230# ERB file:
231<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
232<a href="/hello" class="pl-2 <completion here>">Hello</a>
233```
234
235## Running tests
236
237To 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.
238
239### Minitest with Rails
240
241```json
242[
243  {
244    "label": "test $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
245    "command": "bin/rails test $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
246    "tags": ["ruby-test"]
247  }
248]
249```
250
251Note: We can't use `args` here because of the way quotes are handled.
252
253### Minitest
254
255Plain minitest does not support running tests by line number, only by name, so we need to use `$ZED_SYMBOL` instead:
256
257```json
258[
259  {
260    "label": "-Itest $ZED_RELATIVE_FILE -n /$ZED_SYMBOL/",
261    "command": "bundle exec ruby",
262    "args": ["-Itest", "$ZED_RELATIVE_FILE", "-n /$ZED_SYMBOL/"],
263    "tags": ["ruby-test"]
264  }
265]
266```
267
268### RSpec
269
270```json
271[
272  {
273    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
274    "command": "bundle exec rspec",
275    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
276    "tags": ["ruby-test"]
277  }
278]
279```
280
281### quickdraw
282
283```json
284[
285  {
286    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
287    "command": "bundle exec qt",
288    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
289    "tags": ["ruby-test"]
290  }
291]
292```
293
294### tldr
295
296```json
297[
298  {
299    "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
300    "command": "bundle exec tldr",
301    "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
302    "tags": ["ruby-test"]
303  }
304]
305```