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
161By 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:
162
163```json
164{
165 "lsp": {
166 "ruby-lsp": {
167 "settings": {
168 "use_bundler": true
169 }
170 }
171 }
172}
173```
174
175## Setting up `rubocop` LSP
176
177Zed 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`.
178
179You can install the gem manually with the following command:
180
181```sh
182gem install rubocop
183```
184
185Rubocop has unsafe autocorrection disabled by default. We can tell Zed to enable it by adding the following to your `settings.json`:
186
187```json
188{
189 "languages": {
190 "Ruby": {
191 // Use ruby-lsp as the primary language server and rubocop as the secondary.
192 "language_servers": ["ruby-lsp", "rubocop", "!solargraph", "..."]
193 }
194 },
195 "lsp": {
196 "rubocop": {
197 "initialization_options": {
198 "safeAutocorrect": false
199 }
200 },
201 "ruby-lsp": {
202 "initialization_options": {
203 "enabledFeatures": {
204 "diagnostics": false
205 }
206 }
207 }
208 }
209}
210```
211
212By default, `rubocop` uses `bundle exec` to run in the context of the bundle. To disable that, you can use the `use_bundler` configuration option:
213
214```json
215{
216 "lsp": {
217 "rubocop": {
218 "settings": {
219 "use_bundler": false
220 }
221 }
222 }
223}
224```
225
226## Using the Tailwind CSS Language Server with Ruby
227
228It'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.
229
230In 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`:
231
232```json
233{
234 "languages": {
235 "Ruby": {
236 "language_servers": ["tailwindcss-language-server", "..."]
237 }
238 },
239 "lsp": {
240 "tailwindcss-language-server": {
241 "settings": {
242 "includeLanguages": {
243 "erb": "html",
244 "ruby": "html"
245 },
246 "experimental": {
247 "classRegex": ["\\bclass:\\s*['\"]([^'\"]*)['\"]"]
248 }
249 }
250 }
251 }
252}
253```
254
255With 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:
256
257```rb
258# Ruby file:
259def method
260 div(class: "pl-2 <completion here>") do
261 p(class: "mt-2 <completion here>") { "Hello World" }
262 end
263end
264
265# ERB file:
266<%= link_to "Hello", "/hello", class: "pl-2 <completion here>" %>
267<a href="/hello" class="pl-2 <completion here>">Hello</a>
268```
269
270## Running tests
271
272To 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.
273
274### Minitest with Rails
275
276```json
277[
278 {
279 "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
280 "command": "bundle exec rails",
281 "args": ["test", "\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
282 "tags": ["ruby-test"]
283 }
284]
285```
286
287Note: Plain minitest does not support running tests by line number.
288
289### RSpec
290
291```json
292[
293 {
294 "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
295 "command": "bundle exec rspec",
296 "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
297 "tags": ["ruby-test"]
298 }
299]
300```
301
302### quickdraw
303
304```json
305[
306 {
307 "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
308 "command": "bundle exec qt",
309 "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
310 "tags": ["ruby-test"]
311 }
312]
313```
314
315### tldr
316
317```json
318[
319 {
320 "label": "test $ZED_RELATIVE_FILE:$ZED_ROW",
321 "command": "bundle exec tldr",
322 "args": ["\"$ZED_RELATIVE_FILE:$ZED_ROW\""],
323 "tags": ["ruby-test"]
324 }
325]
326```