Rack,貌似已经把Rails改革了。
Rack
Rack是什么?Rack提供了用ruby开发web应用的一个接口。比如Rails框架,就是由rack承担着跟web服务器之间的交互。简而言之,Rack已经成为ruby开发web应用程序的一个规范,它统一了web服务器和web框架之间的交互接口。它所支持的web服务器和web框架已经非常之多:http://rack.rubyforge.org/doc/
。
Rack的规范非常简单,就是一个call方法:http://rack.rubyforge.org/doc/SPEC.html
。接受一个environment,然后返回status,header和body。这不就是http的全部么?
Rack Middleware
为什么不可以在Rack和web framework之间做些事情呢?于是Rack middleware发展起来了。Rack中间件其实就是一些遵循Rack规范的应用。为什么要发展出Rack middleware?因为很多事情在这里做起来就非常方便,其实就是AOP的方式(你也可以把它理解成filter)。
看一下众多的middlewares:http://wiki.github.com/rack/rack/list-of-middleware
。或者在你的最新(2.3)rails应用下敲下命令行:rake middleware。
ParamsParser:
def call(env)
if params = parse_formatted_parameters(env)
env["action_controller.request.request_parameters"] = params
end
@app.call(env)
end
CookieStore:
def call(env)
env[ENV_SESSION_KEY] = AbstractStore::SessionHash.new(self, env)
env[ENV_SESSION_OPTIONS_KEY] = @default_options.dup
status, headers, body = @app.call(env)
session_data = env[ENV_SESSION_KEY]
options = env[ENV_SESSION_OPTIONS_KEY]
if !session_data.is_a?(AbstractStore::SessionHash) || session_data.send(:loaded?) || options[:expire_after]
session_data.send(:load!) if session_data.is_a?(AbstractStore::SessionHash) && !session_data.send(:loaded?)
session_data = marshal(session_data.to_hash)
raise CookieOverflow if session_data.size > MAX
cookie = Hash.new
cookie[:value] = session_data
unless options[:expire_after].nil?
cookie[:expires] = Time.now + options[:expire_after]
end
cookie = build_cookie(@key, cookie.merge(options))
unless headers[HTTP_SET_COOKIE].blank?
headers[HTTP_SET_COOKIE] << "\n#{cookie}"
else
headers[HTTP_SET_COOKIE] = cookie
end
end
[status, headers, body]
end
Middleware,正不就是做这些事情的好地方么?
又比如,某人开发的google_analytic middleware:
def call env
status, headers, response = app.call(env)
if headers["Content-Type"] =~ /text\/html|application\/xhtml\+xml/
body = ""
response.each { |part| body << part }
index = body.rindex("</body>")
if index
body.insert(index, tracking_code(options[:web_property_id]))
headers["Content-Length"] = body.length.to_s
response = [body]
end
end
[status, headers, response]
end
Rails on Rack
请再次用rake middleware看看清楚。
use Rack::Lock
use ActionController::Failsafe
use ActionController::Session::CookieStore, #<Proc:0x01a76984@(eval):8>
use Rails::Rack::Metal
use ActionController::ParamsParser
use Rack::MethodOverride
use Rack::Head
use ActionController::StringCoercion
use ActiveRecord::ConnectionAdapters::ConnectionManagement
use ActiveRecord::QueryCache
run ActionController::Dispatcher.new
没错,在Rails2.3之后,所有的东西都变成middleware了,包括Action Controller stack本身。
Rails应用的调用就是对middleware堆栈的调用。从最初始的Rack::Lock:
def call(env)
old, env[FLAG] = env[FLAG], false
@lock.synchronize { @app.call(env) }
ensure
env[FLAG] = old
end
到最后的ActionController::Dispacher.new:
def call(env)
if @@cache_classes
@app.call(env)
else
Reloader.run do
# When class reloading is turned on, we will want to rebuild the
# middleware stack every time we process a request. If we don't
# rebuild the middleware stack, then the stack may contain references
# to old classes metal classes, which will b0rk class reloading.
build_middleware_stack
@app.call(env)
end
end
end
而dispacher,正是Action Controller stack开始启动的地方。上面代码中的@app本身,也是一个middleware:
def build_middleware_stack
@app = @@middleware.build(lambda { |env| self.dup._call(env) })
end
_call(env)到底做了什么,还是看个究竟吧:
def _call(env)
@env = env
dispatch
end
def dispatch
begin
run_callbacks :before_dispatch
Routing::Routes.call(@env)
rescue Exception => exception
if controller ||= (::ApplicationController rescue Base)
controller.call_with_exception(@env, exception).to_a
else
raise exception
end
ensure
run_callbacks :after_dispatch, :enumerator => :reverse_each
end
end
你没发现,大部分主要对象都实现了call(env)接口么?
Rails Metal Applications
Rails2.3集成进了Metal Application,它的作用主要是应付那些“少而多”的request。这里的少,是指访问数据库少,逻辑少(个人认为逻辑复杂的不适合放在metal里面做),多是指访问次数多(如果访问频率没有那么高,我觉得没必要)。当数据库访问非常之少时,性能的瓶颈已经在Action Controller stack,问题就来了:为什么不绕开Action Controller stack呢?Metal的作用就是这样的,它作为Rack middleware stack的一分子(在上面那个list中找),在到达Action Controller stack之前对request进行拦截,如果满足,则直接返回。还是看下源代码吧:
def call(env)
@metals.keys.each do |app|
result = app.call(env)
return result unless @pass_through_on.include?(result[0].to_i)
end
@app.call(env)
end
http://github.com/rails/rails/blob/master/railties/lib/rails/rack/metal.rb
更多
关于更多的知识,请见:http://guides.rubyonrails.org/rails_on_rack.html
。在这里会看到script/server的实现,如何定制rackup,如何定制middleware,如何生成metal等。
EOF
ps:
技术总是翻天覆地地变化着,rails2.3又有了很多不同。做一个IT民工还真是他妈的累,不过如果可以苦中作乐,倒也认了。每周一题
越来越名不副实了,不过还是继续学习,继续写吧。
分享到:
- 2009-11-30 20:48
- 浏览 2520
- 评论(7)
- 论坛回复 / 浏览 (6 / 4950)
- 查看更多
相关推荐
Rails::API 是 Rails 的精简版本,针对不需要使用完整 Rails 功能的开发者。 Rails::API 移除了 ActionView 和其他一些渲染功能,不关心Web前端的开发者可更容易、快速地开发应用程序,因此运行速度比正常的 Rails ...
在本篇内容中,我们将深入探讨如何利用Ruby on Rails(简称Rails)这一强大的Web应用程序框架来构建可伸缩且易于维护的RESTful API。Rails以其简洁优雅的语法、高效的开发速度以及良好的社区支持而闻名,这使得它...
这篇博客文章“Rails中应用Ext.tree:以中国的省市地区三级联动选择为例”提供了一个实用的示例,教我们如何利用Ext.js库中的Tree组件来实现这种功能。 首先,让我们了解Rails和Ext.js的基本概念。Rails是基于Ruby...
Rails::Rack::Logger ActionDispatch::ShowExceptions ActionDispatch::DebugExceptions ActionDispatch::RemoteIp ActionDispatch::Reloader ActionDispatch::Callbacks ActiveRecord::ConnectionAdapters::...
config.middleware.use Rails::Rack::Debugger config.middleware.use RailsFootnotes ``` 4. 重启Rails服务器以使更改生效。 5. 访问任何Rails应用页面,你将在页脚看到Footnotes链接,点击它们即可查看相关...
Rack::UTF8Sanitizer 是一个 Rack 中间件用来清理 URI 和 HTTP 请求头部中包含的无效 UTF-8 字符。Rails 的使用方法:config.middleware.insert 0, Rack::UTF8SanitizerRack 的使用方法:use Rack::UTF8Sanitizer
标题 "Rails相关电子书汇总二" 提供的信息表明,这个压缩包包含的资源主要与Ruby on Rails框架有关,特别是从“Rubyisms in Rails”的书名来看,我们可以期待它深入探讨了Ruby语言在Rails框架中的独特用法和特性。...
这个面试练习题可能是为了测试应聘者对于Rails应用的构建、自动化任务管理、测试驱动开发(TDD)以及文件组织结构的理解。让我们逐一探讨这些知识点。 首先,`Rakefile`是Ruby中的构建工具,类似于其他语言的...
- 安装Rails: 使用gem工具安装最新的Rails版本。 - 测试安装: 创建一个简单的Rails应用来验证是否成功安装。 #### 五、练习作业0-Hello World - **目标**: - 学习如何创建第一个Rails应用程序。 - **过程**: -...
Ruby on Rails,简称Rails,是一种基于Ruby语言的开源Web应用程序框架,它遵循MVC(Model-View-Controller)架构模式,旨在使Web开发过程更加高效、简洁。本篇将通过一个入门实例,深入探讨Rails的基本概念和核心...
Rails,全称为Ruby on Rails,是一款基于Ruby编程语言的开源Web应用程序框架,以其MVC(模型-视图-控制器)架构模式而闻名。"Advanced Rails" 涵盖了Rails开发中的高级主题和技术,是Ruby on Rails学习进阶的重要...
我们将从 Ruby、Rack 和 ActiveSupport 构建一个应用程序。 本课的目的是从内部展示 Rails 是如何工作的。 这将逐步构建一些 Rails 组件的精简版。 它会: 创建一个类似Rails 的初始化过程。 使用 Rails 目录...
Ruby on Rails,通常简称为Rails,是一个基于Ruby语言的开源Web应用程序框架,它遵循MVC(模型-视图-控制器)架构模式,以简洁、高效的代码和“约定优于配置”的理念著称。此压缩包中的"rubyonrails21-cn.pdf"可能是...
Ruby on Rails(简称RoR或Rails)是一种开源的网络应用框架,用Ruby语言编写。它被设计用来轻松地实现MVC(模型-视图-控制器)设计模式,从而使开发人员能够快速和有条理地创建数据驱动的应用程序。接下来,我将详细...
rails5-docker-alpine:使用Alpine Linux的Rails轻量级Docker开发环境
Rails :: Auth是一个灵活的库,旨在使用Rack Middleware进行身份验证(AuthN)和授权(AuthZ)。 它将,使用AuthN中间件首先验证凭据(例如X.509证书或cookie),然后通过使用这些凭据(例如(ACL))的单独AuthZ...
Mailgun 网络钩子 为您的 Rack 或 Rails 应用程序添加对 Mailgun webhook... 只需将MailgunWebhooks::Rack添加到您的中间件堆栈中即可。 use MailgunWebhooks :: Rack网络钩子默认情况下,您的应用程序将侦听/mailgun上
chef-rails, 厨房设置一个可以与 Nginx 和 Rails 一起滚动的Ubuntu服务器 主厨 rails安装一个准备为 Ruby on Rails 栈准备的Ubuntu服务器:NginxPostgreSQLRedisMemcached带RVM的rubyPhusion乘客独立要求Ubuntu ...
### Ruby on Rails Guides v2 - Ruby on Rails 4.2.5 #### 一、重要概念及基础假设 - **重要概念**:本指南旨在帮助读者深入理解Ruby on Rails(以下简称Rails)4.2.5版本的核心功能与最佳实践。 - **基础假设**:...