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