rubocop-rails
rubocop-rails copied to clipboard
Cop idea: Detect outdated `load_defaults` for Rails updates
The Rails upgrade process can be tricky. When using the rails app:update
command, a line will be added to load_defaults
corresponding to the previous Rails version. For example if you're upgrading to 6.1, it'll be load_defaults(6.0)
.
The aim of this is to allow for an incremental upgrade process, so you can gradually address the items in config/initializers/new_framework_defaults.rb
, then delete that file, and change load_defaults
to match the current Rails version.
The risk is that if you don't fully complete that process, your app may work fine, but you'll drift further and further from the default configuration of a new Rails app. This makes future upgrades more difficult.
I think it's easy to overlook this, and it would be useful to have a cop to highlight this. I'm imagining that a typical Rails upgrade would happen on a branch, and while in progress this cop would raise an issue. Then when the upgrade is complete, and load_defaults
is updated, it would pass again.
I'm updating a Rails application and exactly that happened, they were updating the gems but removing the load_defaults
statement on config/application.rb
so they were on the Rails 4.2 defaults without being aware. This might be useful.
That would be perfect. There's a guideline for this, too https://rails.rubystyle.guide/#config-defaults
@vizcay Would you like to contribute such a cop provided necessary guidance?
@pirj if you can point me to a cop with a similar implementation I will try to make an stab on it.
@vizcay I'd suggest adding a cop (there is a rake generator task); set Include
in config/default.tml
to config/application.rb
.
To scan through the whole file just once you can use def on_new_investigation
(don't forget to call super
).
Use a node pattern to scan through the whole file:
def_node_matcher? :load_defaults?, "(send (send nil? :config) :load_defaults $float)"
if load_defaults?(processed_source.ast)
returns nothing, then it is missing.
And it will also return a float value if config.load_defaults
was called. I'm not sure if there is a reliable way to detect the exact Rails version the code is supposed to run against (and if it's always the case). Might be TargetRailsVersion
can be used to compare to.