Defect #36245

ActiveSupport::Reloader.to_prepare not working in trunk 21287

Added by Alexander Meindl 14 days ago. Updated 6 days ago.

Status:ResolvedStart date:
Priority:NormalDue date:
Assignee:-% Done:

0%

Category:Plugin API
Target version:-
Resolution: Affected version:

Description

With r21283 in trunk ActiveSupport::Reloader.to_prepare and Rails.configuration.to_prepare is not fired anymore.

ActiveSupport::Reloader.to_prepare is required for plugins (as an example), if some code should loaded after all plugins (other plugins) are loaded.

Maybe there is another possibility with Rails 6 or Zeitwerk for doing this, but imho ActiveSupport::Reloader.to_prepare should work within plugins, too. See https://guides.rubyonrails.org/autoloading_and_reloading_constants.html#autoloading-when-the-application-boots


Related issues

Related to Redmine - Patch #34072: Hook after plugins were loaded Closed
Related to Redmine - Feature #32938: Rails 6: Zeitwerk support Closed

History

#1 Updated by Alexander Meindl 14 days ago

The defect is for the usage of ActiveSupport::Reloader.to_prepare in a plugin - not in Redmine itself (just to make it clear).

I did not find a solution to fix this behavior until now.

Here is an example for a plugin init.rb:

Redmine::Plugin.register :my_plugin do
  name 'My plugin'
  version '0.01'
end

ActiveSupport::Reloader.to_prepare do
  raise 'this is never called'
end

Rails.configuration.to_prepare do
  raise 'this is never called, too'
end

#2 Updated by Takashi Kato 7 days ago

I apologize for the delay in responding.
Before the introduction of zeitwerk, the autoloader loads Redmine plugins on initializing.

After the introduction of zeitwerk, to make the Redmine::Plugin class manageable for zeitwerk, Redmine::PluginLoader runs the "init.rb" for all plugins inside the "Rails.configuration.to_prepare" block (and run on every reload).

https://www.redmine.org/projects/redmine/repository/entry/trunk/lib/redmine/plugin_loader.rb#L108

Now processing written inside the "Rails.configuration.to_prepare" block in "init.rb" can be written directly in "init.rb".
Let me know if there are any problems in creating plugins.

#3 Updated by Takashi Kato 7 days ago

Alexander
It may not be a plugin you want to fix, but I found your plugin on GitHub and made it compatible with zeitwerk.

https://github.com/tohosaku/redmine_emojibutton/commits/zeitwerk

#4 Updated by Alexander Meindl 7 days ago

Hi Takashi,

thanks for your answer. The problem is, you cannot use Classes from Plugin B with Plugin A - because Plugin B is not initialized at this moment. Because of this, till now without zeitwerk, the solution was to use this Classes after all plugins are initialized (with Rails.configuration.to_prepare).

If Redmine::PluginLoader loads all plugins in "Rails.configuration.to_prepare" block, it is not possible to call an "Rails.configuration.to_prepare" block in a plugin again. This would be a "Rails.configuration.to_prepare" block in a "Rails.configuration.to_prepare" block - and this does not work - as it looks at the moment.

Here are some examples: https://github.com/AlphaNodes/additional_tags/blob/master/init.rb or https://github.com/AlphaNodes/redmine_saml/blob/master/init.rb or https://github.com/AlphaNodes/redmine_sudo/blob/master/init.rb (we build an plugin loader for that)

I am not sure, if you get me right. I try to explain, that if you have dependencies between plugins (which we have a lot), there is no way (or I do not know it), how we can run code from a plugin, after all plugins are initialized.

An example: Plugin B requires Plugin C. You cannot use Plugin C code in Plugin B, till it is initialized - and this worked perfectly with Rails.configuration.to_prepare before zeitwerk. Maybe to provide a hook after initializing all plugins could be a solution.

#5 Updated by Ko Nagase 7 days ago

Hi Alexander,

I still haven't tried Redmine trunk yet, but I encountered the similar situation which needs to control plugins load orders in Redmine 4.2-stable branch.
https://github.com/gtt-project/redmine_gtt/pull/130

From glance of Takashi's comment,

https://www.redmine.org/projects/redmine/repository/entry/trunk/lib/redmine/plugin_loader.rb#L108

I noticed that there seems to be after_plugins_loaded hook which seems to be called when all plugins are loaded, so I guess that we can try to use this way as a workaround.
https://www.redmine.org/issues/20263

#6 Updated by Alexander Meindl 7 days ago

Hi Ko,

indeed I found after_plugins_loaded hook some hours ago. But the problem with that is, you cannot use a patched method in Redmine::Plugin.register block (e.g. to add a link to menu for special conditions, which requires a patch, which is applied later with after_plugins_loaded hook).

Maybe the way with after_plugins_loaded hook is the right direction. Not sure, if there are more problems with that.
But dispense with Rails.configuration.to_prepare means a lot of rework/adjustments in plugins.

#7 Updated by Alexander Meindl 7 days ago

  • Status changed from New to Resolved

after_plugins_loaded hook works for me as a replacement for Rails.configuration.to_prepare

#8 Updated by Go MAEDA 7 days ago

  • Related to Patch #34072: Hook after plugins were loaded added

#9 Updated by Go MAEDA 7 days ago

#10 Updated by Takashi Kato 6 days ago

Hi Alexander,

Glad that this is solved!
Thank you for your very meaningful report as it was a case that I hadn't really anticipated.

Also available in: Atom PDF