A RubyGem adding SQL comments to indicate the origin of the SQL
ActiveRecord::Originator
Add SQL comments to indicate the origin of the SQL.
This gem adds SQL comments indicating the origin of the part of the query. This is useful for debugging large queries.
Rails tells us where the SQL is executed, but it doesn't tell us where the SQL is constructed
This gem lets you know where the SQL is constructed! For example:
This gem adds the comments enclosed in /* ... */. From this, you can see that articles'.' status" = ? originates from the published method on line 3 of article.rb, that category_id is filtered in the controller, and where the scope that defines the ORDER BY is located.
Motivation
The simple example I mentioned earlier probably doesn't tell you this gem's advantage.
However, as SQL assembly becomes more complex, this gem will prove its true value. It's common for the location where a query is executed and the location where it's constructed to be far apart, such as when defining scopes. Moreover, when creating classes to construct queries for complex searches, searching within those classes can be quite a task.
With this gem, you can pinpoint how the query was constructed, making debugging easier.
It can also be useful for debugging default_scope because it is difficult to understand where they were applied. 1
Usage
Run the following command to install the activerecord-originator gem.
$bundle add activerecord-originator
That's all for the setup. Just by installing the gem, comments will be added to the queries.
The major difference between these traditional features and activerecord-originator is the granularity of comments (or logs). With traditional features, comments are output on a per-query basis. It's very convenient to know where that query was executed, but you couldn't get more detailed information.
activerecord-originator outputs comments for each element of SQL, conveying more detailed information. Information that was previously unknown becomes clear, increasing the information available for debugging.
The activerecord-originator is not intended to replace traditional features but is used in conjunction with them.
Caution
There are two things to be aware of when using activerecord-originator. One is the use of Active Record's internal API, and the other is performance.
Active Record Internal API
This gem strongly depends on Arel, which is an internal API of Active Record. Therefore, it may easily break with future Rails updates.
For example, it could break due to major internal refactoring.
It may also not work well with older versions of Rails. Although I have confirmed that the tests pass for Active Record v6.0 with some exceptions, and all tests pass for v6.1, there is no guarantee that older versions will continue to be supported.
Since it's a gem that can be easily installed and uninstalled, it's good to think that you might need to remove it from the Gemfile when updating Rails.
Performance
Since processing to output comments is performed every time a query is constructed, it is expected to incur a considerable cost.
Therefore, enabling it in a production environment could affect performance.
However, I haven't done any benchmarking or anything yet, so I don't know how much impact it will actually have.
If you measure the actual impact, I would be happy if you could let me know.
Implementation
Finally, I'll briefly introduce the implementation.
The ToSql class traverses the Arel AST to generate SQL strings. The ArelVisitorExtension module overrides the methods corresponding to each node class in the ToSql class, inserting comments based on the location information recorded by ArelNodeExtension.
These two modules are the core of the implementation. The implementation itself is not very difficult, but it has become heavily dependent on Rails' internal API.
This was an introduction to the activerecord-originator gem, which makes SQL executed more debuggable. I would be happy if you could try it out.
And another module, ActiveRecord::Originator::ArelVisitorExtension, is prepended to the Arel::Visitors::ToSql class.
The ToSql class is a class that traverses the Arel AST to generate SQL strings. The ArelVisitorExtension module overrides the methods corresponding to each node in the ToSql class, inserting comments based on the location information recorded by ArelNodeExtension.
These two modules are the core of the implementation.
The implementation itself is not very difficult, but it has become heavily dependent on Rails' internal API.
This was an introduction to the activerecord-originator gem, which makes SQL executed more debuggable. I would be happy if you could try it out.
The idea for this gem came to me when I saw someone struggling to identify where a condition defined by default_scope was coming from, as it was not clear. ↩