I spend a lot of time each year evaluating frameworks for our clients and their projects, and I keep on coming back to rails.
> Does it turn into unmaintainable spaghetti code after a while? Only if you let it. It's typically caused by developers, not programming languages or frameworks.
After running a number of rails applications in production for going on a decade, this is really hard, and I find it to be one place where rails (really ruby) doesn't help much.
Of all the languages we work in (and it's quite a few), ruby has the worst support for modern language tools: the LSP implementations are weak, and don't play well with containerized development environments. Typing efforts are fractured, and the official way is... well.. it's bad. This is exacerbated by ruby's tendencies towards "fluent" interfaces, which is actually code for lots of methods that take undocumented hashes of arguments --- and hash access with strings and symbols? nightmare fuel.
But I still come back to rails. It's productive, it's fast enough, it scales just fine, and perhaps most importantly there's a "right" way to do just about everything your web application will ever need to do: background jobs, websockets, read-only database replicas.
All in all, its still my recommendation for new web projects going into 2025.
I do find 6-month old typescript to be easier to return to than 6-month old ruby — same goes for most typed languages. The reality is, though, that the benefit of strong types isn't so much in giving you compile time errors as it is forcing the devs to document their method signatures.
I find that a 6-month-old JS project will often not even boot since its exhaustive dependency list will be out of date and now mutually incompatible. You have to feed a JS project with updates every couple of hours, or it will die like a Tamagotchi.
I've seen comments like this almost daily this week.
Does HN not use lockfiles or something? Your node/npm project will work just fine if you use the same version of node/npm and have a lockfile.
Maybe you're using npm i (which can upgrade dependencies in some cases) instead of npm ci [0] (which always uses the lockfile dependencies).
In any case, this is a general problem of package managers and has nothing to do with the language. You'll need something similar if you're using _any_ external dependency in Rust, Python, Go, etc.
> and perhaps most importantly there's a "right" way to do just about everything your web application will ever need to do
A good chunk of chaos in Rails apps is caused by people who either insist they know better than the out-of-the-box solutions, or they “just prefer it my way.”
Even as a bonafide activerecord hater, this sentiment doesn't make much sense to me. The ORM is like 70% of what makes rails fast to develop with, which is the entire reason to use rails in the first place. Everything from routes to rendering to form validation is tightly integrated around object lifecycles. If you get rid of that there's not much benefit to use rails (or in fact ruby) at all.
Wouldn't you say you are a bonafide activerecord hater because of those same issues? I don't expect you hate it because your lost love interest shares the AR initials.
ActiveRecord can both offer fast development and create issues (especially those that only come to bite you later). It exists in a multi-faceted environment. Tradeoffs, as always.
Yes, I think it generally makes rails much more difficult to scale than it has to be, much more difficult to test, and more difficult to verify changes are "safe". I certainly agree with the commentary on tradeoffs, though, and I stand by my comment that AR is a big part of why Rails is such a massive success.
> I stand by my comment that AR is a big part of why Rails is such a massive success.
I think most would agree. It is the "doesn't make much sense" part that we're discussing, though. How does it not make sense when you seem to have the same opinion of it? It seems, as an onlooker, that it makes perfect sense to you.
> How does it not make sense when you seem to have the same opinion of it?
Well, what remains of Rails or of ActiveRecord once you remove the part that's done outside the database? It just seemed like a very shallow view of what rails is.
I think historically that's probably right, but something that has gotten much better with time.
Previously, ActiveRecord gave newer programmers a legible, fluent interface to the database in a language they already knew. So instead of learning SQL, we abused the heck out of AR. I think that the industry, and rails itself, has matured since then and I see a lot less of this nowadays.
Yep, I'm a big fan of building views in postgres and just hitting those with the ORM. I don't even use the join syntax in my ORM (Ecto) - if I need a join, I use a view.
Can you point to any substantial places in rails where method_missing is actually used? The only place I’m aware of is dynamic finder methods like find_by_foo, which IIRC were removed years ago. Most of the more magical ORM stuff is implemented using boot-time metaprogramming things like define_method.
I'll take your word for it—I'm currently blessed by working outside of the rails ecosystem so my knowledge is likely out of date.
EDIT: I'm not bothered by this, but this is a very odd comment to downvote. What on earth is so offensive or distracting about saying someone else is likely more knowledgable than you are? Very confusing.
I agree with you on all your points but I came to the conclusion that I would _not_ start a new app in Rails for those reasons.
I've spent my whole career on Rails and I think it's amazing when starting small but mature applications are a nightmare to refactor. Every monolith Rails app feels like it hits tech bankruptcy after ~5 years.
I think the context here is super important: I run an agency, and a lot of our clients are small startups or solopreneurs. The most important factors in determining their tech stack are (in some order):
* Time from idea to deployed solution
* Ease of pivot
* Ease of finding other devs who can take over
If I were a staff engineer at a large company with an existing tech stack tasked with spinning up some new internal microservice, I'm probably not choosing Rails.
But if I'm truly greenfield on a strict budget, still searching for product market fit? If that application ever truly outgrows rails (and it can become wildly successful without doing so --- look at stripe, instacart, github, shopify) then we've already won by surviving long enough for rails to be the problem.
"tech bankruptcy"! this is a VERY strong sentiment. First of all, I've never seen a rails-based company which has it problems from tech department, and not from product market fit or whatever, and that's in a 18 year carreer. I'm singlehandedly refactoring right now a 10-yearish rails app which had a period of neglect and bad contractors who broke every single test, and it is still very much manageable.
> I've never seen a rails-based company which has it problems from tech department
I've been using Rails since 1.0, owe much of my career to it, and still think it's an incredible framework that I love using.
But I have seen plenty of startups—mostly filled with junior developers—who don't have the maturity and experience to avoid some really bad ideas absolutely wall themselves into a corner. Thankfully the worst of this was in the Ruby 1.8 and Rails 2.3 era, but it still happens today.
A lot of the issue is the tendency that Ruby libraries have toward exposing internal details that end up getting relied upon (Hyrum's law in action).
With a sufficient number of users of an API,
it does not matter what you promise in the contract:
all observable behaviors of your system
will be depended on by somebody.
(There's something about the way people manage to phrase these that I really enjoy. Something about the succinct and clear expression of an idea that's otherwise really fuzzy in my head.)
It's interesting to think about the implementation being necessarily coupled with the interface. In some context that's obvious, but the idea that another implementation can't be freely swapped in -- because nuanced behavior (sometimes called a bug) in the original implementation is still expected -- is one I hadn't, as such, thought much about before.
Over a decade ago when Rails was the shiny new thing I wrote an online ordering system that batched received orders then sent out orders to suppliers for whatever the customers ordered. It was easy enough to get the app setup and it didn't often need any new features but I remember really struggling to get it up to date and working with each new rails version. My memory is clouded by both time and my inexperience at the time but even though the app was "done" it never actually felt finished because I felt the need to continually update to the new version of rails just in case I did want to take advantage of of the new features in newer versions rails.
Anyway over 10 years later now and I find myself writing an API and my initial thinking was to return to rails but then I remembered the bad experience (which was probably my own fault I acknowledge).
Now I find myself writing this API in Rust because the ethos that an app can actually be done is attractive to me. It's taking me longer to write but hopefully I've made a good decision!
I guess my post wasn't a critique of the blog post, it was a somewhat related story. I do actually agree with the blog post about not rewriting something that works. In my case it's a totally new project but it was my previous experience with Rails that made me not want to try it again for this particular project.
The API I'm working on is pretty simple and I want to finish it and forget about it so in my circumstances it seems that rust is a better choice.
Rails, ironically, doesn’t keep you in the rails. I’ve seen a couple of the things you’re talking about, and it’s really just mediocre devs in bad (but common) situations.
If someone gives you a paint-by my-numbers page, and you just scrawl all over it… is that the “fault” of the page?
> This is exacerbated by ruby's tendencies towards "fluent" interfaces, which is actually code for lots of methods that take undocumented hashes of arguments --- and hash access with strings and symbols? nightmare fuel.
Keyword arguments and pattern matching have improved this quite a bit, but not everybody is using it yet. I'm not sure how much Rails is using it either, which doesn't help.
This is exacerbated by ruby's tendencies towards
"fluent" interfaces, which is actually code for
lots of methods that take undocumented hashes of
arguments
Well, I hate this too. I've been away from Ruby for 18 months but my impression was that the community has been moving away from that for a long time and toward keyword args (or whatever they're called, I forget)
and hash access with strings and symbols? nightmare fuel.
What's the alternative? I like hash access with symbols. Prevents typos and the string values for the hashes are interned AFAIK.
After running a number of rails applications in production
for going on a decade, this is really hard,
I don't feel that Ruby is worse than other languages I've used extensively (Ruby, Python, JS, C#) in this regard.
The issue is one's apps dependency graph. You keep dependencies flowing in one direction. Or you do not and you get spaghetti. I have not worked with languages that are really better or worse at this.
To take the example of a typical Rails app: it's very easy to add code to your Model A that depends on Models B, C, and D. Do that in a few models and...boom! spaghetti! Rails does not discourage or warn about this in the slightest.
It's relatively easy to avoid: have a rule that "no model can contain a reference to another model. if you have to do a thing that involves two models, put it in a service class" or some such. Of course, nobody ever does this.
Are there languages and frameworks that encourage/enforce The Right Thing in a more active way?
> Are there languages and frameworks that encourage/enforce The Right Thing in a more active way?
I don't think so, as evidenced by the fact that I'm still so pro Rails after a decade of doing this. But that doesn't mean we can't be vocal about the things that still suck.
> I like hash access with symbols
Oh, I vastly prefer symbol access to string access, but this is really a ruby problem, not a rails problem. The fact that I can pass `{ "foo" => "bar" }` and `{ foo: "bar" }`, and my method has to either call `with_indifferent_access` or _strictly_ enforce being called with one of the two access types is a huge footgun, because improper access doesn't result in an error, it just results in a `nil`.
Type definitions were introduced in Ruby 3. I personally think they are terrible --- primarily because they exist in sibling type files. They are arduous to write, don't have great tooling support, and don't feel like a part of the language at all.
is the "officially supported" one. It's terrible, as is Sorbet. No offense to anyone involved with either of the projects, they just miss the mark in pretty fundamental ways.
In my experience, it's rarely the serving language that causes the hellscape of spaghetti. Possibly the SQL if you've got one of those weird luddites who wants all the business in stored procs running the project. It's the JS+CSS that does it.
> It's typically caused by developers, not programming languages or frameworks.
Best sentence in the article. I’ve worked in well-organized and reliable PHP apps, and giant buggy abortions in TypeScript. Lots of Rails apps with varying degrees of quality. Languages and frameworks can’t fix disorganization, poor architecture, laziness, or most of all, ignorance of how the Web should work (and why.)
The main predictor of how good your app will be technically, is the skill level of your worst developers + how much your best developers care (or are allowed to care, which necessarily varies with business conditions). Regardless of if you’re using trendy languages like Rust, TS, etc.
Of course, while as hackers we desperately wish for the app to be of very high quality, the sad truth is that companies who always obsess over the finest details under the hood don’t tend to perform as well financially as the ones who make compromises to get things to market faster and pivot more effectively, so I think that’s why most of us have rarely worked in commercial codebases where nothing is embarrassing.
Of course, but the trouble remains what is stated in the very next sentence:
> There are plenty of ways to nicely organize your code and you should probably spend more time refactoring.
Ruby/Rails makes this a time consuming process as compared to many alternatives. If you have all the time in the world, Rails is great, but for the rest of us that also have to think about productivity...
IMO rails is a victim of it's own success. By being incredibly productive and easy to get things up and running, you don't have to reason about your data design as much, meaning you are more likely (not guaranteed) to throw together a bunch of badly related garbage.
People love to blame the language and the framework, but in reality once you're past the proof of viability point, it's usually worth taking the time to review some of those initial decisions... except now you need to GrOw! :)
The fact that it's rails is irrelevant. It could be any tool that makes you really efficient by never erecting guard rails.
Over the last few months I evaluated django, laravel, and rails by doing their tutorials.
So far rails has been my favorite to rediscover, I used it 10 years ago and boy has a lot changed!
I was hoping to like django more since I'm a professional python dev, but django felt like I was still clobbering together libraries (whitenoise, celery, etc) and it doesn't have a great front end story.
Laravel was super slick, but I just can't do PHP. I know it's come a long way but it's just not for me.
Rails really stuck for me the most and I really like the hotwire paradigm. As a dad with limited time for side projects Rails is going to be the tool for me now to spin up something quickly.
I'm actually porting over a current side project to rails and stumbled on this magical gem called "Brick"[0]. You just point it at your existing DB then it reads the current state of the database and makes active record models in memory for you to play with. You can then eject the models and controllers into your code base, and bam you have your model layer recreated in rails.
One of the things I love about working with rails is the incredible ecosystem reflecting the elegance, economics, and ambition that exist in Ruby itself.
Rails brings a certain intolerance to BS - boilerplate, verbosity and in general anything that gets into the way of flow.
Many make the same argument about Laravel, Symfony, ASP.NET, etc.
There's a huge amount of value in having an ecosystem of components that are designed to work together, and randomly choosing "oauth X" and "smtp Y" components and trying to string them together, vs using a battle-tested and supported stack, just invites a lot of hurt.
If you have a team of Java web app devs, having them build a web app in Rust or Go will be incredibly costly and inefficient. It seems very obvious to me, but I still get people that say "oh, it's not that hard - library X can do all of that other stuff"... but inevitably it can't. And the communities of people doing web app stuff in (Rust, Go, Scala, etc) just aren't big enough to provide the community support other frameworks provide.
I am unapologetic about despising Ruby - Rails is pretty darn good, though. The Rails and Djangos of the programming worlds are critical for many teams that shouldn't be building their own frameworks from scratch (for any number of reasons).
Attempts are being made (https://loco.rs/) and time will tell if Rust can put together a compelling story for this use case.
100%. Python and Ruby are used for web dev because of Rails and Django, not the other way around.
There's no reason why Rust can't have its own Django. And the day it does I might switch to it for my new web development gigs. In the mean time having access to all my tools with a promise of stability and uniformity will beat the convenience of any one specific language.
> There's no reason why Rust can't have its own Django
I'd argue that the ability to do `python manage.py shell` and get an interactive ORM session for debugging is a fairly major reason why Rust can't have it's own Django.
Except for the sky high complexity cost, you could expose a scripting api that could connect to the database and inspect things that didn't use rust.
I don't know if that's a good idea, but for much of what I personally used the django shell for (did this record get written the way I expected) it could help. Wouldn't help for situations where you want to monkeypatch the running app at runtime (but it's arguable whether you'd want to do that anyway).
There are about a half dozen "Rails-inspired" Rust frameworks under development. They're probably a little too early to start using in production, and you should stick with Actix/Axum Flask-style frameworks for the time being.
The problem was choosing Rust and SvelteKit over Elixir with LiveView (Phoenix) - especially coming from Rails where it’s an easy transition due to shared philosophy and even syntax to some degree. Rust is neat but complex and probably overkill for a web app. But yeah, in general - innovation tokens cost time vs what you already know.
I've worked with Rails, I've worked with Phoenix, I've also built with Rust and Svelte. I'd choose Rust+Svelte every time. Much better experience. Rust's async is not nearly as bad as people make it out to be.
Building new Rails apps is a blast, but dealing with old Rails apps is a pain, they're difficult to refactor.
New Rust apps are great, and dealing with old Rust apps is a much better experience as they're easier to refactor.
Like I've commented maybe 100 times on hn, there's more people who want Elixir jobs than there are Elixir jobs - it's not a real problem. Probably same for Rust. Especially when AI makes it so much easier to get up to speed on a new project, framework, etc these days.
What about Rails and Svelte? While many people are doing things with full stack Rails, there are just as many using Rails (whether as a monolith or separate backend from frontend deployments) with modern JS.
Actually, in recent Rails versions the mistakes of Webpacker have been replaced with much more flexible gems for building frontend assets with esbuild, vite, or any other build tool.
This gives the ability to seamlessly blend the nice pre packaged rails ecosystem with the nice ecosystem of react components or other modern frontend tooling most people are using.
I close this comment with mentioning: you still may not need all of that new stuff! What does your app actually do?
Tbh, if you're already using rails the odds that you'll need svelte / react are pretty low. Sometimes you might, and those pages can pull those in, but generally speaking you can do a lot with Turbo and Stimulus.
I'm not surprised that this conclusion was reached after trying to use Rust for a web development project.
Rails' is what people are going for when they choose it, not Ruby (generally speaking... there are obviously people who like Ruby). Rails provides all of the tooling, conventions, and ecosystem needed to tackle a great deal of web development projects.
Rails is a great example of a killer application. People learned Ruby just so they could use Rails. Wanna make a bread-and-butter website, just build it in Rails. Three-quarters of what you need is available in the framework itself and most of everything else is a library that integrates seamlessly with the framework.
If you need to use a systems-level language to solve a technical problem, you'll know exactly why you need to go through the trouble. If you're using maxims to justify your choice, you have no idea. "Because it's blazingly fast," doesn't matter if -- as the TFA points out -- your most heavily-trafficked endpoint is serving a p90 of < 400ms, your team is delivering the features you need on time, and your users are happy.
I think there are lots of good reasons to use a Rust-based framework. I work in Haskell full time. I get it. But there are huge trade-offs. The most obvious one is that almost no SaaS or open-source components you use will ship Rust or Haskell SDKs. They will ship libraries that integrate with Rails.
If you are doing anything serious, then yes. OTP is a top tier framework for writing any sort of complex parallel/distributed processing. I’d pick OTP over ActiveJobWhatever any day. Elixir code is also easier to maintain at scale due to stronger packaging and typing. OTP’s application abstraction is genius.
Rewriting really improves the quality of the code-base, because it increases our understanding of it, and allows us to replace stupid designs with better ones. Using adifferent language or platform forces you to rewrite much of it, with the same or better design.
In my opinion the ionvestment is not so much in the code, than in the design.
Changelog had a podcast come out with David Hansson (the creator of Rails) a few days ago: "Rails is having a moment (again)" https://changelog.com/podcast/615
I'm not a particular fan of Ruby itself but I can appreciate the value that Rails brings. The interview with DHH was quite interesting... DHH is not someone I find I've always agreed with but his opinions nonetheless always seem reasonable and thoughtful. It seems useful to have someone that Zigs when the rest of the industry Zags.
No, it's not. But it also hasn't gone away. The long tail of viable technologies is much longer than most developers realize. Technology shifts are almost generational.
I do think LLMs change the game a bit. Rails is nice because of the ecosystem and how magic and expressive it is but LLMs can generate and maintain a lot of the boilerplate while they're less good at debugging the magic when it is misbehaving.
I am working on an app that has a frontend in Django and the backend in Go and when I make changes to the Go side I just feel a lot more confident it'll all work as intended. Compared with Django I keep finding myself in the weeds debugging why some random dependency is misbehaving which is difficult because python allows you to do some really heinous stuff like instantiate classes that are chosen using runtime configuration.
I couldn’t help but notice that he was working with two extremes, ruby and rust. A nice middle ground could have been nodejs with TS, with the advantage of using a single language throughout the project. While nodejs doesn’t have something like rails, its ecosystem is largely centered around building web applications.
DHH is an authoritarian and reactionary technologist. He doesn't accept ideas. He thinks that just because someone saves 15 minutes to do a project, that person should be sentenced to spend long hours debugging.
Really struggling to see how Sveltkit is a all similar to RoR. Sveltkit is just a frontend SSR framework lacking the rest of the goodies and patterns of a full stack framework. Sveltkit seems to be a next.js alternative but not a RoR alternative
It's not the same at all. I have a SvelteKit + FastAPI app that ironically I'm porting to Rails after rediscovering it.
Indeed SvelteKit is basically like NextJS for Svelte. It's just a thin server layer + routing which enables SSR, form submissions, and a few other goodies.
You don't get the kitchen sink like with Rails.
Just off the top of my head here's things you get with Rails that you don't with SvelteKit
- auth (new in Rails 8)
- background jobs
- email processing
- database connections and ORM
- caching layer
By the way this is coming as someone who is a fan of SvelteKit, it's just not objectively the same nor an evolution of rails at all.
One minor thing I would add is that of very recently, the new svc utility can set up auth, database stuff, i18n and some other things when creating a new svelte kit project.
Discussion two days ago, 239 points, 219 comments: https://news.ycombinator.com/item?id=42024246
I spend a lot of time each year evaluating frameworks for our clients and their projects, and I keep on coming back to rails.
> Does it turn into unmaintainable spaghetti code after a while? Only if you let it. It's typically caused by developers, not programming languages or frameworks.
After running a number of rails applications in production for going on a decade, this is really hard, and I find it to be one place where rails (really ruby) doesn't help much.
Of all the languages we work in (and it's quite a few), ruby has the worst support for modern language tools: the LSP implementations are weak, and don't play well with containerized development environments. Typing efforts are fractured, and the official way is... well.. it's bad. This is exacerbated by ruby's tendencies towards "fluent" interfaces, which is actually code for lots of methods that take undocumented hashes of arguments --- and hash access with strings and symbols? nightmare fuel.
But I still come back to rails. It's productive, it's fast enough, it scales just fine, and perhaps most importantly there's a "right" way to do just about everything your web application will ever need to do: background jobs, websockets, read-only database replicas.
All in all, its still my recommendation for new web projects going into 2025.
> Does it turn into unmaintainable spaghetti code after a while?
I say this genuinely enjoying JavaScript programming, but my mind immediately jumped to "as opposed to immediately, like most JS frameworks?"
I do find 6-month old typescript to be easier to return to than 6-month old ruby — same goes for most typed languages. The reality is, though, that the benefit of strong types isn't so much in giving you compile time errors as it is forcing the devs to document their method signatures.
I find that a 6-month-old JS project will often not even boot since its exhaustive dependency list will be out of date and now mutually incompatible. You have to feed a JS project with updates every couple of hours, or it will die like a Tamagotchi.
I've seen comments like this almost daily this week.
Does HN not use lockfiles or something? Your node/npm project will work just fine if you use the same version of node/npm and have a lockfile.
Maybe you're using npm i (which can upgrade dependencies in some cases) instead of npm ci [0] (which always uses the lockfile dependencies).
In any case, this is a general problem of package managers and has nothing to do with the language. You'll need something similar if you're using _any_ external dependency in Rust, Python, Go, etc.
[0]: https://docs.npmjs.com/cli/v10/commands/npm-ci
> and perhaps most importantly there's a "right" way to do just about everything your web application will ever need to do
A good chunk of chaos in Rails apps is caused by people who either insist they know better than the out-of-the-box solutions, or they “just prefer it my way.”
The biggest issues in Rails come from trying to do things with the ORM that should be done in the database.
Even as a bonafide activerecord hater, this sentiment doesn't make much sense to me. The ORM is like 70% of what makes rails fast to develop with, which is the entire reason to use rails in the first place. Everything from routes to rendering to form validation is tightly integrated around object lifecycles. If you get rid of that there's not much benefit to use rails (or in fact ruby) at all.
Wouldn't you say you are a bonafide activerecord hater because of those same issues? I don't expect you hate it because your lost love interest shares the AR initials.
ActiveRecord can both offer fast development and create issues (especially those that only come to bite you later). It exists in a multi-faceted environment. Tradeoffs, as always.
Yes, I think it generally makes rails much more difficult to scale than it has to be, much more difficult to test, and more difficult to verify changes are "safe". I certainly agree with the commentary on tradeoffs, though, and I stand by my comment that AR is a big part of why Rails is such a massive success.
> I stand by my comment that AR is a big part of why Rails is such a massive success.
I think most would agree. It is the "doesn't make much sense" part that we're discussing, though. How does it not make sense when you seem to have the same opinion of it? It seems, as an onlooker, that it makes perfect sense to you.
> How does it not make sense when you seem to have the same opinion of it?
Well, what remains of Rails or of ActiveRecord once you remove the part that's done outside the database? It just seemed like a very shallow view of what rails is.
Does anything need to remain? That is where my confusion lies.
This entire response thread looks like the classic AR N+1 problem ;)
Because of the high latency between messages? After all, eliminate the latency and the N+1 problem goes away.
I think historically that's probably right, but something that has gotten much better with time.
Previously, ActiveRecord gave newer programmers a legible, fluent interface to the database in a language they already knew. So instead of learning SQL, we abused the heck out of AR. I think that the industry, and rails itself, has matured since then and I see a lot less of this nowadays.
Strongly agree to this. Rails developers for some reason just abandoning any work in database and tend to work with data in ruby env
Yep, I'm a big fan of building views in postgres and just hitting those with the ORM. I don't even use the join syntax in my ORM (Ecto) - if I need a join, I use a view.
Interesting. Does Ecto have any syntax that supports this behavior? Or do you just use raw SQL for this?
You just treat a view the same way as a table with Ecto.
the extensive use of method_missing doesn't help either.
That's been gone since Rails 4 or 5 (we're on 8 now)
Can you point to any substantial places in rails where method_missing is actually used? The only place I’m aware of is dynamic finder methods like find_by_foo, which IIRC were removed years ago. Most of the more magical ORM stuff is implemented using boot-time metaprogramming things like define_method.
I'll take your word for it—I'm currently blessed by working outside of the rails ecosystem so my knowledge is likely out of date.
EDIT: I'm not bothered by this, but this is a very odd comment to downvote. What on earth is so offensive or distracting about saying someone else is likely more knowledgable than you are? Very confusing.
I agree with you on all your points but I came to the conclusion that I would _not_ start a new app in Rails for those reasons.
I've spent my whole career on Rails and I think it's amazing when starting small but mature applications are a nightmare to refactor. Every monolith Rails app feels like it hits tech bankruptcy after ~5 years.
I think the context here is super important: I run an agency, and a lot of our clients are small startups or solopreneurs. The most important factors in determining their tech stack are (in some order):
* Time from idea to deployed solution * Ease of pivot * Ease of finding other devs who can take over
If I were a staff engineer at a large company with an existing tech stack tasked with spinning up some new internal microservice, I'm probably not choosing Rails.
But if I'm truly greenfield on a strict budget, still searching for product market fit? If that application ever truly outgrows rails (and it can become wildly successful without doing so --- look at stripe, instacart, github, shopify) then we've already won by surviving long enough for rails to be the problem.
"tech bankruptcy"! this is a VERY strong sentiment. First of all, I've never seen a rails-based company which has it problems from tech department, and not from product market fit or whatever, and that's in a 18 year carreer. I'm singlehandedly refactoring right now a 10-yearish rails app which had a period of neglect and bad contractors who broke every single test, and it is still very much manageable.
> I've never seen a rails-based company which has it problems from tech department
I've been using Rails since 1.0, owe much of my career to it, and still think it's an incredible framework that I love using.
But I have seen plenty of startups—mostly filled with junior developers—who don't have the maturity and experience to avoid some really bad ideas absolutely wall themselves into a corner. Thankfully the worst of this was in the Ruby 1.8 and Rails 2.3 era, but it still happens today.
A lot of the issue is the tendency that Ruby libraries have toward exposing internal details that end up getting relied upon (Hyrum's law in action).
Hadn't heard of Hyrum's law before. https://www.hyrumslaw.com/
(There's something about the way people manage to phrase these that I really enjoy. Something about the succinct and clear expression of an idea that's otherwise really fuzzy in my head.)It's interesting to think about the implementation being necessarily coupled with the interface. In some context that's obvious, but the idea that another implementation can't be freely swapped in -- because nuanced behavior (sometimes called a bug) in the original implementation is still expected -- is one I hadn't, as such, thought much about before.
Over a decade ago when Rails was the shiny new thing I wrote an online ordering system that batched received orders then sent out orders to suppliers for whatever the customers ordered. It was easy enough to get the app setup and it didn't often need any new features but I remember really struggling to get it up to date and working with each new rails version. My memory is clouded by both time and my inexperience at the time but even though the app was "done" it never actually felt finished because I felt the need to continually update to the new version of rails just in case I did want to take advantage of of the new features in newer versions rails.
Anyway over 10 years later now and I find myself writing an API and my initial thinking was to return to rails but then I remembered the bad experience (which was probably my own fault I acknowledge).
Now I find myself writing this API in Rust because the ethos that an app can actually be done is attractive to me. It's taking me longer to write but hopefully I've made a good decision!
Isn't the conclusion of this aticle that it's a bad idea, ie. Rust API?
I guess my post wasn't a critique of the blog post, it was a somewhat related story. I do actually agree with the blog post about not rewriting something that works. In my case it's a totally new project but it was my previous experience with Rails that made me not want to try it again for this particular project.
The API I'm working on is pretty simple and I want to finish it and forget about it so in my circumstances it seems that rust is a better choice.
Rails, ironically, doesn’t keep you in the rails. I’ve seen a couple of the things you’re talking about, and it’s really just mediocre devs in bad (but common) situations.
If someone gives you a paint-by my-numbers page, and you just scrawl all over it… is that the “fault” of the page?
> This is exacerbated by ruby's tendencies towards "fluent" interfaces, which is actually code for lots of methods that take undocumented hashes of arguments --- and hash access with strings and symbols? nightmare fuel.
Keyword arguments and pattern matching have improved this quite a bit, but not everybody is using it yet. I'm not sure how much Rails is using it either, which doesn't help.
It's def a dicey situation, but improving.
The issue is one's apps dependency graph. You keep dependencies flowing in one direction. Or you do not and you get spaghetti. I have not worked with languages that are really better or worse at this.
To take the example of a typical Rails app: it's very easy to add code to your Model A that depends on Models B, C, and D. Do that in a few models and...boom! spaghetti! Rails does not discourage or warn about this in the slightest.
It's relatively easy to avoid: have a rule that "no model can contain a reference to another model. if you have to do a thing that involves two models, put it in a service class" or some such. Of course, nobody ever does this.
Are there languages and frameworks that encourage/enforce The Right Thing in a more active way?
> Are there languages and frameworks that encourage/enforce The Right Thing in a more active way?
I don't think so, as evidenced by the fact that I'm still so pro Rails after a decade of doing this. But that doesn't mean we can't be vocal about the things that still suck.
> I like hash access with symbols
Oh, I vastly prefer symbol access to string access, but this is really a ruby problem, not a rails problem. The fact that I can pass `{ "foo" => "bar" }` and `{ foo: "bar" }`, and my method has to either call `with_indifferent_access` or _strictly_ enforce being called with one of the two access types is a huge footgun, because improper access doesn't result in an error, it just results in a `nil`.
> Typing efforts are fractured, and the official way is... well.. it's bad.
Official way? I thought there is none.
As long as there is no support for gradual typing in the core language it will never be used outside of niche programming.
And then I have a hard time imagining that Rails would use it anyway. Unless the performance boost would be tremendous.
Type definitions were introduced in Ruby 3. I personally think they are terrible --- primarily because they exist in sibling type files. They are arduous to write, don't have great tooling support, and don't feel like a part of the language at all.
https://github.com/ruby/rbs
is the "officially supported" one. It's terrible, as is Sorbet. No offense to anyone involved with either of the projects, they just miss the mark in pretty fundamental ways.
In my experience, it's rarely the serving language that causes the hellscape of spaghetti. Possibly the SQL if you've got one of those weird luddites who wants all the business in stored procs running the project. It's the JS+CSS that does it.
May I please ask what set Rails ahead of the .NET and Spring frameworks?
Avoidance of a proprietary MS stack is why I went with Django 15 years ago. I imagine this played a large part in the appeal of Rails at the time too.
> It's typically caused by developers, not programming languages or frameworks.
Best sentence in the article. I’ve worked in well-organized and reliable PHP apps, and giant buggy abortions in TypeScript. Lots of Rails apps with varying degrees of quality. Languages and frameworks can’t fix disorganization, poor architecture, laziness, or most of all, ignorance of how the Web should work (and why.)
The main predictor of how good your app will be technically, is the skill level of your worst developers + how much your best developers care (or are allowed to care, which necessarily varies with business conditions). Regardless of if you’re using trendy languages like Rust, TS, etc.
Of course, while as hackers we desperately wish for the app to be of very high quality, the sad truth is that companies who always obsess over the finest details under the hood don’t tend to perform as well financially as the ones who make compromises to get things to market faster and pivot more effectively, so I think that’s why most of us have rarely worked in commercial codebases where nothing is embarrassing.
Of course, but the trouble remains what is stated in the very next sentence:
> There are plenty of ways to nicely organize your code and you should probably spend more time refactoring.
Ruby/Rails makes this a time consuming process as compared to many alternatives. If you have all the time in the world, Rails is great, but for the rest of us that also have to think about productivity...
Do you have any examples of why RoR is more time consuming to refactor than other languages?
IMO rails is a victim of it's own success. By being incredibly productive and easy to get things up and running, you don't have to reason about your data design as much, meaning you are more likely (not guaranteed) to throw together a bunch of badly related garbage.
People love to blame the language and the framework, but in reality once you're past the proof of viability point, it's usually worth taking the time to review some of those initial decisions... except now you need to GrOw! :)
The fact that it's rails is irrelevant. It could be any tool that makes you really efficient by never erecting guard rails.
Over the last few months I evaluated django, laravel, and rails by doing their tutorials.
So far rails has been my favorite to rediscover, I used it 10 years ago and boy has a lot changed!
I was hoping to like django more since I'm a professional python dev, but django felt like I was still clobbering together libraries (whitenoise, celery, etc) and it doesn't have a great front end story.
Laravel was super slick, but I just can't do PHP. I know it's come a long way but it's just not for me.
Rails really stuck for me the most and I really like the hotwire paradigm. As a dad with limited time for side projects Rails is going to be the tool for me now to spin up something quickly.
I'm actually porting over a current side project to rails and stumbled on this magical gem called "Brick"[0]. You just point it at your existing DB then it reads the current state of the database and makes active record models in memory for you to play with. You can then eject the models and controllers into your code base, and bam you have your model layer recreated in rails.
[0]: https://github.com/lorint/brick
One of the things I love about working with rails is the incredible ecosystem reflecting the elegance, economics, and ambition that exist in Ruby itself.
Rails brings a certain intolerance to BS - boilerplate, verbosity and in general anything that gets into the way of flow.
> I was hoping to like django more since I'm a professional python dev
This is my issue too!
Django honesty feels pretty outdated and behind these days.
The webdev race has sort of left python behind.
Not in the job market. Django to Rails on Indeed is about 3 to 1.
Many make the same argument about Laravel, Symfony, ASP.NET, etc.
There's a huge amount of value in having an ecosystem of components that are designed to work together, and randomly choosing "oauth X" and "smtp Y" components and trying to string them together, vs using a battle-tested and supported stack, just invites a lot of hurt.
If you have a team of Java web app devs, having them build a web app in Rust or Go will be incredibly costly and inefficient. It seems very obvious to me, but I still get people that say "oh, it's not that hard - library X can do all of that other stuff"... but inevitably it can't. And the communities of people doing web app stuff in (Rust, Go, Scala, etc) just aren't big enough to provide the community support other frameworks provide.
Kudos to the author for their epiphany.
This is basically the outcome of not having fulfilled this: https://ntietz.com/blog/rust-needs-a-web-framework-for-lazy-...
I am unapologetic about despising Ruby - Rails is pretty darn good, though. The Rails and Djangos of the programming worlds are critical for many teams that shouldn't be building their own frameworks from scratch (for any number of reasons).
Attempts are being made (https://loco.rs/) and time will tell if Rust can put together a compelling story for this use case.
I like your article, a big thing I think you miss though is 'database migrations' which I think Django does brilliantly well at managing for you.
100%. Python and Ruby are used for web dev because of Rails and Django, not the other way around.
There's no reason why Rust can't have its own Django. And the day it does I might switch to it for my new web development gigs. In the mean time having access to all my tools with a promise of stability and uniformity will beat the convenience of any one specific language.
> There's no reason why Rust can't have its own Django
I'd argue that the ability to do `python manage.py shell` and get an interactive ORM session for debugging is a fairly major reason why Rust can't have it's own Django.
Except for the sky high complexity cost, you could expose a scripting api that could connect to the database and inspect things that didn't use rust.
I don't know if that's a good idea, but for much of what I personally used the django shell for (did this record get written the way I expected) it could help. Wouldn't help for situations where you want to monkeypatch the running app at runtime (but it's arguable whether you'd want to do that anyway).
Rust already has several Flask equivalents (Actix, Axum, etc.)
Rust is well on the way to having a Rails/Django.
Seriously? What's the project?
There are about a half dozen "Rails-inspired" Rust frameworks under development. They're probably a little too early to start using in production, and you should stick with Actix/Axum Flask-style frameworks for the time being.
That said, here are a few examples:
- https://loco.rs/
- https://github.com/levkk/rwf
- https://tokio.rs/blog/2024-10-23-announcing-toasty (Tokio is beginning to assemble the pieces: Axum, Toasty, etc.)
The problem was choosing Rust and SvelteKit over Elixir with LiveView (Phoenix) - especially coming from Rails where it’s an easy transition due to shared philosophy and even syntax to some degree. Rust is neat but complex and probably overkill for a web app. But yeah, in general - innovation tokens cost time vs what you already know.
I've worked with Rails, I've worked with Phoenix, I've also built with Rust and Svelte. I'd choose Rust+Svelte every time. Much better experience. Rust's async is not nearly as bad as people make it out to be.
Building new Rails apps is a blast, but dealing with old Rails apps is a pain, they're difficult to refactor. New Rust apps are great, and dealing with old Rust apps is a much better experience as they're easier to refactor.
If few people know Rust, then even fewer people know Elixir. That's a major concern for these types of projects, often.
Like I've commented maybe 100 times on hn, there's more people who want Elixir jobs than there are Elixir jobs - it's not a real problem. Probably same for Rust. Especially when AI makes it so much easier to get up to speed on a new project, framework, etc these days.
What about Rails and Svelte? While many people are doing things with full stack Rails, there are just as many using Rails (whether as a monolith or separate backend from frontend deployments) with modern JS.
Actually, in recent Rails versions the mistakes of Webpacker have been replaced with much more flexible gems for building frontend assets with esbuild, vite, or any other build tool.
This gives the ability to seamlessly blend the nice pre packaged rails ecosystem with the nice ecosystem of react components or other modern frontend tooling most people are using.
I close this comment with mentioning: you still may not need all of that new stuff! What does your app actually do?
Tbh, if you're already using rails the odds that you'll need svelte / react are pretty low. Sometimes you might, and those pages can pull those in, but generally speaking you can do a lot with Turbo and Stimulus.
There’s actually a couple really good ways to embed React in a Rails template. Let’s you have something really interactive when you need it.
I'm not surprised that this conclusion was reached after trying to use Rust for a web development project.
Rails' is what people are going for when they choose it, not Ruby (generally speaking... there are obviously people who like Ruby). Rails provides all of the tooling, conventions, and ecosystem needed to tackle a great deal of web development projects.
Rails is a great example of a killer application. People learned Ruby just so they could use Rails. Wanna make a bread-and-butter website, just build it in Rails. Three-quarters of what you need is available in the framework itself and most of everything else is a library that integrates seamlessly with the framework.
If you need to use a systems-level language to solve a technical problem, you'll know exactly why you need to go through the trouble. If you're using maxims to justify your choice, you have no idea. "Because it's blazingly fast," doesn't matter if -- as the TFA points out -- your most heavily-trafficked endpoint is serving a p90 of < 400ms, your team is delivering the features you need on time, and your users are happy.
I think there are lots of good reasons to use a Rust-based framework. I work in Haskell full time. I get it. But there are huge trade-offs. The most obvious one is that almost no SaaS or open-source components you use will ship Rust or Haskell SDKs. They will ship libraries that integrate with Rails.
Too bad you didn't choose Phoenix/Elixir. Give it a try, and never come back to Rails.
It seemed to me like a lot of the value of Rails came from all the batteries that are included - would you say it’s the same for Phoenix/Elixir?
If you are doing anything serious, then yes. OTP is a top tier framework for writing any sort of complex parallel/distributed processing. I’d pick OTP over ActiveJobWhatever any day. Elixir code is also easier to maintain at scale due to stronger packaging and typing. OTP’s application abstraction is genius.
Truth
Dupe https://news.ycombinator.com/item?id=42024246
yep, 2 days ago.
I'd love to read more discussion about though.
So I'm cheering for this one to stay up as well.
Rewriting really improves the quality of the code-base, because it increases our understanding of it, and allows us to replace stupid designs with better ones. Using adifferent language or platform forces you to rewrite much of it, with the same or better design.
In my opinion the ionvestment is not so much in the code, than in the design.
Changelog had a podcast come out with David Hansson (the creator of Rails) a few days ago: "Rails is having a moment (again)" https://changelog.com/podcast/615
I'm not a particular fan of Ruby itself but I can appreciate the value that Rails brings. The interview with DHH was quite interesting... DHH is not someone I find I've always agreed with but his opinions nonetheless always seem reasonable and thoughtful. It seems useful to have someone that Zigs when the rest of the industry Zags.
Rails is having a comeback
No, it's not. But it also hasn't gone away. The long tail of viable technologies is much longer than most developers realize. Technology shifts are almost generational.
More accurately: Cost cutting is having a comeback.
Rails was built for the last cost-cutting era, so it seems relevant again.
Don't call it a comeback.
[dead]
Every year rails has a comeback and the next year it needs another one
I do think LLMs change the game a bit. Rails is nice because of the ecosystem and how magic and expressive it is but LLMs can generate and maintain a lot of the boilerplate while they're less good at debugging the magic when it is misbehaving.
I am working on an app that has a frontend in Django and the backend in Go and when I make changes to the Go side I just feel a lot more confident it'll all work as intended. Compared with Django I keep finding myself in the weeds debugging why some random dependency is misbehaving which is difficult because python allows you to do some really heinous stuff like instantiate classes that are chosen using runtime configuration.
Excellent article. This is why I have tied my livelihood to Ruby on Rails.
Rails still gets the job done. That's what you get paid to do -- the job!
This isn't really an argument in favor of Rails so much as it is an argument against being indecisive and scattering your efforts too widely.
I couldn’t help but notice that he was working with two extremes, ruby and rust. A nice middle ground could have been nodejs with TS, with the advantage of using a single language throughout the project. While nodejs doesn’t have something like rails, its ecosystem is largely centered around building web applications.
I'd say adonisjs[1] is the closest thing in TS land to rails. There's also sailsjs[2].
Neither are as trendy as nextjs/sveltekit etc, but those are not really comparable to rails.
[1]: https://adonisjs.com
[2]: https://sailsjs.com
DHH is an authoritarian and reactionary technologist. He doesn't accept ideas. He thinks that just because someone saves 15 minutes to do a project, that person should be sentenced to spend long hours debugging.
Forget Rails and embrace Sveltekit. All the magic of Rails can be achieved in any framework with LLMs.
Really struggling to see how Sveltkit is a all similar to RoR. Sveltkit is just a frontend SSR framework lacking the rest of the goodies and patterns of a full stack framework. Sveltkit seems to be a next.js alternative but not a RoR alternative
Sveltekit is not the same as Rails. It's an evolution. Plus, it's very easy to get any Rails functionality from NPM.
It's not the same at all. I have a SvelteKit + FastAPI app that ironically I'm porting to Rails after rediscovering it.
Indeed SvelteKit is basically like NextJS for Svelte. It's just a thin server layer + routing which enables SSR, form submissions, and a few other goodies.
You don't get the kitchen sink like with Rails.
Just off the top of my head here's things you get with Rails that you don't with SvelteKit
- auth (new in Rails 8)
- background jobs
- email processing
- database connections and ORM
- caching layer
By the way this is coming as someone who is a fan of SvelteKit, it's just not objectively the same nor an evolution of rails at all.
One minor thing I would add is that of very recently, the new svc utility can set up auth, database stuff, i18n and some other things when creating a new svelte kit project.
I suggest trying it out, it's pretty cool.
> Plus, it's very easy to get any Rails functionality from NPM.
Well, that is the issue of modern software development. People download even packages like `is-number` which is in the end few lines of code.