Hacker News new | ask | show | jobs
by tptacek 2811 days ago
The answer is probably that parts of Rails are worth knowing, and other parts aren't.

ActiveRecord and the Rails Controller/Model/Routing system are as good as anything in the serverside framework world. A few years back people might have started saying that AR was in danger of being obsoleted by "modern" databases, but SQL (and particularly Postgres) has come roaring back, and AR remains one of the best (arguably the best) SQL ORM.

At the same time, there's a lot of mechanism in Rails that is aimed at front-end work; templates, different template engines, helpers, the inscrutable asset pipeline. This stuff, not so much anymore. The energy you'd put into learning how to do idiomatic front-end in Rails, you should instead put into something like React (probably: into React).

People with a visceral "No" reaction to your question are probably thinking of what would happen if you started with a couple Rails books and tutorials and just went to town building a 2012-era idiomatic Rails application. Don't do that! But as an API server backend, Rails is fine, and does some things better than other platforms.

For whatever it's worth: we see a lot more Django today than Rails. 5 years ago, it was the opposite. People probably wouldn't recoil at the prospect of you doing an idiomatic Django application, even though it's not that much different than an idiomatic Rails application.

4 comments

Worth noting that webpack (via the webpacker gem) is supported in Rails 5.2, and will be default in Rails 6; using that gets you access to current versions of React, Redux, and pretty much anything else packaged as npm modules. You still need some kind of view layer to serve up the pages that invoke the JS, but if what you're doing is a single-page app that's almost all React, then that view layer doesn't actually have to do very much.
I wonder why Rails 6 doesn't go all in on Webpack and drop Sprockets.
the inscrutable asset pipeline

This has basically all been replaced by Webpack so I’m not so sure

> A few years back people might have started saying that AR was in danger of being obsoleted by "modern" databases, but SQL (and particularly Postgres) has come roaring back, and AR remains one of the best (arguably the best) SQL ORM.

To me, that gives me pause about the viability of ORM as an approach more than it vouches for Rails. ActiveRecord has so many limitations and footguns that using it as a serious production framework is...well, doable, if you're willing to do a lot of the work that ActiveRecord claims to save you from.

People have been saying this about ORMs since the original Rails Blog Demo introduced ActiveRecord, but I don't think we even have to engage with the argument, because no industry trend has made ORMs less relevant; instead, the sort-of collapse of the NoSQL trend has, if anything, made them more relevant. If AR was useful 5 years ago, it's useful now.

If you're going to try to tell me that there's a countervailing trend of people meticulously writing their own SQL statements and record serialization logic, I'm going to say no, I haven't seen anything like that in our client base, or in blog posts, or anywhere else.

Incidentally, lest I come off as a Rails partisan: I don't use it anymore; the last thing I built with Rails (Microcorruption) was in 2013. But I sort of do miss ActiveRecord sometimes.

I can't speak to the broader state of the industry as you can. I don't know what the trends are.

I'm just not actually sure what problem ActiveRecord actually solves. If you don't want to write SQL and you're willing to live with a certain degree of inconsistency in your data, that's what NoSQL is for. If you actually want the benefits of a SQL database, ActiveRecord makes the easy things easy and the difficult things impossible unless you just give up and write SQL, which you could have just done in the first place and wouldn't have actually been that much harder.

It's entirely possible that everyone does the same thing that I did when I worked on Rails apps: manually add all the DB constraints the ActiveRecord documentation tries to talk you out of, write my own error handling code for when these constraints threw exceptions that ActiveRecord had no idea how to handle, liberally call 'connection.execute' or 'find_by_sql' when nothing I wanted to do cleanly fit into the ActiveRecord query interface, and so on. It's also entirely possible that some ORMs other than ActiveRecord does a much better job at these things, but I'm taking you at your word that AR is the best.

> ActiveRecord makes the easy things easy and the difficult things impossible unless you just give up and write SQL, which you could have just done in the first place and wouldn't have actually been that much harder.

Most queries in a typical web application are much easier with ActiveRecord, others with plain sql. A decent rails developer would know to use the right tool for the right situation. Throwing out all of ActiveRecord is throwing out the baby with the bathwater, in my opninion.

Unless something has changed to make this discussion interesting, we're really just recapitulating a decade's worth of ORM debates people can just look up in the search bar below.
> you're willing to live with a certain degree of inconsistency in your data, that's what NoSQL is for

What is this even supposed to mean? Are you suggesting that ActiveRecord, a way to model the data in your database and layer behavior ontop, gives you as inconsistent data as "NoSQL"?

That may be the weirdest thing I've heard on HN.

> the difficult things impossible unless you just give up

Like what?

After reading the rest of your post I just think it's that you haven't used Rails since 2006.

> After reading the rest of your post I just think it's that you haven't used Rails since 2006.

I used Rails on a full-time basis between approximately 2011 and 2015.

> Like what?

Did you actually read the rest of my post? I explicitly covered that:

> ...manually add all the DB constraints the ActiveRecord documentation tries to talk you out of, write my own error handling code for when these constraints threw exceptions that ActiveRecord had no idea how to handle, liberally call 'connection.execute' or 'find_by_sql' when nothing I wanted to do cleanly fit into the ActiveRecord query interface...

And while I haven't used Rails since 2015, a quick check of the documentation reveals that the same basic limitations still exist, which I've written about before:

> OK, what if you want to generate the SQL dynamically with attributes? connection.execute doesn't do sanitization for you by itself (though you can call a private method to do that). If the generation is more complicated than that, you also have to have code to concatenate together strings of SQL code. Not because Rails doesn't have a SQL generation library, just because it's tightly coupled to ActiveRecord and fuck you and the horse you rode in on if that isn't good enough for you.

