> Please don't comment about the voting on comments. It never does any good, and it makes boring reading.
If you have incorrect code and are happy programming, you fix your code.
If you have correct code, but are unhappy programming, you do not fix your code.
There is no correct code and Ruby prioritizes your happiness, so you get fixed code and happy programmers, instead of permanently broken code and unhappy programmers.
Again I’m not interested in how quickly you can create an app.
I’m interested in your ability to maintain very complex business logic over the course of years.
Working at a Ruby shop now, I can say with confidence I will never touch it again with however long of a pole I can find.
I think this is a bit over the top. You can maintain complex business logic in any language (any language!) for decades with discipline and good software development processes.
Ruby lets you do a lot that could bite you, but it's people who write code.
In some other comments somebody wrote about method_missing and ActiveRecord callbacks. Days ago we had a post about a state machine gem.
Leave method_missing to the inner workings of gems. Do not use it in your code. Even in gems, hide them well. Rails used to have auto-generated find_by_field1_and_field2 methods, by method_missing if I remember well. They eventually moved to where(field1: value1, field2: value2) and we are fine with that.
ActiveRecord before and after filters are just callbacks like many libraries have, in any language. They need discipline because of the obvious problems we can run into if we add a ton of code to the callback system, possibly with side effects and multiple definitions of the same callbacks in classes derived from a common model. That's actually a very bad code smell (and a broken architecture?) and something that we could be tempted to do but we learn not to do. I use them very sparingly. The whole validation system is a particular case of before save callbacks. I think that every ORM for every language has got a validation system.
Another case of callbacks are the ones for the state changes of finite state machines. We can define them with function pointers in C structs or with symbol names in Ruby, they are the same thing. The triggers for state changes: same thing.
If I can choose I go with the more explicit alternative because... Finally I confess that I lose time when reading some new code bases to understand if some object.something is an attribute, a method, a state machine callback or something else auto-generated by some other gem. I think that LSP servers have a very bad time following those methods and probably none of them do. Maybe heuristic in IDEs can do something about it.
If I feel that I would be in trouble there, I add a short comment explaining the origin of the method: "this is from gem XYZ", then the docs will explain how and why to the next developers. Maybe they will thank me.