HarmonyOS开发者限时福利来啦!最高10w+现金激励等你拿~ 了解详情
写点什么

用 Sinatra 编写博客应用

  • 2011-01-21
  • 本文字数:4537 字

    阅读完需:约 15 分钟

Sinatra 是 Blake Mizerany 在 2007 年 9 月开发的 Ruby 语言的 Web 框架。它最突出的特点就是轻量、快速。更难能可贵的是,Sinatra 的源代码只有一千多行。

在第一次接触到 Sinatra 的时候,我便被它深深地吸引住了。随后,我在 09 年 3 月的 Shanghai on Rails 活动向大家介绍了这个框架。10 年 8 月份我有幸可以在 RubyKaigi 这样的全球级 Ruby 社区会议上作为演讲者和听众交流 Sinatra。本文则是对 10 年 10 月份在上海 Linux 用户组介绍 Sinatra 的讲座的一些整理和总结。希望读者能够通过本例子能体会到 Sinatra 的精妙之处。

最新版本: 1.1

截止到本文成文为止,Sinatra 最新的版本是 10 年 10 月 24 日发布的 1.1 版本。很幸运的是,我对于 README 的翻译正好在发布的前一天被合并进入了主分支。于是在 1.1 的正式版本中,中文的读者可以直接阅读到中文的 README,从而更好的了解 Sinatra 的用法。官网上也有此文档的链接, http://www.sinatrarb.com/intro-zh.html 。本文的代码全部以 1.1 版本为准。

Sinatra 的基本结构

让我们从 Sinatra 最常见的 Hello world 程序开始:

复制代码
get '/' { "Hello, world!" }

这段简单的 Hello world 程序包含了 Sinatra 程序的三个基本组成部分:

  • 路由(route):

    ‘/’ 就是路由。路由可以是单一的路径,或者带有参数的路径(比如 /:name),甚至是正则表达式。对于 Sinatra 不知道的路由,Sinatra 会返回 404 错误(作为 App 运行的时候),或者传递给下面的中间件(作为中间件运行的时候)。

  • 方法(method):

    get是方法。在 Sinatra 中,HTTP 的四个方法GET/POST/PUT/DELETE都有相应的方法get/post/put/delete

  • 处理器(handler):

    处理器就是最后的代码块,处理器的返回值就是 Sinatra 返回给客户端(主要是浏览器)的内容。返回值主要以字符串为主,也可以是包含状态码,消息头,消息体的数组。

渲染模版

Sinatra 支持的模版类型也在逐渐增加中。Haml 是笔者常用的格式,因为它使用了 CSS 选择符构造 HTML 标签,从而节省编写时间。另一种常见的格式是 Ruby 自带的 ERB,本例子将使用 Haml 作为博客的模版。

渲染模版在 Sinatra 中是很容易的事:

复制代码
get '/' do
haml :index
end

在这里haml :index,就表示使用 Haml 渲染'views/index.haml'这个模版。

传递参数也是很容易的事,可以使用实例变量:

复制代码
# in app.rb
get '/' do
@now = Time.now
haml :index
end
# in views/index.haml
Hello, now is #{@now}

或者用 locals 传递参数(如例子中的哈希):

复制代码
# in app.rb
get '/' do
now = Time.now
haml :index, :locals => { :now => now }
end
# in views/index.haml
Hello, now is #{now}

熟悉了路由和模版,就可以开始构建 Web 应用程序了,Sinatra 也提供了一些简单的辅助方法,比如过滤器、helpersconfigurehaltpass等等,这些就不再这里一一叙述了,更多的内容请仔细参考官方文档。

开始博客应用

文件格式

本博客应用将使用 dorothy 格式的文件存储,不会使用数据库。

例子如下:

复制代码
# 文件名: 2010-10-10-a-lucky-day.txt
title: "A Lucky Day"
date: 2010-10-10
author: " 吴江 "
# 今天是我的幸运日
早上在地铁门将要关上的那一刻,我冲进了车厢,于是约会没有迟到...
中午提前了一点去港丽,居然只排了 42 分钟...
晚上又赶上了末班车...
到家数了数,钱包里面正好有 42 块钱...

