2

Мне нужно более точное управление зерном по порядку обратных вызовов в моих контроллерах. В настоящее время Rails позволяет использовать только append|prepend_before|after_action, но это очень плохо, если вы хотите добавить модуль с его специальными обратными вызовами.Зарегистрируйте другой тип обратного вызова в ApplicationController

Я пытаюсь понять, как работает AbstractController :: Callbacks, и я пытаюсь зарегистрировать новый тип обратного вызова, который будет выполнен в определенный момент, используя синтаксис контроллеров Rail для добавления обратного вызова (только/except + список действий и т. д.).

Вы можете подумать об этом как о пользовательской функции контроля доступа, но этот вопрос не касается контроля доступа, пожалуйста, воздержитесь от ответа на вопрос об убийстве камнями, такими как Канкан.

class ApplicationController 
    include xxx 
    include MyModuleWithCallbacks 
    include yyy 
    ... 
end 

class MyController < ApplicationController 
    prepend_before_action :something_before_my_callbacks 
    my_callback_list :custom_callback, only: [:index, :show] 
    before_action :something_after_my_callbacks 
    # Goal : the order of above callbacks should NOT matter, my_callback does not depend on ActionController process_action callback list 
end 

module MyModuleWithCallbacks 
    extend ActiveSupport::Concern 
    extend AbstractController::Callbacks 

    included do 
    around_action :perform_if_condition 

    def perform_if_condition 
     run_callbacks :my_callback_list do 
     if my_callbacks_went_good? 
      yield # And run the controller's before_callbacks 
     else 
      # log, render error page, etc. 
     end 
     end 
    end 

    # This is the hard part register the callback, I tried 
    class_methods do 
    define_method :my_callback_list do |*names, &blk| 
     _insert_callbacks(names, blk) do |name, options| 
     set_callback(:my_callback_list, :before, name, options) 
     end 
    end 
    end 

Текущая ошибка

неопределенный метод `_my_callbacks_list_callbacks' для PublicController: Класс

Я беру свое вдохновение из исходного кода AbstractController::Callbacks, но я не уверен, что я понимаете, что там происходит ^^ "

ответ

0

Я видел некоторые upvotes, так что вот мое текущее решение:

В примере способа управления доступом очень легкого, оригинальное название my_callback был access_control

# controllers/concerns/access_control.rb 
    module AccessControl 
     extend ActiveSupport::Concern 
     class_methods do 
     define_method :my_callback do |*names, &blk| 
      _insert_callbacks(names, blk) do |name, options| 
      set_callback(:my_callback, :before, name, options) 
      end 
     end 
     end 

     included do 

     define_callbacks :my_callback 

     def perform_if_access_granted 
      run_callbacks :my_callback do 
      if @access_denied and not @access_authorized and not god_mode? 
       @request_authentication = true unless user_signed_in? 
       render(
       file: File.join(Rails.root, 'app/views/errors/403.html'), 
       status: 403, 
       layout: 'error') 
      else 
       yield 
      end 
      end 
     end 

Тогда в ваших других контроллерах, которые включают в себя модуль (опять с примером управления доступом)

# controllers/your_controller.rb 
class YourController < SeekerController 
    your_callback do 
    set_entity 
    allow_access_to_entity(@entity) 
    end