4 ms·
I love Rails and Ruby and miss the ecosystem dearly, but the joy dies once you find yourself lost in layers of code without any types or IDE support. This is es
by fny 2y ago
I love Rails and Ruby and miss the ecosystem dearly, but the joy dies once you find yourself lost in layers of code without any types or IDE support. This is especially true on large teams.
So what are your options... Sorbet? Does this feel like Ruby?
sig do
params(x: Integer)
.returns(String)
end
How about RBS? Does writing the equivalent of header files for every function and class feel like Ruby?
So unfortunately I'm no longer an evangelist or practitioner.
- haven 2y agoDynamically typed languages aren't out in the cold like they used to be with IDE support. Most of the advanced LSP work going on isn't based on explicit types signatures yet they work well. See https://railsatscale.com/2024-07-18-mastering-ruby-code-navigation-major-enhancements-in-ruby-lsp-2024/ https://railsatscale.com/2024-07-18-mastering-ruby-code-navi...
- tenacious_tuna 2y agoThis has been a big frustration for me as a new engineer in a Rails codebase: my ability to 'discover' how the system works is extremely limited because I can't 'see' a lot of the relationships between code. I've grown comfortable with just searching the entire codebase for a given string to find a relevant class or variable, but it's extremely failure-prone without types or import paths to follow. I love the syntax and elegance of Ruby, but it really is maddening how difficult it is to hold all the abstractions and state in my head without the mental boundaries that good type support provides. I often commiserate with a coworker who came from a Java background (and I from Swift/Python) about how frustrating it is when type-based issues leak to prod and cause trouble, or how it lengthens the development process insofar as determining what a given object _is_ at any point in the logical execution. I really understand how unit testing became so popular, given Rails's historical popularity: there's simply no other way to move with confidence through the codebase without a plethora of specific tests for each individual component.
- gls2ro 2y agoRuby and Rails via rails console or irb is these days pretty inspectable. Say you want to understand what does `belongs_to` do? Just open `rails console` and you can do: User.method(:belongs_to).source_location And opening the file that is printed at the specified line, you can discover the following code: def belongs_to(name, scope = nil, **options) reflection = Builder::BelongsTo.build(self, name, scope, options) Reflection.add_reflection self, name, reflection end And moreso that method has a very good comment before the declaration, documenting everything it does You can also try `show_source` command in Rails console if you have the debug gem installed: show_source User.find And this will directly show the source code of the `find` method. I do agree that for methods defined with meta-programming it will be harder to find the methods. But again here rails console comes with help: For example if you do: User.method(:find_by_name) => #<Method: User(id: integer, nickname: string, name: string, created_at: datetime, updated_at: datetime).find_by_name(_name) <edited by me>/vendor/bundle/ruby/3.2.0/gems/activerecord-7.0.8.4/lib/active_record/dynamic_matchers.rb:65> Of course, this is mode complex meta-programming code, but you can still go to it, read it, and see what it does. In case of relationships between entities in the code, you can try Sorbet. It is pretty good these days.
- tenacious_tuna 2y agoComing from a paradigm of being able to read code and understand what it does, having to drop into console to poke at things, even just to then find the source for a given function, was extremely unintuitive to me. At this point I always have a rails console up, just to be able to poke at objects and whatnot, but it feels... clunky. Similarly, when designing system changes I first go through with breakpoints in an existing flow to see what objects and behavior actually are when invoked, because I can't tell just from reading the code half the time--and that drives me bananas.
- gls2ro 2y agoThat seems very Ruby to me: sig { params(x: Integer).returns(String) } I can read it outloud: Signature is defined as: one parameter called x of type Integer and will return a String. Sorbet may have some warts, but the example you show is simple and easy to understand. The `sig` is as Ruby as you get IMO: class MyTest extend T::Sig end MyTest.method(:sig).source_location => ["...gem/ruby/3.3.4/gems/sorbet-runtime-0.5.11495/lib/types/sig.rb", 27] And when opening that file we can get something like: def sig(arg0=nil, &blk) T::Private::Methods.declare_sig(self, Kernel.caller_locations(1, 1)&.first, arg0, &blk) end I do agree about RBS being separate files that is something that can stop a coding flow.
- rognjen 2y ago> IDE support RubyMine is great.