该文件的结构是:以第一个连续换行符("\n\n")为界线,前一半是 YAML 格式的配置信息,后一半则是 markdown 格式的文本。 YAML 格式是一种表示数据的标记语言。这里只使用到它的键值对结构。 markdown 则是很方便的用纯文本编写 HTML 的格式。比如"# header1"会生成"<h1>header1</h1>""*emphasis*"会生成"<em>emphasis</em>"等等。

安装环境

本博客应用使用 Ruby 1.8.7 版本。安装好后,首先安装 Bundler(gem install bundler),然后编写 Gemfile(见下),运行bundle install即可一次性安装好所需的 gems。

复制代码
# Gemfile
source "http://rubygems.org"
gem 'haml' # Haml 模版
gem 'rdiscount' # 渲染 Markdown
gem 'sinatra' # Sinatra
gem 'thin' # 应用服务器
gem 'shotgun' # 重启服务器
group :test do
gem 'rspec' # 单元测试
gem 'nokogiri' # 解析 HTML 输出
end

测试驱动开发

使用测试驱动开发并非为了赶时髦,只是为了能够帮助我们写出更好的代码。

在本例子中,我们的测试需要能够达到以下目标:

  1. 访问"/"的时候能够正确返回文章列表(虽然只有一篇文章)
  2. 访问"/:year/:month/:date/:title"的时候能够正确地展示文章内容

正式编写

在本例子中,将只接受两个路由请求,'/''/:year/:month/:date/:title'

首先编写如下的测试:

复制代码
# in app_spec.rb
describe 'blog' do
before do
@req = MockRequest.new(Sinatra::Application)
end
it "should show index correctly" do
resp = @req.get '/'
resp.status.should == 200
end
end

运行rspec app_spec.rb可以看到失败结果。先编写简单的代码让测试通过。

复制代码
# in app.rb
get '/' do
""
end

然后继续增加测试,我们想让返回的页面中有链接到/2010/10/10/a-lucky-day这个日志的链接

复制代码
# in app_spec.rb
...
it "should show index correctly" do
resp = @req.get '/'
resp.status.should == 200
doc = Nokogiri.new(resp)
(doc/'a[href="/2010/10/10/a-lucky-day"]').text.should == "A Lucky Day"
end

为了通过这个测试则要写一些长一点的代码,为了省略篇幅,Article类的代码在这里忽略:

复制代码
# in app.rb
get '/' do
@articles = []
Dir.glob("articles/*.txt").each do |article_file|
@articles << Article.new(article_file)
end
haml :index
end

在上文的代码中,首先读取了 articles 目录下的所有 txt 后缀的文件,就是全部的日志。 并把这些日志装到@articles这个数组类型的实例变量。

在视图中,则简单的把日期和日志名称罗列出来。

复制代码
# in views/index.haml
...
- @articles.each do |article|
%header
%h2
= article.date.strftime("%Y 年 %m 月 %d 日 ")
%a{ :href => article.path }= article.title

接下来使用同样的方式来编写显示日志具体内容的代码:

复制代码
it "should show article correctly" do
resp = @req.get '/2010/10/10/a-lucky-day'
resp.status.should == 200
doc = Nokogiri(resp.body)
(doc/'title').text.should == "A Lucky Day"
(doc/'article h1').text.should == " 今天是我的幸运日 "
resp.body.should match " 钱包里面正好有 42 块钱 "
end

实现所用的代码相对会少一些:

复制代码
# in app.rb
get '/:year/:month/:day/:title' do |year, month, day, title|
article_file = "articles/#{year}-#{month}-#{day}-#{title}.txt"
@article = Article.new(article_file)
haml :show
end
# in views/show.haml
!!!
%html
%head
%title= @article.title
%body
%header
%h1
= @article.title
%article= @article.body

测试通过以后,也可以使用shotgun app.rb -s thin开启服务器, 访问 http://localhost:9393 就可以看到在浏览器中的效果。

部署

Heroku 是目前为止最好用的 Ruby 应用部署服务之一。在 Heroku 的帮助下,我们可以快速地把这个应用发布给全世界使用。

首先编写config.ru

复制代码
# in config.ru
run Sinatra::Application

