Add a rubocop enforcing `inverse_of` for ActiveRecord associations
Description of the proposal
This is something of a follow-up to #31851 (closed)
Given a pair of models like:
class Foo < ApplicationRecord
has_many :bars
end
class Bar < ApplicationRecord
belongs_to :foo
end
AR will attempt to automatically infer inverse_of: :foo
and inverse_of: :bars
on each association: https://makandracards.com/makandra/33309-rails-4-1+-automatically-detects-the-inverse_of-an-association . The effect of this is:
foo = Foo.first
bar = foo.bars.first
foo.object_id == bar.foo.object_id
However, sometimes this automatic inference fails, and AR falls back to the default behaviour of doing additional database lookups (and so creating duplicate objects) when traversing the graph. We don't get any notification when this happens.
To me, this suggests we should introduce a cop that tells us to add inverse_of
when required. This cop could alert whenever one of a list of known bad attributes is specified to a belongs_to
or has_*
call, or for simplicity of implementation, we could start requiring - a cop already exists, it seems: https://www.rubydoc.info/gems/rubocop/0.61.1/RuboCop/Cop/Rails/InverseOfinverse_of
on all of these calls
It's possible some existing code relies on the implicit reload where inverse_of
is not set at the moment - particularly in specs - so we'd probably want to start by adding exceptions for all existing associations, and only enforcing it on newly added ones.
-
Mention the proposal in the next backend weekly call and the #backend channel to encourage contribution -
Proceed with the proposal once 50% of the maintainers have weighed in, and 80% of the votes are 👍 -
Once approved, mention it again in the next backend weekly call and the #backend channel