I went all in on Rails a couple of years ago. Although the overall feature set is amazing, code discoverability has been a frustrating stumbling block from day one.
The "magic" (convention over configuration, autoloading, metaprogramming, etc) makes it difficult to know what methods are available to use. I end up over-relying on the official docs, which are of inconsistent quality. One example: api.rubyonrails.org lacks code examples, doesn't usually state what a given method returns, and many entries are outright blank.
Editor integration could help, but feels lackluster. With TypeScript in VS Code, hints come up as I write. I can hover anything to see its type, methods, and source code. With Rails, I can poorly approximate this behavior with a collection of half-functional community extensions, or I can buy and use the slow, bloated RubyMine IDE.
Rails enabled me to build my product, but my experience doesn't match the love I hear from other devs. I wish I knew how to make it click.
I went all in many years ago and then moved on several years ago (to different parts of the stack that I found more interesting), but here's my 2c FWIW.
The Rails Guides [1] are quite good (and much better than the API docs, even for the same topics). The "Getting Started" guide, in particular, was my first intro to Rails, and it's what convinced me to go all in — I built my entire prototype by just following along the guide, seeing what they were doing with their toy app, and then trying to whatever similar thing I needed in my app.
Coming from Python, the magic was distasteful to me, too. Rails adds a ton more magic on top — so, eventually, when I set aside Rails and just spent time with Ruby (writing scripts or what not), I realized I loved Ruby the language much more than Rails the framework (and all its baggage).
Stripping Rails down to its API-only mode (though it was a bit rough around the edges last I tried) got me closer to the Ruby of it all. Sinatra turned out to be a delightful little framework (though sadly I never got a chance to use it much). And, even though I've now moved on from Rails, I still like Ruby as a go-to scripting language — it makes it fun and easy to throw together a quick shell script or some data analysis, and it's very friendly to a functional programming style.
I guess what I'm saying is: You're not alone. Many people in the Rails community agree that there's a ton of hidden magic, sometimes too much [2]. But underneath it all is a delightful programming language.
I had exactly the same problem. Recently, with the help of ChatGPT (just free version). When I didnt know anything, I just asked. The result was pretty good.
I also wrote stupid code first in my own version, and copied + pasted to chatGPT, asked it to improve it, or rewrite in ruby on rails style. And wow!! The rewrote version even went with explanation.
This was my experience and I have commented it before. The magic/convention approach is the inferred part of Rails/Ruby culture. Where is the class definition? Well, where are you invoking initialization? This question leads to a question which hopefully leads to answer is hard to play by if you’re new or just trying to squash a simple request.
The whole just fire up an interactive session or rails console is probably the last thing I want to do but probably the only way to diagnose or figure out how things are truly working. What monkey patches are in the mix, what libs override methods I set, etc.
For me, Ruby is one of those programming languages that obviously takes a different programming approach and mindset that I don’t have. I don’t think Ruby is bad but I know it isn’t the tool that fits my skill set.
A good way to explore is getting an interactive session with something like pry and exploring what methods and attributes are available that way. It sounds clunky, but it's quite effective as you frequently get to play through the entire implementation once and it pairs extremely well with TDD.
I love ruby, and find it great to use pry and irb to explore and figure stuff out.
However, many times ruby libraries will use dynamic programming and method_missing to define methods on the fly… this makes it really hard to figure out what methods are actually available.
For that reason, I try to never use method missing to define core functionality in ruby, and hate when other gems do it.
The responsible thing when you use `method_missing` is to define `respond_to` to indicate whether an object responds to a particular method. This alleviates the "is a method available" issue because you can just ask the object "Do you respond to :method_I_want_to_call?", and it will correctly inform you it does or does not. This kind of discoverability is one of the things I miss when I'm working in Javascript/TS as I have been recently - sure you can check the .method_name property to see if it's a function and then execute it but it doesn't feel as nice.
E.g.
def method_missing(name, \*args)
if name =~ /^has_/
has(name, *args)
end
super
end
def respond_to(name)
if name =~ /^has_/
return true
end
super
end
I second this, when I was in Ruby land I used to regularly drop a binding.pry (later binding.irb) in the middle of some code i wanted to understand, and call things like `method` to see where an unrecognized method came from.
Pry is amazing for understanding code. IMO the most useful method is absolutely `some_object.methods`, but you can also improve the output a ton by always doing:
some_object.methods - {}.methods # or some other "parent" class/object
This does set subtraction to remove all the "core" object methods from your some_object methods, so you can see just what's unique about that object. For example, comparing one of my services with a parent Service class it inherits from:
instead of listing out the 187 methods that PaypalService has that it inherits from Service and every other parent object up the line, which is usually a surprisingly long ancestor list in any Ruby on Rails class (even POROs!).
There are a TON of useful methods like this that I'd recommend getting familiar with, which makes exploration and discovery of code incredibly fast and efficient. You can find them all with the same trick: by using `methods` on any method. :)
The "magic" (convention over configuration, autoloading, metaprogramming, etc) makes it difficult to know what methods are available to use. I end up over-relying on the official docs, which are of inconsistent quality. One example: api.rubyonrails.org lacks code examples, doesn't usually state what a given method returns, and many entries are outright blank.
Editor integration could help, but feels lackluster. With TypeScript in VS Code, hints come up as I write. I can hover anything to see its type, methods, and source code. With Rails, I can poorly approximate this behavior with a collection of half-functional community extensions, or I can buy and use the slow, bloated RubyMine IDE.
Rails enabled me to build my product, but my experience doesn't match the love I hear from other devs. I wish I knew how to make it click.