首页 > 解决方案 > 在 if 语句中包装 Rails 控制器逻辑

问题描述

我试图将我的控制器逻辑包装在相同的条件中。不知道如何实现这一点,因为我对 ruby​​ on rails 有点陌生。下面的伪代码是我想要实现的

class Api::BaseController
  include Api::AuthConcern if SAME_CONDITION
  before_action -> { some_function() } if SAME_CONDITION

  if SAME_CONDITION
    rescue_from Api::AuthConcern::Unauthenticated do |e|
      render status: 401, json: { error: e.error }
    end

    rescue_from Api::AuthConcern::PermissionDenied do |e|
      render status: 403, json: { error: e.error }
    end
  end
end

标签: ruby-on-rails

解决方案


你不会需要它的。只需使用方法:

module Api
  # Avoid adding "Concern" to your module names
  # it provides absolutely no information about what the object does
  module AuthConcern
    extend ActiveSupport::Concern

    included do
      rescue_from Unauthenticated { |e| respond_to_unauthenticated(e.error) }
      rescue_from PermissionDenied { |e| respond_to_permission_denied(e.error) } 
    end

    def respond_to_unauthenticated(message)
       render status: 401, json: { error: message }
    end

    def respond_to_permission_denied(message)
       render status: 403, json: { error: message }
    end
  end
end

这允许任何包含该模块的类通过简单地覆盖该方法来自定义行为:

module Api
  class FooController < BaseController
    # ...
  

    private  

    def respond_to_unauthenticated(error)
      render plain: 'Oh noes, you broke it!'
    end
  end
end

如果您需要为模块如何扩充类添加更多逻辑,您可以使用宏模式。这只是一个向类添加方法或行为的类方法:

module Api
  module AuthConcern
    extend ActiveSupport::Concern

    # ....

    module ClassMethods
      def authenticate!(**kwargs)
        before_action :authenticate!, **kwargs
      end
    end
  end
end
module Api
  class FooController < BaseController
    authenticate! except: :index
  end
end

这种模式在 Ruby 中随处可见,从attr_accessorRails 回调到关联。


推荐阅读