That means every feature of Rails is derived from a practical use case, and then it's well tested in that app before it's pushed out to the community. That's tested from an API and functionality point of view. By the time end users start to use it, the feature has likely been running in production for 6+ months. Maybe even serving billions of page views through it if you factor in Shopify and GitHub also running off Rails master.
It's all constantly in use, kept up to date and iterated on as a whole.
Creating a starter kit / boiler plate of libraries and opinions in another language / web framework is not the same. I think this is why even after 10+ years there's only a handful of popular Rails alternatives in other languages.
How quick can I create a minimum simple SaaS like application that has the following functionalities:
- User management (Signup/Login/Reset password/Confirmation...)
- Simple payment processing (like have on single plan, one time fee, and after paying the user will see some other default page then not paying)
- Sending emails in HTML and plain text (for user management and after payment is processed)
- Use slugged/permalink like URLs
- Processing some task in async queue
And so far there are a lot of alternatives out there but for me Rails provides the easiest experience to have this up and running quickly as there are already battle-tested gems for almost all these functionalities.
To be perfectly honest, one of the things that I always love about Rails is exactly how good the database layer is with ActiveRecord. I like using the advanced features of my database, especially PostgreSQL, and I've found that it's really easy to do with Rails.
The "Scopes" feature of active record that let's you save small snippets of a query and chain them together is fantastic. I've used it to create complex filter functions that combine full text search and coordinate distance as simple methods that can be attached to any query.
Being able to add a `.search("fender").distance_from(location, 5, :miles)` onto any query made my life so much easier.
It's been a few years, but I wrote about some of my favorites.
https://www.brightball.com/articles/rails-gems-to-unlock-adv...
There are a couple of footguns in Rails involving transactions - by default, validating uniqueness of a column in Rails will be done at the app layer which is prone to race conditions, and with a typical CRUD model for an application, there's nothing in particular preventing overwrites of model data if say, a field was present on a form and two people were editing it, even if the "later" editor made no changes to that particular field.
When multiple systems and things other than databases (or multiple databases) are involved, you're generally on your own as well.
It encourages you to write validations for things that don't need to hit the DB, but actually uses the DB for handling constraints, since it's the real source of truth for data consistency.
Most CRUD applications go the one extra step of putting a uniqueness constraint on the column instead of just relying on the app layer validation, and comparing hidden time stamps on the form if multiple people might edit the same row simultaneously. It’s exceedingly straightforward.
Did you really think thousands of web apps up to and including GitHub and shopify were squeaking by on blind luck? If basic database transactions and integrity weren’t doable in Rails, that’d have had to have been fixed years ago.
Most of your basic questions are covered by the starter Rails Guide for ActiveRecord, eg) transactions, validations, how to add a uniqueness constraint to the DB in a migration
https://guides.rubyonrails.org/active_record_basics.html
The ActiveRecord Queries guide also covers some mechanisms for handling row-level write contention
https://guides.rubyonrails.org/active_record_querying.html#l...
I think ActiveRecord has #lock (see https://api.rubyonrails.org/classes/ActiveRecord/Locking/Opt...) and that together with #transaction (https://api.rubyonrails.org/classes/ActiveRecord/Transaction...) are enough for my use cases.
In case of file uploads to cloud providers: there I don't know for specific method to help with race conditions when transforming the resources.
Strapi [4] is much less stable than it looks. It's pretty buggy, isn't designed very well, and is just all around messy. I used it in production once and never will again.
Next.js [2] is well designed and well maintained, but is totally a frontend framework. It's not just "missing a few things" on the backend side, there is no backend side. Works great if you already have an API (JAMStack) but can't stand alone in the way that Rails or Laravel might be able to.
Despite being the youngest, RedwoodJS [1] is the best option here. I was actually involved pretty early on as a contributor on the project before I had to step away (unrelated, personal reasons) and was seriously impressed by their progress. TPW runs a tight ship, and all of the devs that work on the project are smart and amazing. They ship very quickly and it's rapidly growing into the closest thing to a Rails competitor in Javascript. I wouldn't be surprised if it takes the JS world by storm in a year or two.
I'm on the other end of the spectrum.
I mean, I see the benefit of such "roll X quick by adding a gem" for a proof of concept, a demo or even an MVC.
But even for the latter, it breaks down rapidly. Such gems bring their own libraries. They force you to "do it their way". A gem like devise comes with its own addons (omniauth) that paint you even quicker into a corner.
I've consulted and developed at many Rails codebase where most of the problems were caused by years of development on top of such gems. A weak, wobbly base, and the entire castle built on top of that. Where 90% of the devise features were unused or worked around. Where more code was present to customise and work around devise-isms, AASM-weirdness, CanCan-troubles, than a complete "roll your own from scratch" would have ever caused.
So, my "devise advise" always is: sure, use it to get your product to market rapidly. But be sure to pull it out and replace it with a focused, fitting architecture, sooner rather than later.
Such gems fit very well in the problematic development-workflow where one "searches for an existing gem which offers some version of Foo" rather than "figuring out how we want to do Foo, then look for a gem that does it our way".
What I've also seen is that a team with plenty of churn or no time for maintenance will have exactly the problems you describe. As knowledgeable people leave the team, the old code becomes "legacy", new people come and partially refactor it, maybe adding some new gem and planning to migrate the entire codebase later on to it (which is very hard to make it happen). Stakeholders' pressure will force the team to focus on delivering features and only tackling debt when it gets to an unattainable state, and then is when consultants are called. I think this is why many freelancers suffer the worst of Rails (or any other framework) if they don't usually work with greenfield projects.
But this is easier and more rewarding in a garden that is well layed out and allows flexibility to move things around.
An old, crumbling shed, in the middle of that garden limits what you can do with it. It is always in the way, always visible and often defines the entire garden, when you really don't find it that important.
A gem, like devise, defines what your users are (it limits your freedom to define the Domain model), how your onboarding flow works (which is probably your most important money-maker) and what features you can implement and what not.
When you started with the garden, it was handy to have a quick and ready place to store your tools. So the first cheap, off-the-shelve shed, is the best solution. But once your garden is defined, you probably want to move it aside, nicely integrated in your garden and well maintained and exactly large enough for your tools, so it leaves as much space for your flowers and trees -the stuff that matters-.
Most of the Java and .NET world eventually moved into full blown CMS, with component frameworks, graphical layout editors, user management and third party connectors to distributed platforms.
For me, Rails just feels too little, with a quite slow language.
[0] - https://www.djangoproject.com/ [1] - https://www.django-rest-framework.org/ [2] - https://dj-rest-auth.readthedocs.io/en/latest/index.html [3] - https://django-allauth.readthedocs.io/en/latest/overview.htm... [4] - https://www.rootstrap.com/blog/registration-and-authenticati...
Disclaimer: I have never tried Rails
At many places where I've worked at this paradigm is exactly what is needed, but people know and want to use JS. If we choose to go that way then, we need to write a lot of glue code and think about setting up architecture standards, folder and naming conventions, ORM support, authentication, job queues, etc; all of this comes by default with Rails and makes life so much easier.
Lately some options seem to be gaining steam:
* RedwoodJS [1]: by Tom Preston-Werner (founder of Github), comes with React and GraphQL baked in, pretty new project though
* Next.js [2]: brings a lot of nice conventions to the frontend, but still some things missing on the backend side
* SailsJS [3]: similar to Rails, but small community
* Strapi [4], hapi [5] et al: plenty of backend functionality, but frontend agnostic.
Has anybody had experience with any of these (or others) and can report back?
[1] - https://redwoodjs.com/
[2] - https://nextjs.org/
[3] - https://sailsjs.com/
[4] - https://strapi.io/
[5] - https://hapi.dev/