Rails3: 新的 Metal 机制

本文转载,来自http://ihower.tw/blog/archives/4561

新的 Rails3 Controller 重构后,变成 ActionController::Base < ActionController::Metal < AbstractController 的继承体系。除了 ActionMailer 继承自 AbstractController,让 API 与 Controller 一致之外,新的 ActionController::Metal 更是充满玩味。

故事可以从上个礼拜,Yehuda 把 Rails 2 的 Metal 移除了(commit),根据 commit 的说明,Rails 2 的 Metal 在 Rails 3 里面,可以用 1. 放在 Route 之前的 Rack middleware 或 2. 放在 Route 之后的一个 Rack endpoint,而这个 Rack endpoint,除了自己实作 Rack app,我们也可以用 ActionController::Metal 来实作出自己的客制化 Controller。

Rails2 发明 Metal 原因是,有些事情不需要完整的 Controller 功能,希望能够越快越好,例如 XML/JSON API 等。而 Rails2 的 Metal 虽然非常快,但是没什 弹性,完全不能使用 Controller 的功能,例如用 Layout, Template, Sessions 等,基本上就跟单纯的 Rack middleware 没什 两样。但是在 Rails3 中,可以透过自继承 ActionController::Metal 做出白纸般的客制 Controller,可以有非常快的速度,如果有需要用到 Controller 的功能,也可以任意选择组合加入,十分弹性。

例如,我们来实作一个超级精简的 Static Controller:

# lib/static_controller.rb
class StaticController < ActionController::Metal
  include ActionController::Rendering
    
  append_view_path "#{Rails.root}/app/views"
    
  def about
    render "about"
  end
end
    
# config/route.rb
match '/about', :to => "static#about", :as => :about

 这个范例有接近于 Metal 的速度,并加入了 Controller 的 Template 功能 (你可以参考 ActionController::Base 这是拥有全部功能的版本)。其中 “static#about” 是 StaticController 的 about action 缩写,而在 Rails3 中,controller action 也都是一个 Rack app。

扫描二维码关注公众号,回复: 586193 查看本文章

如果你在 Rails3 中不需要全部的 Controller 的功能,想要尽量拉高效能,有几种推荐作法:

* 写成 Rack Middleware,然后在 config/application.rb 中插入 config.middleware.use YourMiddleWare

* 写成 Rack App,在 config.route.rb 中将某个对应的网址指到这个 Rack App

* 继承自 ActionController::Metal 实作一个 Controller,其中的 action 也是一个 Rack App

其中的差异就在于后两者会在 Rails Route 之后(好处是统一由 route.rb 管理 URL 路径),如果继承自 ActionController::Metal 可以有弹性获得更多 Controller 功能。原则上,我想我会推荐 ActionController::Metal,写起来最为简单,一致性跟维护性较高。

另外,还有个小玩意, ActionController::Middleware 是 Controller 层级的 Rack Middleware,让你可以在放入到某个特定 Controller 之中(也就是只有该 Controller 使用这个 Middleware)。不过呢,这个功能我到现在还没看到任何实用的例子就是了。

最后,Yehuda 提供了一个 参考数据:

fast: through middleware inserted at 0
slwr: through middleware inserted via @use@
rotr: through endpoint sent via the router
bare: through ActionController::Metal with self.response_body
cntr: through ActionController::Base with self.response_body
text: through ActionController::Base with render :text
tmpl: through ActionController::Base with simple render :template
layt: through ActionController::Base with render :template with layout

         real     rps
fast   0.004271   2900 Rack 极限
slwr   0.067029   2200 使用 config.middleware.use YourMiddleware
rotr   0.088085   2000 经过 Rails Route 之后
bare   0.103868   1900 使用 ActionController::Metal 的最快速度
cntr   0.355898   1070 使用 ActionController::Base 的最快速度
text   0.557127    825 使用 ActionController::Base 加上 render :text
tmpl   0.639581    765 使用 ActionController::Base 加上 render :template
layt   1.678789    375 使用 ActionController::Base 加上 Template 跟 Layout

猜你喜欢

转载自fztree.iteye.com/blog/2148653