然后运行如下代码:

复制代码
# git 初始化
git init .
git commit -a -m "Initial Commit"
# heroku 部署
heroku create
git push heroku master

当看到"Launching … done"的字样的时候,就说明我们的程序部署成功了,赶快点击下面的链接看看结果吧!

评论

Disqus 是目前我知道的最好用的评论管理系统。更要命的是,它能够很简单的把一个评论系统加到我们的博客中:

复制代码
<section class="comments">
<script type="text/javascript" src="http://disqus.com/forums/#{username}/embed.js">
</section>

只要把上面这段 html 代码加入到我们的系统中,一个完善的评论系统就出现在用户的眼前。本地调试的时候则要额外加上一句:

复制代码
<script type="text/javascript">var disqus_developer = 1;</script>

借助了 Disqus,我们的评论系统就不会逊色于任何的博客应用。

思考

如果读者能够在整个过程中感受到快乐或者惊奇,那么我编写本文章的目的就算达到了。 详细的代码请参考本文的项目地址: https://github.com/nouse/text-blog

以下则为笔者在制作这个应用过程之中的一些思考。

5 年前,Rails 的创造者 David Heinemeier Hansson 向全世界介绍了 15 分钟编写 blog 应用(优酷视频链接)。在5 年后,我们又用Sinatra 重复造轮子,如果读者对比两者的差别, 就能深刻感觉到这5 年里Ruby 世界的一些变化。

基本工具(RVM 和Bundler)

这5 年间,Ruby 基本工具有了很大的发展。这其中最大的亮点就是 RVM(Ruby Version Manager)。 除了如它的名字所述,可以帮助开发人员安装不同版本的 Ruby 以外。它的 gemset 功能也非常 好用。不同的 gemset 之间是一个个独立的环境,从而避免同一个 gem 的不同版本之间的干扰。

如果在项目目录下添加.rvmrc(rvm use version@gemset),就可以让项目处于一个独立的环境之中。 再编写好 Gemfile,将项目中需要的 Ruby 库全部交给 Bundler 管理, 就不会出现部署的时候缺乏相应的库导致失败的情况了。

方便的部署

Git 的普及和 Heroku 的崛起,大大简化了部署的过程。如果 5 年前有 Heroku 的话, DHH 的博客应用可以有更大的反响。“编写完成”–>“git push”–>“上线!”。 一个博客应用就一瞬间仿佛活了一样,从一个本地的演示项目变成了一个真正的线上应用。

Disqus 等第三方应用的兴起

5 年前,Web 2.0 刚刚兴起,只要编写一个使用 Ajax 增强交互功能的应用, 就可以吸引用户的眼球。但是随着 Web 2.0 的概念深入人心,做一个 blog 显然不再能吸引用户的眼球了。

如果 Disqus 这样的第三方应用能够逐渐增多,那么我们就能够把更多的时间放在我们真正想实现的功能上。 就像这里,我们只要把博客的内容展示做好就够了,其他的则交给成熟的服务来处理。 Rails 的成功就在于简化了开发 Web 2.0 应用的时间。借用一下 jQuery 的口号“write less, do more”, “写的更少,做的更多”是软件开发永远的主题。

Sinatra 和 Rails 的关系

DHH 在推出 Rails 的时候,让深陷于 Java 世界的开发人员看到了希望,Rails 也借助 Web 2.0 的热潮迅速走红。 其实,笔者所做的演示的功能模仿的是一个 Rack 应用程序, toto 。 所以读者们也不必迷信,用 Sinatra 经过 15 分钟能做出更好的博客应用,就说明 Sinatra 会取代 Rails。

当前最流行的方式是融合,比如 gemcutter.org,也就是现在的 rubygems.org。 他们整个站点使用的是 Rails 3,而客户下载 gem 的请求则是被 Sinatra 处理。 这样就可以保证网站在升级的时候不会影响下载 gem 的请求,而且 Sinatra 处理请求的速度也优于 Rails 3, 用来处理每天超过访问网站数倍的下载请求也十分合适。

不管怎样,只有更多的了解一个框架的优缺点,才能在真正使用的时候做出正确的选择。而 Sinatra 的源代码只有一千行,要了解它并做出选择,相信不是件难事。