> I generally advocate for find_by_sql and select_all, but think about what that actually does. It instantiates a bunch of ActiveRecord objects that have to be of a particular model (what if the query joins tables together and returns a result set that doesn't actually neatly contain the intended columns of a given model? I can't even use ActiveRecord::Base.find_by_sql, I have to choose an actual ActiveRecord model arbitrarily), has the columns of the result set dynamically bound to it as methods during runtime (slow), also has the methods of the model itself bound to it, which may have unexpected behavior based on the query (especially if we just choose an arbitrary model), and in exchange we get to treat the result set as an array of structs rather than an array of hashes (which admittedly has its performance advantages, but not if the fields have to be dynamically bound to each object as methods!). Oh, and if you're writing an INSERT statement you have to use connection.execute after all. Have fun!

https://news.ycombinator.com/item?id=11750676

> The expectation is that "validates :field, uniqueness: true" would validate that the value of the indicated field is unique among all rows in the table. However, this abstraction breaks spectacularly. Any web application, even a Rails app, is usually run over multiple processes, often on multiple different hosts. Uniqueness validation does a non-atomic check and set, which is a known race condition in this kind of environment. The guide does say:

>> ...it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index on both columns in your database.

> But what actually happens when we do this? The race condition where you would otherwise get non-unique values inserted into a column of unique values is instead a race condition where a database adapter throws a generic exception for "the DB complained" with an error message about a failed constraint, and your site throws a 500. Your only recourse is to capture an overly generic class of exception that's thrown by e.g. the MySQL adapter, pattern-match the exception text for a magic string like "uniqueness constraint failed" depending upon which DB you're using, and write your own custom code to recover from that.

> That's right: Rails has adapters for MySQL, PostgreSQL, etc, but "adapting" different SQL variants to ActiveRecord doesn't go as far as turning constraint failures, lock wait timeouts, etc. into generic, application-intelligible exception classes.

> ...

> In other words, something that Rails pretends happens in one line of code does not actually happen at all, and to make it actually happen, you have to write a whole bunch of code that has to resort to string-matching a bucket exception class for "the DB complained" for the specific exception text that your particular DB engine throws. This is probably the worst example, but it's illustrative. Rails provides the illusion of simple interfaces and enjoyable programming. After working in Rails for just a few years, though, the illusion has vanished for me and I spend far too much time asking questions like "how the fuck did THAT get set to nil?" and "what does does it take to turn this multiline string of raw SQL into objects I can actually use?".

> What I would do, given Rails' existing framework of "programmatically discover the table schema and magically generate logic from it", is set it up so that it observes uniqueness constraints and programmatically adds the validation when found. Also, the adapters should interpret server error messages, throw a custom exception class for "uniqueness constraint failed", and ActiveRecord should catch this exception class and turn it into a failed validation when you attempt to save a record.

> If that's too much work, just be fucking honest, remove the uniqueness validation (because it's completely useless), and be upfront with us that we have to roll our own solution for it.

https://news.ycombinator.com/item?id=11752199

What's your view on ORM's like Ecto (for Elixir) and possibly Sequel that, from my impression so far, stick closer to the underlying SQL? I find myself generally agreeing with your view on things, but my impression of ActiveRecord has somehow become relatively negative. I don't know enough to know what to think, so I'm curious how you see ActiveRecord in relation to the alternatives.
Minor nit: ORMs and associated pain go back at least as far as Smalltalk (Objectivity/DB from 1990), pretty much before the rest of the world discovered OO. There was a lot of energy put into OO databases, to little avail.
I always wondered what really happened to OO databases. They were supposed to be the future... 20 years ago. And then MySQL exploded and everyone went back to tables. What was the problem: speed, difficulty, price, all of the above...?

I’d love to hear an insider perspective from anyone who might have worked on those things.

We ran some benchmarks and didn’t see a lot of speed.

Also there is always an ecosystem influence issue with choosing databases

Why React over rails front-end? It seems like it adds undue complication. What’s the real benefit? Basecamp works great and it’s a rails front end. Rails make full stack development pretty easy.
You can have the best of both worlds and use webpacker to mix React or VueJS into the Rails frontend where it makes sense, eg complex forms or widgets. Many webapps are not Facebookish and don't need to be SPA blobs, with all the additional complexity, SEO and accessibility costs.
It really depends on the application. If you're making something that has a highly interactive UI, then React is a great tool for that. It doesn't have to be all or nothing though, you can use Rails server side rendering with React components for the complicated stuff. Basecamp is not a fair comparison, they use Stimulus which is their own frontend framework.
React buys you two things: (1) reusable components (2) React Native

https://thinkster.io/tutorials/what-exactly-is-react

It's major criticism: there is a kernel of truth in the joke that React is a dressed-up PHP (in the sense of how you put the components together)

Some other options are Vue and Elm.

It's been a long time since I wrote or even had to look at PHP, but I have done work in PHP. I use React constantly. I do not see any similarities between the two, like, at all.
Yeah, I was shocked when I first heard of it. But when I thought it about it, it makes sense: https://www.reddit.com/r/reactjs/comments/58wmnz/so_reactjs_...
Here's another comment from that reddit thread:

"If you're at all familiar with the history of React, there's actually some amount of truth to this. React grew out of an internal PHP extension at Facebook called XHP. See the recent post describing React's history at https://facebook.github.io/react/blog/2016/09/28/our-first-5... for more details."

"That said, the parallels only go so far. PHP is frequently rather unstructured, while React lends itself to some very specific structures. I don't think I'd necessarily say that PHP typically involves "recursively breaking down parts of the page". But sure, some similarities. (Then again, just about anything that involves template-ish work has some similarities... )"

That blog post section describes JSX, not React. JSX is just a notation.