Skip to content

Conversation

@mateuscruz
Copy link
Member

@mateuscruz mateuscruz commented Jan 3, 2026

Every time there's a new Rails release, active record internals are refactored which, inadvertently, breaks the intended behaviour for this gem.

I've had to fix it multiple times (#201, #84, #79, #41 – that one was a patch which is supposed to be non-breaking) and, at this point, I'm just done. I don't want to fix the same issue, over and over again, every time they release a new version.

On top of that, it looks like they intend to deprecate many of these internal methods we hijack to favour the higher-level ones, and I think that makes total sense.

The higher level methods have been mostly stable since Rails 5.1. When new changes are added, they are usually backwards compatible.

With that in mind, I'm changing how we hijack the adapter methods.

Lower-level method higher-level counterpart
exec_insert insert
internal_exec_query select
exec_query N/A
execute N/A
exec_update update
exec_delete delete

exec_query and execute do not have higher-level counterparts, as they're meant to be used directly, so they will still be hijacked. I'm also adding exec_insert_all to the list, it's an exception to the rule. It doesn't have a higher-level counterpart, but also, it's not meant to be used directly. Instead it is called by InsertAll.execute when Model.insert! is called.

All the higher-level counterparts are stable API and are compatible with both raw SQL strings and Arel trees. That also gives us the chance to leverage a custom Arel parser to simplifly the AST when pattern matching read replica queries.

I'm also removing all the multiple tests for each hijackable method, since they test the exact same thing. Instead, I'll be adding new integration tests for the active record model API in #208 (i.e. Model.all | create | first, model.save | update | destroy, etc). Those will help us detect breaking changes more easily. The current test suite is not able to find those automatically and yields false positives.

@mateuscruz mateuscruz self-assigned this Jan 3, 2026
@mateuscruz mateuscruz marked this pull request as ready for review January 3, 2026 06:15
Every time there's a new Rails release, active record internals are refactored which, inadvertently, breaks the intended behaviour for this gem.

I've had to fix it _multiple times_ (#201, #84, #79, #41 – that one was a _patch_ which is supposed to be non-breaking) and, at this point, I'm just done. I don't want to fix the same issue, over and over again, every time they release a new version.

On top of that, it looks like they intend to [deprecate](rails/rails@3fc2ca0) many of these internal methods we hijack to favour the higher-level ones, and I think that makes total sense.

The higher level methods have been mostly stable since Rails 5.1. When new changes are added, they are usually backwards compatible.

With that in mind, I'm changing how we hijack the adapter methods.

| Lower-level method | higher-level counterpart |
|---------------------|-------------------------|
| `exec_insert`| `insert` |
| `internal_exec_query` | `select`|
| `exec_query` | N/A |
| `execute` | N/A |
| `exec_update` | `update` |
| `exec_delete` | `delete` |

`exec_query` and `execute` do not have higher-level counterparts, as they're meant to be used directly, so they will still be hijacked. I'm also adding `exec_insert_all` to the list, it's an exception to the rule. It doesn't have a higher-level counterpart, but also, it's not meant to be used directly. Instead it is called by `InsertAll.execute` when `Model.insert!` is called.

All the higher-level counterparts are stable API and are compatible with both raw SQL strings and Arel trees. That also gives us the chance to leverage a custom Arel parser to simplifly the AST when pattern matching read replica queries.

I'm also removing all the multiple tests for each hijackable method, since they test the exact same thing. Instead, I'll be adding new integration tests for the active record model API in #208  (i.e. `Model.all | create | first`, `model.save | update | destroy`, etc). Those will help us detect breaking changes more easily. The current test suite is not able to find those automatically and yields false positives.
@mateuscruz mateuscruz force-pushed the hijack-only-higher-level-active-record-adapter-methods branch from 304baad to 1e12d6a Compare January 3, 2026 06:18
@mateuscruz mateuscruz merged commit 030afda into main Jan 3, 2026
16 checks passed
@mateuscruz mateuscruz deleted the hijack-only-higher-level-active-record-adapter-methods branch January 3, 2026 06:33
mateuscruz added a commit that referenced this pull request Jan 6, 2026
Add ActiveRecord model integration tests

#213 follow-up.

This change adds integration tests for common ActiveRecord model methods (e.g. create, save, update, destroy, reload, etc).

The current test coverage ensures that the methods we're hijacking at the adapter layer itself work, but the on the higher model layer, the chaining of those methods has changed at each major Rails release, which introduces regression on this gem every single time.

The goal os these tests is to try and catch those errors in advance and fix them before we loosen the gem constraints to allow newer rails versions. It should also catch regression overall whenever a change is made.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants