dmferrari
dmferrari

Reputation: 161

Ruby on Rails - Run callback code after initialize method in class

I am using Ruby on Rails 5.2 with ruby 2.4.2p198

Let's say I have a controller (for example this: https://github.com/spree/spree/blob/3-6-stable/backend/app/controllers/spree/admin/reports_controller.rb) and I want to run some code using a callback after the initialize method.

For this, I've created a decorator (for example: reports_controller_decorator.rb) and added the method that I want to run in the after_actioncallback.

My issue is that this works (the method is called) if I use the callback on the index method, but it doesn't work if I pass the initialize method as parameter in the callback:

# It works (note the index method in the callback parameter)
Spree::Admin::ReportsController.class_eval do
  after_action :post_initialize, only: :index

  def post_initialize
    Spree::Admin::ReportsController.add_available_report!(:custom_sales_total)
  end
end
# It doesn't (note the initialize method in the callback parameter)
Spree::Admin::ReportsController.class_eval do
  after_action :post_initialize, only: :initialize

  def post_initialize
    Spree::Admin::ReportsController.add_available_report!(:custom_sales_total)
  end
end

What am I doing wrong? Is possible to run callbacks after the initialize method?

Upvotes: 1

Views: 2597

Answers (1)

robertoplancarte
robertoplancarte

Reputation: 1171

Rails uses the before, after and around _action filters only on "actions". Restfull controllers should only define 7 actions:

  1. show
  2. index
  3. edit
  4. update
  5. new
  6. create
  7. destroy

Usually controllers don't define an initialize action, although they do inherit an initialize method from their parent class. That is to say there is no route in rails that will go to the initialize method of a controller. Since there is no initialize action to run when you open the index action of Spree::Admin::ReportsController the post_initialize filter is never run.

Rails has no after_initialize callback for its controllers, only for its models. If you want to add code to the initialize function of the controller you can reopen the class and overwrite the initializer (not recomended) or subclass the controller and call super in the new initializer and add you code afterwords.

Spree::Admin::ReportsController.class_eval do
  def initialize
    super
    Spree::Admin::ReportsController.add_available_report!(:custom_sales_total)
  end
end

or

class CustomSalesTotalController < Spree::Admin::ReportsController
  def initialize
    super
    Spree::Admin::ReportsController.add_available_report!(:custom_sales_total)
  end
end

Which is actually what Spree is doing under the hood.

Upvotes: 1

Related Questions