The years when Rails monoliths were the de facto web stack were some of the best of my career. As I progressed in my career and the popular tech stack shifted to things like microservices, document DBs, serverless functions, Node, importing tiny nom packages for everything, docker containers, React, and GraphQL, the sheer cognitive overhead of getting a simple app up and running gradually took all the fun out of the job for me. The fast, satisfying feedback loop of writing a feature in Rails was replaced with weeks-long coordination efforts between independent microservices, constant discussions about tooling, and doubts over whether or not we had chosen the “right” flavor-of-the-week framework or library for our product. Every time I started a new project or a joined a new company, we had the reinvent the wheel for our bespoke Node/serverless stack and have the same tiring conversations about naming conventions, logging, data consistency, validation, build scripts, etc., all of which Rails gives you by default. I ended up spending more time on tooling setup than actual business logic.
I eventually gave up and switched to a semi-technical product management role.
At Arist (YC S20) we've found that we can have our cake and eat it too by using Ruby on Jets, which is a nearly 100% drop-in replacement for Rails that runs on AWS Lambda. Our service sends messages to hundreds of thousands of people at scheduled moments in the day, and traffic is incredibly spikey, so combining the productivity of Rails and the Ruby ecosystem with the cost effectiveness and scalability of Lambda was a no-brainer. It also passed muster recently when we subjected our platform to a comprehensive penetration test.
We also get the benefits of a mono-repo and the benefits of microservices in the same application footprint, because every controller method is automatically deployed as its own independent lambda (this is core to how Jets works), but we're still in the usual Rails mono-repo format we all know and love. Also very strong integration between ApplicationJob and background lambdas has been killer for us.
One thing I've always said is the real difficulties in software development happen at the seams where services connect with other services. This sort of strategy (and particularly, the mono-repo format) minimizes the number of seams within your application, while still giving you the scalability and other benefits of microservices and serverless.
Is AWS lambda really cost effective? It has been many years since I was part of a team that was assessing AWS Lambda as _workers_ but the resource limitations at the time alongside cost calculation made PHP+VMs the cost-effective choice by orders of magnitude.
Its loved because it means your technical costs are always guaranteed to be a % of your total computing needs, and your computing needs should (theoretically) always be proportional to your total company revenue.
From a business standpoint, that's a pretty great pitch.
Is it actually the most cost effective solution? No more so than any other tool. It depends on exactly what you're building, how, and how you measure the cost. AWS can be extremely costly, or cheap, depending on your engineering needs, constraints, and practices.
I have been at exactly one (web) company in my life where the cost of computing resources actually mattered, and compared to bandwidth, even that didn't matter.
The companies I have been at where computing costs did matter were doing extremely specialized, long-running calculations that are inappropriate for lambda.
I'm sure there are rare exceptions, but this all smells like premature optimization. Developer salaries are, 9.99 times out of ten, the cost you want to optimize.
Another area that this workflow really empowers is it frees you up to have infinite and arbitrary staging environments. In our case we have a GitHub action set up that creates a fully deployed version of the app for every PR automatically, and a bot that comments on the PR with a link to the deployment. You can of course do this with any kind of infrastructure, but only with a serverless sort of architecture is it virtually free to do this kind of thing. On the db side, we allocate extremely tiny instances so it is still quite affordable to just have one running for all of our branches. They are automatically destroyed when the PR is closed so the overhead is basically $5/month for each PR that is open for a whole month (in practice they are open for a few days at most).
This is an interesting use case, thanks for sharing although these days, setting up kubernetes environment emulators is supported by most CI systems out of the box.
With a spikey workload, it's almost always worth it because we have to scale up 1000x and then 10 mins later scale back down to 1x for the rest of the day, and this can happen any time of day randomly. You can also do this with load balancers but in practice I've found these to be much slower to scale and much more costly with the same workload.
For reference, 90% of our bill is database related currently.
Huh. With the context of the rest of the comment, I realize (the very obvious comparison) that a database engine designed to shard to many thousands of small workers could potentially be a very attractive future development path.
Iff the current trends in cloud computing (workers, lambda, etc) continues and some other fundamental doesn't come along and overtake.
Which is probably (part of) the reason why this doesn't exist, since I think I've basically just described the P=NP of storage engineering :)
> Huh. With the context of the rest of the comment, I realize (the very obvious comparison) that a database engine designed to shard to many thousands of small workers could potentially be a very attractive future development path.
Yes. I've been patiently waiting for the database community to realize this for the last 5 years now :)
I have no delusions I'd be able to viably make a dent in the area (at least anytime soon), but I do wonder how this would actually work.
The optimal solution would of course be to shard both the compute I/O and the storage footprint, so each worker only needed to hold onto maybe 1-100MB of data.
Perhaps some existing (simpler) designs could be modified to "hyper-shard" the compute angle, but would still likely require carrying around a large percentage of the database.
In any case, you'd need an internal signalling fabric capable of (cost-effectively) handling very bursty many-to-many I/O across thousands of endpoints to make consensus work in realtime.
It would honestly be really interesting to see how something like this would work in practice.
I have worked with many teams and found lambda to be by far more cost effective. Did your calculations include the time lost waiting to deploy solutions while infrastructure gets spun up, the payment for staff or developers spending time putting infrastructure together instead of building solutions, the time spent maintaining the infrastructure, the cost of running servers at 2am when there is no traffic. Perhaps even the cost of running a fat relational database scaled for peak load that needs to bill you by the hour, again even when there is no traffic.
Serverless as an architectural pattern is about more than just Lambda and tends to incorporate a multitude of managed services to remove the cost of managment and configuration overhead. When you use IaC tools like Serverless Framework that are built to help developers put together an application as opposed to provisioning resources, it means you can get things up fast and ready to bill you only for usage and that scales amazingly.
Funnily enough, I have made almost the opposite experience.
In my experience IAC and serverless bring all the troubles of dev ops to „regular“ developers. Your plain vanilla mid-level full stack dev now needs to understand not only a bunch about FE & BE code, but also a much bigger bunch about servers, networking, VPCs, etc. than in a non-serverless setup.
How do you resolve this in your projects? (Serious question).
This is such a big problem for some of the projects that they are now only able to hire senior develops (which brings it‘s own set of problems).
But VPCs and networking and distributed computing aren't serverless. Serverless is using AWS Lambdas or GCP functions and not dealing with VPCs beyond having an endpoint to hit.
There's not getting around the networking and such - that's the full part of full-stack (FS) - it's more than simply FE+BE. Maybe call them distributed systems engineers instead.
What it sounds like though, is your organization (regardless of what we call it) is large enough to organize into FE, BE, and FS roles, with FS running the platform and being in charge of the fleet and for them to work on the system itself so that FE and BE can work without having to know about fleet - and FS folk are building internal tools that the rest of the org use to do their job, and to shield them from any of the implementation details your fleet has.
Again though on my framwork-ification point -- in our case, we have a full VPC setup, and jets actually allocates the VPC for us we just configure it in our application.rb file. I'm sure the serverless framework has something similar. Either way, we have gotten away with not having a dedicated devops person or persons because of how much the framework does for you.
Yeah, framework-ification of this process has been the real differentiator in the last 5 years that has taken lambda from being obtuse and glitchy to work with to quite a joy if you just lean on your framework.
All of that said, I vastly prefer google cloud functions personally and would switch to that in a heartbeat if they had capabilities like API gateway but it's not there yet.
I also regret that there isn't a better cross-cloud solution currently, but that's something I have a lot of open source ambitions about creating soon. I don't like serverless that much so stay tuned for something from me in the coming years, probably in Rust.
They bill by the millisecond for usage now, which has helped bring down the cost a ton (at least for web services). And if you don't need fancy stuff, they have a cheaper version of API Gateway now too.
Lambda also supports Docker and is pretty damn fast now, so it's less painful to use.
Most seed stage startups don't even surpass the free tier in my experience, and depending on the product this can be true for a lot of Series A startups as well.
Needing anything more than a few seconds out of API gateway is just bad application design though unless we're talking about websockets or streaming as you said. If it's a webhook, you risk the client hanging up if you do all that work up front (you should instead be scheduling a background lambda that will do it based on the webhook params). If it's an actual user, I'm assuming you're not expecting to have a user wait 30+ seconds for a page to load, so probably some JSON API endpoint with a progress bar on the frontend. In those cases there's really no need to use API gateway as it isn't visible to the user anyway (you could just use your lambda naked in that case).
If you're talking about web sockets, yeah, I feel ya. I haven't had to navigate that situation yet but my plan of action is to bypass API gateway entirely and use a naked lambda running at its full execution time, and when we approach the 15 minute boundary, send a command that resets the connection. Don't know if it would work well but I haven't had a need to use web sockets for any projects I work on for a while.
For streaming, like you said, maybe an elastic beanstalk cluster is more the way to go depending on your workflow. If you can find a way to get it all to work in Lambda though, would probably be a game changer cost-wise I would expect as long as you figure out a way to deal with resetting every 15 mins.
I'd say it's still the case for the majority of the cases. Which is a shame, because I like this idea of having hw limits for your software and being able to efficiently maximise hardware at the datacenter level for redundant, trivial applications (like serving web requests). Most web servers are half idle "just in case" because hardware is cheap and engineers time is expensive.
I migrated some mid business (500-1000 people company) lambda setup to ec2 spot instances and a standard app and the costs dropped.
It would have been even cheaper on something like heztner, but good luck getting a buy-in from the infra team.
I venture most small businesses will have less load than them. Certainly it's not worth it for my tiny side businesses.
I was running some calculations for a project though, and if you "abuse" them with lengthy / expensive calculations run very infrequently (think like a cron job), you may end up being quite cost effective.
We trialed switching over to lambda for our worker queues just last month. We went for $500 a month EC2 costs (auto scaling spot fleet), to $500 a day.
So what I would say is, we've gone ahead and done a lot of the upfront investment of making Jets much more production-ready than it was a year ago. Pretty much every feature path a typical startup Rails app would hit, we've used in production with jets at this point (and in some cases had to get issues fixed, etc). We also sponsor the jets project at $1k/month, and have a great relationship with Tung, the creator of Jets. We're at a point now where we haven't had to get anything fixed for a few months, and everything is stable and working the way we want.
While we did have to spend some $$ to get things up to snuff (particularly so we could pass SOC 2), this pales in comparison to how much we would have had to spend to do devops and the usual server wrangling to get our use-case up and running in a typical elastic beanstalk sort of situation.
One area of difficulty was Oauth so if you ever need help implementing that in Jets feel free to reach out or read the public issue history of how we got it working.
Is there a blog post about the tech stack? My main concern with serverless/lambda is cold start time. How do you deal with it? What does the p99 latency look like?
Also how do you scale the usual bottleneck which is the database?
There is an auto-warming option -- we keep it warmed up every 5 seconds so it's always super peppy -- requests served within 100ms generally, sometimes much faster. Appdex hovers around 0.996 but some webhooks are included in there so it's probably faster in reality.
DB-wise we utilize the usual postgresql cluster setup with read clones in several regions. We could easily partition by course or by org if we had to but honestly we could probably scale up to series C+ before needing to do that.
Out of interest, have you considered moving to a "serverless" db like Aurora Postgres or even DynamoDb, to avoid the cost of unused database capacity at idle times?
I'd love to, but when I've tried to set up Aurora, it seems impossible to do multi-regional with postgresql (not multi-zonal, but multi-regional). Would love to hear how to do this if anyone has got it working. Last time I tried was about 2 years ago.
Ah ok, interesting - I haven't tried Aurora, my company uses a mixture of RDS postgres and Dynamo. Cockroachdb and Yugabyte also seem like good options but a harder sell for us not being AWS native.
More generally though, all of these "newsql" offerings feel a little too good to be true for me, I can't see how you could really have all the relational integrity of postgres with the elastic scalability of a distributed DB without trading something off. Am I too cynical?
I can relate. I was just about ready to exit programming until 2 things came along that removed all the analysis paralysis for me.
1. Elixir + Phoenix
2. TailwindCSS
Elixir because you can build a monolith with it and everything is naturally separated by design. The runtime makes it impossible to hurt yourself. It addresses virtually every web use case in an ideal fashion that balances development speed with long term maintenance and scalability because of the language design trade offs.
TailwindCSS because it removed the decision about which of the million frontend stacks in should be using. It makes it so easy to do anything I can dream up without feeling like I need to hire somebody to help with a pet project.
And honestly, even though I like DevOps and database work just using Heroku/Fly/Gigalixir so I don’t have to worry about it makes my life easier.
The type system problem is somewhat mitigated by ubiquitous use of pattern matching. In python, the function
def foo(mymap):
blah
Has no real information about what my map is. In contrast, a staticly typed language like Java would have
public static HashMap<String,Integer> foo(HashMap<String,Integer> mymap){
return mymap
}
which encourages you to have a lot of classes defining different types of things, which is rigid, but at least makes it clear what exactly the function is expecting. Elixir is somewhere in between, where you'd write
def foo(%{"username" => username, "password" => password}) do
{username,password}
end
which makes it abundantly clear what the function expects ( a map, with keys "username" and "password"), and handily unpacks those values for you, making it feel more immediately useful than "In the future it'll be nice to have more clear code", which helps with adoption.
In practice, the Python example is likely to have considerable information hidden in the “blah” from which existing tooling can often infer much of what would be declared in a language with mandatory explicit static typing; and it has existing tooling for optional explicit static typing, too.
So does Elixir with typespecs and Dialyzer, but I'm talking about quick, at a glance analysis of a function definition. Which is really the only benefit from a brittle type system like C or Java's, in contrast to a proper type system like Rust's or Haskell's, which have their place and cannot be adequately replaced merely with pattern matching.
Python 3.10 introduces pattern matching: I've not had the chance to really play with it yet so can't say how fully featured it is, but you can do something like:
def foo(login_data):
match login_data:
case {"username": "foo", "password": "blah"}:
return True
case _:
return False
In addition you can use type hinting:
def foo(login_data: dict[str, str]) -> bool:
match login_data:
case {"username": "foo", "password": "blah"}:
return True
case _:
return False
Unfortunately I don't think you can yet do the neat argument unpacking as per your Elixir example, but it's some of the way there.
I don't know that that's the big issue with dyanmicism, at least not for me.
In Ruby the main thing that bugs me once in a few months is a silly typo - calling a misspelled ivar or method. It happens maybe once in half a year but it's still humbling when it happens.
It's rare because usually your IDE is very good in spotting these mistakes - even in Ruby, and also decently tested code should break right away.
But I do wish and hope the tools will become better - whether it's Rubocop or something completely new, that the chance of this happening will be almost zero. It's not there.
I worried about this too, but I found that 90% of the places I want "types" are elegantly handled with pattern matching and what other langs would call "function overloading." I also love that you can treat structs like a map, which I feel is the best feature from javascript.
I feel there's more to the dynamic language world that's not clearly explained by the lack of types. I have used both Python and Elixir for production apps, and I get an order of magnitude more type errors with Python than Elixir, for some reason.
IMO it's a disservice to compare Elixir's typing to languages like Python, and we need a new category to distinguish the two.
The fact that there are a lot of standard behaviours (GenServer, Supervisor, Agent, e.t.c) and conventions followed makes this not such a big issue for me. Dialyzer is also a great tool which catches a lot of errors for me.
I'm in exactly the same boat, and hoping that others follow suit. It feels like "the good old days", but the community is still small and resources are scattered, so sometimes doing simple things mean a bit of trial and error at first. Still, it's actually been enjoyable again.
I agree that Elixir & Phoenix are the natural evolution in a post-Rails world, but looking further ahead, I think we've reached a point where the compiled & typed languages are starting to have all the goodies that used to be reserved only for the highest of the high level languages, and with web assembly support on the rise, it's going to start to become possible to use languages like this for both backend and frontend in a unified way. So for me, the next natural evolution is using something like Rust or Crystal but with very solid Railsy conventions and intelligent code sharing between frontend and backend. I think this combined with something like the Phoenix live view, but in Rust, is at least where I want my future to be, and I think a workflow like this could become the dominant pattern before, say, Elixir/Phoenix overtakes Rails.
I tip my hat though to people diving into Elixir --- it is definitely a cool direction and one I would follow if I weren't already so sold on Rust/Crystal/etc.
Well the game has also changed for dynamic languages. Writing JS or Ruby with a powerful IDE today isn't what it used to be 5-10 years ago and it will keep getting better. The tools and linters will become smarter about catching silly typos. It will never be like writing in a compiled language but the gap will narrow.
Also - I don't think we'll ever agree on any language. Sure, some languages will be dominant - Java maybe or Rust or whatever, but there will always be room for alternative approaches. Humans don't fully agree on much.
yes, it's true that with sophisticated gradual typing and expressive static langs, dynamic and static languages are far more similar than they used to be.
personally, I still enjoy the extreme dynamism of lisp and lisp-like langs (julia), but we may never see a resurgence of them in popularity
I get that for sure. I've been avoiding learning React because I keep waiting for the space to settle down. I was very interested to see how the Rails folks are talking about their latest version: https://rubyonrails.org/2021/12/15/Rails-7-fulfilling-a-visi...
In particular there's a theme of JS being totally optional: "Rails 7 takes advantage of all of these advances to deliver a no-Node default approach to the front end – without sacrificing neither access to npm packages nor modern JavaScript in the process." "The same approach is taken with CSS bundlers that rely on Node. [...] If you’re willing to accept the complexity of a Node dependency, you can pre-configure your new Rails app to use any of them"
That seems like a smart goal. They're not trying to go it alone, but they're clearly trying to draw some boundaries that keep the JS chaos/complexity at the edges.
React feels pretty settled now, it's been out for 10+ years, hooks and functional components have become the standard.
If you want to learn it I think it's at a mature enough place.
Popular libraries like redux have been rebuilt to use hooks and simplify the integration.
I'd also check out Remix[0] if you wanted to get into a React framework. It's fairly new but extremely promising and easy to get up and running and even deployed anywhere (express server, cloud flare workers, deno, etc)
> hooks and functional components have become the standard
Now if only the React ecosystem settled on standards too, that would be wonderful.
But alas. There is flux, redux, mobx, hooks, routes, sagas, thunk, observable, styled components, emotion, tailwind, react-antd, axios, fetch and so on and so forth. Edit: on top of, obviously, webpacker, grunt, npm, yarn etc.
Contrary to e.g. Rails, none of these come with React. You'll need to organize it all yourself (or go with something as react-boilerplate). You'll need at least some of these pieces to have something workable very early on. Things like redux or saga are not some "we've grown out of vanilla React and need additional tooling", they are essential to do things that practically every app needs: pages, communication with a backend, some styling, some consistency and deploying it to a public server.
There's a lot here that feels like you're purposefully conflating to make it seem more confusing than it is and a lot of what you mention is also an issue in Ruby on Rails. It's also a false comparison to begin with. Ruby on Rails is more equivalent to Nextjs or Remix.
When I had to learn a little ruby on rails I found the convention over configuration far harder to wrap my head around. It's quite nice to be able to see for yourself exactly how pieces are wired up and configured instead of having it magically done for you and dictated to you that it has to be done this way.
There are standards in some of what you mentioned. Mainly hooks, fetch, npm, and css.
Ruby doesn't "solve" css either, you're just using regular css files which you can do trivially in React as well (<Foo style={myStyles}/> and define myStyles as an plain old javascript object wherever you want - same file or not) or just include the stylesheet on the server response.
The rest of it, state management, webpack vs grunt, etc is pretty simple to select from and even in all that there are obvious choices - redux, webpack, npm that are certainly considered standard.
With rails, there are really only a handful conventions, and while they take a little time to learn (table names plural, model names singular, controllers plural, name view files based on controller/action, foreign keys names in the obvious way) and that's about it. Once you have that you can look at a URL and know exactly where the code is. That is really valuable and worth a little effort.
There isn't much magic in rails, and just stepping through the methods in a debugger makes everything pretty clear if you do want to know exactly how everything is wired up.
My point, however, was that this is not obvious for anyone starting with React.
This is caused by the fact that React is "no batteries included", which means that you have to find the right batteries at a moment when you lack all knowledge about batteries in the first place. You search "how to send to backend" and saga's pop up, explaining why they are better than useEffect or redux or whatever (at a moment you may not even know useEffect or its downsides).
Compare that to Rails which has "all batteries included" (and which is a nightmare in itself, too, though), where all those choices are made for you. You can choose to ignore Rails' testing suite and instead erect an rspec setup next to it, but you'll do so consiously. Because that moment when you asked yourself "how do I test in rails" the One True Way was there, configured, ready for use and documented.
Both have tradeoffs and pros and cons. But the React community (with tutorials, this weeks best practices, breakspeed iterations of tooling) is not helping here. At all.
Exactly. It's discussions like this that are exactly what I'm thinking of when I say that React still doesn't feel settled to me. There are quite a lot of people who say, "Oh, just do it this way". But I don't have much sense that they are all saying the same thing and will still be saying the same thing in a year.
There are some default choices in Rails that I disagree with. E.g., I think it's too database-focused, and I build things that often aren't. But I still know I can get started with Rails and expect it all to just work. I know that people with Rails experience will be able to jump in without much pain. And then if I depart from the standard path, I have a good sense of where I might get into trouble.
Working on a project with a significant number of sagas, I have to heartily agree with you.
There are some very clever things you can do with them, but this really need to know all the ins and outs of it first, and by the time you've learned them you implemented a giant nightmare.
We've been trying to generally discourage Redux users from using sagas in most cases. I've always felt that they were absolutely overkill for basic data fetching scenarios, and this is even more true now that data fetching libraries like RTK Query and React Query exist.
Where sagas _do_ still make sense is highly complex async workflows, including responding to dispatched actions, "background thread"-type behavior, and lots of debouncing/throttling/etc.
But yes, I've heard of plenty of cases where sagas made a codebase unreadable, and it's a shame that they get so heavily pushed by some early Redux users.
FWIW, I've actually been working on designing a new "action listener middleware" that we'd like to ship in an upcoming version of Redux Toolkit. It started off as very simple callbacks, but by adding a few key primitive functions like `take`, `condition`, and `delay` I think we've been able to to come up with something that can handle maybe 75% of what sagas can do with a much smaller API surface and bundle size. I'd love to have you or anyone else using Redux take a look and give us some feedback on the current API design and let us know if there's other use cases it ought to cover:
The last time I did web development, I used Angular 1.2 or something like that. I had some forms and many different views that talked to some REST APIs.
It was never clear to me why/when I would need React. I read and worked through some tutorials years ago, and while the reactive/one way flow pattern was nice, I never had a problem with Angular.
I recognize there have been many versions of Angular since then. And there are several web development frameworks, complex build tooling, etc. etc.
Meanwhile, I’m still writing services in Java that handle 20,000 requests per second for a service that brings in revenue in the billions of dollars a year. And I’m writing C++ (very straightforward, no templates, few uses of pointers, etc) for cross platform mobile code. I have some Spark pipelines all written in Scala.
Meanwhile the web stack continues to evolve… new technologies all just for rendering web pages. I don’t understand why. Admittedly there’s far more complexity in our use cases today than the HTML I was writing in 1999, but much of it is unnecessary bloat from bored developers.
Sometimes running into AngularJS was not too bad of an experience, since it's relatively simplistic when compared to what's needed to get it running (no complicated toolchain, such as with TS -> JS).
But most of the times it's a pain, because of it not scaling well to larger projects. I've actually seen projects where controllers grow to the length of thousands of lines because the developers didn't feel comfortable with introducing new ones in the pre-existing codebase, due to how the scoping works, due to how they'd need to set up the data models and care about initialization of everything, as well as custom integrations with validation libraries and other JS cruft (due to it not quite being "battieries included", like the new Angular is).
Now personally, i really liked how they did error messages (which gave you URLs that you could navigate to, with a bit of context in them; though it would be better with a locally hosted docs server), but a lot of things were awkward, such as their binding syntax: https://blog.krawaller.se/posts/dissecting-bindings-in-angul...
Luckily, AngularJS seems to finally be dead, so we'll get to migrate to something else soon, hopefully. And the projects that won't will be red flags enough for the people who don't like such challenges to turn the other way - truly a litmus test of sorts.
It hasn’t been out for 10+ years. Even if you count the prototype FaxJS predecessor it’s barely 10 years old, and that was only a Facebook internal project.
Any of them will allow you to build a complex system - vue, svelte, react and others.
It's more important to pick one and just get started with it. You can do some reading about how they're different or their different philosophies but they all work.
It's more important to get started. If you want to build something to learn a skill to get a job, react is the most popular. If you want to build something to learn something new, any of them are a good choice. Just get started.
Yea, I'm really glad they dropped Webpacker. It was the worst "Webpack abstraction" I've had to deal with, and the only documentation was always out of date and confusing.
I think it's important to be a little careful with the terminology here: JS itself is not optional, really. If you want in on Hotwire and the rest, it's inevitable that it's there.
What's optional is whether you need to use node or npm itself as a developer-facing tool, and needing ESM support in the browser for the way they've done it means it's only relatively recently that that's been practical.
Recently I switched back to Rails after 10 years. I can't say I enjoy the whole asset pipeline business but I yearn for a simpler time and Rails gives that (to a degree).
My only wish it was simpler to host. I don't necessary want to buy into render.com or heroku.
Why do you think it isn't simple to host? If you yearn for the simple times, no one is stopping you from just spinning up a VPS with Ruby, Passenger, Nginx and your favorite database.
Of course the larger your project is, the more hassle, but that's not specific to Rails.
I have been doing this for upwards of 10 Ruby projects for over a decade.
It is not simple. Python or Node.Js suffer the same issues, though.
Compared to dropping a go-binary or rust build somewhere and firing that up, Rails/Ruby (Rack, Sintra, Rails etc) are a mess.
In no particular order, the issues I had to deal with in the last three months:
* asset pipelines crashed randomly; turned out the ~2GB build VPS had too little memory to run the asset pipeline.
* puma and unicorn and phusion cannot be ran and configgured easily on one server.
* rbenv builds are hard to manage.
* getting the correct gems on your server is a mess. There is bundler, rbenv, vendored, rubygems.org, gem, Gemfile, Gemfile.lock, ruby-version in gemfile, ruby version .ruby-version, all of which can -and will- conflict at some point.
Add to that, that a typical Rails app requires at least redis, postgresql/mysql, quite some lib-x headers to build native gems, and imagemagick etc, and you have a very complex setup.
This isn't more complex than your typical Django, Laravel or ExpressJs setup. But it is far more complex than deploying a go, rust, or Java bundle.
This hasn't been my experience at all. Deploying Ruby-based projects in recent years is streamlined and repeatable. The term soup you're throwing out there makes me wonder why you're either overthinking this or not streamlining your own processes.
One cause of the problems is that the servers are handling multiple ruby deamons amongst which some Rails apps.
I know things get simpler when you keep "one app/thread - one server". But price-wise that doesn't make sense, especially since many common Rails apps hardly run on a the cheapest VPS (a throttled dual-core 500MB server). If you run ten tiny services, ten servers add up quickly.
I also host some larger apps on their own server, some loadbalanced over multiple servers.
But throwing 10+ ruby services on a VPS is hard. Especially if you don't want to, or cannot constrain their ruby-versions, app-server, etc.
It is hard for the exact same reason why setting up a local env may be hard. I recently had to help a co-worker on an old MacOS machine who broke her entire mac-desktop because she installed RVM because somehow that was in the tutorial for getting the app locally.
Anything with a runtime is harder than anything without that runtime. This is too obvious, but does warrant some highlighting.
Ruby's runtime is one of the hardest of all runtimes because it comes with so many moving parts. Python is a close second, and on Ubuntu (my main driver) probably worse than Ruby, because fing up Node is fine, but fing up Python can render your machine unusable, unrecoverable so without good understanding of all python things.
I started prebuilding assets in ci or locally and rsyncing to the server. Much faster and avoids the issues with constrained resources on the vps. Also saves me from installing asset-related gems and node modules on the server. Let me know if interested and I'll share my capistrano setup
I've been doing Rails for about 12 years and at our shop we have it down. `cap production deploy` and it's done. Essentially zero downtime for deploys.
Some things I'd note--
* Don't use puma or unicorn. Phusion Passenger and Apache is just fine performance-wise and is much more robust IMO.
* To avoid ruby version conflicts use .ruby_version as your sole source of versioning. I use this in all my Gemfiles: `ruby File.read('.ruby-version').strip`
* RVM isn't as popular as rbenv but it's amazing and you won't run into the issues you mentioned. It integrates with Capistrano and Passenger+Apache really well.
* 2GB might be a bit light for a production app even with light load. We start our new VMs at 8GB and then adjust up or down as makes sense.
We still do a single Ubuntu LTS VM for each app rather than anything fancy. Once you've added the stuff you need via apt it just works. Our sysops folks use Ansible playbooks that automate everything so there's no mystery when we need to do an OS upgrade or spin up a new VM.
I've been using Rails for 12 years, over at least a couple dozen apps. I use RVM to manage my environments, and use Capistrano to deploy. I've hosted on full servers, on shared servers, and on Heroku. With the exception of the classic bugaboo of getting the older execjs compiled in different environments, I have never had the sort of problems you say you're having trying to keep gems sorted. In fact, I would have said that was one of the stacks' greatest strengths, to keep that sorted out for you. I guess my takeaway is that RVM > rbenv, but I REALLY don't intend to start a flamewar about it.
And please don't try to tell us that a real-world Java web application is simpler than, well, anything. ;-)
Are you hosting multiple ruby versions and multiple apps on one server? Because as I explain below, that is the main (but not the only) cause of many issues.
Execjs, libreadline, libsqlite3, lib-postgres, (older)nokogiri etc. Quite a lot of the headers keep being a problem. Not major, often a mere ddg+apt-get away, but still annoying. It does get problematic when you have multiple apps depend on different libreadlines, for example.
And I'm not often deploying java, but at least the runtime and tooling has become omnipresent. The latest deploys were a mere "move all files there, and restart the service". With Rails you at least need to rebuild the gems.
Often java-services are an `apt get jenkins` away. There is no equivalent apt-get gitlab or apt-get mastodon that just sets up the stack entirely. But that is probably due to their popularity more than technology.
> And please don't try to tell us that a real-world Java web application is simpler than, well, anything. ;-)
Tongue in cheek, but honestly, that's probably debatable.
Under the hood, Java apps (at least in my experience) are Eldritch horrors with hundreds of beans/proxies/servlets/God knows what, needless layers upon layers of abstractions and dangerous amounts of reflection and dynamic behavior, all to launch and initialize a web application in a "simple" manner. I've always seen the exact same horror, be it working with Spring Boot, Spring, JavaEE, Struts, or even something like Dropwizard (though it seemed a bit more sane). Only the microframeworks seemed decent in comparison, something like Vert.X (has a different paradigm, though), or Quarkus/Helidon.
But when it comes to running them... well, historically they were still a nightmare, if packaged with .war and relying on certain application servers/JDK versions being present. But packaging them as executable .jar files (think Spring Boot) makes them similarly easy to Go, at least as long as you have the JDK version that you need. You just drop the file in a folder and if you have some configuration (which your Go app would also need in one way or another), you can probably launch it.
> I have never had the sort of problems you say you're having trying to keep gems sorted.
Ruby suffers from the same problem that Python, Node, PHP and other non-statically compiled technologies suffer from - messing around with dependencies. If i develop on Ruby locally against version X.Y.Z, but only X.Y.W is available on the server due to Debian packaging older versions, then i'll run into problems because of the project refusing to build/run. I've also run into situations where building the native stuff (DB drivers in this case) will fail, for example, when libpq-fe.h headers were missing and pg couldn't been installed, so the gem native extension couldn't build. Also, on Windows, Ruby 2.7 downloaded the sqlite gem with 3 different trojans (Win64.Alien.eg, Win64.Alien.ef, Win32.Agent.xahigh) in the extensions (btreeinfo.dll, memstat.dll, memvfs.dll), as picked up by Kaspersky. No idea how that happened, or whether that could have been a false positive, but i didn't appreciate that much either.
That said, i have a folder that has about 112 images of all sorts of software breaking in various ways to date, and the number is only so low because i don't screenshot things on my work computer and not even every small instance of something breaking. In my experience, all of the technologies out there are bad in some ways, it's just about identifying and managing these tradeoffs towards whatever is suitable for your circumstances.
Well... Java developer here, 20+ years exp... yada yada yada.. I haven't deployed a war file in over a decade. No you do not NEED a specific kind of server, just like any programming language there are LOADs of options for deployment. Nowadays we have an NGINX + Docker container. Image just contains an executable JAR. Without docker it is not much different, you just have a Spring boot executable JAR. But even if you loathe Spring, you can build an executable JAR using a build in webserver (Tomcat, Jetty, what ever).
For ruby, PHP and Python my guess is Docker is the solution as well. And if you are building applications daily with it you know the best ways of deployment. I think we should all stop bashing ANY programming language; they all have their key selling points. There is always someone willing to stand up against the bashing of their programming language their are working with.
I do not program in Java exclusively; I use BASH, Groovy, Scala, TypeScript, JavaScript, as well. I get angry at Node sometimes at well but then I remember that I do not use it nearly as much as I do Java...and go to stackoverflow...
> If i develop on Ruby locally against version X.Y.Z, but only X.Y.W is available on the server due to Debian packaging older versions
Either you use RVM locally to develop with Ruby X.Y.W or you install RVM on the server to use Ruby X.Y.Z there. Of course if the OS on the server is too old or too new there could be some versions of Ruby that won't work. It happened to me because of versions of openssl.
Docker is amazing for deploying things on servers and i use it extensively - nowadays almost everything on my homelab is containerized since i no longer need to have that many separate VMs anymore...
That said, Docker is also oftentimes a poor option for local development, unless you're talking about external dependencies the app needs (e.g. MariaDB/PostgreSQL, RabbitMQ, Redis etc.), or maybe very specific setups that just won't be achievable otherwise (specific userland needed).
For example, when trying to run Ruby/PHP/Node/Python/Java apps in Docker containers, i've run into the following:
- problems with file permissions
- problems with file line endings
- problems with Docker Desktop bind mounts (e.g. directory won't be mounted, path parsed incorrectly etc.)
- problems with Docker Desktop bind mount performance
- problems with networking (e.g. host.docker.internal sometimes refusing to route to non-containerized stuff on the host)
- problems with run profiles (e.g. your IDE + Rails integration just won't work, at best you can just launch a different container/Compose stack with some other parameters)
- problems with test runs and coverage (if you use the IDE integration, though that depends on the stack and how deeply your IDE is integrated, e.g. Java with IntelliJ IDEA)
- problems with remote debugging, breakpoints, flame graphs etc. (most of those either don't work when the code is inside of a container, or need additional setup, e.g. remote debugging, where supported)
In my eyes, whenever possible, develop locally with the native runtimes for the IDE integration etc., use Docker for deployment or maybe QA/test environments as well - anything that will go on a server somewhere.
I find RVM much easier to manage than docker, for local development. To deploy on servers, it depends. Deploying with Capistrano to one server is easier than building a docker container and push / pull it. For cloud / serverless environments... the number of companies that really need that is surprisingly low. Most businesses are small and are well served by a single VPS.
You should try phoenix and elixir, only been playing with them for less than a week and as a long time rails/ruby developer this is what it feels like again.
I bounced from Rails to Phoenix and couldn't be happier. I've done lots of functional programming before my Ruby days but never saw it coordinated in such a way that made sense to me. And since I only do web dev it was a perfect fit.
That said, I'm _really_ excited to get into all the goodness that Rails 7 has to offer. I really thought they lost their way with the whole webpacker debacle. I recently installed a fresh Rails 7 app and the word webpack doesn't even exist anymore! It's like a breath of fresh air to be done with that. Those were some dark days. (I'm exaggerating only a little)
I'm also a Rails dev, currently doing Advent of Code in Elixir, I haven't tried Phoenix yet, but writing Elixir feels a lot like writing Ruby for the first time. It's the same kind of sexy, of-course-you-can-do-that feeling.
For me Elixir didn't feel too much like Ruby, but Phoenix sure felt a lot like Rails. YMMV since Phoenix has gradually become more and more of its own thing than it felt like in 2016 when I learned it.
There's really nothing I miss about Ruby for web dev and Elixir feels like a complete win to me these days. Ruby is still far nicer for unix-y scripting, though.
Elixir and Ruby have nothing in common as languages and ecosystems, I really don't get why the 2 keep being brought up together. Oh I do get it - whenever someone mentions Ruby some Elixir user will say - hey have u tried Elixir?
Ruby and Elixir do have surface syntax in common, and Rails and Phoenix are clearly from the same conceptual direction. They're more similar than, say, Rails and Spring Boot.
This is not surprising: the Elixir folks were fairly high-visibility in the Ruby community before they did Elixir and Phoenix.
I'll give you surface syntax in common, other than that not much. I think a Rails dev would have a much easier time picking up Django or Laravel than Phoenix. How hard is the switch from Rails to Django? Probably trivial. But Ruby to Elixir is a mind shift.
Ruby to Elixir is a mind shift. Rails to Phoenix...I don't think so.
But most Rails programmers write Rails, not Ruby, and it's important to differentiate them. Ruby is a big playground. Rails is...not, by design. (This is why I do not like Rails, personally--if I am choosing to write code in Ruby, it's because I expect to need to get weird with it.)
Rails->Phoenix omits a lot of the stuff that makes Elixir cool, both in itself and in OTP, but that's not a bad thing and I do think the transfer isn't too onerous for somebody coming purely from Rails.
I'm really not. I've built tools and systems around Rails for a long time. Most Rails programmers I've worked with live in the controller and the view. Absolutely there are those who do not--and they're often building libraries and tooling for those who do. IME, at the hireable junior/mid levels, Rails driving is pretty tightly coupled to the framework--this is often a positive, to be clear, and not a dunk on anybody. This is the baseline way to get a web application out the door.
Roughly equivalent interfaces exist in Phoenix, and the mapping isn't quite 1:1 but it's close enough that the adjustment is an adjustment, I think, and not a re-learning.
I partly agree with what you're saying but still - you're exaggerating. Doing Rails without a decent knowledge in Ruby is exactly what you said - it's being a junior. You'll rely on the existing codebase without any ability to provide your own ideas, only shifting code from here to there without fully understanding what you're doing and will always need a senior whenever things go awry. That's what being a junior is like in any language.
I don't think we can compare languages based solely on the experience of juniors. I'm not saying it's irrelevant, it is, but it's only a part of what writing software is. In the end of the day you need the seniors and people who really get it to maintain the code and steer the ship in the right direction.
But I do agree that Rails is a kind of dialect of Ruby and that you can get pretty far with Rails without being great in Ruby (you still need to be decent though, no way of getting around that).
> Most Rails programmers I've worked with live in the controller and the view
Where is the business logic at? They also write services or something similar or stick it in the Model. Whatever isn't ActiveRecord will be pure Ruby - Rails has no opinions there.
> You'll rely on the existing codebase without any ability to provide your own ideas, only shifting code from here to there without fully understanding what you're doing and will always need a senior whenever things go awry.
Absolutely, and I would submit that this is most developers' experience up until a senior-ish role. Not title, you can have juniors doing this, but the pyramid of tool-users versus tool-makers.
> In the end of the day you need the seniors and people who really get it to maintain the code and steer the ship in the right direction.
Again agreed--but jeez, there are just so many fewer tool-makers at most places I've found myself. (This worked out great for me early in my career because there were tons of vacuums to start doing that work even in my first year out of college--building systems that other people could rely on to go faster, because nobody else was doing it!) Thinking about it, this impression perhaps sticks more because of the businesses I consulted for, which is perhaps where my perspective comes from--hiring uncritically 'til you're in a pit where you're paying the medium bucks to get somebody to come dig you out.
> Where is the business logic at? They also write services or something similar or stick it in the Model.
Found the guy who hasn't seen too many 10KLOC controllers in his time out there. ;)
You may be right that I am grim about this, but at the same time, reading your description makes me go "I haven't seen too many places that actually do-it-right". The truth's probably somewhere in the middle, and outliers exist on both sides. But yeah, I've absolutely been consulting for more than one company whose primary product was thin models, gargantuan controllers, and no service abstraction to speak of. They make a lot of money, too. (Fortunately for me, they brought me in for devops stuff, not "please save our megamonolith".)
> But yeah, I've absolutely been consulting for more than one company whose primary product was thin models, gargantuan controllers, and no service abstraction to speak of.
I don't get why this is still happening. It's kinda common wisdom now to not let your controllers get fat. I"m not saying that fat models are great but as a community we kinda agree that most business logic stuff is easier tested on the model/service and should be placed there.
CTO's/team leaders have to be real sloppy to let teams build code as you describe At the same time - being a consultant, don't you more often than not see codebases in bad state? I mean those are the ones that usually need consulting. So maybe you have an overly negative view on how Rails projects usually look.
> Rails->Phoenix omits a lot of the stuff that makes Elixir cool, both in itself and in OTP, but that's not a bad thing and I do think the transfer isn't too onerous for somebody coming purely from Rails.
I'm not following you here. Could you please explain your position a bit more?
The reason I'm confused by your commentary is that Phoenix makes extensive use of OTP and since it is just Elixir + macros, there is nothing at all limiting you from employing every Elixir (and Erlang, for that matter) feature you want to in your Phoenix apps.
Sorry - omits is the wrong word, because of course Phoenix uses that stuff. More that in my experience, for the kind of "in the framework" developer that I've run into in the Rails space, the mapping to using Phoenix is very simple and doesn't demand of the end user the conscious use of processes, genservers, etc. -- it can, and from POV often seems to be used as, plug-and-chug. This totally isn't a criticism either, I want to stress; it's the mark of a good framework, that you don't necessarily have to care about that stuff to ship a thing.
At my current company, we use Phoenix and we use a lot of its bells and whistles. But we also have a lot of people who understand OTP--definitely way more than I do. I also see people ship Phoenix apps without getting deep into that when their needs are relatively small.
> Rails->Phoenix omits a lot of the stuff that makes Elixir cool, both in itself and in OTP
How do you think Phoenix could better take advantage of Elixir and OTP? IMO, it already is doing plenty to take advantage of what's cool about OTP, through channels and especially LiveView. I suppose Phoenix apps could use Mnesia instead of relational databases. But would the benefits actually outweigh the costs?
I have extensive experience with Elixir/Phoenix, Ruby on Rails, Laravel, and Django and I have to say I disagree. Rails and Phoenix are both opinionated in similar ways, both have similar generators, both have excellent/similar tooling, and many of the same ideas exist in both (e.g., Channels and Action Cable). I view Elixir/Phoenix as a natural evolution of Ruby/Rails.
The creator of Elixir was on the Rails core team and involved in the Ruby community, even for a little while after Elixir was released (until about the time Phoenix came around). The Ruby community is where Elixir gained a big chunk of its initial attention from.
That doesn't mean much. He came from Rails and then switched direction to a functional, Erlang based new language. The historical "initial traction" also doesn't mean much.
The two languages aren't similar at all.
Even 6 years ago when I started, you could just run it in production with `mix phx.server`, much like running `rails server` and use the exact same deployment patterns. Or you could build a release and copy it up to the server however you saw fit. At that time it was painful for some coming from different habits that involved pulling in config at run-time rather than compile time, but those patterns have also been supported since at least 2019.
Since then, the team has been continually making it easier.
I've just tried heroku so far and took me about 30 min to deploy my prototype, but I read there are limitations. Go take a look at fly.io and I think there's also another one that specialize in elixir hosting. Once I understand elixir/erlang better, I will probably want to host there.
I got around to trying https://render.com/ recently, it's also pretty easy and cheaper than Heroku, I think they support Phoenix/Elixir but I've never used it or tried. Also side note Heroku seems to have just stalled and atrophied as a product since the Salesforce acquisition, still one of the easiest hosts though.
I generally use a VPS, but Render is a top-notch host if you want something managed. In many ways, I think it's like Heroku was before Salesforce bought them.
what type of results do you imagine you'd get for that kind of query rather than what you'd want to get? especially given the context of postgres extension, i'd assume if there was content out there that google would find it with that query.
A friend of mine who worked at an SEO agency once had a client who's company name was a misspelling of some noun that google would automatically fix which i found hilarious.
https://www.gigalixir.com/ is likely what you're referencing. Since they're focused on Elixir first it supports a buncha the nice things the BEAM supports, such as native clustering, hot upgrades, and opening a REPL to a running cluster.
I've deployed Rails at a few different companies. I wouldn't quantify it has hard by any means, there's just a lot of configurations to read through and verify every time. Realistically, the defaults are complete sane and could be deployed as is without much change.
at a base, you can use heroku. That said, you won't be able to have your nodes communicate with each other. This restricts you from some of the more advanced featues. For Example, at my startup, we use horde to dynamically spin up individual websocket connections per customer for a integration partner. This was easy to do using horde and simply connecting the nodes together. Additionally, we can use the built in key store which is global to the cluster.
I would take a look at render.com. they support connected nodes and autodiscovery
It really is a nice experience. The BEAM family of languages was the first for me where doing multiple things at once came natural. It doesn’t require pulling in a library or adding redis or having to worry about shared state. You just add a process to a supervisor.
Yeah and then how do you deploy new version? In practice you still need Redis for most stuff.
Also if anyway you have to deploy containers then value of BEAM is dimnished and provably better go with Go.
Could you be more specific about the issue you're having with deployments?
I've never used Redis in any of my Elixir/Phoenix apps. In cases where I might need something like Redis to store state, I'd reach for a GenServer or maybe Mnesia instead. I've never had an issue with deployments using this strategy. Also, K8s and BEAM work together just fine using libcluster. I'm not a fan of K8s or Docker and don't use either one, but you easily can.
The benefit of BEAM is that it can surgically handle a vast array of failures without restarting the node. K8s, on the other hand, will take the pod down and restart it. In many cases, solving a problem with BEAM is like using tweezers to remove a splinter whereas K8s is more like using a sledgehammer.
You don't need Redis if you learn the BEAM and OTP. Elixir runs on top of a distributed VM with builtin clustering. Use it.
And I see nothing wrong with having the BEAM run in Docker or K8s. There's some overlap in concepts, but they work at totally different layers. Using the BEAM is like having resilient microservices _inside_ your app with none of the downsides.
as someone on his 3rd year on a startup built on elixir, you're making the right choice. Our system is faster than an equivalent node setup while building features is almost as productive as rails. In some ways better. Plus, if you're goal is realtime or anything heavily websocket based, its going to easily outperform node or rails.
I simply cannot understand why people care about "fast" anymore with cheap containerization, CI/CD infra and no more dedicated servers. Who cares if its fast? Just add another box. I have this suspicion that anyone who still cares about backend speeds is stuck in the vertical scaling mindset where they need to keep adding cores and processes to a single machine
Not everything scales horizontally. Your database for instance is going to be scaled vertically to its max long before you think about using federated write servers. Sure you can use planetscale but that comes with its own considerations and tradeoffs.
Also, higher performance translates to lower machine costs. Our server costs would easily be 4x if we ran rails. given that elixir is 80-90% as productive for writing code in the short term, its a fair deal. Over the long term, we've found elixir to be more maintainable since there's very little magic and the immutable data structures and lack of magic make it super easy to debug.
Thanks to the performance of our system, we've also managed to get by without setting up caching. (we'll probably need it eventually but our performance gains have come mostly though fine tuning our sql queries. Ecto gives us way better control over the output sql than active record or sequalize)
A lot of engineers take great pride in improving performance even if it's mostly meaningless to the company. The users don't really care if the number of instances went down from 30 to 20.
It is what it is, engineers will be engineers.
>I simply cannot understand why people care about "fast" anymore with cheap containerization, CI/CD infra and no more dedicated servers. Who cares if its fast?
People who pay for those extra boxes? Not everybody has your budget (especially when they're building things themselves, on the side, so they aren't even paid).
Ok? That's a non sequitur. No one is forcing you to buy a dedicated server for $1300 a month which probably has the same performance as $250 worth of separate boxes. And separating services isn't what we're talking about here. It's adding horizontal processes across machines instead of on one machine.
It doesn't. They mean "fast" as in one box can handle more load which in their opinion is cheaper because you don't need to containerize and horizontally scale. I find that unlikely.
What's Phoenix/Elixir like for deploying these days? When I last seriously played with it a few years ago the development was a lot of fun (and Elixir has influenced how I write and architecture on other platforms) but I remember deployment to production being a pain.
I think it can be simple if you keep it simple :). In my book Deployment from Scratch I show people how to run Rails on a cheap VPS with a couple hundreds lines of Bash.
You're welcome to adapt the AWS deployment scripts I setup for Haven[1]. I tend to adapt them when deploying other personal projects like the sites I've built for my family tree or privately hosting/sharing old family home movies.
Python/Django developer here, but I've found Digital Ocean+Dokku to be a pretty decent cheap alternative with more flexibility than Heroku, especially for an early-stage side project where a single server is enough for your needs.
Take a look at Cloud66. Been using it for every project over the last 10 years or so... It's like Heroku except you can control a lot more and not get locked into "enterprise" pricing when you need to scale or simply don't want to expose your database to the open internet (imagine that).
Check out https://www.hatchbox.io/, it lets you easily host stuff on various hosting platforms (using your own account) with similar ease to Heroku. Which also means it's WAY cheaper. Heroku's pricing has always seemed insane to me.
I think it used to be harder to host than it is now. I think the only thing that might be hard now is sifting through all the tools for hosting and the analysis paralysis that can come with that. Heroku can get pricey at scale, but heroku and others are options that make it dead simple. Then there are a ton of options for how you might want to self-host. There are plenty of guides for getting docker setup with it, opensource heroku-like alternatives (most using docker under the hood), and plenty of resources (maybe too much).
I've had good success on my side-business with Piku: https://piku.github.io
It's essentially a lightweight PaaS that you can run on your own hardware (even ARM)
I have been using a software called dokku for about six years. It‘s like Heroku, but you self host. It even uses the same buildpacks.
You just run the dokku installer and off you go.
If you don't mind hosting on AWS, Elastic Beanstalk is a pretty streamlined way to host Rails apps, and it doesn't cost anything more than the AWS resources you consume.
Just that React, Webpack, graphql backends and millions of other packages and pipeline tools are on npmjs.com does not mean you have to use them. You can still create super-slim, to the point, and timeless backends using express.js (which was inspired by Ruby's Sinatra after all) and vanilla frontends. Doesn't get you brownie points on your CV though, which I think is the actual problem.
That, and the OP mentions they have a business background. If you don't come from a "how to write code starting with no batteries, forming your own opinions, etc", and all the tutorials are "you need to put some spaces before a string? We'll include leftpad!" style dependency hells, I can see Rails feeling like a breath of fresh air since it's batteries included, and heavily opinionated.
True, as long as people mindfully not using them drive the team. But the fact that "they are there" - and the fact that visible folks in the community usually either make the tools or endorse them (no wonder because they have to do personal marketing) means that it only takes that many new team members until every one of them regrets "not having" their favourite mini-tool used on that particular team, on this particular project. It takes extreme will (and some unpleasant conversations) to drive against that trend, and in the end folks might leave because of being denied using what they would like to try. So while you can "not use" all the new fancy tooling you will have the weight of convincing your peers that they do not need them either.
By contrast, Node was a breath of fresh air for me. With Rails, you had to start with this already complex system and bend it to do what you want. With a greenfield node server, it only does what you tell it to and nothing more. No surprises.
There's a tool for every job, but for most of my use-cases, I'd rather have a webserver which is just a webserver, and get my front-end elsewhere. But I'm sure there are places where Rails is a great fit in the right hands.
I'm not even using node very much these days. Serverless is what I would reach for for most professional applications these days.
Suppose you have been given 100,000 developers to work on a website, but it will have millions of customers and things cannot fail.
Now it is actually useful to be able to parcel out the database layer to a group of 1000, and they can split up each service into groups of 100 etc.
There are enough people to decide what conventions, logging, validation people ought to use and perhaps measure them. If all of them hack on the same Rails codebase they might be running into each other all the time.
Of course, for a solo developer, it makes sense to use Rails/Django/etc.
Now there is a little spot in between 2-99,999. It is possible that there is a team or two at this level. And I think that gear shift or pathway has not yet been discovered. Typically you start on rails, suspect you should switch and then switch way too late.
This is an interesting example of the 80-20 rule (or some variant of it)
The vast majority of businesses/projects are small, and will only have one or a small number of developers working on it. So Ruby on Rails (or PHP or Wordpress) is a suitable choice for maybe 80% of projects.
At the same time, a very small number of businesses require 100,000+ (or even just 1000+) developers. These businesses, because they have so many developers, employ the vast majority of professional developers. Thus, maybe only 20% of professional developers work on products that are typical of business needs.
This disparity explains why communities on Hacker News are typically so negative towards Ruby on Rails. It also explains part of what makes Ruby on Rails so remarkable. Even after all these years, it has a thriving community and has resisted the pull to become more "enterprisy." It's still a tool that is targeted at and well suited for a large swath of business cases, the vast majority of which will likely never need to migrate to something "better".
Excellent advice! I recently worked at a company where the "architect" insisted on using Broadway and Kafka for what should have been basic CRUD operations.
That's refreshing to see. In a lot of startups he would've been promoted to some high level position, hired dozens of engineers to maintain the new monster and then invited to an AWS conference to brag about how they solve their (self-inflicted) problems, all while the business is bleeding money in cloud bills and engineer salaries.
> I ended up spending more time on tooling setup than actual business logic.
This is exactly why, in 2004, I moved from Java (Struts/Spring/Websphere/XML/...) to Rails. History repeats but we never learn. Kudos to Rails for remaining relevant.
A big project in any stack has many problems. Vanilla Rails is going to scale way better than some wacky bespoke configuration of stitched-together NPM packages, which in my experience is what a lot of folks build now because they don't know any better.
I've successfully run Java/Go projects with huge amounts of code without a lot of degradation in any direction whereas Rails seems to quickly come to a stopping point compared to other platforms. I've written my side project which is now at a huge size in Elixir, I'm yet to see any degradation so far. I'm sure Rails would have been a pain by now. Sorry I don't have much Node experience so can't comment.
Simply hasn't been my experience at all, and I've worked with numerous Rails projects large and small since 2008. If you prefer Java/Go/Elixir, knock yourself out, but I'm throughly satisfied with Ruby-based solutions.
Got it. It's not impossible but I've been at multiple jobs involving Rails monolithic apps, they all really sucked from a maintenance and development perspective.
P.S would have been happier if you had a better choice of words than "knocking myself out".
Yes, I’m at one of those companies now, spaghetti code galore, and the project is becoming increasingly harder to maintain.
As the company scales they really need to break things into more services to distribute work and satiate work happening in other languages, but now that’s nearly impossible because of the mess they’ve created
Rails is great if your building a basic “dumb” web app, but rails folks seem to think it’s more than that and need to get their heads out of the clouds
I've worked on a lot of legacy Rails apps. Most of the problems of "spaghetti code" occur because people write bucketloads of un-Ruby-like code that betrays a serious lack of understanding around how Rails really works. Whenever I hear "aw man, Rails sucks. I switched to writing (X) in Rust/Go/Haskell/TypeScript/whatever…"
Let me stop you right there. If you tell me Rails wasn't meeting your needs so you rewrote (X) in a different manner using Ruby + something else, I'd totally understand. Otherwise, all it tells me is that there was a tragic lack of deep Ruby knowledge, respect even, to begin with as the project unfolded. Often I muse on how in some ways it was unfortunate that Rails became such a darling in the startup community early on. It meant that a ton of people jumped into Rails web dev thinking they were writing "Rails". No, you're writing Ruby, and Rails just provides a nice set of base classes and some decent defaults and assumptions. If you end up with a giant wad of spaghetti mess, that's on you. It's totally feasible not to end up there, and plenty of projects end up in far better shape.
It takes a lot more effort and housekeeping in Rails to make it scale well. When Github was built, Rails didn't have many decent alternatives. As of today there are a good number
> It takes a lot more effort and housekeeping in Rails to make it scale well.
It takes increasing the number of pods on your k8s which is how almost all teams deploy nowadays. Bigger amazon bills yes but the devops overhead isn't really larger in Rails,
I knew a few people at university, who were pretty hyped about it. That was in 2008, I think. They used it at some companies where they jobbed and found it too limiting.
I was building customized stuff with bare PHP in those days and found it quite flexible. Later, the Rails hype came to PHP, but I already left for Node.js and never looked back.
GitHub and GitLab use Rails. Many UK government websites do.
Like anything else, Rails is good for some things & terrible at others. Rails tries to minimize developer time, at the cost of computing time (Ruby is not a fast language), and focuses on CRUD-type applications. Whether or not that's a good match depends on what you're trying to do.
Out of those, though, I have to blame document DBs (and the start of NoSQL craze) on Rails :(
To cut a long story short, Active Record (especially at the time) wasn't super keen on generating super good SQL that would do as much as possible in database, and Ruby 1.9 arrived with stable ordered hashes. Then someone implemented basic ActiveRecord wrapper on top of key/value store (I think it started with Berkeley DB or similar), and from there NoSQL was off to the races as "new hip thing"[1]
[1] Meanwhile IBM IMS has been selling pretty well for last 40 years at the time ;)
ActiveRecord was, even then, a much better ORM than exists in the Node world today. It was full featured and well hardened, and required basically no setup other than a class declaration. Plus, you could always drop down to the SQL if you needed to. Generally, it was a joy to use, and the performance was usually good enough.
At some point, I gave up on even trying to use any Node ORM's because they were clunky and offered no value. It was easier to just drop straight to a knex session and write the queries natively.
Oh man, so much this - TypeORM is such a disaster when you know how to write SQL. So many times fighting with TypeORM I thought “I’d be done by now if I just write the SQL directly”
Objection (knex-based) is well designed and maintained. It clearly takes inspiration from ActiveRecord. It's light-years ahead of Sequelize in usability and footgun avoidance.
I don't fully understand your argument. Document DB's never fully got traction in the Rails community. Then Node.JS became popular because it did concurrent IO better, and it put document DB's front and center for no apparent reason.
It didn't get a lot of traction because it required some effort, but essentially the groups that jumped on them were also highly correlated with those that soon jumped to NodeJS, helped along with JSON serialization being rather obvious in JS context
Though I would also consider their exodus to be a good thing for Rails ;)
They were only a de fact web stack at certain types of shops, I have been doing Java, .NET and C++ all along, Rails came and went, and I kept doing boring technology.
I guess by now Rails could also be considered boring technology.
It is tiring to keep track of latest fads, specially those that don't happen to stick around, so only move when dust settles down.
Yeah one might lose business opportunities from not being first mover, on the other hand, there are business opportunities to port back the surviving projects into classical development stacks.
For me, still much better than dealing with management.
Sounds like the managers that came before you failed you! Not to sound accusing but if this happened with multiple jobs then maybe you could have asked more questions at the interview stage. You can usually see dysfunction like that a mile away.
There's no need to chase the latest Node JS shenanigans. It feels like it's all we talk about on HN but a huge, huge number of developers are out there happily coding away in Java, C# and all the rest. Even within Node world the majority are using the exact same React stack (the homogeneity of which is the reason for using it in the first place).
IMO Ruby has faded because it never found its niche. Java and C# thrive in the corporate world. Python already exists as a dynamically typed server language. As much as people complain, writing server-side web stuff in JS does make sense given it's what you're using in the client. So where does Ruby go?
The language is less important than the supporting tooling. IMHO we are just now, a decade later, seeing frameworks crop up in node that look anything like the out of the box usefulness that was the rails and django apps I was first exposed to. My honest opinion from several startups is that most sub ten year vets just don’t know that stuff existed already and / or just how much you can ask of your tech stack. I generally agree with your point though.
100% this. I've always said that the ecosystem, the tooling, the editor support, the libraries, the frameworks and the availability of people to hire are far more important than the language. For example it irks me when people say they like react because jsx or Vue because templates...that's the smallest of the reasons to choose one or another!!!
Same thing with Rails/Laravel/etc...people don't choose it because PHP or because Ruby , etc...the language doesn't matter at all, the tooling does matter it all.
Ruby's has been startups—Stripe, Coinbase, Instacart, Teespring, Podia, Twitch, Gitlab, Github, etc... despite never having been the most popular language or even close, it's been absolutely dominant as an initial back-end language for top-tier startups.
>IMO Ruby has faded because it never found its niche. Java and C# thrive in the corporate world. Python already exists as a dynamically typed server language. As much as people complain, writing server-side web stuff in JS does make sense given it's what you're using in the client. So where does Ruby go?
In the web server side, helping you build web apps faster. That has been it's niche (with Rails) and it's still doing well there.
> Python already exists as a dynamically-typed server language.
Ruby isn't new; it's only slightly younger than Python, and brought things to the table. Rails and Django are roughly the same age (and Django started off more as a CMS). That Python exists isn't an argument against Ruby. Lots of other languages exist, each with their own cost/benefit tradeoffs.
> [...] writing server-side web stuff in JS does make sense given it's what you're using in the client.
I don't understand the argument. Matching client/server language is a different goal than matching task/language, and the task isn't the only driving factor.
There's some crossover in that the language is the same, which means you could standardize on JS developers, but the ecosystems are not the same, and the required overall skillset is different. In wee shops the tradeoff may be worth it, but at scale, the benefit is oversold.
> JS does make sense given it's what you're using in the client.
Well JS is forced upon us on the browser and not everyone is tremendously happy about it. It has improved, but still. Plenty of folks out there will seek other languages, we will never all fully agree on what's good on the backend.
BTW - are we positive JS will have a monopoly on browsers 5-10 years from now? (I'm talking about WebAssembly). Cos if the monopoly is gone JS will die a violent death I think.
> BTW - are we positive JS will have a monopoly on browsers 5-10 years from now?
Yes.
I will assume your question arose from the exuberance of youth.
"Good enough" + inertia = Yes
It's not enough to be better; it has to be so much better, existing infrastructure and training must become moot. And preferably an obvious best to avoid balkanization.
See: Fortune 500 and their continued reliance on COBOL and mainframes rather than opting for replacement and retraining costs.
Ruby captured a lot of webdev market before python became mainstream, and you can see it in the maturity of the tools around this domain (ruby's way more evolved). The tables turned because python became the de-facto ML language, and everyone and your engineering manager will be afraid of betting on anything other than python in fear of hampering future ML-based optimizations (which is in practice utterly wrong, but try tell that to management...)
Agree! But isn’t it kind of weird that we accept that ml happens only in python? I’m biased because I’m working on a startup that makes machine learning sdks in ruby, elixir, golang, php, JavaScript etc. Also, to clarify what you are saying, you think companies are choosing to write their entire stack in python just because ml tools are in python?
> you think companies are choosing to write their entire stack in python just because ml tools are in python?
Going with the masses (e.g Java/Node/Python) is the easy thing to do. It feels "safe". But who knows where Python/Node will be 10 years from now, people are restless and will come up with new things (Deno?) and it could be they will start declining.
Java is pretty much unavoidable though.
Eh I’ve been down this road and the tooling in python is just so evolved it’s hard to replicate. Julia is having a hard enough time, I see ML libraries pop up in other languages and they usually simmer out or are used by hobbyists.
As an ML engineer it’s really hard to justify spending your time in a language you will be handicapped by instead of just using python
"the popular tech stack shifted": this says it all.
Choice of a stack shouldn't be about popularity but rather about meeting the cultural,organizational,functional and non functional requirements of the solution.
I said it already and I will continue saying it: our industry is driven more by fashion rather than good engineering practices. Every new trend solves a problem of the old generation but also introduces additional costs and new trade-offs. Adopting something blindly is not a good engineering approach. Software engineering is the art of balancing carefully your trade-offs and not to go with the latest fashion.
> and have the same tiring conversations about naming conventions, logging, data consistency, validation, build scripts, etc.
Sounds like bike-shedding to me. Eg. You start with solving trivial problems instead of the hard problems.
Usually the first thing that is decided is what framework to use, often by a non technical person that herd from a friend that is was good. Rather then having the engineers sit down and think about what are the biggest challenges, and what is the best framework suited to solve the hardest problems.
Because of this unnecessary complxity in the webdev ecosystem, I switched my development career to other areas[^]. If I have to do webdev for a hobby project, I use Django and Postgres, with no JS frameworks whatsoever. It's liberating and fun.
[^] Mostly data engineering at work, and low level os/system dev in my spare time.
I hear ya. I perversely yearn for my days with Perl and CGI::Application. When I get up in the morning my eyes just happen to land on a stack of O'Reilly Perl books and it sets me off.
Ditto for me except swap RoR for PHP monoliths. Gone are the days where my only cognitive overhead was deciding between Less or Sass and CodeIgniter or “the fancy new” Laravel. Likewise I got fed up of where dev was going in the workplace, and moved into a Solution Architecture / Product Manager role. I still get a lot of satisfaction creating side projects in the tools of old (which IMHO work much nicer than 95% of “modern” applications), but thinking about doing development in my day job would give me a headache from the outset.
> I eventually gave up and switched to a semi-technical product management role.
Could you let me know what your job title is - I am looking for something similar where I would like to work on some semi technical stuff and at the same time manage developers but not sure what title I am supposed to look for.
Search for "Project managment". There is "Product management" which sounds similar but it's a bit different: project manager talks with developers and manages task complition while product manager talks to product owner(and other business people) and team lead and manages product money making and overall future strategy.
“Solution Architect” is normally the role that lies between Product Owners and the Dev team. It’s somewhat technical, especially if you don’t have a Technical Architect counterpart.
I like monoliths... which are modular inside... no need for microservices, easy deployment even without Docker and Kubernetes... just a single binary...
I started as a rails developer. This is just looking at the past with rosy lens.
Given the popularity of rails at the time, if node.js was unproductive like you say it is, it would have never caught on.
The reality is that express was considerably simpler and easier than rails and that's what made many of the internet companies we have today even possible.
Node productivity changes after a few years, I can give you examples from my work from this week (no internet stories) where the npm packaging bullshit wasted my time , and I just had to hack my way for a fix and postpone the inevitability that a giant cleanup needs to be done in our dependencies.
After the sit I seen with my own eyes(not internet stories) I am convinced that there are packages like "red" that defines the color RED="#ff0000" and a package colors that depends on all colors, and probably a few big dev tools that depends on the colors one, this node/npm ecosystem is crazy but we are paid to maintain and fix other people stupidity.
EDIT forgot to mention why stuff gets complex after time,
you hit cases where you need to get a new version of package A , but A needs say a new node version or some new other shit, but you have a package B that will fail on the new node version with some stupid error, and package B was abandoned or the fix is to upgrade to a new major version... also you will notice that your packages are now abandoned and might have security issues when you inherit some old project , it is a big mess.
For some reason I inherited a project that has tons of such packages, this include popular at that time frameworks and dev tools. Din't leftpad prove that the node community was and still doing this bad thing. Sure I have the option to have 0 dependencies but if you inherit an old node project the chance the project depends on a few bad packages is 100%
Have you tried implementing a well structured and well developed migration system for node? How about a unified folder structure, best practices and patterns? Scheduled cron jobs? Templating and asset bundling? All of this came with Rails out of the box with sane defaults.
I guess I should be thankful re-inventing the wheel on all of these aspects in node has given me hundreds if not thousands of hours in compensation.
For sure. The longer somebody has been coding, the more examples they can list where the worse technology won out.
Exhibit A here is the JS language itself. It became popular not because it was the best language, just the most ubiquitous one. You could read the 25 years since as trying to turn it into a solid language.
Or look at the rise of PHP. It started out as a tool for making a Personal Home Page, which is a fine use case and was certainly a popular one in the mid/late 1990s. It eventually turned into the foundation for one of the world's largest companies. But nobody can argue it was a particularly good language. E.g. https://eev.ee/blog/2012/04/09/php-a-fractal-of-bad-design/
Same thing with Java, really. Bunch of interesting ideas, some of which worked out and some didn't. Even at launch a lot of the things that have turned out to be problems were criticized. They say that Java is the new COBOL, and that seems pretty fair to me.
I could go on all day. The most popular technologies are not always the best. That applies to movies and music and pretty much everything. And personally, I've accepted it. It's part of how the world works. The trick for those of us who like "better" things is to figure out how to get them to become mainstream.
When all dimensions are considered, the better thing is the thing that wins.
All the counter examples in other replies focus on one aspect of a piece of tech that was bad while completely ignoring the rest. Php might have been bad as a language but for its time, it was easier and more productive than the alternative (J2EE): the better thing won until it was supplanted by something better.
That is an error in the other direction: focusing only on a single good aspect of a piece of tech. PHP wasn't up against J2EE in that first wave, it displaced perl and cgi-bin. And the only thing it had going for it was easier deployment. Arguably first-class templating too, but I don't think that was the killer feature, and really perl wasn't that far behind. Perl had better OS support, a massive ecosystem that PHP didn't catch up with for about 15 years, and a community that actually cared about code quality. And it was renowned as a "getting stuff done" high-productivity language.
The easier deployment story for PHP3 meant you saw massive expansion at the bottom of the market as cheap webhosts were able to offer very locked-down accounts for peanuts, which meant a generation of developers came along whose only experience was with PHP. They didn't have anything to compare to and nobody was really offering them anything else at anything like the same scale. The virtualisation revolution hadn't happened yet, so these were all shared accounts on physical boxes, and they couldn't install their own stuff either.
It's just not reasonable to say PHP was "better" except in a very limited, and largely accidental sense. It just so happened that that one advantage was enough to catapult it into first place.
Is express still easier than Rails?
Im a noob and the reason I’m asking is that I’m getting somewhat stuck with a project in spring and I find their docs very fragmented and the community is more advance/intermediate or business oriented.
It’s just me building this and I have no one in my circle that’s familiar with spring.
I've been a software engineer for 32 years (I'm in management now, but I still write non-critical-path code). During my career, I've used Express, Koa, Rails, Django, Laravel, Pyramid, Sinatra, Flask, Pedestal, Luminus, Phoenix, and several other backend frameworks. If I were starting out as a "noob" today, I'd learn Elixir and Phoenix.
I have spent a lot of time with node(express), Java(Spring) and rails. I see a lot of complaints about node, but node with typescript has been a joy to work with. It is lightweight and has a type system. I know where every piece of code is coming from, there is no magic involved. I either wrote the function in that file, I am importing it, or it is a method on a js object. I only have know one language for both front end and back end. A better standard library would be nice.
Rails is nice in terms of getting the project set up, not bikeshedding about the tooling, and working with the db. But the actual coding has been painful for me. I really dislike working with a non typed language. I dislike optional parans in function calls and optional braces for hashes. I dislike all the magic of rails. I never know what is going on because there is some functionality that inherits from a rails class or some other part of the code base. I would rather write a bit more code for a bit more clarity. Maybe if python were typed I would like Django? But python has all of that nonsense around virtualenv.
Spring has been ok, but not great. Too much bloated abstract factory creator nonsense. Dependency injection never really clicked for me. All of these annotations. I quite liked plain Java but Spring just felt like this monster.
All in all node(express) has been the nicest for me.
> I dislike all the magic of rails. I never know what is going on because there is some functionality that inherits from a rails class or some other part of the code base.
This is also my only complaint with Rails.
I'm a programmer, not a wizard, and I'm not good at magic.
I understand the "too much Magic" criticism of Rails from novices & intermediate Rails developers, but once you reach a sufficient level of mastery, I think this goes away.
After using Rails every day for 12 years I know pretty much all the ins and outs, and what is "magic" to others is just the robust tooling I love. Just like any tools, they are overwhelming and daunting when you don't know how to use them, but once you become proficient with them, they make your life so much easier. While it might be difficult when the "magic" doesn't do exactly what you want for your edge case, when you have a sufficient level of mastery, it's easy to find a way to adapt/modify/override the tooling and make it do what you want. Further, many times the tooling is there to keep you from doing things you probably should not be doing, and this kind of strict, opinionated, best practice enforcing philosophy has gotten me out of trouble at times, and I think it makes it much easier for engineers to move between Rails codebases and start being productive even faster.
I've done plenty of Node/JS/React and I honestly do not understand how people can prefer to use these stacks over Rails. For full stack web dev, Rails is such a pleasant place to work every day.
I've been doing Rails for literally decades. I understand the magic but I still struggle to figure out what's going on in larger codebases. The amount of context you have to pull in to understand what a particular block of code is doing can be huge.
I never really understood the criticism about "magic" in Rails.
We are surrounded by magic (which only means things we can not realistically be bothered to take the time to really understand, in contrast to things which are incomprehensible). I have no real clue why the terminal works. I have no real clue why my OS works. I have no real idea how TCP/IP does its thing. Sure, I can use them – but I couldn't really explain and much less recreate them.
What I need in all the above is replicability. I do x, and I know y is going to happen. Get x, do y. This is true in Rails.
If I really wanna know more Rails is open and easily explorable. No one is preventing me from finding out how any piece of the "magic" works.
"Magic" class inheritance is a thing in JS as much as it is in Rails.
> I never really understood the criticism about "magic" in Rails.
I'll state my case as clearly as possible: The magic in Rails REQUIRES memorization... freaking everywhere. And it provides virtually no hints to jog your memory.
There's just too much tooling, hidden away out of sight, and applied through shenanigans with Ruby that other languages/frameworks make MUCH more obvious.
Simple trivial example? Rails fucks with imports left and right. Rails allows you to not even write a require statement half the time - it's just going to load things from places. Hope you have that list memorized.
Does it save you some time? Yes.
Does it make the code look "Cleaner"? Sure.
Does it make my life a fucking chore every time I have to run a damn console to find the source location of an object at runtime because it's entirely unintuitive about where it freaking came from? Damn right it does.
---
If you started early in your career with Rails - you probably don't notice this. But if you have experience with a solid selection of languages (ex professionally I've used: GoLang, C, C++, JS/Typescript, C#, Java, Netlogo, Rust & Ruby) I find the discoverability in Ruby/Rails about the lowest on the list.
Very fast to work with if you happen to have it all memorized. But that's about the only compliment I can give it.
> GoLang, C, C++, JS/Typescript, C#, Java, Netlogo, Rust & Ruby) I find the discoverability in Ruby/Rails about the lowest on the list
What's interesting to me about this comment is that among the languages I'm familiar with that you list, the difference between the best discoverability and the worst feels way larger than the difference between the worst one and Ruby. To me, C is barely any better than Ruby; sure, Ruby lets you define methods/types at runtime, but C doesn't even _have_ methods, making finding all the things you can do with a given type way worse in my opinion. Plus, you can still have some wonky generated stuff with macros, although I'll concede that's usually less common than Ruby metaprogramming. Java, C++, and Go are a bit better, since you get a namespace instead of just a random identifier without context, but these namespaces are generally split across multiple files, so in practice I would need to rely on tooling to do this for me, and at least with RubyMine this wasn't in practice _that_ much worse.
Don't get me wrong - there are definitely some C/C++ codebases where the macros have gotten way out of hand. But in general, they're both typed - which helps SO freaking much.
Ex: C doesn't have methods, but if you store most of your data in structs then you can easily do two things:
1) find all the places where the header defining that struct is included
2) Do a global search for the struct name
Both will present you with a nice list of places that data is used, and show the functions that accept it as an argument.
Where as with Ruby - I basically have to use RubyMine to get anything even sort of working, and even then it chugs along very slowly trying to do it. Solargraph in VSCode doesn't really work at all (at least 50% of the time it finds no definition for me) and just using a basic editor is a nightmare. Sometimes you can do a global find for "def [classname]" but that only gives you the definition, not any of the places that use/modify it.
Basically - Ruby is one of the few languages where I feel like global search just doesn't work well, and it also eschews import/require/include statements when used in Rails. It's just a tangled mess, and there's NO way to unwind it without tooling, and even the tooling struggles (RubyMine is a guaranteed way to get my fans running at full speed for large projects, and it's the best I've used).
I have to work with a lot of legacy codebases day to day, but generally it's get in, figure it out, make a change, test it, and go. With Rails, I just end up in that "figure it out" loop over and over.
In my book it's a write-only coding environment like everyone used to complain about with Perl and PHP. People crank that stuff out really fast and move on and leave future generations to suffer. But they love it, of course.
How much effort did you put into learning Ruby and Rails properly? It's easy to get started but rather hard to master and it sounds like you're invested in other tech.
Right back at ya: "Which version of Ruby and Rails?" :P
Because to me - RoR is in the death spiral period that the original ASP.Net was in before Microsoft threw the whole thing out and started over with the Core version.
Namely: Rails trys to give you opinionated best defaults, but the "best defaults" have changed dramatically since the framework came into existence. So you end up with 6 very different set of opinions as the framework has evolved, and the documentation is poor (honestly, at least ASP.net had okish docs - I find Rails docs pretty damn bad) and you get a complete wash on 3rd party sites trying to find relevant info for the version you happen to be using.
Also - Unlike MS and ASP, Rails doesn't even fucking try to keep naming consistent. They seem to favor making the syntax as close to natural language as possible, often deprecating the old syntax in favor of new method names solely "because it reads better". Which drives me freaking nuts.
Inertia will keep it running for a long time, but it's not the thing I would pick for greenfield projects anymore.
These are fair criticisms. These kinds of problems can also be difficult to demonstrate to others who may help.
For example "some function `f(x)` gives 5 when it should give 7" will get an answer in 5 minutes on stack overflow, whereas "my thing's not working and I don't know why" will receive 4 downvotes and no answer in the same time.
2.
I tend to be the kind of learner who doesn't sit down for 30 days and read the docs cover to cover, but rather I start using the new tool on day 1 and figure out what I need to know as a I go. But rails rewards the former approach (i.e. reading through the rails guides - or even just skimming them). This may take a few weeks, but it gives the ability to at least know where to start to look if something has gone wrong.
3.
> And it provides virtually no hints to jog your memory.
I kinda agree. I feel like this should be easily addressed (although I'm not totally sure how).
When multiple teams work on the same rails project, you're bound to have someone enhance some class somewhere, and all of a sudden, your isolated class is doing things it's not supposed to do, or at least you think it's not supposed to be doing it.
You try to debug it, but there are no types no way for the tools you're using to let you know easily, here is where this specific piece of logic coming from.
In Typescript, entities have types and when you misuse something the typescript checker tells you while you're coding why, that's not what you're supposed to do. You can super easily track down the type and navigate the code base to the source and adapt either your code or edit the source. Easily.
With rails, you're often required to do mental gymnastics to debug simple things, after the fact
> When multiple teams work on the same rails project, you're bound to have someone enhance some class somewhere
It really isn't that common just like it isn't that common to do it in JS or in Python. Some people used to do that shit a decade ago, it became frowned upon and I don't really see it anymore.
Let's not pretend javascript Promises and async/await are not magic in the same way some of Rails is. Lots of gotchas and unintuitive behavior, let alone cryptic error messages and stack traces. At least Ruby generally gives pretty useful stack traces. When something breaks, it gives you a pretty clear indication of exactly what line it happened on and what the problem is.
I love Rails (though criticism of its magic is fair), but this isn’t a good analogy. Async/await is literally syntactic sugar over the Promises abstraction. There’s nothing magic about Promises, and certainly nothing magic about async/await. In fact, I’d argue you’re in for a slower learning curve if you believe there to be magic in these areas.
> In fact, I’d argue you’re in for a slower learning curve if you believe there to be magic in these areas.
I 110% agree with you.
This is Rails striking again!
"Don't look at the magic, just memorize it." might as well be Rails' slogan.
Convention over configuration really just means "Memorize all my conventions, and don't ask why I picked them".
Great for the case where your use-case is in line with the chosen conventions and you don't want to think all that hard (or you just need to pump out content - like a contract agency). Pretty terrible for just about everything else.
Promises/async/await seem very different than Ruby's (and Rails') metaprogramming to me. I'd need an example of a cryptic stack trace to know exactly what you're referring to--half the problem is because of the overuse of anonymous functions that bork the trace. There's an easy solution to that (and it makes the resulting code easier to test as well).
the fact that there is a long chapter in a book series written on the edge cases of javascript[0] leads me to believe that it's not generally well understood either.
JS uses an event-loop (which is really just a variation of a message/event queue that we've been using for GUI based applications for decades now). If you understand this, asynchronous code in JS is pretty easy to understand.
async/await is pure sugar on top of promises (it's literally just wrapping the rest of the function in a .then() for you, and coercing the return value of your function to always be a promise)
IMO that's an explicitly different issue than a comparison between Promises/async/await and Ruby's metaprogramming, though.
Not to mention that part of the issue with Promises is the various polyfills invented before broad acceptance, which is a separate can of worms, and a different type of complexity than the (relatively) heavy use of metaprogramming in Ruby (relative to JS).
Large Rails projects are the worst I’ve ever encountered as far as being able to find the code that’s actually going to run when I’m looking at a function call in some code. Even with Rubymine, the jump to definition support is a joke compared to typescript, Java, etc…
You just see these functions and there is no require in the file to tell you where they come from. Rails just loads that shit from somewhere. It could be from a mixin, it could be from one of the 50 classes in your hierarchy, who the hell knows. You press jump to definition and rubymine just fucking chokes and gives you like 30 different method definitions with the same name in different places.
Hey @here i have had the same issue with tracking what is executed when jumping into a new code base, sometimes the code base is so large that instead of contributing you start learning what exists. There is AppMap, google maps for codes, used it quite a few times and unlike rubymine, you can track functions, methods easily by tracing views with just instant clicks. Here is the site https://appland.org/ and they have a vscode extension to ease the process of recording maps
I think rails should have explained a bit more about what rails does... every single rails method call like has_one or belongs_to inside a controller is just a method call that sets up a few methods based on the name of the thing you pass into it. not that much magic there. it's just ruby. in fact the single best thing to know that they are not some spooky things to be feared but they are just simple method calls outside the scope of a method.
Express isn't really like Spring, Rails or Django. Express is very simple and may be good for someone learning the basics, but how is a novice web developer supposed to know what is missing? There concerns from security, authorization, sessions, and many more that Express doesn't handle out-of-the-box.
> ... how is a novice web developer supposed to know what is missing?
That is a great question. Is it the job of the tooling to prevent a novice developer from shooting themselves in their foot? Do we need higher-level abstractions in our frameworks that are analogous to memory safety in programming languages? Perhaps.
Alternatively, I don't think that security practices are particularly hidden. Anyone who's used the web knows has used a login form. I would give most novice developers the benefit of the doubt that they're going to be curious and look into that.
I would argue that it is, in part, their responsibility to learn these things. It's our responsibility perhaps as stewards of the secure web to teach and enforce best practices. I don't think baking in these best practices into frameworks does these developers any favors, except that it allows them to focus on something else.
I often think of languages like Haskell that could offer the clarity and expressiveness and the static types I want, but the developer experience and killer software (react, phoenix, rails) has just never been there.
TypeScript to me is the compromise I'm willing to settle on. It is also lackluster from many aspects but day by day it gets a bit easier.
If you haven't already found it, you should look into IHP (https://ihp.digitallyinduced.com/). It aims to build the convenience of Rails on top of Haskell's powerful type system. I've not yet built anything serious in it, but I've been following its progress, and it's looking really good so far.
Im a noob starting a project in Spring and I get lost in the jargon. I find that all the Spring knowledge I’ve gathered is to know what is NOT written in the code that Spring is doing for me.
In other words, feels like knowing Spring is being able to read between the lines and placing annotations more than building with it. Which is fine, but it’s easy to get lost when starting out.
It’s also for me to find help since the community seems much smaller and none of my friends are interested in helping out because they don’t want to learn Spring.
Yeah, Spring is incredibly 'magic' heavy. Works great when you know the exact right annotation incantation, but it's a pain to actually understand what's going on.
I've found the official documentation to be very detailed, so it's helpful if you really need in-depth knowledge, but if you don't it's a bit hard to parse out the relevant bits. Copying something from the official guides seems often the easiest way...
In regards to the community, I didn't find it to be much smaller? The stack overflow tag is very active. I have the same experience that nobody I know wants to learn Spring out of their own volition though.
I tried this route and what I found is either outdated or was of poor quality and the code examples didn’t compile. It’s easy to get the barebones up and running but once you need to start customizing is when things have many different ways you could go about getting them done.
I can't vouch for them, but it looks like they're being actively developed.
I like the idea of full-stack JavaScript (or TypeScript), but last time I tried to use Node for a back end, I couldn't find anything that compared to libraries/frameworks like Django, Rails, SQLAlchemy, etc.
We're using django-stubs and we've been pretty happy with it. We've started the project with it, which was fairly simple. There's one or two model field types that are not supported but those can be skipped. We're using pre-commit to run mypy, this makes sure that we never commit a state that isn't type-checked.
Idk if its just me but I find the testing frameworks for expressJS to be _awful_ -- chai and mocha work great but throw in sinon and its like pulling teeth.
The lack of good documentation is painful and often treats me like I don't already know the concepts involve.
Sequelize isn't as intuitive as Django's ORM either imo.
Ah yes, that's definitely true, automatically generated getters and setters are a pain with sequelize. It's not impassive to have type safety though, it's just complicated.
I had to write my own types around the existing ones to get getters and setters to work.
Sure, I always have to spend time checking logs and tuning the queries like that. By default, Django selects everything. I used to discover that joins and prefetches were hauling in large text fields when I only wanted an id or a slug.
Prisma has a great API for this, and it's easy to tune. By default is prefetches and selects related even several levels of joins deep.
Let me assure you, there is 0 magic in Rails. Just because something is available to you via a convention doesn't mean there's magic, it means you haven't read the docs and don't understand the convention.
Couldn't disagree more, but I think you're taking the term "magic" too literally.
There is a ton of magic in Rails. It consists primarily of magic. I've been doing Rails since <1yr of introduction (Ruby for longer than that, and Lisp for longer than either). I'm very familiar with metaprogramming. Metaprogramming fits the canonical definition of magic in this context.
Ruby, and Rails, also makes it very easy, and seductive, to add more magic. This is powerful, but dangerous. Like Lisp macros. Understanding the magic is not just a matter of "understanding the conventions" and reading the docs.
Everytime you see something you don't know where it's coming from, it's magic. Every time I interacted with Rais ive seen it, you have to know that some file somewhere registered or autoloader something else, etc. You don't see the imports to find it, you have to grep the repo instead and sort through all the matches.
Same experience with a medium sized Rails project here. I joyfully ejected after several months, I needed a detox from the untyped mess, every singe library was different, there were no coherent apis/interfaces at all. All Rails patterns were replaced with some random "smarter" counterparts, dry-rb here, some "better" orm developed in a shack there, all glued together. I recognized it's not the issue with Rails per se, it's the Ruby devs culture and I'm not compatible with it (even though the team was quite good, just a lot of cruft to deal with).
This is my #2 problem with Ruby, and it's also the reason why a lot of folk love it. I think of macros in the same way I think of RegEx, if you're writing one you better hope it works perfectly because chances are that you'll be the only one to maintain it.
Other Ruby "features" that I dislike:
1. Blocks + Procs + Lambdas are all function-adjacent. Can't we just call them functions?
3. Out of bounds indexes on Arrays/Maps return nil.
4. method_missing() is super cool and super abusive. Again it feels like magic when functions come from nothing.
> Blocks + Procs + Lambdas are all function-adjacent. Can't we just call them functions?
Well, Ruby has functions, they're just called Procs. Lambdas are a special, more strict breed of Procs, and blocks are just (pretty complex) syntax sugar for passing a Proc to a method. The main function-like concept is always a Proc.
> Out of bounds indexes on Arrays/Maps return nil.
Calling the #[] or #slice method on an Array with an out-of bound index returns nil, calling the #fetch method raises an IndexError or returns an arbitrary default value. You can use whichever suits the situation.
Ruby on Rails is awesome to write, horrible to maintain. It’s the fastest way to build a web app but good luck with staying productive once you have 100 engineers working on it and a million lines of rails soup to wrangle.
So its been a while since I used Rails but when I did I enjoyed it. In particular, say what you will about DHH I think having a fairly "opinionated view" on how the framework should function makes it much easier to deal with. Every time I need to do something full stack with Node I feel I need to go back and figure out what the current state of ORM's are.
However the reason I don't use Rails as much is that I'm not writing a lot of "full-stack" apps. A lot of the work these days is gluing together various SaaS services. Okta/Firebase for Auth, Contentful for CMS, Stripe + Webhooks for Commerce etc. I just don't do anywhere near as much "CRUD" style programming as I used to do earlier in my career, which is both a comment on my career and the state of programming today.
I'd love to see a project that wraps up a bunch of best-of-breed technologies and creates a full framework and doesn't try to be all things to all people. ie React for Front-End, Bookshelf ORM, Express Server etc (pick your favorites, but have an opinion that evolves but only in one direction.
DI/IoC is a separate thing from the ecosystem; the benefits are just as strong in JS or Ruby--it's just that in JS/Ruby some of the benefits aren't as noticeable because of language malleability and openness.
Prediction: the big move in the next few years is going to be "back to hypermedia"
People are realizing that you can accomplish quite a bit more with hypermedia than you could in the past, and that the complexity of javascript stacks isn't worth it in many cases.
Older, mature hypermedia-based technologies like rails, django, and even PHP, will experience a resurgence and a lot of older lessons and techniques in web development (caching, SQL tuning, etc.) will be rediscovered.
I have a dog in this fight, w/ htmx, but I think we are increasingly seeing evidence for this move.
The biggest CMS of one of the biggest languages is moving away from the approach you call hypermedia by implementing a JS-based editor and REST apis. Effectively they are building a headless version on top of their legacy platform, which can be used like a JavaScript stack.
This can be used as an argument for the hypermedia approach: "Let's just use this thing for now, we can always implement our SPA inside it later, if we need to."
>Older, mature hypermedia-based technologies like rails, django, and even PHP
Not sure what you refer to as hypermedia.
In the first part of your comment I assumed something like a new version of Flash. Here you seem to simply imply http/hypertext.
But then again, those technologies where never lost (to need to be rediscovered). They're as popular as ever, people just add more stuff on top, at the client JS layer.
If we see a return to "hypermedia" it won't be wholesale, but rather in the form of a static site generator that does the 80% work and is easy to extend the rest of the way. Something somewhere between Svelte and Gatsby. The react component model and JSX style bracketed DSLs both have a lot of traction, the main issue is the amount of groundwork and glue needed to do simple things with them.
i think it will rather be in non-javascript technologies with strong existing hypermedia infrastructure again, like rails, django, etc
the front-end component model is anti-RESTful and is really a mechanism for handling the complexity of the current client-server approach, it becomes significantly less important as hypermedia is re-embraced
I think RESTful APIs will die before component based interfaces do. Component based UI has been a thing for like 30 years outside the web dev space, and GraphQL/post-based RPC APIs solve a lot of problems and can be derived cleanly from a database schema or functional modules.
Hypermedia also doesn't play well with offline-capable applications, which limits its use cases.
the component problem, in as much as it is one that can't be dealt with via just standard template includes, can be solved server side and offline-capable isn't a huge percentage of web apps
we just disagree, the future will tell us who's right
I think requirements have generally shifted quite bit from what plain html can do, if that's what you mean with "hypermedia". Though true, there's probably a growing understanding that one doesn't need React on every website. So maybe it'll rather be more refined understanding of when to use certain technologies.
Certainly interesting but I fail to understand what's the big benefit? Also I would be afraid to have some corner cases that would need to be covered with JS, and that could get really ugly.
Yeah it's funny... Now 10 years+ in the web dev business. I occasionally got drawn by the hype, dug myself considerably deep into express based frameworks, sails.js, koa.js, nest.js... But in the end i had to conclude, my first go-to framework django always came out superior in terms of developer productivity. It even eventually covered the bases where i still thought node was superior like async/websocket communication. Imho Django and similar batteries-included frameworks are as state-of-the-art as they've ever been.
Especially if you couple it with HTMX / Alpine.js you get a really good stack that covers all the dynamic page updates people are getting used to, without adopting massive frameworks.
I just started with HTMX and so far I think it's really promising. Similar things happening with Rails and Hotwire.
It took a while for these frameworks to accept that JS and the frontend are also important aspects of the stacks, and hard to avoid if you want to build modern applications. But now that they're picking up, heavy JS frameworks start making less sense.
At my first job we were migrating from Coldfusion to Java. This Middle Aged Sri Lankan guy refused and only worked on ASP.NET. Much respect to him! He knew what he was comfortable with - and most likely looked at Java in disgust the same way Java folk would look at ASP.NET :P
I've said this before on here, but the Rails philosophy really clicks with me. Working with Rails is just more fun than with any other language/framework, especially JavaScript. I understand that this is subjective, but it's good that different choices, including Rails, exist.
PHP clicked with me for 15 years. I was extremely reluctant to use Node/Express because it required me to be more nuts-and-boltsy, I liked how PHP just did everything (like multi file uploads from forms). What one me over about node was that PHP never forced me to develop with module patterns, it was just brute force, spray code everywhere and walk away (we all did that, actually, which made support a nightmare). It also came with robust CI/CD testing (Jest is a big deal once you get over the step-function). Perhaps PHP has all of this integration and testing, but I'm so into node now that I don't really want to go back.
And I see very little reason to pick Rails over PHP over Django over Node!
Whatever works for your team is what matters. I bet you could find a Fortune 500 company that uses any one (or all) of those.
I can't speak to PHP, but I can speak to the others.
Node's easy, as it's technology, not a framework, so you'd pick Rails over it if you wanted a lot out of the box. JS also "thinks" differently than Ruby (callbacks, and now async, pretty much everywhere). PS - If you haven't played with lots of curried functions in JS, it's fantastic (IMHO).
If I wanted a more same-same comparison, the choice is between Sinatra and Node, and IMHO that's a lot more even (and for me, broken by one of them being in Ruby ;) )
Django's more subjective, but my experience with it was very not-great. There's a lot of decisions in Django that look good on the surface (apps, for example) that then don't pan out (apps all end up blurred together, for example). Particularly compared to Rails, I found Django waaay more boiler-plate and frictiony (particularly the migrations), but that's fitting for a language (Python) that's actually more lower-level than expected. Python (and Django) are opinionated where Ruby (and Rails) are welcoming, IMHO.
Good point about tech vs framework. Node isn't opinionated, to borrow a UI term.
I was really happy when I was able to stop using Bluebird and switch to JS promises, and formal async/await in JS was a game changer: it cleans up code significantly. It is hard to use languages that don't have async/await now that my brain has become so habitualized.
However, I'm a little bummed currying was effectively nixed (or just ugly) with JS module imports; require() had an edge there.
Comparing JavaScript (or Node) to Rails doesn't seem right, since, like you said, one is a programming language, the other is a framework.
But the reality is that this comparisoin is what you end up with in real life decisions. Even if you pick a Node framework like Express, it will only give you a handful of tools, not really a batteries-included framework like Rails.
I haven't come across a Rails-like framework for Node. I wonder why? Didn't people try to make it? Is it because of the language specific features and Node ecosystem that it's hard to come up with a coherent, opinionated, all-inclusive framework?
I've sometimes read that Sails.js is the "Rails" of the JS world, but when "I did my own research" about it there were enough red flags experienced by real world devs that I never considered it for a project. For instance, all benchmarks I read showed a very poor performance compared to other frameworks, also very poor real world adoption so it doesn't look good on the resume.
I chose to go the Rails API with a Vue.js frontend route (actually, Quasar), and I'm very happy with it.
Just to throw my hat in the ring, Currently CTO /founding engineer of health tech company that runs a Rails backend that serves about 150QPS.
I hear over and over that rails doesn’t “scale”.
Performance wise, we have never had a problem scaling rails itself. The issues were always at the database level. Most slow endpoints (1.5s+) are 10% Ruby, 90% Postgres.
Even if Ruby was magically infinitely fast, these endpoints would go from 1.5s -> 1.35s.
Optimizing data infrastructure gets 10x returns compared to the application code.
Maintenance wise, it’s a bit harder, Rails loves to put everything in the global namespace. This comes down to your team being conscious of properly namespacing different logical parts of your app.
Having built a Rails app with my team that handles ~76k rpm on peak days (99% of responses within 90ms), I've learned that you scale your architecture, not your framework. Rails is just fine.
Agreed. Scaling application servers is "easy" since they can be scaled horizontally; in other words, you can just throw more hardware at the problem. Scaling databases is "hard" because of CAP/PACELC-type issues in maintaining consistency, and because some DBs (like Postgres) don't have good support for horizontal scaling.
I’ve found DDD’s insistence that cross-aggregate aggregation be done through IDs to be helpful here. It makes transitioning to other persistence implementations easier.
Preach! I do not understand this criticism at all. Rails scales just fine, in a web app it's the DB that's the bottleneck 99% of the time. Sure, the ORM can get you into hot water easily if you do dumb things (or just don't pay enough attention to N+1's etc), but one should be using the ORM wisely and deliberately, rather than living ignorantly of what's happening behind the scenes.
Anyone have any recommendations for books or resources to look at when scaling a rails app beyond a single database, or when your app starts to move into the realm of "big data"?
You can "componentize" various parts of Rails and make it less of a monolith by using Rails engines.
I do it by having a new folder "components" on the Rails root and adding `gem 'name_of_component', path: 'components/name_of_component'` which looks like a vendored gem.
Rails engines has the ability to "isolate_namespace" which is I think the default for a new engine. This is where you can avoid global name spacing issues where each component can be thought of separately. Effectively, you have something _kinda_ like a microservice but it runs as a monolith. And if you need you can have each component depend on others so long as you don't wind up in a loop.
Note: I have a component "common_models" which is just for commonly used items across various components. The main app should have nothing in it's Rails.root/app since you instead have components.
I'm not related to this but here's a basic idea: https://cbra.info . (Pretty sure the author of this page made the Railsconf talk that inspired me to move to this years ago.)
My takeaway from this is that it’s extraordinarily important to try different tech stacks.
I’ve primarily worked as a Java dev for the past 20 years, but I’ve got significant time doing python and one non-trivial Rails app.
The funny thing is I’m most comfortable and I believe most productive in the Java ecosystem, but only because of the time spent working in other languages. Coming back to Java after python, one gets a better feel for what’s essential and what’s cruft. Similarly, when Rails first came out, it can’t be understated how revolutionary it was with respect to web development. Coming from the J2EE universe it was like the true essence of web development had been hidden from us with servlets, JSPs, wars and ears.
That being said - I’m happy being a Java - well JVM at least - developer. The ecosystem is alway changing and often improving, but I assure you it wouldn’t if not for the evolutionary pressures of things like JS & Node, Ruby & Rails and Python & Django.
I'm in a similar boat to you - I've built non-trivial side projects in other tech stacks, but I'm a JVM developer at heart. I've been conflicted about whether to dig into ruby/rails more to jump ship recently because of the philosophy in the community.
I love kotlin as a language and enjoy working with spring boot but the hype in the JVM community around JSON API + React SPA does make me wonder whether I'm moving away from it philosophically.
I'm particularly excited by Spring Native right now. Having a Spring Boot app startup quickly and use less memory will fit heroku-like PaaS environments perfectly.
Same boat as both of you guys I find myself in this weird world of loving Go's simplicity, loving Rails get shit done mentality + community and Java reliability (but SpringBoot makes me sad).
I'm glad I ventured out of my Java only mindset however. Lots of interesting things going on but decision paralysis sucks.
Same same but different; I've worked in many, many different languages, but in my heart I'm a Rubyist. Definitely second the "things I've learned from other languages", so much so that I gave a talk about it: https://rubyconf.org/program/sessions#session-1198 (I don't know when the recording goes up :P )
The Java space though unloved but the younger crowd is still super strong and Spring Boot gives all those competing platforms a run for their money leveraging the enormous JVM ecosystem. Java may not be the most concise of languages but I think many people would be surprised by how little boilerplate there is in modern Java and Spring.
Spring is pretty lean as long as your use case is typical and common - you can practically setup most of the foundation just via config. However, anytime you have to deviate from the typical, the complexity of the Spring framework underneath starts to show and the beans and boilerplate start to grow pretty fast - not unmanageable but not exactly lean either. Fully agree about the ecosystem.
At the same time, this flexibility is a core feature of Spring. In most other frameworks, when you have a use case that isn't supported, you're entirely on your own. Or, worse, end up with in-house patches and hacks to the framework itself. Spring is an integration framework, and so closer to a framework for building frameworks. It just so happens to have a bunch of well supported ecosystem defaults.
> Coming from the J2EE universe it was like the true essence of web development had been hidden from us with servlets, JSPs, wars and ears.
20 years ago, Java development wasn't that complicated. Big consultancy came in and complexified the ecoystem just for the sake making the entry level way too high. A Rails developer only needs to know Rails and Active record and maybe Capistrano and some server.
A Java developer has to know Servlets, Glassfish, Tomcat and other containers, JSP,JNDI,EL, JSTL, JSF, JDBC, JPA, CDI, EJB, Hibernate, Spring, Maven, Gradle and God knows what to find a job.
For a beginner, the documentation is also all over the place. Java the language is improving sure, but some people are still stuck with maintaining struts applications to this day, with tons of XML files...
Just reading these make me depressed. I'm taking over a JSF project that uses gradle these months which puts even the complicated old spaghetti gulp build files to shame in terms of complexity.
Even more confusing is that there are some people who love that complexity. They are actually proud of it! Why would you have a globel gradle file in your $HOME that has project specific configuration? Why does your stupid project only run with some specific Eclipse plugins? Why does it take 2 days of depressing configuration work to have a running instance? I used to love Java! What happened when I wasn't looking!? They tell me "but you do it once!!", I digress.
The cool think about rails is not just that you don’t have to take care of the “pluming” (you get that from any halfway decent framework and could stick with JavaScript and nestjs for example to get that benefit) but the libraries that exist to get you going quickly for login, third party apis and so on. That is the bigger benefit of rails.
In other languages there might be multiple frameworks and multiple libs all of which might do none of just part of what you need and if you find a lib you might not find an integration into your framework and need to build that yourself.
Rails was so big and the community was/is cooperative enough that you usually get fewer libs that are more complete and more likely to fit you needs and come with rails integration.
No need to test 10 or more libs to find out all of them sort of suck and then do it yourself or chose the least sucky one and integrate it yourself. THAT is what maid Rails productive and at times frustrating (you often only deep dive the components once something goes wrong).
Long term it will be interesting to see how many companies run with setups that are Node.js heavy in comparison to not just Rails but also Python, PHP and even Java, .NET and Perl (yes old but not dead).
Perl was one of the early languages and I don’t think there will be as many projects in it as there are in PHP. Python has a good amount of stuff and they didn’t really have a time of heavy hype (like PHP, Ruby on Rails or Node.js enjoyed) and Java and .NET are going to be more heavily traditional corporate than the rest.
Would be nice if somebody knows a link or two to explore this a little bit better.
Yup, but there is more. I think overall we as a community appear to show good taste in what we do (this is opinionated) and if we do something it tries to be as complete as possible.
When I think of all the half backed JS projects I’ve looked at when searching for a solution and compare that with Ruby, there is a difference.
Things have been moving so quickly in the JS space and because the JS community is so prominent on Twitter. It's ended up with a lot of JS 'influencers' who feel they have to come up with a new hot-take on code smells or the latest cool new thing every week in order to stay relevant. They tend to default to exclusionary behaviours whereas Rails is a lot more friendly.
What's ironic is that there is (or... was. I've not been as active recently to see if it's still there) a marked difference even between the Rails community and the core Ruby community. The closer to Matz you get, the nicer people tend to be.
Nest.js really helps to put a solid structure around Node.js/Express.js projects . I have found the teams much more productive, with strict conventions to help them build solid and scalable backend platforms.
As you mentioned, the Node.js ecosystem is full of specialised libraries to achieve typical use cases such as authentication/authorisation, ORM/persistence, etc. The Nest.js documentation is a great reference as they include a list of recipes for all those common scenarios and how to implement them in a Nest.js backend.
I don't think I've ever had a great ORM experience with node. I inherited a project that was nest + typeorm. I've found nest pretty pleasant but typeorm is buggy and was generating way to many queries for stuff.
This has been my experience as well. I've been happy with nestjs but haven't found an ORM that fully did what I expected. MikroORM seems to lead the way though (I know it isn't the most popular). My main issues with MikroORM could of very well been self inflicted and I ended up writing my own SQL.
I agree that ORMs in the node world do not provide a good experience at this stage, so I mostly go with knex these days.
I had a decent experience with TypeORM after I spent time understanding how it works under the hood to optimise the queries (notably by defining the relationships better).
Comparing Rails to Express is not apples to apples. You should compare Rails to something like Next.js that has a lot of the magic and plumbing taken care of for you on both the front end and the back end.
I agree that for side projects, underfunded startups and especially for product/business-focused founders, using the quickest magical prototyping framework is definitely the best idea so I agree with the overall sentiment of the post, just not the specific conclusion that Rails is the best way to go in 2021. I still believe strongly that having the same language on the front end and backend is paramount to developer productivity.
Next.js is extremely limited compared to Rails, so you're still not comparing apples to apples. Add to next.js a librarydatabase access, background jobs, csrf and related security stuff, migrations, server side caching of data, *validation*, email sending, email receiving, testing, and I could spend an entire day listing things Rails gives you that Next.js won't give you. Web development is not just rendering html, unless you're building just landing pages, there's a lot more going on.
The commenter you replied to did provide a fair correction as far as the right layer to be comparing. They didn't specifically suggest that Nest.js (started in 2017) is as mature as Rails (created in 2004) or Laravel (created in 2011).
I'm not sure I buy the "same language front and back" thing. Counting the number of efforts across the industry to improve js or replace it I think that many people would like to avoid using js at all.
I'm the developing a rails backend with a Vue front-end, and the more I work with js, the more I'm happy that I don't have it everywhere.
React is way better on the view side than ERb/HAML/whatever.
I miss ActiveRecord. Prisma is relatively clunky. I like having fat models integrated with the DB.
It also feels like I'm fighting with the type system because every variation of a row with different joins becomes a different type. I'd rather be lazy about joins.
Working with Prisma on a side project, migrations are a pain. Rails' migrations were so easy to use. I am in the early stages of working on the side project so might even consider flipping over to Rails if this keeps getting messier.
Totally agree since I went in the opposite direction. Express is closer to something like either Sinatra or Cuba in the Ruby world.
A much better comparison would be either Blitzjs, Nestjs, redwoodjs, featherjs, or several other full stack js / ts frameworks. I'm pretty sure these frameworks were inspired and influenced by Rails
I feel like something like Blitz.js is a better comparison instead of Next.js. Next.js is still very frontend focused and does not have a lot of key components needed by a full framework like ORM, Authentication etc.
For me it actually boils down to the language. I hate almost everything about JavaScript, its syntax, the decisions made and steps taken in its development, and writing Ruby, any Ruby, not just the Rails flavored kind, feels like a breath of fresh air after suffocating in the JS dungeon. My productivity takes a huge hit each time I have to work on a JS codebase, because my brain just doesn't enjoy thinking in JavaScript.
(Yeah I know this post isn't terribly informative, but neither is the article, so I'm expecting some light-hearted posts)
That's really interesting because I feel like ruby/rails is suffocating. There's virtually no static analysis tooling, it's difficult to find function/method definitions, and the language supports meta-programming to such a degree that things become too dynamic.
That's because half of Rails core functionality uses meta programing so methods are generated during run time. To effectively debug with Rails, you need to understand the inner workings of the framework itself.
What he liked was Scheme, not Java. You can catch a whiff of it every now and then. He got told to give it a Java-like syntax by a PHB so they could ride on Sun's marketing coat-tails.
And that's part of the problem: if what we'd started with was Java--, we might not have quite such a mess today.
I feel the same way. Unfortunately, you can't escape Javascript. Typescript definitely dulls the pain a lot and I highly recommend it as an alternative.
Try using a lot of curried functions in JS. Absolute game-changer for me. I didn't feel suffocated, just always lost and confused, when working in JS, until I started going a bit overboard with the curried functions.
I can see this. I worked with Rails for years and recently switched to an all JS stack (serverless, React). I have fun with it in general. TypeScript and the intellisense I get with that in VSCode is great, but overall I feel like I've gone way down in productivity. At first I thought it was due to my being new to this ecosystem but it has been a while now and I've concluded that there definitely is some extra burden with this modern stack. Perhaps it will turn out that the extra work and headache will lead to a more performant and maintainable codebase than we might have achieved with Rails. Time will tell for that one but at the moment it feels like we drown a lot of developer time on tooling, strange issues, and reinventing things that have come with battery-included frameworks like Rails.
I firmly hope that javascript has peaked. The complexity of the tooling has increased by a factor of 10 in the last 10 years with subjectively very little to show for it.
Anyone starting out with backend webdev should learn Python Flask. There is no gentler and more thorough way of learning web fundamentals, whilst still being productive from day 1.
Flask is arguably objectively an extremely poorly written library and there are lots of alternatives out there that are much better, like FastAPI.
This is also pretty much obvious from the get-go. When handling a HTTP request, the morally correct function is something like a function which takes a request as a parameter and returns a response.
In flask, for no good reason, a lot of things that are only accessible inside a request get put into global objects, and if you try writing code that accesses them outside of the right context, it will simply crash. You might accidentally refactor such code to the wrong place and you will have no idea until it crashes. This kind of design on top of a dynamically typed language is kind of like drinking poison and then shooting yourself.
Flask is full of insane things like this and it boggles the mind that it ever got as popular as it has. I suppose there weren't many alternatives.
IIRC, Flask was originally written as a joke. It was also created in the era when using thread locals was still somewhat common but going out of style. I've always been a bit stumped as to how it got so popular. I usually recommend Django + DRF, Pyramid + SQLAlchemy, or FastAPI, depending on the project.
Yeah I’m not sure I agree with you. Spinning up a web server in Node.js using Koa takes minutes. You don’t need TypeScript or anything else really.
Everyone talks about the complexity of the tooling and I have no clue what they’re talking about. This is from a backend perspective. If you jump on the TypeScript bandwagon, which makes everything infinitely harder, then maybe, sure, I’d agree with you. But JavaScript is dead simple to use.
Even now in frontend land there’s still innovation. Vite has been an absolute pleasure to use and spinning up a React app takes minutes. The irrational hate for JavaScript is really weird.
I am curious why are you saying that. I know Flask well and while I never wrote something with bottle.py, it seems ~90% similar, at least in the basics.
For me, a big one is that Bottle.py has zero dependencies; the entirety of the framework, including the template engine, lives inside the single `bottle.py` Python script. That means it's simple to use even without pip or a virtual environment: just pop the bottle.py file in your project, import from it, run `python my_script.py` in your terminal, and you server is up and running.
From my experience with Flask (albeit, this was years ago), it was a bit more complex and ending up with circular dependencies was common.
What is happening? The two trending posts are about monoliths and "stable" languages? Are we finally breaking from the madness of unnecessary complexity, evangelized by the FAANG disciples?
I resurrected a Python project of mine after 7 years. Upgraded the dependency management to Poetry, upgraded the major version of Flask. Boom. Back in business. Try that with a modern Node project after 7 months.
Respectfully, I really think that "modern Node project" bucket is too large to be a useful descriptor. I do this with Node frequently with no issues (across roughly 140+ distributed systems, most using hapi & mongodb, but also some more low-level services using the core node UDP/TCP APIs).
I'm sure there are modern projects that can make this painful, but if you're judicious about dependency management and staying on the LTS version of node, its rare you see any major headaches in our stack.
Even for super old / legacy services (ones without automated dependency mgmt through CI), it takes maybe 15-30m to get everything up to date.
I had a similar situation to the person you replied to and it wasn't bad.
I took a project with ~20 top level dependencies and around 5k lines of Python / Flask (plus a lot of tests). I YOLO'd upgrading everything to their latest versions in 1 shot including Python 2.7 to Python 3.7, Stripe API versions and everything.
I did that around 2.5 years ago and it took around 45 minutes. The app was using SQLAlchemy, Celery and had a bunch of things you'd expect to see in a SAAS app (users, custom admin, payments, custom CLI commands, migrations, etc.).
This is kinda sorta equivalent to "from Apache HTTP Server to Phoenix Framework" though.
Like, yes of course an actual RAD framework has more things built into it than a server runtime. That's kind of why they exist.
Your programming environment should more or less reflect your requirements, strengths, and priorities, and starting with plain Node makes sense for a development style that OP just doesn't seem to want to follow, so he's spending a ton of time building 'boilerplate' to try and shim his process into his tools when the tools should be the ones doing the work for him.
Like, all that stuff about CRUD and auth. Just use Prisma and Passport?. No need to twist yourself into a knot building the same abstractions over and over by hand, the things exist and are there.
Supabase (or similar) is going to change all of this very soon. I can't wait for open source technologies like postgrest and typescript RPC to mature. No more boilerplate HTTP code, no more boilerplate database endpoints. Need a backend function? Just define the interface, and boom you are writing backend code that you can call directly from your frontend. Really really exciting stuff is right around the corner IMO.
Yes. I was reading through wondering if someone was going to mention Supabase. Not a web developer by day. I do telecom stuff. I’ve been bouncing around trying different frameworks because I want to build a website, and once I found postgREST and then Supabase I loved it. Supabase has a a lot of components, but all specific and exactly what you might need.
I am documenting my process of building my first web app here: http://tbonesteaks.gitlab.io/blog/. Just started it today, so it’s rusty.
Remix.run has this figured out. Basically your backend is just a loader/hook that is colocated in the same js file. It would be great to have this idea in Rails view layer, for more complex UX cases.
I would have enjoyed an example or two. The author didn't really make their case...
They made vague statements that to me seemed laughable without examples.
2 weeks in expressJs? doing what?
2 days in ruby? again....what?
is the author bad at bootstrapping perhaps? do they overcomplicate it.? I need examples to appreciate their insights. otherwise I cannot fathom Hello world taking two hours in modern node.
I've been doing web programming for about 25 years, starting with PHP and MySQL in, oh, about 1997. I wound up doing a LOT of PHP work, some ASP, and then lots and lots of Rails. What I'm trying to say is that I am INTIMATELY familiar with everything that a web app does, in every layer.
A few years ago, in a previous role, I was forced to use Java to start a new web app. I spent a couple months reading up on things, and trying to find a comprehensive example of a CRUD app in Java/Spring/React. I finally admitted defeat, and corresponded directly with the author of JHipster, and he pointed me to an example he had on GitHub, which had never come up in searches, but, unfortunately, was so out of it date, the code wouldn't work in modern versions of the stack. However, I finally cobbled together a working "show" page with nested objects, as ANY real-world web app will need to do. At this point, I again got stuck at trying to figure out how to update nested objects in a form.
As a mental exercise, I rewrote everything I had done in 6 months in Java/JS in Rails in 2 days. These 2 lines of Rails...
class BankAccount < ApplicationRecord
self.table_name = 'offer'
belongs_to :owner
end
... represented over 250 lines of Java/Spring/JS. A lot of people around here hate that Rails is "doing so much for you," but do I really care to write every line of code required to define the relationship between BankAccount and Owner to the compiler, when it's a simple many-to-many connection implied by a foreign key?
I found another job.
P.S. There's a lot of talk on this forum about Typescript and how great it is, but very often in my months of trying to write this application, I couldn't get the types to line up through the stack, and just had to use generics.
> P.S. There's a lot of talk on this forum about Typescript and how great it is, but very often in my months of trying to write this application, I couldn't get the types to line up through the stack, and just had to use generics.
When you say "use generics" do you mean typing things as `any` ?
I would guess commodity plumbing like hooking up the front end alongside a data store in the backend, and other stuff like auth. There's a lot of work you have to do to get something like express on par with Rails or any other Rails inspired framework for which there are many in multiple languages even in the JS/TS world.
Whilst I don't have and direct experience of Rails I get the frustration with how the JS ecosystem can force me to spend a lot of time learning and deciding about things very unrelated to the core of the product I am trying to build.
I am quite excited to try out Redwood JS though which is approaching a 1.0 release and aims to bring that same opinionated ethos that Rails has to JS.
Clearly it is not going to be as mature as RoR for a long time, but as someone who knows enough JS to be dangerous it looks like an appealing option, especially when faced with having to learn an entirely new language.
Ruby is extremely consistent in that everything in it is a class and it's thoroughly OO. I'll admit it's added some new things in the past decade, but nothing close to to the decades of accumulated cruft JS has.
The really amazing part of JS cruft is how constructs that should have been dead for 20 years just keep coming back. E.g., the keyword "with" is a footgun for hiding object scopes that mostly disappeared before I learned JS, but then it showed up in Vue of all places!
Variables are scoped either to blocks or their enclosing functions, depending on how they're declared. Functions either create a context for the keyword "this" or not, depending on how they're declared. Both of these traits are maddening for learner.
JS uses a prototype chain and prototypical inheritance, but now also has a classical-looking class-based syntax as well. There are half a dozen ways to create an object and it's a much bigger hurdle for people to learn than Ruby's more or less mainstream choices.
Building larger apps in JS on the back-end also means spending a lot more time thinking in callbacks, promises or async than working with Rails would, too. Sometimes it's inevitable but it's a hurdle for learners.
While I get the argument for Rails, I find I'm much more productive when working in one language (Javascript) across both the frontend / backend.
As to the low level nature of Node/Express vs something like Rails or Django, I've tried SailsJS and Loopback, which are probably the closest comparisons in Node, and ending up regretting it. Every time I chose a high level API framework / ORM, I felt like I was fighting it or trying to find a workaround for the simplest things.
> I decided to try Rails after writing boilerplate in Node for two hours with Express, Postgres, EJS, Knex, etc and having a simple ‘hello world’ to show for it.
Well there's your problem. If you were to `npx create-next-app` you'd have most of what you want already done for you.
Yes, but imagine you've existed on a diet of nothing but oranges for your entire life, frankly you're bored of having to peel the damn things and the bitter pith left behind is, truthfully, frustrating as hell.
Someone throws you an apple - what is this food that you can eat without peeling? Think of all the time you can save not peeling fruit! Surely you must tell all your orange-peeling friends the good news?
> Building the web app in Rails took me 2 days – the same thing in Node would have taken 2 weeks. I’ve also included things I wouldn’t have attempted to build on Node/Express until I proved the idea out (editing a profile? Psht please - I’ll wait till someone requests that
I would love to hear more about what you are doing, and perhaps more importantly, how you are doing it if everything is so incredibly difficult for you.
Ruby only has one thing going for it, and it's not a very unique thing and you can get the same thing in a lot of other places: it has batteries included(and then some). This can make you very productive from the start, yes, but it can also constrain you to work in exactly the way the authors intended and otherwise make your life difficult if you have needs that just fall slightly outside of the garden path.
With node, you have nearly an infinite number of choices. But if you pick a stack, and you set it up properly, there is nothing preventing you from moving at speeds similar or surpassing RoR, and usually without any of the same limitations.
I am currently building a full-stack application in TypeScript using React and GraphQL on top of Next.js. It is easily the most productive stack I have ever tried, even though it took some work to get there. I can change a database model and the change will propagate through my entire stack all the way to the frontend, giving me type errors in every place I need to change anything, and things like that. There are great "plugins" for nextjs like next-auth which make auth laughably simple, and then you can pick between whatever ORM you want(We are using Prisma, which has been great).
With that said, if RoR fits your use case and meets your performance demands and it makes you more productive.. well, that's great news. Seems like a no-brainer to go with it then.
I have observed this but with Laravel/PHP. If you are a specialist NodeJS is not bad. But if you are a generalist with deadline and business logic to implement a more mature development ecosystem is advisable, in my opinion.
I've worked many years with Django (doing old style MVC), then moved to do all the SPA stuff (worked with React mostly and some Vue). Now I'm back to MVC using Laravel and Livewire and it is simply awesome. If the decision is on me, I'm not going back. Laravel is awesome, and current day PHP is not 10 years ago's PHP the same current day JavaScript is not 10 years ago's JavaScript
It feels really good to be in a "post-justification" phase now for Rails. With the release of Rails 7, the successful marketing of Hotwire, the resurgance of Ruby (don't call it a comeback!) with v3 and beyond, and the amazing vitality of web-scale platforms built on top of Ruby/Rails like GitHub and Shopify, we're way past the point of having to "justify" why someone should pick Rails for their web stack. We're here to stay and kicking ass. There are plenty of stacks out there to build web software with, and everyone has a favorite, but Rails is a solid choice—arguably the best choice in certain categories—and there's no need to explain why you've picked Rails for a project. It continues to be one of the most productive and rewarding frameworks in the business.
The biggest thing holding me back from moving to Djagno or Rails is the DB interaction. As someone who is comfortable and prefers raw SQL, do I just have to man up and embrace the ORM for everything but situations where I _need_ to make raw queries?
I've also grown like sqlx (both the Rust and Go versions, despite them not being related as far as I know). The methods for mapping directly to structs work really well and captures one of the biggest issues I've had (literally the object-relational mismatch).
I feel like I'm in a state of decision fatigue with web frameworks. I've used many shallowly, but I just never know if I'm making the right decision. It's probably safe to assume the best bet is the one I choose and stick to though...
ActiveRecord (Rails ORM) provides an interface for raw SQL queries if that's really what you want to do (`connection.execute`). You can use it whenever you want. You can also swap out ActiveRecord for something else like DataMapper (or whatever) if you really want.
But, the whole point of using a framework like Rails is to let the framework make certain decisions for you, so you can develop quickly according to convention, and not think of lower-level technical decisions. Bypassing the ORM certainly works against that.
DO NOT USE `connection.execute`. It does no kind of escaping. It's fine (and encouraged) to use in migrations but `ActiveRecord::Base.find_by_sql` is what you want for production code. I wish this was made more clear because it's crazy how much I've seen the former in production code.
SQL injections on code without an ORM is just a function of how many developers, are working on the project, eventually someone will write something that goes around the escaping.
I think the main thing about using an ORM (and I believe that Rails' active record is among the very best ORMs out there) is that you should never just blindly let it run without inspecting the queries it produces.
I'm constantly monitoring the logs during development to make sure it's doing exactly what I want. And the odd time when it's not the answer is usually within ORM api itself and doesn't require me to shift to raw sql.
This is why I never understood the argument that ORMs are for people that don't know SQL (not to suggest you were making such an argument). If anything being proficient at SQL makes you that much better at handling the abstraction that the ORM provides and that much better at examining the resulting queries.
You can use raw sql in django where it matters and let the ORM handle standard CRUD operations (https://docs.djangoproject.com/en/4.0/topics/db/sql/). I usually start with the ORM and if I need to do something complex or if there's a slow query I just rewrite it in SQL when it becomes an issue.
Also if you'd like to manage the tables with SQL there's an easy way to generate the models from the database schema (https://docs.djangoproject.com/en/3.2/howto/legacy-databases...). I've used it before at a startup to migrate from hand coded schemas and migrations in SQL that only one person was brave enough to touch (they had no way to run things locally) to a full consistent REST API for like 20 tables ready in 2 days.
I'm also managing an SQLite db on a mobile app that uses hand written SQL (with 20ish tables and a few 100 queries) and any changes to the database end up being a nightmare of manually editing raw strings.
If you've never really gotten over the hump of going all-in with an ORM, I think it's worth giving it a shot. It's a different way of thinking than always-raw-SQL, and it can be uncomfortable at first, but I've found it ultimately freeing to be able to offload nearly all the SQL I had to write back in the day. YMMV.
This is where I was before I picked up Rails. What I realised was that while I preferred SQL in general, what I actually cared about was the ability to really go to town on the 5% of queries that actually needed attention, and the other 95% were boilerplate and entirely unsurprising. Letting the framework make those ones just go away under a layer of syntax I didn't even have to specify, but that got automagicked up from the database schema, was a breath of fresh air.
I believe DB interaction is the principal value in web frameworks, the primary productivity boost. Easily turning ephemeral in-memory data into queryable ACID records unlocks a ton of important features for web apps.
However, most of the other features of these frameworks are just bloat, added complexity that doesn't really make things easier than writing vanilla $lang with rock-solid libraries.
For example, in Go: URL routing, request handling (middleware), html templating, websocket communication are all trivial to implement with standard or well-known libraries. But it's the DB interaction where things get tricky and very code-heavy.
I'm trying out an approach, leveraging pgx and the new Go generics, where I define a simple generic Wrapper struct with some low-hanging fruit methods: CRUD, filtered+pagified lists, unique constraints, etc.
How? `encoding/json` and Postgres JSONB columns. The generic Wrapper is hardcoded with a simple and flexible table schema: an id column and a JSONB column (I also added some timestamp metadata columns as an experiment).
The end result is that I implemented a dumb "ORM" with around 200 lines of idiomatic Go, and can do the following:
wrapper := Wrapper[MyStruct]{pgx.Conn, "mytable"}
record := wrapper.Insert(MyStruct{some,real,data}) // returns a generic Record object which includes the DB id and pointer to the (actual, not interface{}!) struct, as well as other metadata perhaps
record.Data.myField = time.Now()
wrapper.Update(record)
for i, record := range wrapper.List(Params{}) {
\\ do stuff with all the MyStructs
}
...and so on and so forth. The goal here is not to implement a perfect ORM (e.g. pointer/FK spaghetti) but to secure that initial productivity boost of easily ACIDifying my data. As my data model gets more mature, I can individually migrate these "weak" JSONB schemas to proper, (de)normalized, relational Postgres schemas and define their data access appropriately.
It’s established, so it is “boring” now and that is not necessarily a bad thing. I do get the feeling that Rails is becoming “more popular” again but not in the way you would expect. Some of the old Rails guys that moved on are getting nostalgic (me and one of my friends for example) and some guys that tried a few web frameworks are giving Rails a chance now that it isn’t the “hipster” tech it once used to be.
P.s.: Just take a look at how this article is exploding (also most of the other Rails articles on Hacker News lately). They don’t just explode in popularity and comments but every single one of them has given me ridiculous amounts of karma. I would say that is a heavy indicator of a Rails popularity bounce-back, vocal AND silent.
It’s around and popular, but it doesn’t have zealots to suck all the oxygen out of the conversation.
Look at the people in this comment section that are emotionally upset that the author didn’t prefer JS over ruby. They’re calling the author stupid, saying the author is bad at bootstrapping or just not using the right frameworks.
People don’t seem to be emotionally connected to Rails in the same way.
They used to be at one point. Then the hype machine switched track. The thing that did it, from memory, was Twitter coming out and saying they'd switched away because they couldn't make it go fast enough. All of a sudden all the cool kids decided that execution speed was the only thing that mattered, and oh look, v8 can handle a tonne of connections without slowing down and the circus moved on.
Another rails dev (10 years) it’s not the bright shiny new toy it used to be. But it’s still used by many, the jobs are plenty (I get tons of recruiter calls), and experience in it tends to pay very well.
I'm seeing the very same. Because I had some Rails experience in the 2.3/3.x days, I get recruiters constantly bombarding me to come work with their Rails monoliths. The few companies that I've actually spoken with are all trying to get AWAY from those massive Rails apps. They're moving to Elixir "microservices".
My read on this is that many of these apps were begun as PoCs/MVPs and as the original engineers have tried to scale, they've lost interest. So we have a large amount of 5-10 year old code bases that are looking for maintainers. One friend in particular contacted me and asked if I knew anyone who'd be willing to contract with his firm to upgrade a Rails 5.x app. This tells me, they had no one on staff that could do so.
So yes, the need for Rails devs is large. The popularity of it? At least in my area... not so much.
All those successful efforts with Rails over the last ten years -- many are moving on to other tech, many are just getting bigger with Rails.
I thought I had moved away from Rails into Go (I find the two very complementary), but I got pulled back into some solid, meaningful projects using Rails.
People complain about the tech, but I would rather have a bad tech stack on a product/app with a chance than the perfect tech stack making the next twitter for dogs.
The latter. Rails isn't cool but you see it used in so many places. I'm currently contracting with a UK Government dept and Rails is one of the two approved stacks, it's used on basically all externally facing projects.
No doubt it's very popular still - I see it used every day. Just most of the people using it are busy using it and it's not the new hotness that warrants constant new discussion.
To be fair, Java has been evolving at a much more rapid pace over the past 5 years and has started to creep back into conversation. Pressure from Scala and Kotlin have been pushing it to evolve (for the better).
Oh yes, and I was glad to see recent Java GC improvements get some press. Java's big win over Ruby and Python is that Java is fully specified such that anyone could write a new implementation and mechanically check if it is compatible. (AFAIK both Ruby and Python say "my implementation is the specification".)
(JavaScript is a bit of an oddity since it has a formal language spec, but NOT a formal virtual machine spec.)
It's still productive. It's just not "cool" anymore. Further, some of the choices DHH and company have made have been the opposite of other communities: for example, rails omakase still doesn't default to a single page app, though it is supported.
If I started a project today that was slated to be on the web, I'd pick one of two languages. If the least interesting part of the work was the code, and I didn't see significant places where I was worried about future performance in the business logic layer, I'd pick rails. (This is 95% of cases.) If I thought this system would have performance-critical components or would need to scale to thousands of programmers of varying skill, I'd pick java.
(I have a soft spot in my heart for clojure and elixir, and there are some edge cases where I might pick those, and a java ecosystem would allow for clojure interop. For example, some problems lend themselves to functional thinking. And, of course, there are some problems where another language shines - I could see defaulting to another tool if necessary.)
I switched from Ruby on Rails on my side project to PHP.
Building the web app in PHP took me 2 hours – the same thing in Rails would have taken 2 days.
Now i have time to read HN.
It'd be more interesting to see how you replaced rails framework stuff that need 2 days to build your project with vanilla PHP code that takes 2 hours.
If there was only a good Ruby in browser implementation, I'd be more than happy to go Ruby everywhere.
New Rails with turbo streams is great, but often times it's desirable to do data processing on the client, and then getting back to JS feels like a step down.
I'm reminded of this all the time whenever I want to do a side project. I think to myself I should checkout a new framework or language and aside from Phoenix/Elixir and Rails/Ruby I have not found any that use conventions that allow you to concentrate on features and your product decisions as much. Node is a clusterfuck of technical decision making at every step in comparison.
In my eyes this kind of feels like another sign that things have stagnated in tech (on the fundamental innovations front, not the 'people are doing things' front). There was a massive explosion of thing happening a decade ago but today not so much, even to the point that you can get away with using years old tools without really much disadvantage.
This is a pattern I've noticed throughout history. I really wish there was a popular science book that tried to answer the question: why do humans seem to make so much progress with each initial invention? It seems like everything from bridges to antibiotics, the initial inventions have lasting power because they address 80% of the problem. The track record of success inventing an 80% solution as the first entrance is astounding but it is clouded by our focus on the exceptions like flight where we were stumped for a long time. Surely there's some survivorship bias too. We don't remember the bridge designs that failed immediately, but I'm focused less on that. Why are _any_ of the initial designs in so many fields still around? Why are fundamental shifts that completely upend our understanding of fields so rare?
I've also noticed this trend, but I never see it discussed or talked about within tech or without. It feels like the second renaissance in computing brought on by the smartphone is petering out. Maybe it's because I'm cynical about cryptocurrency, which is where people say most of the "innovation" is right now.
The performance degradation for 99% of web app use cases is negligible compared to the productivity increases. My team switched from a node/react environment to a full stack rails monolith with stimulusjs and we're shipping faster with less bugs.
IMPO, the only significant advantage of micro services and JS is client-side rendering. If you need to publish content to hundreds of millions or billions of clients, then that makes sense. But for most systems, a Linode VPS running Rails, PHP or whatever (with a CDN in front of it) is more than adequate.
This comparison feels like it's less about Node vs Rails and more just about "batteries-included framework" vs not. (Although, perhaps there isn't really a Django/Rails equivalent in Node yet? I'm not definitively sure.)
>I’ve always found it hard to climb out of the plumbing, forget about it.
This is the crux it of it, and it's true for any web project not relying on "magic" frameworks. And of course, it comes with tradeoffs. Namely, frameworks can be inflexible, and they can be difficult to understand/debug under the hood.
There is no escaping these tradeoffs, with any framework or language. More magic means less plumbing and more initial speed, but less flexibility and potential issues as complexity/scale increases. It's all about trying to choose the best tool for the job.
"Building the web app in Rails took me 2 days – the same thing in Node would have taken 2 weeks"
From my experience with Rails and Node, I could not believe a Node framework, e.g. Nestjs takes 5x more effort than Rails (nothing against Rails, it's a perfectly fine choice today for projects).
Yes, the author also mentioned login and NestJS has built in PassportJS integration, which in turn has a supported OAuth2 module so the end result is you can hook up authentication for most major providers in 20 minutes (with working sessions too).
One thing I want people to consider when choosing new tech stack is what startups are using. At the beginning of december I analyzed random 39 startups from last 3 years in YC. This is what they recruit people for (backend technologies)
Startups use whatever is easier to hire for to get stuff out the door ASAP, unless the founders have a specific technical taste. That's why now it's JS and 10-15~ years ago it was Rails.
I think Rails is great (although some of the "magic" tends to concern me), but I gotta say Typescript is the biggest factor for me sticking with node. I just really love type annotations even if the underlying runtime is dynamic.
Comparing Node to Ruby on Rails seems misguided, wouldn't a more apt comparison be something like Next.js or Svelte Kit to Ruby on Rails? Ruby has its fair share of minimalist[1] web libraries and small gems that aren't very different from Node web servers and npm packages.
Edit: I've noticed at the bottom the author mentions that they use "Node" to mean Node web frameworks, but still I think there's something lost to not mention the new wave of frameworks like Next and Svelte Kit.
You're right, but frameworks like Blitzjs (built on top of Nextjs) and NestJS are probably better comparisons. I went in the opposite direction from Ruby to Node land, and it's just as easy and quick to build an app now just like Rails. The issue with nodejs is the paradox of choice. Just like in Java, there are so many full stack frameworks to choose from that it's easy to get decision paralysis, where as there's only really one choice in both Ruby and Python.
I've been using Remix a bit and absolutely love it as a framework. It has a great mechanism of separating server and client side code where you can colocate server side code that only applies to a given route on your page.
This makes it trivial to write awesome web apps that don't need any JS on the client to work. Of course if JS is enabled client side you can do a lot more but this way the app is good to go without needing to parse any client side JS.
All data can easily be fetched on the server and passed down to the client for any route.
20+ years of experience here, including a decade of Rails in the middle. And Ruby/Rails have certainly caused me enough headaches. And as a proponent of pure fp, I’m not fully convinced anyone should be using a dynamic language if they have a reasonable way to avoid it. Still… I will admit, you can get a lot done quickly with Rails. And if I had to build a db-backed CRUD-ish website/API, Rails would be on my list of choices. AND AND, as a fan and believer in SQL, I still actually like ActiveRecord.
I d like to see a sociological analysis of this. It seems to me that the JavaScript fad (which is fading now) came from a generation of developers who have different priorities. While RoR came at a time when developers wanted to ship working websites fast, it seems javascript serves other priorities, like showing off your colorful code to investors or impressing your superiors in Megacorp Inc with your new 11 level abstraction that is perpetually compiling. In the end people always get what they incentivize
I’ve come to learn that technology is both cyclical and fashion, but driven mainly from advancement if course.
Is this Rails version still a monolith? Because the way Web3 is trending and with decentralization, microservices should remain the dominant architecture.
I built the site I'm currently working on in Python (Flask) based purely on the fact that I knew it best.
I've been toying with the idea of adding a React/Vue frontend for months but I can't bring myself to do it because, well, it's complicated. I barely know where to start.
It's not a 1:1 comparison to Rails (I'd love to try it someday), but I feel a lot of what the author is talking about. Boring, well developed, well proven tech makes rapid featured development a breeze.
If tou aren't in business of building SPAs then React makes little sense, except that with JSX you get full typesafety in client logic which is super branchy due to edgecases.
I'm interested in the opinion of people that have experience in both the "classic MVC" frameworks (Rails, Django, Laravel, Spring) and in the "frontend first" frameworks (React, Vue, Angular). If you had to build a web app that's a subset of Excel, sold as SaaS, as a solo developer, what would you pick and why? I know that you can use both together, but I worry that by doing so you lose part of the productivity that's associated with MVC frameworks.
MVC all the way, because otherwise you're never going to finish it. Doing a separate backend + SPA is an insane amount of work compared to a traditional full stack framework. Just thinking about validations (both server and client) make my brain hurt. Also you'll have to rewrite the frontend before even finishing it given how fast the landscape changes.
And even being a small team and not just yourself, I'd only think of an SPA if 1) You need an offline first experience, or 2) You don't have full stack engineers at hand and you only have backend people which don't want to touch JavaScript and frontend people which only want to work with JavaScript..... but this is more of a people problem than technical one.
I've done a lot of Django in the past, then a lot of SPAs for the last 6 ~ 8 years, and now I'm back to Laravel + Livewire and I'm living in a dream right now. Everything is so easy that I feel I've been cheated the last few years.... so much time and money (from my employers) wasted...
What Rails has done with HotWire and the Laravel community has done with Livewire is the sweet spot for me. Everything is in one place, very little doing things twice -- like validation -- in the front-end and back-end, one router, HTML over the wire, a single auth layer, cost-effective and straightforward infrastructure (db, cache, queue, load balancer, app), and well-defined idioms/conventions to do just about everything. Never looking back.
Blaming Node is like giving pros to Ruby instead of Rails in this case. You're comparing a framework to a runtime with poorly chosen frameworks.
I bet rails is very productive. But getting a SSR hello world up with Node should take two minutes. Express, EJS, done. Most of the admin pages on fastcomments are server rendered and we add features pretty quickly (IMO).
My experience of light tinkering with frameworks in the Rails/Django mode is that they are outstanding if the task at hand falls withing their paradigm.
If one has a requirements shift, and is told to integrate some other prior art, then deep exptertise on both the language and the framework are needful.
That is: the silver bullet is mainly available at the gun range.
This seems like this is mostly based on their choice of technology
> Building the web app in Rails took me 2 days – the same thing in Node would have taken 2 weeks
This is ridiculous, you are comparing a language framework with a runtime. Anyway, my problem with rails and other template based server side rendered frameworks is that the output looks decidedly un-modern and extending it to add the interactivity you can get from modern JS frameworks is hard. I have worked with code bases that were django or rails that bolted on react and other javascript frameworks and the result was not pretty.
For my personal projects today what I do is the following, I use nextjs to build the frontend and I use nestjs with prisma for the api (a lot of the plumbing you were talking about is autogenerated here). I probably can't get up and running in 2 days but I can do it in under a week and adding new features is painless.
When I hear someone say "Node", I implicitly understand that they mean an application with the libraries that go with. The same way I assess React with the libraries that go with. Perhaps the difference isn't "framework vs library", but rather, "explicit framework vs implicit framework"
You'd be surprised what you can get out of nothing more than Rails + Turbolinks. As long as your site idea follows a "pages" analogy it is pretty much instantaneous. Anything more than that and you're trying to make an SPA
> the output looks decidedly un-modern
You could say that about anything. The output styles to how you style it.
Also since when is modernness more important than content?
>Also since when is modernness more important than content?
Design is just as important as content. Design in terms of how nice the site looks and design in terms of ux and usability. If people ignore your site because it looks cheap then the content is pointless. Most users really expect SPAs, they don't expect having to reload the entire site to see new content.
Then you get into usability and many react component libraries really work well with you there. Accessibility for the visually impaired is baked into the library and the popular libraries follow modern UI conventions.
Things like Turbolinks, HotWire, LiveView, and similar html over the wire tools don't reload the whole page. LiveView(Elixir/Phoenix) and HotWire (Ruby/Rails) can update something as small as a single html tag attribute and if you want to, a lot of people sprinkle on something like Alpine for purely cosmetic changes in the UI.
It's really quite amazing what you can do now with these HTML focused frameworks.
It might be better than I think, I just personally don't want to go back to writing html in custom templating languages. I don't have fond memories of that experience.
ERB isn't my favorite, but stuff like Elixir/Phoenix's Heex look react like and are mostly just html. I use Phoenix/LiveView for an internal tool at work and dom updates are so fast that it looks like nothing happened sometimes. It's super easy to maintain too, there are well defined ways to handle state changes and the event api is well designed.
Phoenix/LiveView looks pretty great, hopefully things start to swing this way.
I recently had to quickly add a front end feature that really should have been a separate web app to my main project at work (Vue SPA) to get ahead of some external audit.
Another team hastily built the back end + rest api. There's no filtering / pagination / anything nice in the api, so we just get back 1000s of records and do it all on the front end.
Found out prod deployment that it's used exclusively by contractors in India on very low power VDIs. So extremely bad performance. Doing it literally any other way would have probably been better, but something like LiveView would have been great for the interactivity. Although I don't want to go back to a world without static types.
I don't really find myself missing static types with LiveView, I just write some Ecto Changesets and anything invalid gets bounced back to the browser with an error. That plus some DB constraints and some structural types in function signatures gives you a ton of safety. I basically never see any errors coming from the CRUD stuff, only the more complicated pieces that touch old parts of the app.
Funny you say that, I have the same feelings about putting arbitrary HTML in my JS with React. Seems like we've all collectively forgotten about separation of concerns?
Give me templated HTML any day of the week please :)
The thing is that this was never "separation of concerns", it was always "separation of languages". There were cross cutting concerns across each language (CSS doing layout, styling, animations; JS doing business logic, animations, layout, styling; etc).
Mixing your JS/Other Language/CSS/HTML into components is a separation of concerns that really matters: separation of business/application concerns. Having everything you need that works together to solve a problem in place is very powerful (not to mention convenient).
The separation of languages is a natural byproduct of each language being specific to its domain. HTML does layout. CSS does styling. JS does frontend functionality. Server enforces business logic, controllers, and the data model.
It's clean, clear-cut, easy for IDE's to parse, and everything is in its place.
Dogma or not I still prefer everything in its place vs trying to watch my IDE twist itself in knots trying to figure out which language to use for a given context. To say nothing of all the little eccentricities in the JS engines' reimplemented parsers.
> HTML does layout. CSS does styling. JS does frontend functionality. Server enforces business logic, controllers, and the data model.
In practice nothing works out like this. JS and HTML are tightly coupled, the frontend ends up needing to enforce business logic as well for usability reasons, etc.
> trying to watch my IDE twist itself in knots trying to figure out which language to use for a given context
My team doesn't suck I work with some of the best in the business.
> Why would I bring it up if it wasn't?
No idea, I say it's not an issue because it's not. Millions of people work in react with typescript and have 0 issue working with html, javascript, and css in one ide. I didn't have to put in a lot of effort to configure my IDE either. So this idea that ides can't handle this workload is completely bogus and you are lying though your teeth or just ignorant.
Your IDE. Which if I had to guess is VS Code. Which not everyone uses. And neither does everyone use typescript.
And if some of the best in the business can't (or won't) keep separation of concerns, then I can't help but chuckle to myself at the mess they're creating.
How many levels of metaprogramming do you have to do? Most IDEs start to falter around the third or so. I've been assigned to shit that is Ruby writing HTML containing Javascript writing even more HTML in React's bullshit not-HTML dialect. And yes my IDE chokes. And if that project's designers weren't fucking insane it wouldn't have to, but I digress because modern tooling is a fucking joke. Typescript... pah. Crutches for people who suck at JS.
Besides, the "best in the business" are out there writing embedded C code or zerodays or format codecs. Not writing web apps
With thins like LiveView, you're encouraged to have separate Heex files most of the time, and to keep them free of logic, other than the odd if statement.
Reddit is not 'real time' app, and this seems like a feature, not a bug. Slack is way beyond where Campfire started out, but can you boil the difference down to interactivity?
In my experience, speed matters the most. Not just of development, but in user-experience. Rails is pretty damn good at this, especially recently. I still can't believe how fast a big Rails site like dev.to loads.
Also wasn't Slack in beginning written in PHP? The most not-realtime web stack there is. Maybe you don't have to go all in and can keep the boring application logic parts in Ruby/PHP/Python and offload the realtime performance stuff to more performant system (that can be even be in Ruby/PHP/Python because all of them offer some sort of async addon nowdays). It's strange in world where everybody is talking about microservices to be so afraid to use multiple connect tools that make specific parts easy. Like "Go all microservices but all of them in Node or Go".
I fully agree with this post but it's missing one important (to me) factor. With TypeScript I can reduce the number of tests I have to write and I can be significantly more confident when writing code solo. So I'm more than happy to spend 2 weeks (more like a day) to set up the boilerplate.
Oodles of anecdotes and hyperbole. As someone who moved from Ruby/Rails to Node, my happiness index has been steadily higher. Why is it that we get a rise out of bashing one ecosystem to favor another?
It's a bit different for JavaScript. If you don't like python or ruby or php, you can just decide not use them.
JavaScript is much harder to avoid because there's isn't really a native alternative in the browser.
JavaScript is forced down our throats, liking it or not.
So yes, I personally resent js and its community for it. And I feel extremely pissed when I'm told how supposedly awesome this technology is, because I'm having an indigestion. It's not about getting a rise out of bashing, it's just the expression of an immense fatigue about this ubiquitous stack.
So there's the light trolling of other stacks, and there's js. :)
damn. I've probably worked with 20 languages over the course of a career in as many years and I can't ever recall that kind of seething hatred for something as inanimate as a programming language. I'd suggest your rage is misguided and misplaced. Perhaps redirect that energy towards moving to a sector of the tech industry that doesn't lean on JS.
So... Maybe you were right about the hyperbole part. If you felt it was hatred I probably went a bit to strong haha. But I certainly don't like when you have limited or no choices about something. Also it's not an inanimate thing, there's a community of actual people building and expanding the thing, I blame them for my sufferings :p
I'm an entrepreneur of sorts so there are stuff that I can't really avoid because no one else will do them for me. Doing frontend work is part of that list. I also do a bit of "devops" freelancing and it's hard to avoid to have to fiddle with npm there as well. The size of the part of the industry where you can avoid js is shrinking by the day
I think it really matters whether the core of added value of your solution is on the client side or the backend processing.
For example (in a parallel but similar universe to ruby) you have python, django and vast sea of data science / machine learning "plugins" you can just pull into your project.
Add to that that the idea of creating "desktop like" experiences in the browser seems to go against the grain of what the web is and we may indeed have reached "peak javascript"
Maybe the success of vue and the emergence of htmx point to this underlying reality
I keep saying, half-jokingly: write it in Rails, if you hit Rails limits, it means you've made it! There are very few projects that need something else than Rails from the very beginning.
I think learning new things is always good, if anything I have worked along the years primarily with Symfony/PHP, but as a freelance you try to get projects regardless of tech stack, I've worked on projects using ASP.NET MVC, Phoenix, I've done iOS with ObjC/CocoaTouch back in the days, or Django, and I have the impression that being exposed to different kind of solutions is always enriching and you can bring back to your main stack some fresh ideas/approaches
Comparing a language like node to a framework like rails is like comparing a language like C++ to a database like H2 they both have different goals and use cases.
Sure you can build a database like H2 in C++ and yes doing so will take ages which I think is why most people don't do that and just use MySQL instead of reinventing the wheel. Does this mean we should switch from C++ to H2? Obviously not, what am I missing?
Wouldn't a more useful comparison be something like Node vs Ruby or Rails vs Sails
I've been using Sveltekit, which offers a back end server if you use their `node-adapter`.
Sveltekit uses an intuitive file based routing system, so for side projects at least, you can build out an app/POC very quickly.
Personally, I like Sveltekit's back end server better than Rails (to be fair, I haven't used Rails heavily since v3/v4) and Express. Having said that, I'm not sure Sveltekit's node adapter has been proven to scale yet.
Rails has a lot of nice stuff baked in though. So in terms of the many other moving parts of making an app, such as migrations, db connectivity, I think that's where a lot of time can be added on the Node side, especially if you don't already have a shortlist of go-to libraries for the core functionality you want/need.
Being able to deploy Sveltekit to Cloudflare Pages is pretty amazing. And with their new auto-adapter, you don't even have to change anything from the basic init setup and it just works.
After trying ruby on rails some years back I didn't really liked the framework. I see the benefit of the "batteries included approach", but I didn't like several design choices and back than also the configuration of rails was not fun.
I'd prefer Spring, Quarkus, or Micronaut with Kotlin, because I think these frameworks have better APIs and the performance is better. I also enjoy static typing with a modern language like Kotlin.
This is probably going to generate a lot of controversy around these parts, but I'd argue that PHP is an equally good option to try these days if you're coming from the Node world and want to try something "new". If you keep an open mind, I think you'll be pleasantly surprised, and end up being able to build actual products much faster, as the author here did with Rails.
I was similarly motivated to go with PHP and Laravel instead of Node for a personal project recently. Does anyone with experience in both Laravel and Rails have thoughts on how they compare? Both the frameworks themselves and the surrounding ecosystem?
- no admin (although there are good free projects like filament admin)
- not well defined models
+ queues builtin
+ task scheduling builtin
+ livewire builtin
+ webpack builtin (this saves a ton of time as if you have a problem someone else likely has had it as well)
+ builtin relatively sane api framework (although the inertia integration for things like Vue, seems to almost encourage exposing more data than you mean to, I see this a potential data leak vector with unexperienced developers)
+ composer is way better than poetry/pip/pipenv/ whatever
+ first party support for many things you'll need (Payments, Browser testing, Hosting, Docker development, etc)
+ cheaper developers
+ Laravels facades such as Collection, Arr, Str remove many of the warts of PHP and in some cases can make some manipulations almost as concise and readable as Python
+ Laravel seems to monetize things better which imo is a path to sustainability.
+ Encourages use of modern css frameworks / javascript frontends.
Django:
+ admin (although dated looking and very hard to sell for client facing admin stuff, as it will never look like they want it to), honestly maybe the best admin out there for speed of setting up etc.
+ better models with db columns defined in model, could use typing though.
+ way better documentation
+ python's better more concise syntax on most things
+ fully automatic migrations (although you will eventually run into issues here, with good practices can work very well)
- python packaging in a horrible state
- too many basically essential packages not in core (api, queues (even database based queues))
+ python packages for basically anything out there somewhere
- Django rest framework (this project was okay for its time, but it is seriously dated, and takes the air out of some better projects such as django-ninja)
Having some experience with both, agree with everything you said.
I'd also add Django is great if you're building only a backend with it (and you have no frontend and/or it's an external SPA).
For full stack development, Laravel all the way. Just it's templating system (blade) is a joy to use compared to Django's templating system which feels stuck in the 90s.
Just want to say thanks for mentioning django-ninja. I hadn't heard of it. It looks exactly what I've been wishing was out there. Django is just so good, but the lack of type hints make FastAPI super attractive, so django-ninja seems to have found quite the sweet spot.
I am looking into learning app development with no programming experience. Should I learn Node.js or Ruby on Rails? I hear opinions like Ruby on Rails is obsolete and then other people say it's better because it's more traditional. If it really is obsolete then how are people still using it? But then is Node.js easier and more useful?
25 year vet who knows both well: learn Ruby on Rails, the on-ramp is very gradual and you probably won't need anything else if all you want to build are SaaS-like web apps.
Rails is unquestionably better now than when it was new and cool. Before, the ecosystem and core framework were evolving at a rapid pace, leading to some suboptimal patterns and sometimes making maintenance a bit of a nightmare. Now there's a pretty settled solution for most things. If you want to get started building apps without much fuss, there's no better way.
People who say rails is dead or obsolete have no idea what they are talking about. Rails is better than ever, the core community has stayed strong even while everyone hopped on the javascript hell bandwagon. Enjoy your life, learn Rails.
When I started my web dev career. I have to say Rails was the easiest to get into(It was Rails 4 then). You need to give into the magic in the beginning. I still love it and is main goto thing unless scalability is millions of requests per second.
Some problems I had
- Upgrade from Rails 4 to 5 was a pain
- Memory was a big problem in some apps
"I feel like I’ve struck on a magical treasure from the past" - dang I feel old. Recently got to dig into a MERN stack application. Seemed really easy to build but I still have no idea how the plumbing works. I'm using 5 applications where I used to use 2.
This issue is not about choosing RoR vs NodeJS, this is about Framework Vs Libraries or more technically speaking being lazy and choosing what other people say Vs doing proper research what best suits your project needs.
Really want to try and use Rails for future projects but the magic is just too much for someone new to Ruby/Rails. I had to rewrite the routes with brackets in Rails to understand the working.
One thing that often gets ignored is the importance of getting new developers up to speed. You go to an existing C# ,node.js or Java app and its painful to twist your mind around the architecture. Ruby on Rails helps you with that. Oh db change well lets jump in to models. Oh the business logic change well jump into the controllers. Its easy to get up to speed when joining an existing project.
i love rails, but i’d point out that business logic exists all over the place in a rails app, not just in the controllers. that’s because rails has no standard solution for compound requests (those involving many models and/or multiple actions) that go beyond the simple semantics of http verbs (which i totally appreciate for what they are). some might say that’s a design issue to be worked out depending on the situation, but sometimes, you just need to do lots of different stuff in a single request context.
rails doesn’t cope with that issue very well (some suggest a command or strategy pattern, others service objects, etc.), which is one of the only major criticisms i have with rails. node/npm dependency was another big criticism, but they’re fixing that with rails 7. =)
I like creating a service/coordination layer between controllers and models to put the business logic. Controllers call the services or coordinators which can interact with models, kick off jobs, or call other services. Easy to test and change and keeps controller and model code more manageable. For smaller apps you can get away with shoving all your business logic in the models but that can become a little tough to manage as the logic becomes more complex.
On Linux, you settle on a single interpreter, and makes a virtualenv for each project. Make sure to never install anything systemwide. On Windows, get used to your system being broken (oh, no problem, you already are), but it won't be because of python.
That's basically the same instructions you will have for ruby and javascript. Ruby package management is about as good as python's, while javascript is a toxic wasteland.
There are languages with better dependency management, and languages with worse ones (ok, not worse than javascript, no dependency management is still better than javascript). But python and ruby do not have much difference.
Very true but with conda and docker it's not as bad for production as it used to be. Most of the packaging issues that I run into these days are related to CUDA / C++ libraries, plain python dependencies are not really an issue.
Yes, from my perspective, at least as of 2019. Every year or two since 2010 I have to stand up a new Python project, or upgrade an existing one. I'm overdue, but packages have never not been a nightmare by comparison. The last thing I used was Pipenv, which I will praise for being a tolerable experience by the end of things, but now I hear it isn't even "the thing to use" anymore? Now it's Poetry or Conda? The problem in Python is partly an issue of the individual tools, and partly an issue of the constant churn/change in the ecosystem around them.
Ruby settled on a two-part solution, Rubygems and Bundler, over a decade ago. One is the package format, hosting server, and default distribution, the other is dependency management. In practice they are two sides of the same coin, and you don't have to give much thought to them. I hate reading reductive "It just works!" quips, but it really does apply here.
> On the Python side I think the movement has started to fix the packaging mess. It's going to take a while me thinks.
I hope you are right, but ... this is the pattern: every year or two someone decides to fix it, goes about 80% of the way to a complete solution (which is maybe 50% of the effort, of course), that becomes 'the thing to use'. But then it is abandoned because that last 20% of functionality is a lot of work, and someone else comes up with a new shiny thing, and the cycle starts again.
Better ORM and better migration? That has to be a joke, that's the weak point of the framework...
Yeah there's less magic I give you that, but also because it does much less.
Also for me the Python packages are a minus, they are usually not tested very well and it's very easy to burn yourself when migrating (good luck finding some equivalent of rspec)
> Better ORM and better migration? That has to be a joke, that's the weak point of the framework...
That was probably only true 6–10 years ago. Migrations are a solved problem in Django and I can only think of one very obscure query that I couldn't get done in the ORM and had to drop into raw SQL. Aggregations, annotations and other query expressions in general have lifted the ORM to a truly strong position
I've made a full project about 2 years ago with Django, unless things are improved since then or I'm too inexperienced with the framework it still does not compare to activerecord.
Where are my scopes? Where's the equivalent of strong_migrations? The equivalent of db_consistency? Where are delegate attributes? Concerns? Arel?
The ORM isn't bad I'll admit that but some complex features are tedious.
Last time I used Rails was like 8 years ago so I'm not up to date on the changes to their ORM but when it comes to django the ORM is pretty top notch, especially when it comes to Postgres support.
I've never used rspec but it sounds like pytest and hypothesis would do the job. In ruby there's no hope for pytorch / tensorflow / ray / numba.
Django I knew had pretty weak testing tools compared to Ruby/Rails mostly because the culture was no there. It was way harder to find a Rails App with had little to no tests. Quite a contrary in Django world.
Rails is a Web Framework. I don't understand the point about ML. Those categories are totally different. I guess it might be a tiny plus, but not very practical. Going this route one might conclude that game studios should build Websites in C++?
Because most machine learning models are still deployed behind a web server? For ranking, filtering, recommenders, visual search / nearest neighbor search, NLP, image recognition and etc python is a great first choice.
> I've never used rspec but it sounds like pytest and hypothesis would do the job
Sorry it really does not, having factorybot + rspec + rspec-mocks really is a super power when it comes in testing.
The issue is that most of the time I land on a django project, it has really poor testing whereas most of the time I land on a Rails project, it has very close to complete testing. The reason is that the tests are more tedious to write.
And this culture trickles down to your dependencies as well. Anything you install with rails is almost guaranteed to have the upmost quality of testing.
It's nowhere near as equivalent, where's the behavior testing? Where is stuff like allow_any_instance_of(...).to receive(...).and_return(...)? What about shared examples? How can you patch globally the current time? Where are partial matchers like an_object_having_attributes? What about automatic db rollbacks?
They are automatically generated from the model. It presents some warts etc, but works pretty well. It basically does require some hooks to ensure that developers don't work on the same migration at once, but not a big deal.
For some people Python is not a plus, usually for us Ruby guys. I did like Python a lot more though before I found Ruby but afterwards Python became sort of “practical” and unexciting.
We usually also want the “magic”.
I can’t argue with you about the ORM and Migrations since I haven’t used Django much. The feeling I get though comparing the two is that Django is more fixated on building business facing backends and Rails is more focused on building customer facing frontends.
Over all I would recommend figuring out if you are more of a Python/Django of Ruby/Rails type. It will tell you something about your personality.
While I love Django's backend I have found a few clients balk at its general style and non-responsive design, even for un-exciting admin tasks such as approving new objects etc.
As far as getting things done, well its probably the best admin site out there.
> Over all I would recommend figuring out if you are more of a Python/Django of Ruby/Rails type. It will tell you something about your personality.
I eventually gave up and switched to a semi-technical product management role.