< Return to Blog

My thoughts on (Ruby on) Rails, and why I'm left with a bitter-sweet feeling.

Here's more context as to why I'm not as thrilled with the direction of Rails.

Yesterday, I responded to a tweet and feel like I need to provide more context as to why I'm not as thrilled with the direction of Rails.
(1) The final say in the direction of Rails belongs to DHH, completely.
(2) Therefore, it isn't much of a surprise that every new release serves to improve his interests first - (a) Basecamp and now (b) HEY.
If you look at hotwired.dev - They even say 
[..]you can use these Hotwire designed frameworks created by the team at Basecamp to power HEY
featured on hotwired.dev
This all looks quite OK at first glance, but it has been a while since certain events started to chomp my bit and leave me with a bitter-sweet feeling considering I have dedicated so much of my working life within the Rails ecosystem.

Let's rewind to 2010

I stumbled on Rails and what drew me in were the usual tenants.  Ruby was new and I instantly enjoyed its metaprogramming aspects, taking me deeper and deeper down the eigenclass rabbit hole.  Writing code that wrote code was a fun exercise.  Duck-typing was great (especially when learning something new) as you could write the most poorly structured code, and it would still get the job done.
The community was generally helpful, but not entirely kind to newbies and "stupid" questions one may ask. However, I stuck to it and having spent over a decade providing eCommerce solutions with Spree (now Solius) / RefineryCMS and worked on quite a few mature Rails codebases that continue to operate in production.

2021: Reflecting over 2+ years at E-Accent BV

This has by far been the highlight of my career where I found a gem of a team, and more importantly a fantastic owner/boss.  I started off as a new hire and later progressed into Senior dev + pretty much SRE and CloudOps lead for a stack of Rails codebases, that revolved around an "extranet" that implemented SSO (Single-Sign On via Doorkeeper).
The Ops tooling was primarily Ansible based, with hosting spread out across various cloud providers.
Our frontend was a bespoke Webpack build, with E2E testing with Cypress.  We also injected React/Redux/Rematch into certain areas where we wanted a really modern frontend experience, with a stateful-clientside backed via an API exposed in Rails.

Reflecting further on common patterns

This is quite possibly where you may start to disagree with me, and that's good.  But my comments in this article are completely biased and skewed by my personal experience and what I've come to observe across a multitude of teams.
(1) Rails is mainly used in its most bleeding-edge agnostic form.
"What do you mean?!", I hear you say, well, this simply means using Rails quite simply as possibly one can.  This means, most of the code-bases I've been will go with the least amount of "fluff" provided via the dictators at Basecamp.
Let me digress a bit to explain my point.  Rails 3 was a great release and brought us UJS, as it wasn't an overly obtuse advancement; and it wasn't a huge leap.
Rails 4 is when things started to shift, a wee bit.  Remember pjax? Turbolinks, for all its benefits, is a bit more obtrusive and is something you absolutely want if you plan to adopt it. And much of the teams I've worked with and code-bases I've come across, you've guessed it, had left Turbolinks out.
You'll see where I'm going with this as we were given another optional piece of technology in Rails 5 by way of Action Cable. When it was announced, I was actually quite excited by it, but later found that not many teams really cared for it.
Rails 7 combines Turbolinks and Stimulus to bring us Hotwire and it's great that we have the option of using these, but quite honestly, if you consider the bulk of frontend talent out there, the chances are it'll be a Vue.js or React based frontend, with TypeScript. Why? Well, right now at least, they are the most popular options for building great frontend experiences. Have you found any job postings asking for frontend devs with "Hotwire" experience?

The straw that broke the camel's back

Even with all that I have said, Rails is self-serving - fine.  But as developers we help the ecosystem with all the contributions we make, whether from single bug reports, to even tweaking small bits of documentation. I've directly contributed a very little to Rails, and that's using my own time.
In April last year, Basecamp pretty much shutdown any talk at work that would distract anyone from making $.  Say you've got a family member having ICE issues (in the US) and that's causing you pain, nope shut it down. Any political issues causing your day to be blue, shut it down mate. Also @brandonwalowitz has asked me to wake up as  "jesus, Jason fried just wanted work to be about work."
Oh I bet he did.

This brings us to my pet-peeve with companies that are self-serving

Wait...wait wait.  What company isn't self serving?
That's a great question. Yesterday I was watching a great documentary on Netflix called Downfall, and I encourage you to do so as well as it covers such an important topic.
It goes in great detail to compare Boeing as a company, and its core-values before it acquired McDonnell Douglas. See prior to the change of CEO, its core-values were to treat its staff as a large family.  Everyone was working to a common goal - to engineer the safest aircraft ever. "If it wasn't done right, it isn't going to fly" -- and I'm paraphrasing here. The post McDonnell Douglas company was driven by pressures on Wallstreet and heavy losses of market share to the French A320neo.
They were now engineering for "cost-efficiency", and well as Brandon would put it, they made sure to make "work to only be about work".  Any backlash from employees toeing the line, would get shut down.

Oh c'mon Mike, just move on

Oh I'm glad you said that.  I have.  I've moved onto contract work building APIs dealing with transactional spikes > 300k req/s in Rust and Axum.  The community (on Discord/Reddit) are fantastic and are even kind to entertain the most newbie questions you can imagine.
Why Rust? It's something I've come to love as it connects my C/C++/Assembly roots with a modern language that is highly performant, async/multi-threading safe (out of the box), and is a governed by a non-profit organisation the Rust Foundation. Improvements to the language are provided by community discussed RFCs (not a single person's whim and fancy), and also importantly has been highly adopted by the likes of AWS and many cloud providers for internal tooling.

*Addendum*: I never said Rust is a great alternative to Rails, first the former is a language...

and the latter is a web-framework. However, if you were so inclined, there is nothing stopping you from serving HTML with Rust and Axum (or Rocket).
The same way, nothing is stopping you from using Node.js/Express or Python/Django.
Choose your poison wisely young padawan!

What about Rails in 2022

I've always said pick the best tool(s) for the job and also make sure your entire team are happy working with them.
Rails is still the best out-of-the box, battletested MVC stack. Thankfully since features such as Turbolinks, Action Cable are "opt-in" you can just disable them completely.
If you consider options such as Node.js/Express or Rust/Axum, there's more work and burden of security falls onto you as the developer. Do you want CORS enabled? You have to add a feature for that (It's in the Axum docs, like everything else). Rails on the other hand has security measures that you may not even be aware of, out of the box.

Where does Rust/Axum factor into this?

Ideally, I would say that Axum shines as an API solution.  It is lean, mean, and blazing fast.  It's typically inherent for APIs to take internal workings of HTTP into detail, i.e. here are some of the things you'd be looking at
  1. Dealing with the entire request/response cycle on a per handler basis. In Rails we call these Controller "Actions" which are routed to via routes.rb.
  2. Adding middleware - this is where you have full access to the request/response call-stack that exists between the first request and finally the controller handler.  Since you can have many middleware layers, they run in sequence.
  3. Mutating and massaging aspects like route params, request params,
  4. Differentiating between HTTP/TLS traffic,
  5. Various response codes, and response format options - plain text, JSON, XML etc.
It is no secret, we all implement API endpoints in Rails, but the issue that typically arises is one of performance and multi-threading. Rust/Axum definitely have the edge in this case.

Summary

I continue to run a few personal Rails instances and these aren't going to change, including the code that runs this here blog, but generally moving forwards if I dabble in Rails it would be for client work, but I personally do not wish to contribute to Basecamp/HEY moving forwards.
It's not like I'm going to be missed either :)