我们都知道 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
感兴趣的也可以找我来索要视频录像,视频剪辑好以后会发布在这。
这是我们全栈程序员 的其中一节课,目前还有 4 个名额开放,有兴趣的可以赶快来报名吧。
我们希望这次训练营结束以后,可以覆盖平常常见的开发场景。