I think the first IDE I used was Borland Delphi in 1999. I remember being marveled by its code insight features, where the editor would suggest what properties and methods were available for a given symbol. I remember being puzzled about the programming sorcery powering that — pretty much the same feeling I have today when I play a modern video game.
I then got deeply involved with Java and the IDEs available back then. A little-known one, Together by Togethersoft, had a deep impact on me, featuring a bidirectional sync between code and UML diagrams in real-time — a feature that, in hindsight, was as cool as useless. I even went to build a toy IDE that did the same, which got me into language processors and model transformations. I eventually settled down on Eclipse, but all the Java IDEs featured excellent code assistance since the early days.
Rails had been on my radar since it was released, but I got serious about it around 2010. Coming from Java, everything felt better except for the editor. I chose TextMate, which Rails itself helped to popularize. While I could appreciate how Ruby being so concise played well with a simple editor, I still noticed a steep downgrade. At some point in 2011, I switched to RubyMine, an IDE, which is the editor I use to this day.
The thing is that there is something in plain editors that is appealing to me. I have tried Sublime, Vim, and Visual Studio code, but my attempts don’t last because I always find the same frictions. Virtually every Rails programmer I know — a group that includes people way smarter than me — uses a plain editor, so I sometimes wonder if I am driving in the wrong way, but then I conclude that everyone is wrong but me ¯\_(ツ)_/¯. I’m kidding, editors are just a tool and all that, but I will still try to explain those frictions next.
Browsing symbols
Most of the time, in an editor, you are reading code. And, when reading code, the most common operation is jumping to symbol definitions — such as a method invocation — to understand how the system works. RubyMine does a fantastic job here. I want to show some examples with real-world codebases next:
This one from console Console1984 shows how it can infer the right class to locate methods based on a static analysis of the code:
Because Ruby is dynamically typed, it is often impossible to infer the right type. There is frequently only a matching method for a given name; in that case, it will just jump to it. When there are many, it will offer possible alternatives. This is still a qualitative improvement over having to search manually. Here’s an example from some code I recently worked on in HEY:
Then you have the case of external libraries. I check code from gems all the time. In RubyMine, this works seamlessly. Here’s how I can navigate to the .encrypts method from Active Record Encryption in a class from HEY:
The system works the same for Javascript (no TypeScript required), and even for CSS:
Of course, you can locate any definition you want using simple text search, but I find that slow and inconvenient after tasting this way of browsing code.
Finding references
After finding symbol definitions, the next most common thing I do when reading code is searching references to symbols to understand who is invoking a piece of code. For example, who is invoking this #file_in method in HEY:
Renaming
At writing-code time, the operation I perform more frequently is renaming things. I want to put the cursor on a symbol, select a new name, and let my editor care about the scope of the change. For example, here I’m renaming a block argument without having to care about the local variable in the method above:
Extracting things out
This is another big one for me: select a block of code and extract it to a method or extract an expression to a constant or local variable. Here is an example from HEY extracting a private method:
The basics first
So those are my editing basics. I still appreciate and leverage good support for lower-level editing actions at the file, line, and character level, but my editing happiness relies on this layer of higher-level actions. In other words, I need an IDE.
No types tax
I know Typescript and Sorbet offer a fantastic editing experience with Visual Studio Code, featuring the IDE-like features I referenced above. In fact, people often include the improved editing experience among the reasons to go with those. The problem is that I have no desire to add types to my Javascript and Ruby. I wrote some thoughts on this subject back in the day, and my opinion is essentially the same today.
RubyMine proves there is a sweet spot where you can get 80% of the power of a types-powered IDE without paying the tax of adding types to your code. The thing is that formal type information is terrific for editors and RubyMine already offers first-class support for RBS to improve its assistance, so I appreciate the effort to provide RBS descriptors for the Ruby standard library and external gems. Still, I wouldn’t like to have to create and maintain RBS files – or Sorbet annotations and RBI files – in parallel to my Ruby code.
Conclusions
I suspect that my exposure to fancy Java IDEs early in my career made my mental model for editing code incompatible with plain editors. I seem to be among the few suffering from this syndrome in the Rails world, so I am not entirely sure this is positive, but it is what it is.
Because I like it, I follow this space with interest. Stripe and Shopify have made some outstanding contributions with Sorbet and all its surrounding ecosystem of tools. I’m particularly interested in the tooling built around Visual Studio code that does not depend on Sorbet, such as ruby-lsp. With companies of this caliber investing in the tooling, I expect things to improve quickly in the near future.
If you have managed to enjoy these IDE-like features with Rails in your plain editor, I would appreciate if you let me know how. I know there are alternatives, but I haven't seen anything that can remotely compare to what RubyMine offers out of the box.