用Sinatra编写博客应用

本文介绍Sinatra,一个轻量级的Ruby Web框架。它以其简洁和高效著称,适用于快速开发小型Web应用。文章详细讲解了Sinatra的基本结构、路由、模板渲染及如何构建一个简单的博客应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 =\u0026gt; { :now =\u0026gt; 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块钱...\
\

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

\

安装环境

\

本博客应用使用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 \u0026lt;\u0026lt; 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 =\u0026gt; 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是目前我知道的最好用的评论管理系统。更要命的是,它能够很简单的把一个评论系统加到我们的博客中:

\
\\u0026lt;section class=\"comments\"\u0026gt;\  \u0026lt;script type=\"text/javascript\" src="http://disqus.com/forums/#{username}/embed.js"\u0026gt;\\u0026lt;/section\u0026gt;\
\

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

\
\\u0026lt;script type=\"text/javascript\"\u0026gt;var disqus_developer = 1;\u0026lt;/script\u0026gt;\
\

借助了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的博客应用可以有更大的反响。“编写完成”--\u0026gt;“git push”--\u0026gt;“上线!”。 一个博客应用就一瞬间仿佛活了一样,从一个本地的演示项目变成了一个真正的线上应用。

\

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行业的咨询公司工作。

资源下载链接为: https://pan.quark.cn/s/abbae039bf2a 无锡平芯微半导体科技有限公司生产的A1SHB三极管(全称PW2301A)是一款P沟道增强型MOSFET,具备低内阻、高重复雪崩耐受能力以及高效电源切换设计等优势。其技术规格如下:最大漏源电压(VDS)为-20V,最大连续漏极电流(ID)为-3A,可在此条件下稳定工作;栅源电压(VGS)最大值为±12V,能承受正反向电压;脉冲漏极电流(IDM)可达-10A,适合处理短暂高电流脉冲;最大功率耗散(PD)为1W,可防止器件过热。A1SHB采用3引脚SOT23-3封装,小型化设计利于空间受限的应用场景。热特性方面,结到环境的热阻(RθJA)为125℃/W,即每增加1W功率损耗,结温上升125℃,提示设计电路时需考虑散热。 A1SHB的电气性能出色,开关特性优异。开关测试电路及波形图(图1、图2)展示了不同条件下的开关性能,包括开关上升时间(tr)、下降时间(tf)、开启时间(ton)和关闭时间(toff),这些参数对评估MOSFET在高频开关应用中的效率至关重要。图4呈现了漏极电流(ID)与漏源电压(VDS)的关系,图5描绘了输出特性曲线,反映不同栅源电压下漏极电流的变化。图6至图10进一步揭示性能特征:转移特性(图7)显示栅极电压(Vgs)对漏极电流的影响;漏源开态电阻(RDS(ON))随Vgs变化的曲线(图8、图9)展现不同控制电压下的阻抗;图10可能涉及电容特性,对开关操作的响应速度和稳定性有重要影响。 A1SHB三极管(PW2301A)是高性能P沟道MOSFET,适用于低内阻、高效率电源切换及其他多种应用。用户在设计电路时,需充分考虑其电气参数、封装尺寸及热管理,以确保器件的可靠性和长期稳定性。无锡平芯微半导体科技有限公司提供的技术支持和代理商服务,可为用户在产品选型和应用过程中提供有
资源下载链接为: https://pan.quark.cn/s/9648a1f24758 在 JavaScript 中实现点击展开与隐藏效果是一种非常实用的交互设计,它能够有效提升用户界面的动态性和用户体验。本文将详细阐述如何通过 JavaScript 实现这种功能,并提供一个完整的代码示例。为了实现这一功能,我们需要掌握基础的 HTML 和 CSS 知识,以便构建基本的页面结构和样式。 在这个示例中,我们有一个按钮和一个提示框(prompt)。默认情况下,提示框是隐藏的。当用户点击按钮时,提示框会显示出来;再次点击按钮时,提示框则会隐藏。以下是 HTML 部分的代码: 接下来是 CSS 部分。我们通过设置提示框的 display 属性为 none 来实现默认隐藏的效果: 最后,我们使用 JavaScript 来处理点击事件。我们利用事件监听机制,监听按钮的点击事件,并通过动态改变提示框的 display 属性来实现展开和隐藏的效果。以下是 JavaScript 部分的代码: 为了进一步增强用户体验,我们还添加了一个关闭按钮(closePrompt),用户可以通过点击该按钮来关闭提示框。以下是关闭按钮的 JavaScript 实现: 通过以上代码,我们就完成了点击展开隐藏效果的实现。这个简单的交互可以通过添加 CSS 动画效果(如渐显渐隐等)来进一步提升用户体验。此外,这个基本原理还可以扩展到其他类似的交互场景,例如折叠面板、下拉菜单等。 总结来说,JavaScript 实现点击展开隐藏效果主要涉及 HTML 元素的布局、CSS 的样式控制以及 JavaScript 的事件处理。通过监听点击事件并动态改变元素的样式,可以实现丰富的交互功能。在实际开发中,可以结合现代前端框架(如 React 或 Vue 等),将这些交互封装成组件,从而提高代码的复用性和维护性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值