I was developing mostly PHP, some bash, some Java and kinda liked ruby but could only partially feel it.
Until I read "why's (poignant) Guide to Ruby", from start to end, I completely fell in love with programming. Everything before was just getting to this point.
The documentation and community is what has drawn me into Ruby. The language and now very major ecosystem is why I still stay :)
Hello Ruby by Linda Luikas is one of the sweetest 'programming books' I've ever seen.
Aside from being cute, and maybe harking back to why’s guide; I like how this feels like it aids in understanding. Each illustration provides character that helps aid in memorizing or creating a mental landscape of the exceptions.
Theres probably a lot of documentation that could be aided by illustrations like this along the lines of analogy and metaphor. Aside from making the process of reading documentation more fun, it probably helps differentiate long and complex documentation that otherwise might blur together.
I don't appreciate how it seems like an elaborate ad though: Every error has a link to the paid service they're selling , with the error/exception "Enemies" list as their product
On the contrary, I quite like how it's a very elaborate and useful ad. The link to the paid service is very discreet and the website provides real and free educational value even if you don't use their service.
Why so? This is in my book the best form of advertising. It provides anyway something useful for the interested reader, while exposing the (alleged, at least) usefulness of their services. Much better this that a banner or a pop-up in some random website that tracked you down as a Ruby developer.
I don't appreciate it either, maybe I'm a bit dull. I feel tricked as it is unclear from a quick glance what I am looking at is really an advertisement, not a tutorial or some kind of reference. And as an advertisement, it may or may not be useful. At least the incentives are clearly there to present information in a way that benefits their funnel even if it doesn't benefit me as a developer. Even if its not a straight up lie, they will obviously not mention an alternative solution to their product and could very well be quite incomplete.
For a reference, I want something I can trust to give information relevant to my purpose, something that is complete and valid. Not a playful hidden advertisement, funneling me into a single paid solution. Maybe this is why I prefer python, even after working with rails for many years. As I said, I might be a bit dull.
15 years ago I would have agreed. Today, Python is a "gateway" to programming that is also the real thing.
It's like one of those old languages designed for beginners to learn coding... and then you can continue to use the same language for your entire professional career as a software engineer, to build just about any production-ready application.
Ruby is a beautiful language, but unless you are going to be working with Rails, it's not a very practical language to build something in. And I don't think telling a beginner "just learn Ruby for now, but once you're actually ready to write your first useful program, you're probably going to have to learn another language" is very motivating.
'If you want to build a ship, don't drum up people to collect wood or assign them tasks and work. Instead, teach them to long for the endless immensity of the sea.'
This resonates with how I feel about programming languages. Python might be more practical, but does it ignite a passion for coding like Ruby has historically done? I remember dabbling in Python, Perl, and JavaScript (ES5) back in high school, but it wasn't until I rediscovered programming through Ruby that I truly began to enjoy it.
Nowadays, I might not default to Ruby for new projects, having moved on to OCaml and Elixir, among others. Yet, there's something about Ruby's community (its charm and gentleness,) that's missing in many others. This nurturing environment is invaluable for beginners. It's noteworthy how members of the Ruby community, like José Valim with Elixir, Yehuda Katz with Ember.js and Rust, and Chris McCord with Phoenix, have carried this spirit of playfulness and a deep care for developer experience into other communities they've joined.
This is more or less personal preference though. When you say that Ruby ignites a passion for coding for you then that might not happen for other people. For example I only feel a headache when I look at Ruby code.
For context: I worked with C, C#, some Python and now mostly work in Go.
How often do you see people describe that kind of passion for Python? Maybe for lisps, Erlang, Haskell, Smalltalk. It may well put some people off, that's fine, but personally I dread it when I have to work with languages that don't instill that kind of passion.
There are plenty of things I'd like to be different about Ruby and the tooling, but with Ruby I feel like I'm crafting something that at least has the potential for elegance, whereas looking at Python code is like staring at a brutalist building that spews its innards all over its surface.
(and yes, I realise some people love brutalist buildings, and I can too, sometime, when particularly well done, and that's why I chose that example - it's possible to do amazing and elegant things in any language, even - as ugly as I personally find it - Python)
At least when I was learning Python (which admittedly is over a decade ago at this point), there was a lot of that passion for Python and what made it great - you'd get things like the Zen of Python quoted, there was the "import antigravity" XKCD comic, a lot was made of things being "pythonic" and "for humans".
I think the major reason for cultural change is that there's fewer people learning programming for fun, and more people learning it either because it's mandatory or as a career path. In which case, the humour and culture that comes out of that is naturally going to be different. I think that's affected Python more than Ruby just because Python is more widely used, particularly by these newer developers. As a result, there's been less cultural shift in Ruby than in Python.
So I think in a sense, you've got the cart before the horse. Python has less of the twee humour now because it's more widely used by newer developers, who in turn are no longer treating programming as a hobby and instead as a career. That said, I can imagine if you want to teach the joy of programming as a hobby, Ruby might be a better choice. Although with that said, I feel like a lot of the hobbyist Python community has moved to things like Raspberry Pi and MicroPython, so maybe it's just a case of finding other hobbyists and doing whatever they're doing: the community is more important than the tool!
I'd agree there might have been more before, but even back then I didn't see the same level of excitement for the language. For specific uses, sure.
But most Ruby use is "corporate" as well - its use is dominated by Rails shops. The "joy of programming" aspect of Ruby is partially embedded even in corporate Rails use, but also outside of it. It may well have hampered Ruby growth, but it's also not something I think would disappear if Ruby use increased.
In the mid naughts ruby/rails was catching on and rubyconf was getting bigger, but the events were on the _weekends_ because most of these were people doing it for fun and not able to expense it to their employer or get time off. There was pushback from prominent people about how ruby was no longer an insurgency and needed to grow up and have employer-paid conferences, which got a nice response from _why the lucky stiff which I can no longer find.
Don't underestimate Perl's influence on Ruby and its community. Larry Wall's TIMTOWTDI (There Is More Than One Way To Do It) is the essence of what differentiates Perl and Ruby from Python and why creatives tend to gravitate to Ruby. You don't build a creative community on the principle of there being only on way to do something.
I think Ruby is polarizing. It is the only language I have used that I feel a genuine dislike for. Other people I have talked to feel the same. Then there is a group who loves it.
For me that language is Python (well, and x86 assembler). Python just feels fundamentally inelegant and messy to me, in a way that makes it tedious to read and write. I'll work on it if I must, but thankfully I rarely must.
> How often do you see people describe that kind of passion for Python?
It's part of modern science/technology culture to indiscriminately hate the most widespread things.
Personally, I find Python simply amazing and delightful to work with. And I consider its syntax, especially semantic indentation which eliminates so much visual noise, to be the best among all languages that ever achieved widespread adoption.
> It's part of modern science/technology culture to indiscriminately hate the most widespread things.
This is evasive. How often did you see people describe Python that way before it became as widespread as it is now?
> And I consider its syntax, especially semantic indentation which eliminates so much visual noise, to be the best among all languages that ever achieved widespread adoption.
And for me it is why Python will never even make my top 10 preferred languages, and is a language I actively avoid when I have a chance, because I find it visually absolutely awful. I'd suspect (yes, it's pure speculation) you'll find about as many people who detest Python over that alone, as who find Python "delightful". Useful, sure, but finding people who describe Python as delightful is a rarity.
But as I said, some people find brutalist architecture to be amazing too, and that's fair enough.
> This is evasive. How often did you see people describe Python that way before it became as widespread as it is now?
Quite a lot back in the early 2.x era before the Rails hype first kicked in. It really was a breath of fresh air compared to VB, Perl, JS, early Java or PHP of the time. It had a concise elegant clarity and consistency missing in other mainstream languages back then. And it was a relatively unknown underdog.
I've spent the last decade in Ruby shops and not done much Python recently, but I still miss those early Python days. Ruby never gave me the same sense of happiness it gave others and there are still things I prefer about Python. But it is subjective and I couldn't objectively say Python is better than Ruby.
Things are very different now - it is a much larger language with a much longer history to trip over, pulled in multiple directions with conflicting expectations, and the user base has changed from that small passionate dedicated community to being the intro to coding blub language that Java or PHP used to be where the average skill level is much lower.
People have different ways of expressing passion. I like Go a lot, but most of the time I'll say that it "just works" or "gets out of the way". But I have a real passion for the way Go was made for software engineering rather than programming. I wouldn't describe Go as elegant, and not as brutalist either. It kind of feels like home to me. We don't have an equivalent to that Exceptional Creatures website, which I find beautiful. But we have my favorite technical writing ever. It's always a joy to read something written by Rob Pike, Ian Lance Taylor, Alan Donovan, Russ Cox, and lots of others.
I think you missed my point, Its the community around a language that creates that "longing for the endless immensity of the sea." Not the language itself.
When I was young, and I had zero experience with programming, I was more comfortable with Ruby rather Python because:
1. significant whitespace was so hard to grasp. I was a beginner so I just needed to write awful code
2. Ruby was so "pure" from the OOP perspective that I had one thing less to think about: method calls start from object instances, period. Python has "exceptions" to this rule that made me confused (f.e. `len` in Python is a global function, while in Ruby is `array.length`)
3. I found Ruby matching more to English language
Later I found that Ruby has deeply obscure islands (metaprogramming mainly, but also exotic syntax coming from Perl), but I was already sold to the language
I never 'learned' python and ruby is the path I went with and still use for 90% of my own software.
However Python is a easy transition. I rarely struggle to do anything with it when I need it. Even Django wasn't to weird to grasp after years of rails.
IMO it's not to relevant which language you choose to learn in the beginning of your career. Whatever is more fun or works better for your interests.
This (that it doesn't matter what you choose to learn early) is a key point.
Early on you should aim to get exposure to multiple languages, ideally at least some very different ones.
So I agree with whatever is more fun. Anything that makes you want to stick with learning is great. Then you can, and should, explore.
If you want something that'll be a marketable skill right away, maybe Python will be a shortcut in the short term, but a developer who knows only one language - whichever one - is eventually going to be at a disadvantage.
The most important skill is not any specific language, but learning how to think about software.
The biggest difference between both is mainly their machine learning story but if you don't intend to go in it (this is a very specific career choice), I'd say both are equally good options.
I'd say both are pretty bad at performance critical tasks or UI stuff where usually you would use neither of those.
Python is so much bigger than Ruby. It's not just machine learning. There's also numpy and Jupyter for the scientific community, which are huge. There's arcade for making 2D games. There's Micropython for microcontrollers. There are async database drivers and web frameworks. There's interop for many other programming languages, and it's really easy to make a distributable package with Python runtime included.
And that's just what I can recall of the top of my head as someone whose primary language is not Python.
Yes, it is only machine learning. Trying to separate it from the scientific community is creating a wall that does not exist. Besides, barely anyone uses python for 2d games or microcontrollers (out of hobbyist programs, and ruby also has a stack there with mruby or dragonruby, which have professional adoption mostly in japan), and you can't say with a straight face that python is a meaningful player in the Web application space, beyond its niche (and async python is a s**show).
> Yes, it is only machine learning. Trying to separate it from the scientific community is creating a wall that does not exist.
What? 99% of science has nothing to do with machine learning. Jupyter is used in a million different environments such as pure mathematics or computational chemistry where machine learning is almost completely absent.
> and you can't say with a straight face that python is a meaningful player in the Web application space, beyond its niche
According to the 2023 Stack Overflow Developer Survey[1], Django is more than twice as widely used as Ruby on Rails.
> I didn't mean as it's the same thing, I meant there's significant overlap across the ecosystem for both. The most obvious example is numpy, and the role of narray as an almost native type.
> According to the 2023 Stack Overflow Developer Survey[1], Django is more than twice as widely used as Ruby on Rails.
Even I'd consider SO surveys relevant, it'd still be a niche, just a bigger niche than rails.
Most people are not going to run into most of those, whether or not they use Python. They are niches. Sure, Python is more widespread, but it's still only one of many.
"Nobody" uses Python for 2D games. "Nobody" uses Ruby either, but there's Dragonruby (write once, deploy to Windows, Mac, Linux, Web Assembly, iOS, Android, Nintendo Switch, XBOX One, and PS4).
There's interop for many other programming languages, including several options for embedding Python code in Ruby (and the reverse). I've come across Ruby embedded more places than I've come across embedded Python (the number of companies I've come across both are in the single digits).
But ultimately it doesn't matter. If you pick jobs based on currently used languages rather than what you want to work on, you're painting yourself into a corner with either language.
Yeah sure you can, you can do pretty much anything in any language nowadays anyways, it doesn't mean that its going to be the industry standard. Even Ruby has DragonRuby for games (but not too popular either)
For games, none of the big engines are python or ruby based and Micropython is more of a Python dialect to me with some partial compatibility, you can't just pip install what you want.
As far as the "UI stuff" goes sadly the Python ecosystem is way better - Python has both PyQL and Pyside which are a very solid choice for doing thicker client apps. Ruby doesn't even have decent Qt bindings, at all. Or didn't the last decade I've been checking.
The tools and libraries for both GIS and Civil Engineering are also much much more developed in Python compared to Ruby. As are the tools for most areas of mathematics, and probably most other scientific and engineering fields.
"not a very practical language to build something in"
You mean something like Shopify, Stripe or Github? So switch to Python instead so you can be constrained by single-line lambdas and a runtime that performs almost exactly the same as Ruby?
I don't know what it is about Ruby that turns every HN thread that mentions it into a flame war about how it's not the perfect language. People don't do this with other languages. What gives?
I think python is the only language where the inevitable flamewar isn't about the language itself (it is instead about static vs dynamic typing). Java might be in this list too (usually the war is about OOP in general, but there's plenty of criticism levied at Java itself).
Discussions about C devolve into a religious war about simplicity and portability vs safety and an inadequate standard library.
Discussions about C++ devolve into a religious war about memory safety, bloat, developer competency, UB, and more.
Discussions about Haskell devolve into a religious war about powerful type systems and language constructs vs performance concerns, development complexity, and "endofunctors, lol."
Discussions about JS devolve into a religious war about npm, web dev in general, "== vs === lol" and more.
Discussions about Rust... oh boy.
In my experience, most discussions of specific components of languages inevitably spill into these broad and neverending religious wars.
Discussions about Go devolve into a religious war about simplicity and portability vs "the creators of the language said its only for dum dums and it shows", "it took them 10+ years to get generics", and more.
Discussion about Zig devolve into a religious war about living in a universe where C exists and not wanting to write it versus "there's too many C-likes", "why isn't this Rust", and more.
Discussions about Erlang devolve into a religious war about standing up fault tolerant and scalable distributed systems, Joe was the nicest guy ever vs "you can do that in X all you have to do is Y".
Discussions about Elixir devolve into a religious war about Erlang and Ruby's love child, José Valim is the nicest guy ever versus "you can do that in X all you have to do is Y", "but what about types" and more.
Discussions about Clojure devolve into a religious war about people writing impressive programs in their spare time, "I actually get paid to write Clojure" versus "does anyone actually get paid to write Clojure".
Discussions about Elm devolve into a religious war about type safety and staying sane versus Richard Feldman lost his temper once, the 0.19 release and "everyone has Stockholm syndrome over there".
Discussions about V devolve into a religious war about "this is not a scam" versus "this is a scam".
Discussions about Nim generally don't, or the language creator is going off on D-forums / Twitter / X again.
Yeah, absolutely. Ruby just has its own unique flavour of holy wars because it somehow manages to make people either to be totally enamoured with it or utterly sickened by it, with almost no middle ground ― which is quite an achievement TBF. So when the latter group reads something like "This is absolutely delightful! As a non-ruby developer I see things like this and get jealous of ruby developers", they can't help buy conclude that the other side is straight up demented and should probably be disallowed to handle sharp objects like scissors and monkey-patching, and the holy war may commence.
I think any language with big fans will inspire equally motivated critics. Especially if the critics believe the accolades are undeserved.
You can see that in Go. It was a hugely hyped language, backed by Google, but without a lot of wishlist items that C++/Java/Python/Ruby/etc developers would have liked.
You can see that with Rust. There is the “rewrite everything in rust” crowd, which inspires anti-rust people to speak up.
I find it crazy how much criticism Rust, Go, Ruby, etc receive when Python has such glaring flaws. From the 2-to-3 migration, to package management. The consensus seems to be that’s just the cost of doing business.
By the way, I’m a Python developer. I don’t hate Ruby. But it seems like most Ruby fans love the elegance and consistency of its design, whereas that never resonated with me. E.g calling obj.length rather then len(obj) is surely more elegant. I never really cared though?
I guess I just find it interesting how some languages cons are excused while others aren’t. And how people can be drawn to some languages while others hate them.
There is a significant anti-Ruby sentiment in the tech industry right now, especially in certain fields like InfoSec, that is being pushed by a very vocal subset of the community. Whenever they see Ruby come up, they will try pushing the meme that Ruby is dead/dying/irrelevant and cite TIOBE; despite Ruby developers continuing to release new libraries, frameworks, and tooling. Or they will claim no popular websites use Ruby; apparently GitHub, LinkedIn, and AirBnB are not popular enough? Or claim MetaSploit is the only security tool written in Ruby; off the top of my head I can think of BeFF, CeWL, Evil-WinRM, and Ronin. Or claim no company uses or supports Ruby; GitHub, Shopify, Stripe all use and support Ruby. Or they will derail any positive discussion about Ruby into some intractable debate about Static vs Dynamic Typing, GC, interpretive languages, etc; even though many of the arguments against Ruby can equally be applied to Python, and yet there's no similar criticism of Python. It's really annoying and inconsistent.
It's painful to see method_missing called out as a first class solution in the first creature https://www.exceptionalcreatures.com/bestiary/NoMethodError.... . "Practical Ruby" has three chapters dedicated to method_missing. "define_method" is more common these days and also painful to see.
Ruby gets a lot of criticism for embracing magic and indirection ("Ruby, the bad parts of Perl"). It has some good parts (no function colors, for example), but the ecosystem is the biggest problem by promoting magic. method_missing is not a good part of Ruby, it's a very bad part that you should only use if you know it's bad _and_ you know you still have to use it. I wish all tutorials would say this. "You can do this with Ruby, but don't, because your coworkers debugging an outage for an hour will hate you once they find out the bug is caused by method_missing".
Respectfully mostly disagree. Ruby is full of sharp knives. Other languages have dull knives.
Writing code without thinking will cut you either way.
Things like method missing are exactly the right solution for a certain set of problems. If used thoughtfully, they’re amazing. If used thoughtlessly, bloody mess. But this is true in every language.
Where other languages have footguns, I've often described Ruby as offering footchainsaws, while tempting you to juggle them for fun. Far more damaging if you aim it at the wrong thing, but also far better at cutting down things that stand in your way.
I think it's the most enjoyable language I've used. With care and feeding it's amazing. I would absolutely not want to use it in a large company, that would be a walking nightmare.
Yes, I want to highlight what you say about large companies. ruby really shines, I think, if you are a solo dev or a small team, where everybody is on the same page and the codebase is completely understood. It is also good for libraries with a clear focus. For larger projects, it might work too, but you would need some good culture of "keep it simple" around it. A few ego-trips of supposedly smart devs and things can get hard to understand and hard to work with fast.
Here we go again with the Ruby isn't suitable for large projects nonsense. Github, Shopify and Stripe seem to be managing perfectly fine with Ruby, thank you very much.
Sure, but as I said, probably not without establishing some culture around it. Just for fun, let's look at shopify's Ruby Style Guide under "General"[0]:
Avoid mutating arguments.
Avoid monkeypatching.
...
Avoid needless metaprogramming.
Prefer public_send over send so as not to circumvent private protected visibility.
Write ruby -w safe code.
...
Every big company has (and if they don't, they should) style guides. In Ruby people tend to use something like Rubocop (which is a static code analyzer/linter) to agree on a style. That will even be added as a default in Rails 8.
If you want to be wowed by how incredible method_missing and define_method are, read through ActiveSupport and ActiveRecord's source code.
Early in my career I made my own toy ActiveRecord implementation and it's full of define_method and was literally the first time in my life that programming felt like a real superpower.
I’ve always really disliked the sharp knives metaphor. A chef’s choice of knife doesn’t impact their coworkers, nor does it end up on the plate to a customer.
If we were chefs a knife would be your laptop, your editor, your cli tools. Not your programming language.
A better metaphor would be the lumber in a building or the soil in a garden. I don’t know what I’d call ruby in this metaphor, maybe “lightweight wood that splinters”…
The value of metaphors is not their ability to stay relevant at arbitrary inclusion of scope.
That being said, the original "Sharp Knives" piece is talking about powerful language features and whether to ban them in your kitchen, so yes, it has plenty of effect on their coworkers. Because it's a shared decision to not ban sharp knives from the kitchen, but trust and educate, and realize that people who're doing harmful things can do so with dull knives too. It's about the techniques you allow in your codebase, it doesn't propose that ruby is one "knife".
And programming language features does not, generally, end up on the plate of the customer either. The fact that this site is written in a language that allows even more powerful meta programming than ruby is not bleeding through in the sense that we now have the tools of the language available to us. We haven't been served sharp knives. We've been served the consequences of the engineering that went into it, and the people doing that engineering had the opportunity to leverage or ignore the sharp knives of the language. That language being lisp, I'm pretty sure they had at it.
When you have small children, you put your sharp knives out of the way. If children get a bit older, you first teach em responsible use of a knife, then give a sharp pocket knife. And some kids not even that.
Point being: In Ruby, sharp knives are too accessible, come with no warning or even encouragement.
Yet contrary to actual sharp knives (or guns pointed at feet) the feedback loop is slow. When you shoot yourself in the foot, or cut your finger, you feel it right away and (hopefully) adjust before more accidents happen.
With Ruby, a footgun is fired today. Or a sharp knife carelessly tossed in the bag yesterday. But you'll feel the pain in months or years only. And probably not even you, but the person who followed your follow up.
Sharp knives are cool. But they need education on their dangers and responsibilities.
But we’ve learned over the decades that footguns should usually be avoided and discouraged rather than made easy to use like Ruby does. There’s a reason we aren’t writing GOTOs anymore, GC is a thing in all but the most performance-critical situations, and static typing is gradually winning.
I definitely prefer Clojure/Elixir-style macros to Ruby’s meta-programming features.
They’re still better than nothing, though. Method-mossing and friends played a critical role in making a framework like Rails possible in Ruby. In contrast, languages like Python and JavaScript just aren’t quite expressive enough to do it. A lot of energy went into attempts over the years, too! At best, something like Sails could get 2/3 off the way there and offer significant advantages on another axis, like making websockets first class.
python has `__getattr__` (and a lot of other dunder magic), what is still missing? With named arguments and (kw)args, there is even more ergonomic magic I think. And django's orm also has similar magical abilities as activerecord.
I think a lot of the metaprogramming abilities Python has are just used less often than in Ruby. Not because it is less expressive, but because it has a culture of simplicity whereas brevity and generality are more valued in Ruby (Rails) culture.
If when looking at the pile of regexes which is Django’s router, your thought is “good, this way I can reason about types!”, then Ruby is definitely not the language for you.
No, I just implement a custom router class as the docs suggest, and move on with my life. It’s a much better use of my time than fighting mental-masturbation DSLs.
No, Python is much less expressive at the pure language level. Ruby is better designed for composability. It's the Lisp influence. Python completely lacks the Lisp, Smalltalk & Perl heritage which makes Ruby a really great language. Python lacks culture.
The page you linked to discusses NoMethodError, which is raised when a method is not found. Among other things it shows how method_missing is involved in searching for a method. Nowhere in the text is it promoted.
One rule I try to go by, and I feel like this should be a pretty moderate take but isn't actually that commonly stated:
If we're talking about Rails at least, then meta-programming/magic/indirection, all that should be very rare in application code. It makes sense sometimes in more abstract libraries, where you have to handle flexible problems, but in application code it's really worthwhile to just be straightforward and verbose.
Rails, to me as someone who loves Ruby and use it for "everything" (including my editor, terminal, window manager), is a poster-child for poorly written Ruby.
It creates code bases that seems to have a tendency to turn into sprawling messes. I appreciate that it has driven a lot of people to Ruby, and in that way it's an amazing and impressive success, but recruiters get it somewhat right for the wrong reason when they sometimes list Rails as a "language".
I'm very happy to use "magic" in Ruby, but it should be high-impact, low code, and contained. E.g. I'm very comfortable with the "magic" in my window manager that turns event classes received from the X11 binding into method call on a target class, so that MotionNotify turns into target.on_motion_notify(event) without me having to specify every event class. It's simple, small, and let me cut a lot of code.
A lot of non-Rubyists would hate it, though.
The irony, though, about your complaint is that Rails code is some of the most verbose Ruby code you'll find, because it's geared at making cookie cutter creation of sites easy, and so a lot of patterns involve an excessive separation into vast amounts of low-impact, verbose classes that do way too little (the obsession with some Rails devs of writing "service classes" for things that should just have been a single method, for example, drives me crazy - yes there are valid uses of service classes, no almost no uses of them in Rails apps are reasonable)
Every Rails app I’ve ever been introduced to had layers upon layers of “before_filter” and “after_filter”, deeply nested into 6+ subclasses of stuff. Whether or not this “should” or “should not” be in application code is beside the reality that it absolutely is all over application code. Makes it a fucking nightmare to debug.
Oh yeah, I guess it's better to limit the use of that. But I actually don't count using those as metaprogramming. It's just part of the framework, and you have to know about those features. Rails has a lot of magic and I think a lot of it is annoying and unnecessary. Using those features is one thing, but defining your own is too far imo, unless you're making a library.
"but the ecosystem is the biggest problem by promoting magic."
This argument isn't entirely true anymore. The Ruby ecosystem has mostly moved away from meta-programming, and embraced classical OOP. Rubyists now tend to avoid `method_missing` and `const_missing` when possible, and abandoned the craze of making everything a DSL. The most meta-programming that Rubyists still use on a regular basis is defining `self.included` on modules in order to inject other modules. Also, Rubyists have embraced API documentation, such as YARD, in order to document and communicate any "magic" that might exist or occur.
It's not really any different to, say, lisp (which is lauded for its intuitive support of macros) and smalltalk (which is what ruby was directly influenced by).
As a dynamic language, Ruby gives you a lot of tools to create fully expressive code. This is just one aspect of it that you can, but don't have to, use.
method_missing is a tiny offense compared to what was getting popular at one point - creating classes by forking metaclass and injecting methods into... without knowing you're doing so (something IIRC got lost between people there...)
Result was objects that shared no structure, no field
That's what I thought as well. If someone's opening metaclasses to define singleton methods they probably know all about the Ruby object model. I don't see how it could be done "without knowing you're doing so".
The people who did it first did understand the meta model.
Unfortunately some people started following without full understanding. I wasn't at forefront of things back then, so I only noticed when the people who did know better started to writing about abuse of this technique.
In every language without method_missing or equivalent, people end up writing custom dispatch based on message values sooner or later, sometimes re-implementing full method dispatch, and occasionally a full inheritance mechanism in the process.
If the set of messages you need to handle dynamically is to only ever be small, define_method() is the better choice, but when it is not, I'll take careful use of method_missing over some monstrosity that ends up emulating the same machinery with lots of extra code any day.
If you struggle with debugging due to method_missing, consider reviewing how you debug code, as it wouldn't even make my top ten of debugging challenges in the Ruby code I've worked on in the last 17 years of daily Ruby use.
I have no idea what you're talking about in your first paragraph. I've put code in production in half a dozen languages, and ruby is, by a immense marging, the biggest offender on this. The only thing that comes close would be AOP in Java, that is bad but at least it's compile time magic with decent IDE support.
All the most heinous bugs I've had to deal with in my life were about magic in ruby. I've worked in 3 of the biggest rails codebases in the world, and in the end we had build checks to deny code with magic.
Software code should be optmised for reading and debugging, not looking nice for first time writes.
Pretty much any switch/case or multipronged if is dispatch in disguise. Sometimes the switch/case/if is the right choice, sometimes it's making the code more convoluted. Once you step up a degree in complexity, you get e.g. lookup tables and class hierarchies to emulate more dynamic dispatch. Complex dispatch is all over the place in most large systems.
Ruby is "an offender" in this to you because you hate the pattern that untangles the huge unholy mess that less dynamic languages use instead. E.g. hacky workarounds like whole class hierarchies or (marginally better) maps from values you dispatch on to first order functions/closures
I have worked in over a dozen languages, and I've never seen a medium to large sized project where some form of dispatch mechanism hasn't been part of the codebase somewhere.
And I'll take the simplicity of dynamic dispatch over hand rolling verbose mappings any day.
> All the most heinous bugs I've had to deal with in my life were about magic in ruby. I've worked in 3 of the biggest rails codebases in the world, and in the end we had build checks to deny code with magic.
I have no like for Rails, it encourages a lot of awful shit, but I also find this really curious, because the backtraces will clearly indicate you've passed through method_missing, you can breakpoint requests and attach remote debuggers to in flight requests, and execute code in-context in those requests.
If that's too complex, sure, maybe a large Rails code base isn't right for you. I don't want to work on Rails codebases either, but because of Rails, not Ruby, nor because the dynamism makes it any harder to debug.
> Software code should be optmised for reading and debugging, not looking nice for first time writes.
These days (years) I work mostly in Java and would love to have method_missing or define_method. Of course I can do everything I want without them, but it's not fun.
You keep saying method_missing is "bad" but what exactly is so bad about it?
The main complaint about method_missing has always been the inefficiency. The class hierarchy is walked every single time and only then is method_missing called. The use of define_method is a pretty neat solution to that problem. The method that wasn't found gets defined and it doesn't rely on method_missing again. Like a cache.
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.
> I’m interested in your ability to maintain very complex business logic over the course of years.
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.
Reading your comment one would think Ruby is the only programming language with exceptions. In fact, lots of programming languages have them, even PHP.
I agree that too much cleverness is unclever. Just don't use clever features and enjoy the rest of the language. Examples:
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.