rails: Rails 6 RC2 joins / arel regression

We have a query that works with all versions of Rails from 4 to 6 RC1:

https://github.com/thredded/thredded/blob/c691be6c9b4b25dea291ea4cfe7ea9b0de773c89/app/models/thredded/messageboard.rb#L131-L138

In Rails 6.2 RC2 the very first join (joins(:topics)) is no longer produced (INNER JOIN "thredded_topics" ...), resulting in an invalid SQL query.

Originally reported in https://github.com/thredded/thredded/issues/822. This was reported for PostgreSQL, not sure if other databases are also affected.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Reactions: 1
  • Comments: 20 (19 by maintainers)

Commits related to this issue

Most upvoted comments

Maybe it’s then time to reconsider Arel as public API, because a lot of people/companies are using it. Without Arel, there’s no viable alternatives to building complicated composable and parameterizable queries with ActiveRecord. Also I believe it’s safer to use Arel than strings.

In my current and in my previous company, it was forbidden to use the built-in string format, everything has to be done in Arel, what cannot be done with ActiveRecord::Relation directly. We started to use Arel everywhere in Rails 4.X, and it has been getting better with every release (exception was 5.1)

That is splitting a hair finer than I can discern the difference. If Arel wasn’t part of the public API of Rails, it is because it wasn’t part of Rails, clearly advertising itself as a standalone component, upon which Rails just happened to depend, right up until the point it was absorbed into the bowels of ActiveRecord and vanished.

As for “never”, I only had to go back to Rails 4.x to find public API methods that explicitly accept and return Arel objects, and there are still references to Arel in Rails 6.1 public docs.

One may as well suggest that GlobalID isn’t part of the Rails API either, it has even fewer mentions in public and is also a separate gem.

I know that merging Arel into rails/rails made a lot of sense for maintainers, but for advanced users it was more like a Central Committee suddenly disappearing an old friend for being too difficult and too powerful. I could only file that in the drawer of Very Unhappy Outcomes. It also added barriers to being an occasional third-party contributor to Arel because I have to extract and build the docs myself now.

If there are plans to expose it in the future, please link them, so we can all contribute. I really think the multi-storey concept of software is super applicable here.

It was public, and it was intended as an ORM builder. It boils my head that the Rails core team not only co-opted Arel, decided it was wizards-only and should be locked away in the tower, and is now lying about its historical status. Do you think we can’t read the old README?

It’s totally against the spirit of the multi-story model of software that Yehuda Katz and Ernie Miller spoke about at RailsConf 2014, talks that Sean Griffin then cited as inspiration for the Attributes API.

Some things can only be composably/neatly achieved with Arel and this holier-than-thou line so often parroted about it being a “private API” is just a load of elitist, revisionist claptrap. Arel is incredibly useful at times and is sometimes the single most impressive component of Rails. The advice should be that it is powerful, dangerous, that all Arel-based expressions should have tests, and that breaking changes may occur, but not that it is somehow an untouchable, unknowable, unspeakable wizards-only secret.

@inopinatus 👏👏👏 The fact that they locked Arel away and have tried to gaslight us into believing it was never part of the public api (arel_table was literally in the Rails Guides) continues to frustrate me so much.

Arel should be public, or ActiveRecord should expose everything Arel does, full stop.

I believe we could fix this issue, but arel is private API of the framework and there is no guarantee that query will always work.

I like how we are invited to use so called non-public API’s to fix this kind of shenanigans:

DEPRECATION WARNING: Dangerous query method (method whose arguments are used as raw SQL) called with non-attribute argument(s): “random()”. Non-attribute arguments will be disallowed in Rails 6.1. This method should not be called with user-provided values, such as request parameters or model attributes. Known-safe values can be passed by wrapping them in Arel.sql(). (called from …)

(emphasis mine).

@danielricecodes Recently merged was https://github.com/rails/rails/pull/36696 making the specific example of lteq possible using a range, as in where(valid_from: ..Date.current). However, the general point remains true, because some intervals cannot be represented as a Ruby range and need Arel or SQL.

In practice, outsiders are welcome to contribute to Arel, but not welcome to use it. My feelings on this cannot be expressed politely.

Maybe it’s then time to reconsider Arel as public API, because a lot of people/companies are using it. Without Arel, there’s no viable alternatives to building complicated composable and parameterizable queries with ActiveRecord. Also I believe it’s safer to use Arel than strings.

In my current and in my previous company, it was forbidden to use the built-in string format, everything has to be done in Arel, what cannot be done with ActiveRecord::Relation directly. We started to use Arel everywhere in Rails 4.X, and it has been getting better with every release (exception was 5.1)

Agreed. There is no better way to do time range scopes than by using Arel.

scope :started, -> {
  where(arel_table[:valid_from].lteq(Date.current))
}

AFAIK - this is perfectly valid and even encouraged in the older Rails Guides (as previously noted above).

Built-in alternative are strings.

Strings are not composable, parameterizable, or cross-DB compatible (important for library authors).

It was never public.

It wasn’t tagged as a private API in the rubydoc, the methods were documented with examples, and the Arel gem itself was available standalone.

Lots of people thought (and probably still think) that it’s public (e.g. https://thoughtbot.com/blog/using-arel-to-compose-sql-queries#arel).

This is what docs looked like:

image