I totally understand the desire for a minimal and clean codebase. If I’m not going to use 80% of Rails, why would include it, right?
But in practice, I have found there is basically zero cost to using Rails instead.
At the company I used to work for we built our invoicing system's API with it and it was fantastic, plain succinct Ruby with Sinatra, Sequel and not much else.
For public-facing apps that require signup, clever routing, image uploads and other non-trivial functionality, Rails definitely makes more sense.
I think the answer to 90% of these "framework A vs. framework B" discussions comes down to "use the best tool for the job".
The simplicity of these frameworks allows arbitrary changes with minimal friction, patterns, restrictions, and other people's opinions, i.e. conventions.
Just thought I'd provide some counter data here. I've built small services in Sinatra, which did not warrant the usage of Rails and never had to change anything, having them in fully functional operation for years.
I could have built these little apps in Rails, but I did not need it, never did, and my code/deployment/etc. is cleaner and smaller because of it.
Also these services have always been quite small (a few endpoints or functions), which is what I think Sinatra is best for.
Non optionated means that I can really easily setup the model that I want/need without having any framework in my way. Love it. One caveat: I am a senior engineer 7+ years of experience. I would not have been comfortable having to do those design choices earlier in my career and Rails would have been better suited then.
I don’t know if the codebase has stabilized but the transition between 2.x to 3.x to 4.x was pretty rocky from my recollection. Hopefully it’s better, since Rails is probably the best framework to get a site up and running quickly.
Since that time both ruby and rails have stabilized their upgrades significantly. The biggest issue since then was updating to strong params, and that was only an issue for apps with a large CRUD surface area.
These days I think Rails is the perfect balance of stable and flexible for a wide swath of prototypes and apps. The areas where I'd look for an alternative would be web sockets, heavy concurrency (ie. needing more than background workers), or where raw compute is the bottleneck.
v2 -> v3 also was the merb merging and a pretty significant rewrite, so it's pretty impressive that we didn't have even more trouble IMO.
I actually always say that despite the apparent easiness of the micro framwork hello world, you have to actually be very skilled to use them correctly to do anything beyong a few pages. While a full feature framework will make a beginer produce a decent work by default.
I agree that, should a system get significantly complex, eventually you will want Django; but a lot of projects simply never get there. That's why it's good to have a choice anyway.
E.g : sqlalchemy sessions are very often badly handled. Of course you could write sql by hand, but then you loose the entire ecosystem of blueprints.
Blueprints for models?
Relatively few lines of code that comes with validation, API playground, and defined routes plugged in via the swagger doc.
The main I ssue is having a nice admin page, tbh. Flask doesn’t have one like Django but eh. Good enough I suppose.
You see because flask is so minimal, many beginers use it for an easy start, only to rewrite square wheels when the project gets real.
When using flask, you have to be able to make decisions about those. Many devs are not able to.
I'm ok with it: not everybody has to be an expert to be a great element in a company. But flask gives those profile a false sense of easiness.
> But flask gives those profile a false sense of easiness.
It allows you to prototype very fast, not everyone needs nor wants the hand-holding that django provides.
Don't get me wrong I think django is fantastic at what it gives out of the box but saying that flask is insecure is just fud.
Also - try Pyramid, you'll never know when it suits your needs https://trypyramid.com/
ORM, sessions, auth, administration, form validation, template rendering, API infrastructure, static file management, RSS feeds, ...
If you think your service will ever need more that 2 of these, use a framework. These will integrate well with each other and save time.
Not really. You want an ORM? choose an ORM library. You want templates, choose a templating library. You want to send mails, choose a mailing library. I don't see how big frameworks like Rails make all these things better, especially when they don't give you the choice as to what tool to use. If you ever developed a non trivial application, you also know that your first concern will be to avoid unnecessary bloat and complexity and only bring in libraries that are strictly required. And as we are moving from traditional html rendered server apps, big frameworks lost even more value since there is no need for a templating libraries, html form libraries,...
That’s not always perfect or suitable for every use case, but it’s not a bad thing.
This sentiment also was a major theme of my forward to The Rails Way.
I’ve been thinking about this stuff a lot in the context of Rust...
Do you mind extrapolating further, or will that be the topic of a future blog post?
I'm, admittedly, out of the loop when it comes to Node, but I do remember Sails looking promising when it was first announced. I recently suggested it to someone (who uses Node regularly) as a possible solution for a project we're working on and they'd never heard of it. So, between that reaction and the fact that I haven't heard of anyone else using it (or anything similar), I think you're right that a Railsy solution never took off.
Elixir is an interesting counterpoint, though. It seems like Phoenix was released and saw broad adoption very early on.
I'm wondering if this dichotomy is a result of where people are coming to these newer languages from: people writing Elixir probably aren't coming from the FE/JS world, but there's a very good chance people writing Node are. Prior to the somewhat recent proliferation of JS client app frameworks, using a smattering of libraries was a very common approach to solving problems. (It arguably still is, albeit at a different level of abstraction in React/Babel/Webpack land.)
Anyways, I'll be looking forward to reading the post you alluded to above, should it ever come together.
When working with a framework that doesn't make those decisions for you, you end up with two big downsides - you waste time and energy arguing over which of these low-value choices you want to take, and new developers take longer to come up to speed with your particular architecture, since they need to learn each of the choices and how they are integrated, whereas in Rails it's obvious where everything is and how it's configured if you're familiar with the framework.
Bloat is also over-emphasized, particularly for the backend. You'll load the gems in memory, sure, but they're a fairly small footprint on their own and it's not like Rails is calling the parts of the framework it's not using (save maybe middleware, although most of that is useful for most web applications).
It really helps team cohesion for DHH to tell you that you're using X instead of Y as opposed to the most domineering devs getting their way every time. In my mind this even compensates for some suboptimal choices Rails may make.
But I'd rather spend my time creating business value than researching ORMs, templating libraries and mailers. And since I've never not been able to accomplish something with the ones Rails includes by default, I've never seen the need to use something else.
If you're building a CRUD app (most are), then any popular MVC (Rails/Django/Laravel/.NET MVC/etc) will likely do. If you're worried about "Twitter/Facebook/Google scale" when you're starting, then you're doing it wrong.
So now you need to factor in research time. Then, continual research time, every time a new library or version of a library comes out. And if your research turns up that, no, in fact, version X or new lib Y is not substantively better (by whatever metric you're looking at), do you count that research time as 'wasted'?
> how do you know you're not wasting time and effort?
You look at the results of what you're doing vs what expectations were, firstly. You can then, periodically, look at your efforts, and compare reports from others who are claiming to do the same thing, and ... occasionally... spend time determining if a different approach offers radically better returns on the effort/results you have now. Switching to XYZ may also involve huge amounts of refactoring, upgrade, migration, etc. How do you know all that effort won't be "wasted" if new platform XYZ is abandoned 18 months from now?
"efficiently" doesn't necessarily mean "at maximum efficiency". Also, "business value" is almost always intertwined with hitting particular date/time goals, which often trump technical metrics.
That's different than if I don't know that Sequel exists and I blindly use ActiveRecord. They're both ORMs. They can both read and write data from a database. And guess what — ActiveRecord is better for the vast majority of situations and everyone in the Rails community knows it, so my research into Sequel would have been time wasted.
Rails helps you avoid wasting time on this kind of stuff and pre-packages stuff that most everyone needs and where the alternatives are not substantively different.
You also get a uniformity of understanding of your library and a support network.
The sweet spot that Rails covers, however, is a pretty common sort of web application - one in which you're primarily doing CRUD on different sorts of objects. If you treat every single application as a unique snowflake that needs a 100% bespoke collection of libraries to solve, you'll end up wasting a whole lot of time on architecture and library selection and not a lot of time on solving actual problems.
Rails excels at being the web layer in this situation. All the heavy lifting is done by the DB to spit back feature structures or do routing and native libraries to do image composition.
And, anyway, Rails is pretty modular; you can rip out and replace anything that isn’t to your taste.
All people I worked with that had your philosophy didn't so that last part, and it had important consequences for the whole project duration.
After that, I needed to make some microservices orchestration and NodeJS (using Koa as the HTTP server wrapper) was a better tool to deal with all these asynchronous tasks.
But: Routing? Parsing JSON? Storing files in S3? Dealing with databases? Serve some static assets (e.g. Swagger)? Up to you! And good luck finding the up-to-date and standard library for your needs.
Overall, using workers, doing asynchronous tasks (e.g. starting a thread after hitting an endpoint) and coding orchestration endpoints (e.g. GraphQL) was a enjoyable experience where you have almost full control of what you were doing, but I still miss those days working with Rails where the community was so helpful in finding a friendly path to dealing with some common problems. My impression is that it feels less fragmented overall.
I haven't found myself an ORM as good and expressive as ActiveRecord or Sequel. Overall I think it has to do with all the metaprogramming tools you have available on Ruby. That's something amazing to deal with cookie-cutter problems, but also a problem when you need to do more granular control or get out of the typical CRUD problems.
I have developed very nontrivial applications with Modern, which can be thought of as Sinatra-like, without regretting the choice or without implementing a bunch of Rails things. The web application is an immutable spec and defined as such; state is offloaded to dependent services pushed into your HTTP action handlers. Done. But, then, in 2018 (or 2016 when I started its predecessor), "an application" no longer required bashing into it ERB templates or the like, so I'll grant that it's a little easier.
https://github.com/modern-project/modern-ruby
That said, in the Node world I do use Hapi over Express, as it conforms better to the way I think about things.
But that's also the value in it: After you constructed a big enough Sinatra application you understand why and how Rails is doing the things it does. I think that's very useful.
Use the solution to fit your problem. Microframeworks for small composable problems.
For some reason rails devs see it as the hammer for every nail, screw, bolt, pipe fitting and joint.
This is an important point. If you've ever developed a non-trivial application using Sinatra, Express or any other "micro" or "non-opinionated" framework, you'll have hit this wall quickly.
To riff on Greenspun's Tenth Rule, "Any sufficiently complicated $MICRO-FRAMEWORK application contains an ad hoc informally-specified bug-ridden slow implementation of half of Ruby on Rails."