我们都知道 Rails、Grape 等等都是 Rack App 框架。
所谓 Rack App 是指遵循了 Rack 协议的 App,其中最主要的,或者最容易理解的一点就是,他们有共同的入口点:即 config.ru
文件。
其中,对于 config.ru
的规定是:
run
命令后面加一个可以响应call
方法的一个实例- 这个
call
方法需要返回一个数组,其中,第一个为 HTTP 状态码,第二个为 Hash 组成的,代表 HTTP 协议中的 Headers,第三个是个字符串数组,数据个数为 1。 示例:[200, { 'Content-Type' => 'application/json'}, ["I am html body"]]
对于 Ruby 来说,具有call
这个方法的默认的就有 Proc, proc, lambda 等等,当然也可以自己声明。
依据上面这些基础知识,我们可以实现一个所谓的 Web App:
# config.ru run proc { [200, {'Content-Type' => 'text/html'}, ["Hello, world!"]] }
这时候我们在这个文件所在的目录下运行:
$ rackup -p 300
我们就能在浏览器里面查看了: http://localhost:3000
到目前来说,我们算是可以实现一个简单的 Web APP 了。
那么我们如何实现一个 MVC 分层的 Web App 呢?
首先,我们可以按照 Rails 框架的思路,做一个分层: 数据库我们用 Sqlite 3,
# app/model/user.rb class User attr_accessor :name, :email def initialize(name, email) @name = name @email = email end def self.all @users = [] db = SQLite3::Database.new "toyapp.db" db.execute('select * from users where 1 = 1 limit 1;') do |row| @users << self.new(row[1], row[2]) end @users end #method_missing end
View 层我们用 ERB 来实现:
# index.html.erb <div> name: <%= @user.name %> <br> email: <%= @user.email %> </div>
Controller 层,我们简单的模仿 Rails:
class UsersController def index @user = User.all[0] puts @user template = File.open("./index.html.erb").read template = ERB.new(template) template.result(binding) # 通过 binding 切换作用域 end end
我们通过 Application 可以把这些串起来:
class Application def call(env) # env 参数是 Rack 默认会传过来的,其中包含了一个请求常见的信息 [ 200, {'Content-Type'=>'text/html'}, [UsersController.new.index] ] end end
然后我们通过 Rack 来运行我们的 App:
# config.ru run Application.new
现在,我们可以来试试我们的 Web APP
$ rackup -p 3000
源码地址:https://github.com/rocLv/no-framework-app.git
感兴趣的也可以找我来索要视频录像,视频剪辑好以后会发布在这。