Rails源代码分析(7):ActionController::Filter(1)

Filter类似于钩子方法,
在调用某个controller方法之前、之后或者包围调用这个方法,很有用的方法,利用这个可以很大幅度的减少代码量。
  • 1 先研究下种类:
    • 1.1 before_filter 
多用于验证之类的
    #     before_filter :verify_credentials
    #
    #     private
    #       def verify_credentials
    #         # make sure the user is allowed into the vault
    #       end

    • 1.2 after_filter
多用于log之类的后续处理
    #   class OutputCompressionFilter
    #     def self.filter(controller)
    #       controller.response.body = compress(controller.response.body)
    #     end
    #   end
    #
    #   class NewspaperController < ActionController::Base
    #     after_filter OutputCompressionFilter
    #   end

    • 1.3 around_filter
一般用户来捕捉异常,按照2所说使用方法可以包括:
      • 1.3.1 传递filter方法名
    #   around_filter :catch_exceptions
    #
    #   private
    #     def catch_exceptions
    #       yield
    #     rescue => exception
    #       logger.debug "Caught exception! #{exception}"
    #       raise
    #     end
      • 1.3.2 传递外部Filter类
        • 这个也可以用两种接口实现filter方法 或者 实现:before和:after方法
    # 1:
    #   around_filter BenchmarkingFilter
    #
    #   class BenchmarkingFilter
    #     def self.filter(controller, &block)
    #       Benchmark.measure(&block)
    #     end
    #   end
    #
    # 2:
    #
    #   around_filter Authorizer.new
    #
    #   class Authorizer
    #     # This will run before the action. Redirecting aborts the action.
    #     def before(controller)
    #       unless user.authorized?
    #         redirect_to(login_url)
    #       end
    #     end
    #
    #     # This will run after the action if and only if before did not render or redirect.
    #     def after(controller)
    #     end
    #   end

      • 1.3.3 传递inline方法 
    #   around_filter do |controller, action|
    #     logger.debug "before #{controller.action_name}"
    #     action.call
    #     logger.debug "after #{controller.action_name}"
    #   end
  • 2 使用方法
    • 2.1 传递filter方法名(要用Symbol) 
    # 这个是最常用的方法
    #     before_filter :audit
    #
    #     private
    #       def audit
    #         # record the action and parameters in an audit log
    #       end
    • 2.2 传递外部Filter类
    #   class OutputCompressionFilter
    #     def self.filter(controller)
    #       controller.response.body = compress(controller.response.body)
    #     end
    #   end
    #
    #   class NewspaperController < ActionController::Base
    #     after_filter OutputCompressionFilter
    #   end
    • 2.3 传递inline方法
    #   class WeblogController < ActionController::Base
    #     before_filter { |controller| head(400) if controller.params["stop_action"] }
    #   end

  • 3 Filter的顺序
    prepend_before_filter 可以将指定的方法放在所有filter方法之前

    #   class ShoppingController < ActionController::Base
    #     before_filter :verify_open_shop
    #     before_filter :verify_base_ready
    #
    #   class CheckoutController < ShoppingController
    #     prepend_before_filter :ensure_items_in_cart, :ensure_items_in_stock

          上面程序中filter顺序为
          1 :ensure_items_in_cart 
          2 :ensure_items_in_stock
          3 :verify_open_shop
          4 :verify_base_ready

          一般而言执行顺序就是按照before_filter设置的先后
  • 4 Filter的忽略
如果基类中定义了before_filter,子类中有时候不需要调用,就可以用skip_filter忽略    
    #   class ApplicationController < ActionController::Base
    #     before_filter :authenticate
    #     around_filter :catch_exceptions
    #   end
    #
    #   class WeblogController < ApplicationController
    #     # Will run the :authenticate and :catch_exceptions filters.
    #   end
    #
    #   class SignupController < ApplicationController
    #     # Skip :authenticate, run :catch_exceptions.
    #     skip_before_filter :authenticate
    #   end
    #
    #   class ProjectsController < ApplicationController
    #     # Skip :catch_exceptions, run :authenticate.
    #     skip_filter :catch_exceptions
    #   end
    #
    #   class ClientsController < ApplicationController
    #     # Skip :catch_exceptions and :authenticate unless action is index.
    #     skip_filter :catch_exceptions, :authenticate, :except => :index
    #   end
  • 5 Filter的条件选择,可以调用 :only 和 :except 选择需要挂这个filter的方法
  • 6 这几种Filter如何控制程序执行
1 simply call render or redirect to halt

before and around may halt the request before a controller action is run.

3 after will not be executed if the chain is halted.

3 If around returns before yielding, 
   after will still not be run,  before and controller action will not be run.

4 If before renders or redirects,
   the second half of around and will still run, after and the action will not.

5 If around fails to yield, after will not be run.

    # The filter chain will look like:
    #
    #   ...
    #   . /
    #   .  #around (code before yield)
    #   .  .  /
    #   .  .  #before (actual filter code is run)
    #   .  .  .  /
    #   .  .  .  execute controller action
    #   .  .  .  /
    #   .  .  ...
    #   .  .  /
    #   .  #around (code after yield)
    #   . /
    #   #after (actual filter code is run, unless the around filter does not yield)



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值