| It's hard to answer, in the sense that yes, you can use ActiveRecord relationships for the purpose of _building a query_. The point is, you should use them only for that. And it comes with the downsides of distancing you from SQL, which is not negligible. The problem is if you try to access relationships that you didn't load from the object, that shouldn't be done.
It's the autoloading from the database that is the real problem. If you have enough discipline and enough authority to ensure that never happens within the software you are working on, you can. It's really culture problem. As soon as you pass around a `user`, someone will type `.posts` on it, or `.save`, suddenly your business logic depends on the database shape, rather than on contracts.
What if your database shape is wrong? What if your database shape needs to change? The goal of good architecture is to be resilient to change, or to even _postpone the choice_ to a moment in time where you have more data to make the right one. The safest way is: query with activerecord, map to plain ruby objects and discard the activerecord ones immediately. This will also help you discover the entities you didn't know about, for example, if you have a table of users identified by email, that's the "User" table in Rails. However, let's say that you take only a subset of that table (with select), such as "Full Name" and "Email": this could represent something different. A Newsletter::Subscriber for example. And the newsletter subscriber entity can be used in the Newsletter::Weekly::Send object, as well as the Newsletter::Unsubscribe.
If you realize that this should not have been in the users table in the first place (I have no idea myself), the cost of change is way lower than if you passed an activerecord object around. I hope this answers some of your questions. There is a lot to say on the topic.
I'm happy to chat more on slack or an online videoconference session |
I think I understand more of the sentiment now.
> As soon as you pass around a `user`, someone will type `.posts` on it, or `.save`
I'm not much of a fan of the active record pattern, and I can see (have seen) how optimistic/naive developers can get in trouble - but I feel these are two separate problems:
> someone will type `.posts` on it
This doesn't have to be all bad, just make sure there was a join or include first - perhaps via a scope (eg: User.with_posts).
I suppose some rails apps end up doing "much more than crud", and then it can be easy to stumble. But I find that with some modicum of discipline, "fat models" can go a long way towards making "slim controllers" fall out naturally.
> someone will type.. `.save`, on it
This why I use AR objects, so I can do crud. Sure if dealing with "posts" (plural) you want to avoid: posts.map... save in favour of update_all.
And while there's save! - data integrity belongs in db constraints. But validations are a great tool for better ux and error feedback. The major problem today, is probably that you'd want to (only) run them as client side js.