关于作者:吴江,Ruby 和 Javascript 程序员。从 09 年开始,在国内社区中积极宣传和推广 Sinatra。10 年 8 月底,以演讲者的身份参加了在日本举行的 RubKaigi。现在上海一家 Ruby 行业的咨询公司工作。

2011-01-21 00:0010541

评论

发布
暂无评论
发现更多内容

手把手实践丨基于STM32+华为云设计的智慧烟感系统

华为云开发者联盟

云计算 华为云 华为云开发者联盟 企业号 6 月 PK 榜

亿级大表毫秒关联,荔枝微课基于腾讯云数据仓库Doris的统一实时数仓建设实践

科技热闻

Amazon CodeWhisperer 初体验

Coder9527

含有CPU芯片的PCB设计需要考虑的五个主要方面

华秋电子

一文读懂责任分配矩阵,解决你80%的项目难题

敏捷开发

项目管理 Scrum 敏捷开发 责任分配矩阵 RACI矩阵

让AI无处不在!Intel拿出全新VPU:超高能效碾压GPU

E科讯

简洁实用的文本编辑器:FSNotes中文版

真大的脸盆

Mac Mac 软件 文本编辑器 文本管理 文本处理工具

行云堡垒V7亮点有哪些?具体看这里!

行云管家

IT运维 行云堡垒

2个场景实例讲解GaussDB(DWS)基表统计信息估算不准的处理方案

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 6 月 PK 榜

强化学习基础篇【1】:基础知识点、马尔科夫决策过程、蒙特卡洛策略梯度定理、REINFORCE 算法

汀丶人工智能

人工智能 深度学习 强化学习

强化学习基础篇[2]:SARSA、Q-learning算法简介、应用举例、优缺点

汀丶人工智能

人工智能 深度学习 强化学习

数据隐私为先:EMQX Cloud BYOC 架构解析

EMQ映云科技

物联网 云服务 mqtt

中移链资源管理介绍

BSN研习社

人工智能工程总体介绍

紫晖

人工智能 软件工程 数据开发

堡垒机重要吗?为什么?求解!

行云管家

堡垒机 安全运维 录像审计

执行计划缓存,Prepared Statement性能跃升的秘密

华为云开发者联盟

数据库 后端 华为云 华为云开发者联盟 企业号 6 月 PK 榜

玩转服务器之应用篇:从零开始构建小型高可用环境

京东科技开发者

高可用 云主机 云服务器 企业号 6 月 PK 榜

分享几个索引创建的小 Tips

江南一点雨

MySQL

软件测试/测试开发丨Pytest测试框架学习笔记

测试人

程序员 软件测试 pytest

我又和redis超时杠上了

蓝胖子的编程梦

redis 性能分析 云服务器 线上事故 接口超时

单点登录的三种实现方式

Authing

SSO 单点登录

rocketmq4 docker安装 阿里云linux2(centos7)

folo

Docker centos RocketMQ部署

TiDB集群数据库灾难恢复手册

TiDB 社区干货传送门

管理与运维 备份 & 恢复

TiDB数据迁移实践DM工具

TiDB 社区干货传送门

迁移 实践案例

TiDB 落地SAS机器实践

TiDB 社区干货传送门

实践案例 应用适配 HTAP 场景实践

圣邦股份:品类持续深挖,高端加速推进,模拟龙头稳健发展

华秋电子

魔法门之英雄无敌3下载,死亡阴影 for Mac中文版

理理

mac游戏 英雄无敌3 英雄无敌3高清中文版 魔法门之英雄无敌3下载 死亡阴影中文版

【5.26-6.02】写作社区优秀技术博文一览

InfoQ写作社区官方

热门活动 优质创作周报

通过FP&A实践,释放企业深度价值

智达方通

全面预算管理 财务规划和分析 FP&A

这本数智平台白皮书讲透了大型企业数智化升级业务痛点

用友BIP

白皮书 数智底座 数智平台 平台白皮书 数智化转型白皮书

浅谈EOS区块链性能测试

BSN研习社

用Sinatra编写博客应用_Ruby_吴江_InfoQ精选文章