写在前面: RubyConfChina 结束了,感觉组织者的辛苦付出。期待明年带给我们更多的启示。另:让我们买本英语 500 句,每天学一点吧。
Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.
大意:Rack 是个 api,这个 api 会调用一个方法,它是 call()。
A Rack application is an Ruby object (not a class) that responds to call. It takes exactly one argument, the environment and returns an Array of exactly three values: The status, the headers, and the body.
大意:Rack App 需要提供一个方法,它就是 call()。
答:它不是。
之前我对 Sprockets 的概念完全被 Rails 给代替了,那么注意下面标注的文字,原来只是 Rails 替我做了额外的事情,我没有察觉。
You'll need an instance of the Sprockets::Environment class to access and serve assets from your application. Under Rails 3.1 and later, YourApp::Application.assets is a preconfigured Sprockets::Environment instance
. For Rack-based applications, create an instance in config.ru.
那么,我如果自己单独使用 Sprockets 呢?
If you are using Sprockets with a Rack application, you will need to mount the environment yourself. A good way to do this is with the map method in config.ru:
require 'sprockets'
map '/assets' do
environment = Sprockets::Environment.new
environment.append_path 'app/assets/javascripts'
environment.append_path 'app/assets/stylesheets'
run environment
end
map '/' do
run YourRackApp
end
Sprockets 可以支持 SCSS/SASS,LESS,CoffeeScript,甚至.scss.erb。
注意那个不起眼的 config.ru,我可以用它来写一个自己的 Ruby 框架。当然啦,这个框架现在什么也不做。
# config.ru
require ::File.expand_path('../my_app.rb', __FILE__) # 这句话copy自Rails,吼吼
run MyApp::Application
# my_app.rb
module MyApp
class Application
def self.call(env)
[200, {"Content-Type" => "text/html"}, ["<h1>It's My App</h1>", '<p>Yeah!!!</p>']]
end
end
end
rackup -s WEBrick -p 1212
如果你看过这篇文章,那么你会发现,我们熟知的 Rails 启动方式,还可以这样完成:
# Rails.root/config.ru
require ::File.expand_path('../config/environment', __FILE__)
use Rack::Debugger
use Rack::ContentLength
run Rails.application
写这篇文章的缘由,是在开发一个功能时,想到它可以包装成一个 gem,而后有看了Rails Guides: Getting Started with Engines,中文在这里,这之后有了对 Rails 进行解构的想法,而后,便是更加清楚的意识到 Rack 的存在了。
那么,sinatra,和其他同类型的 Rack-based app(非 Rails),都是我们可以尝试的选择。
当我们rake middleware
的时候,我们可以看到 Rails 加载了哪些 middleware,这些不是写在 Gemfile 里的,但是他们可以来自 gem。这就有点奇怪的感觉了,不是么?
如果我们选择 sinatra,选择一些自己要使用的 gem,再挑选一些 middleware,我们就可以搭建一个 app 了。比如,一个管理 jekyll 的 app blog。
这篇短文的意图,是想通过 Rails 的解构,对 Rack 和其他 Rack-based App 有一个清楚的了解,当我们选择功能方案的时候,会从另外一些角度,选择我们合适的实现途径。Rails 给我们的贡献,就像 Prem 在 RubyConf 上讲到的,我们可以看看,把 Rails 的哪些东西可以放到我们的项目里。
这篇博文是两次完成的,因为期间要参加 RubyConfChina,所以在之前把半成品放了出去,听听大家的意见。回来后发现了一些新的资源,一并补充进来。再次感谢提出意见的 ruby-china.org 的小伙伴们。
http://guides.rubyonrails.org/v3.2.13/rails_on_rack.html
Rails meets Sinatra #2 - Mix n' Match
原文地址:里克的自习室:Rack, 我忽视你了