晒晒我的开源项目们
October 6th, 2011
在等“bundle install”的时候闲着没事,打开 我的Github ,发现还有那么一些东西值得分享一下的。

啤酒游戏 :《 第五项修炼 》里讲的啤酒游戏。多人协作游戏,适合培训时候用。培训详情请联系 小刀 。
合作的进化 :这就是《 合作的进化 》那本书里讲的生存竞赛游戏。可以自己写新的策略放进来,看看重复囚徒困境中的最佳策略是如何被选择出来的。
Jungling :作为技术人员的TWer到客户现场启动一个新项目时需要注意哪些事?带上iPad和Jungling,你的丛林冒险手册就有了。
每天一小时 :1.HourFor.Me 的源代码。每天一小时,每月就能做成一件事。欢迎贡献,如果从代码里发现了漏洞,还望高抬贵手请勿攻击。
TRSS :TRSS 的源代码。 把RSS同步到新浪微博(因为新浪自己的同步功能貌似不工作了)。后面还可以有很多发展,例如同步到各种微博之类的。同样,欢迎贡献代码,多谢请勿攻击。
jquery.image-preview :一个比较体面的图片预览插件,实现就像Google Images那样的 效果 :鼠标悬停在小图片上,小图片就会放大预览。主要的难点是当小图片位于页面边缘时,预览也要出现在合适的位置。
图灵机 :这两天开始写的,照着 图灵的论文 ,用 Clojure 实现一个原模原样的图灵机。后面也许还想在iOS上实现一个有图形界面的。
发现我的开源项目们有个共通的问题:虎头蛇尾。每个点子都没有耐性深挖下去。想写代码练手的年轻同事们可以找我啊,我这里要干的活很多的⋯⋯
Chef学习手记之叁:红宝石菜谱
March 2nd, 2011
有了一台 基本的服务器 ,现在我就要在上面配置Rails服务器。当然这件事已经有人干过了,但我不想用别人的菜谱,再怎么说我也是 RubyWorks 的开发者…
(还有,我觉得Fedora还是不如Ubuntu好用,所以我偷偷把EC2的机器换成了Ubuntu 10.04。)

新建一个菜谱真容易,用knife一下子就搞定了:
$ knife cookbook create my_rails_gig
菜谱放在 #{chef-repo}/cookbooks/my_rails_gig 下面。首先要看的是 recipes/default.rb ,缺省菜色的做法就写在里面。在我开始做自己的配置之前,我得先保证Apache和 Passenger 都配好了。
# default.rb include_recipe "passenger_apache2::mod_rails"
然后涅,我要用“railsapp”这个用户来部署Rails应用──不可以用root来跑服务。所以我得确保有这个用户(以及它独占的一个组)。
# default.rb group 'rails' do group_name 'rails' action :create end user 'railsapp' do username 'railsapp' action :create end
接下来,按照我们RubyWorks的传统,Rails应用应该部署在 /var/rails 目录下面。所以要确保有这个目录。
# default.rb deploy_to = '/var/rails' directory deploy_to do owner "railsapp" group "rails" mode "0755" action :create end
现在是最挑战的部分:配置Passenger…但是只要是像我一样经验丰富的Rails服务器管理员,这个也小菜一碟_ Apache2那本菜谱 讲了怎么在Apache里做web_app,你只要调用就行:
# default.rb
web_app 'rails_app' do
template "rails_app.conf.erb"
docroot "#{deploy_to}/current/public"
server_name "#{MY_COOL_HOSTNAME}"
rails_env 'production'
end
唯一的trick就是 rails_app.conf.erb 这个template:我需要把它放在 templates/default 目录下(规则和Rails有点像)。别的么…就再没啥啦~~(不信就 看代码 )噢对了,别忘了在这台机器的角色里加上新的菜色:
"run_list": [
"recipe[passenger_apache2::mod_rails]",
"recipe[my_rails_gig]"
],
噢也~菜谱写完开始做菜~先把菜谱上传到服务器:
$ knife cookbook upload my_rails_gig
再跑到我的服务器上执行一下 chef-client …这就好了。用 railsapp 用户到 /var/rails/current 下面建一个应用(为什么要“current”?问 Capistrano )。浏览器访问80端口,看后台日志,Rails已经开始工作了。
嗯,虽说写自己的菜谱挺好玩的,不过 这个菜谱 很值得学习──其实很多菜谱都值得学习,所以…
(未完待续)
Chef学习手记之贰:基本套餐
February 20th, 2011
现在我要配置一台体面的Rails服务器。也许我会用它来跑 1.HourFor.me 。
要配置一台Rails服务器,首先要有一台服务器。于是我到 EC2 搞了一台服务器。EC2之于DevOps就像SourceForge之于轻量级J2EE:它让你有机会去尝试那些原来只有在超级大企业里才会出现的东西。你可以在自己家里、在业余时间积累经验,而且不花多少钱。我装了一台Fedora 8的机器。
在 学习手记之壹 里我说需要有一个Chef服务器。其实Chef有三种运行的方式:你自己装Chef服务器;压根不要Chef服务器(叫 Chef Solo );或者用OpsCode做你的Chef服务器。第三种方式蛮好,又不用自己多架台服务器,又可以在世界任何地方共享我的大餐。所以我就要这样做。

首先要在OpsCode注册,并创建一个组织(organization)。这部分蛮简单,照着网站的指示一步步做就行了。我创建了一个叫“thoughtworkers”的组织。创建组织的时候小心,有免费的plan可以用的。我现在还不需要收费plan那么强的功能。
紧跟着要搞定开发环境。我要在自己的机器上建一个 Chef Repository ,配置与Chef服务器连接的身份认证信息。基本上,按照 这个文档 来操作就可以了。
接下来要在EC2那台Fedora机器上安装Chef客户端。这也蛮简单,也有 一个文档 。其实关键就是要把RubyGems升级到1.3.7以上,然后就可以“gem install chef”啦。装好之后执行一下“chef-client”,应该会报错,需要从本地环境拷贝/etc/chef下面的client.rb和validation.pem去Fedora机器上。
现在可以写程序咯~在Chef Repository下面的roles目录里建一个base.json文件。先不管是Rails服务器还是Django服务器,我的体面服务器必须满足一些基本条件,比如有GCC啦,有Git啦,之类的。所以我在base.json里这样描述我的体面服务器:
{
"name": "base",
"default_attributes": {
"chef": {
"server_url": "https://api.opscode.com/organizations/thoughtworkers",
"cache_path": "/var/chef/cache",
"backup_path": "/var/chef/backup",
"validation_client_name": "thoughtworkers-validator",
"run_path": "/var/chef"
}
},
"json_class": "Chef::Role",
"run_list": [
"recipe[build-essential::default]",
"recipe[openssl::default]",
"recipe[chef::client]",
"recipe[chef::delete_validation]",
"recipe[git::default]"
],
"description": "Basic Server",
"chef_type": "role",
"override_attributes": {
}
}
然后涅…那台Fedora机器咋知道它自己应该有“base”这个角色呢?当然答案是它不知道。我得告诉它。Knife 是Chef的便利命令行工具。比如说,可以列出所有可管的节点(必须在Chef Repository目录下):
$ knife node list # 下面是输出回显 [ "ip-10-130-9-17.ap-southeast-1.compute.internal", "jeffxiong3650" ]
有两台机器。下面这个是我自己的笔记本电脑,上面那个名字很长的就是在EC2的Fedora。我要让它知道,自己有“base”这个角色要扮演:
$ knife node run_list add \
ip-10-130-9-17.ap-southeast-1.compute.internal "role[base]"
# 下面是输出回显
{
"run_list": [
"role[base]"
]
}
好乖~现在ssh登录到Fedora上去,执行一把“chef-client”…体面的服务器就这样装好啦~试试git,没问题的说~嗯嗯,当然这只是第一步。接下来要配置好体面的Rails服务器才行呢。
(未完待续)
Dreamhost还是挺不方便的
November 16th, 2009
Lonely Planet Images
August 31st, 2009
Lonely Planet, the experts in independent travel information now present Lonely Planet Images (LPI). LPI is a digital image library with a unique and comprehensive collection of over 300,000 downloadable travel photographs taken by some of the best travel photographers in the business.
Its Chinese collection is relatively small so far. Hmm hmm…
ActiveRecord Changed :include Behavior?
August 12th, 2009
Company.find(:all, :include => :people)as something like
SELECT * FROM company SELECT person.* FROM person WHERE person.id in (...)In 2.1.x, it used to generate SQL as something like
SELECT * FROM company LEFT OUTER JOIN person ON person.company_id = company.id
It seems for the sake of performance…the current statements return smaller data set. However, it could generate a very long SQL statement if you have lots of ‘people’ in this case, and thus spend longer to parse and execute.
And…WHEN did this change happen? I’m wondering…
Move To Multi-threaded Rails
July 17th, 2009
When doing performance in local box, we found that requests are waiting to be processed due to Rails is single-threaded by default. We changed the configuration to enable multi-threaded mode as described in this blog entry:
(also refer to Rails 2.2 release notes )
The most important change was to eager-load /lib directory, and thus move libraries for test out of it.
config.threadsafe! also disables automatic loading by ActiveSupport::Dependencies. Alternatively, you can just add lib/ directory to eager load paths. The following inside production.rb will do that :
config.eager_load_paths << "#{RAILS_ROOT}/lib"
We had some rough tests to ensure the functionality is not broken. Multi-threaded mode also might require more memory than single-threaded mode. Still keep testing.
rake stats (again)
June 8th, 2009
用Ruby翻新一个Java的系统。原来系统功能代码47311行,测试代码13440行(都只计算Java代码)。还没翻完。
+----------------------+-------+-------+---------+---------+-----+-------+ | Name | Lines | LOC | Classes | Methods | M/C | LOC/M | +----------------------+-------+-------+---------+---------+-----+-------+ | Controllers | 1403 | 1188 | 31 | 131 | 4 | 7 | | Helpers | 361 | 311 | 0 | 52 | 0 | 3 | | Models | 2236 | 1837 | 77 | 270 | 3 | 4 | | Libraries | 2115 | 1740 | 30 | 156 | 5 | 9 | | Model specs | 2443 | 2022 | 0 | 18 | 0 | 110 | | View specs | 0 | 0 | 0 | 0 | 0 | 0 | | Controller specs | 3315 | 2716 | 0 | 2 | 0 | 1356 | | Helper specs | 374 | 310 | 0 | 0 | 0 | 0 | | Library specs | 822 | 708 | 0 | 3 | 0 | 234 | +----------------------+-------+-------+---------+---------+-----+-------+ | Total | 13069 | 10832 | 138 | 632 | 4 | 15 | +----------------------+-------+-------+---------+---------+-----+-------+ Code LOC: 5076 Test LOC: 5756 Code to Test Ratio: 1:1.1
这次是JRuby on Rails。我特别喜欢它的部署脚本。
JRuby/LDAP over SSL
March 25th, 2009
Integrating ActiveDirectory with JRuby on Rails. Blocked by SSL issue. (Actually not AD but ADAM. Check how to configure ADAM for SSL on Windows XP without a certificate server )
Jeff: Here we have a question about JRuby/LDAP: how to establish SSLConn to ActiveDirectory, given we have got the certificate file (xxx.cer)?Ola: Very good question. At the moment I don’t have the answer – and I’m not sure it’s possible. Have you considered using net/ldap instead? It’s pure Ruby and very nice.
~~(╯﹏╰)~~
And then I figured it out. What we need is (1) import the certificate to a keystore, and (2) specify the location of keystore to JRuby.
# command line
keytool -keystore "./cacerts" -import -file Authority.cer
# JRuby
java.lang.System::setProperty("javax.net.ssl.trustStore", "/path/to/cacerts");
And…that’s it. Now we can connect to ADAM over SSL.
conn = LDAP::SSLConn.new(host=LDAP_HOST, port=636)
快速冲锋步
December 24th, 2008
快速冲锋也有节奏。把节奏记下来,下次可以改进。这就是泰勒在伯利恒钢铁公司做过的事。
- 愿景(1小时):我要做个东西,要快。也许应该试试用Rails做?因为它很快。似乎没有特别的原因阻碍用Rails?是的,没有。
- 空谈(1小时):它好像是个什么东西。它看起来有点像Mephisto吗?呃,Mephisto是什么?你看,我用Mephisto做了我的blog和AgileChina的网站。不错,看起来有点像。
- 部署(3小时):给我服务器,我把Mephisto架起来。没问题,连域名都给你。
- Rails 2.2在Windows上不好使,因为MySQL gem的原因,也许应该装Ruby version而非win32 version
- 在Windows平台使用Apache2.2和Mongrel运行Ruby on Rails
- 原型+反馈(3小时):现在你可以添加内容了。管理后台和我想的不一样。我们可以定制Mephisto。定制是一堆破事,重做也是一堆破事。你让我想想。
- 抛弃(30分钟):现在我基本上知道你要什么了。我决定重做。
- 堆砌(2小时):插件,generator。我知道所有的convention。没有测试。我要看到第一个页面,让我可以部署它。
- 第一个model不是User,而是核心概念
- 第一组数据写进fixture,直接load到产品系统
- 第一个migration叫做release_1,不允许回滚
- 第一个build脚本就用上svn.rake
- 用TODO文件来管理storys/defects/unknowns
- 再次部署(30分钟):尝试过Mephisto,现在我知道该怎么部署了。
- 反馈+小步前进(6小时):好像可以发布内容了,酷。用户权限我是这样设想的。能不能这样简化?以后我们可以这样去改变。可以,我们可以先控制邀请。
- 给build脚本加上stats:我允许现在测试覆盖率低,但从现在开始它必须一直提高
- 每次代码修改开始加上测试,因为我开始记不清每个细节了
- 没有Selenium
- 每个story完成后立即部署
- 发布+反馈(1小时):告诉我一个帐号。quentin和admin都可以。我添加了一些东西,有些更多的想法。TMD…我本来没打算发布的。看在你费劲的份上,就算我发布了吧,现在开始不再清数据库。
- 新的migrations:每个migration只做一件事,每个migration都可以rollback。
- 继续小步前进(6小时):SMTP server帮我搞搞好。80端口给我。我收到邮件了。80端口腾出来以后我再改Apache配置,共计需要删掉4字符。
- 界面的手工验证开始变多
- 复杂的业务逻辑出现,借用了上一个项目的经验,还是出了一点tricky的错误,耗时30分钟
从周六开始,共计5天业余时间,或换算成3个工作日。



