123
 123

Sun 22 July, 2007

Click here to bookmark this link.Channel Image18:10 Capistrano 2.0» Riding Rails - home

Capistrano 2.0 is real. (What is Capistrano?)

Install it thus:

gem install capistrano

It’s been through four preview releases, and has seen significant changes since 1.4.1. If you’re currently using 1.4.1, be sure to check out the upgrade documentation at http://www.capify.org. If you’re altogether new to Capistrano, you might like to read about getting started.

Since the last preview release (number four, version 1.99.3), the changes are primarily bug fixes, but the following featureish modifications snuck in, too:

  • The uploader has added a tiny bit of sleep to prevent the CPU from going bonkers during uploads.
  • You can specify the $CAPISTRANO:HOST$ placeholder in the filenames that you give to “put”, and it will be replaced with the actual host that the file is being uploaded to.

Also, some people reported SFTP uploads were hanging for them. If this happens to you, try adding the following line to the top of your recipe file:

set :synchronous_connect, true

That will cause connections to the servers to be established serially, rather than in parallel, so if you’ve got a lot of servers that you are connecting to, it might make things a bit time-consuming. However, this appeared to work around the hanging SFTP issue.

You can read the complete changelog here. If you are using Capistrano at all, please also consider joining the mailing list, it’s a great place to share tips and report issues.

KNOWN ISSUES

Yes, there are a few of these. Two are of immediate significance:

  1. If you try to use the ‘put’ command to upload a file to two or more hosts via a gateway, you run a good chance of encountering “corrupted mac” errors. This is due to design flaws in Net::SSH and Net::SFTP, and (to my knowledge) cannot be worked around. The current best practice is to upload to a single host, and then use scp or rsync from the remote hosts to pull the file.
  2. A very few people have reported commands hanging inexplicably and infrequently. I suspect this is also due to flaws in Net::SSH, but I’m not certain yet.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:53 你的心情还好吗?» 梦想风暴

周末,跨越了大半个北京城和几个老朋友聚到了一起,由于有一段时间没有见到,自然一个个都变成了话痨。一个朋友的精神状态对比于之前见到的他来说,明显好了许多,生活显然也丰富多彩了一些。聊到原因,他从之前一个很糟糕的情况逐渐摆脱了出来,心情好了,自然而然人的状态也随之好转了。当然,朋友们也看到了我类似的变化。加入到ThoughtWorks后,我整个人的状态变得明显不同了,更活泼了。按照一个朋友的说法,明显是被释放的结果。

曾经和老妈聊天,我说找工作的标准是“钱多和心情好” 至少有一样。其实,虽然我也知道金钱的重要性,但我一直没有树立了一个良好的追逐金钱的观念,所以,我真正看重的是心情。工作最初的部门给我留下了一些很美好的回忆,其中一个重要的原因就是那里给了我一个良好的心情,周围的环境让我感到很舒服,所以,在那里我的表现也得到了大家的认可。虽然后来我离开了那里,但原因也与环境无关。反而,每次我回到沈阳,都会回到那个部门与一些老朋友叙旧。在我正式离职之前,我还曾经到那个部门与大家分享了一些Ruby的东西。

之后工作的那个部门,虽然我从中也学到了不少的东西,但自己整体评价我那两年的表现,很糟糕。自我分析的结果是,我一直没有找一个让自己心情愉快的理由。虽然大家也经常在一起玩,但那个部门的整体氛围一直不是我很喜欢的,人和人之间表现得也不是那么友善。正所谓祸不单行,有一段时间,我觉得自己很“背”,把该倒的霉在那一段时间都倒了。所以,在这种氛围中工作了一段时间之后,我感觉很压抑。我知道自己肯定会离开,只是不知道什么时候,下一个落脚点会在哪里,直到我找到了ThoughtWorks。

一个朋友看到我写的那篇《一月思想工作者》给出的评价是如鱼得水。经过长时间的压抑之后,我感觉自己一下子解脱了。我很快就融入了这样的环境中,以至于一些新来的同事误以为我已经在这里工作了很长的时间。ThoughtWorks给了我一个我喜欢的环境。我不会为了那些没有意义的东西,消磨自己锐气。

在ThoughtWorks的招聘流程中,有一条原则,如果应聘者让你感觉不舒服,你就完全有理由拒绝这个应聘者。这是一条看似不合理的原则,但对于维护一个良好的企业文化却至关重要。因为招进来的人是要和我们一起工作的。如果这个人在应聘过程中让人不舒服,那么在日后的工作过程中,他可能也同样会表现得让不舒服,让人不舒服的结果就会是影响工作效率,精力被浪费在一些无谓的地方。事实上,正是有这样一条原则,所以,几乎与所有ThoughtWorker在一起都会让人感觉很舒服。不管这个人来自哪里,即便是刚刚认识,也会很快就会熟悉起来。

你的工作环境给了你怎样的心情呢?


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:00 code complete» Ruby Object Oriented
这周六读到”code complete”这本书. 我直接翻到了”表驱动法”那一章 一看,哈,我遇到的一些经验被”表驱动法”很好的描述了出来,同时又有一些我没有遇到过的新的有意思有实用价值的相关技术. 于是我用”Table-Driven(7-21)”,来表示7月21日那天,我读到了Table-Driven(表驱动)这个概念. 然后我结合关系数据库,想到了如何来Table-Driven.一个记录是一个节点,可以用关系数据库来表示树结构或图结构. 结合”基于表示和搜索”的人工智能思想,就可以解决很多问题. ============== 上面的是昨天的事情. 今天,我又翻看了一下”code complete”这本书,还是翻到了表驱动法这一章.这次我看到了上次我没有看到的一些细节,例如: 1.索引技术访问表 2.阶梯法访问表 其中又顺便看了看”循环”,外循环与内循环,”把最忙的循环放到内循环中”这些优化循环速度的代码调整技术,以及循环合并,if语句和循环语句的调整等等,实在是拍案叫绝,哈哈,有意思.”如果已经知道某件事情了,那么就不必在判断” ============= 今天我想到的两个量词搜索的问题: 查询表的时候,判断是否所有的x,x是p,可以或者应该转化为搜索”是否存在x,x不是p”,然后取反.哈哈,虽然对于”任意x,x是p”和”不存在x,x非p”在逻辑上是等价的,但是在基于搜索算法的效率上面,后者却有可能是优化了的. class Array   def any?      each do |item|       return true if yield(item)     end     return false      end   def all?      !any?{|i|!yield(i)}   end     end    p [1,1,0,1].any?{|i|i==0} p [1,1,0,1].all?{|i|i==0} p [1,1,0,1].all?{|i|i>=0} 同样的道理,适用于关系数据库里量词的搜索:判断”是否存在某属性”,只需要搜索到一个记录,就可以停止搜索.判断”是否所有”,可以转化为搜索是否存在相反属性,如果存在,这表示不是”所有”,如果不存在相反属性,则表示”所有成立”.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image14:05 IP class» Ruby Object Oriented
class IP    include Comparable   attr :ip   def initialize(ip)     @str_ip=ip     @ip=ip.split(".").map{|c|c.to_i}   end     def +(n)     rs=[]     ip=@ip.dup     while c=ip.pop       n,cc=(n+c).divmod(255)            rs<<cc     end      self.class.new(rs.reverse.join("."))       end      def <=>(other)     self.ip.each_with_index do |c,i|       if c!=other.ip[i]         return c<=>other.ip[i]       end      [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image05:25 I used to tell my senior st...» Projectionist
I used to tell my senior staff to get me poets as managers.

Sidney Harman


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 A billion dollars doesn't buy much these days» Loud Thinking by David Heinemeier Hansson

Just days after Microsoft announced spending a billion dollars on extending the Xbox 360 warranty, my own console surrended to the dreaded three flashing red lights.

Now you'd think a billion dollars would buy Microsoft some premium, grade-A service and expedition to make short order of such a widespread problem, no? Think again.

It took three separate tries to even get through on their support line. The final attempt required about an hour on the line. All that to get a paper box shipped as the return package using UPS 3-day service (unlike, say, Apple's overnight delivery).

But much worse, expected service time is 4-6 weeks! Between the attempts at calling support and shipping boxes back and forth with snail service, I'm looking at a two-month turn-around from problem to resolution. Yikes.

How am I supposed to cope with no Forza Motorsports for that along!? It's inhuman, I tell you.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 こんなTシャツはエンジニアしか思いつかないぜ!夏/Tech総研» Matzにっき
個人的には以下のものがウケた。 Honey, you are my jewel. Ruby and perl are not. あと、 grep me も悪くない。でも、最近だと実用性の観点からは「Google me」なんだろうなあ。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 [Rails] Webアプリケーションセキュリティフォーラム - Journal InTime (2007-07-05(木))» Matzにっき
セキュアなRailsプログラムの作り方。 こうやってまとめておくとありがたい。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 The easiest rubinius core library patch tutorial ever. << The Plan A» Matzにっき
やさしいRubiniusの拡張法。 確かに簡単なんだけど、これだと便利すぎて厳密な互換性は実現できそうにないな。 to_intのような変換システムはどこで動くんだろう。 しかし、こうやって簡単に機能が拡張できるというのは それはそれで素晴らしいことのような気はする。 効率もよくするんだって言ってるんだし。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 Large Binary Data is a Weakness of Erlang << Metalinguistic Abstraction» Matzにっき
Erlangは巨大なバイナリデータの扱いが苦手、という話。 基本的にパターンマッチで処理を行うのだが、 毎回文字列のコピーを作っちゃうから、長い文字列だと効率が悪いということらしい。 copy-on-writeとか、部分文字列のようなのが必要なのかもしれない。 Rubyはその辺、ちょっと工夫はしてるけど、 文字列の構造がもっと複雑になってもいいなら(あと、Cレベルの互換性が下がってもいいなら)、 まだまだできることはあるんだけど。どうしよう。 本当に困ってる人が出てからでいいかな。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 Google デスクトップ» Matzにっき
ようやっとインデックス作成が一段落したようだ。 えーっと何日かかったんだ? 2週間? 結局30万アイテム強であった。多い。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Sat 21 July, 2007

Click here to bookmark this link.Channel Image22:11 IP段与国家代码» Ruby Object Oriented
http://ftp.apnic.net/apnic/dbase/data/country-ipv4.lst 相关资料:找到全部大陆IP段
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image16:55 mongrel启动时报错的解决» Ruby On Rails Techlogs --1ster..!
记不得时候在本地机子上安装了mongrel,今天把1stlog用mongrel运行时,报告: -e:3:in `load': no such file to load -- mongrel_rails (LoadError) from -e:3 看错误提示貌似mongrel_rails 这个加载不到,那么应该就是配置的问题了,问题解决如下: 找到RadRails的 preferences > Rails > configuration ,在这里指定mongrel_rails的路径就可以了(注意不是bat也不是cmd,而是那个没有后缀的) ok,解决了,如果有谁遇到这个问题,也算帮忙了。呵呵。。。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image11:00 Yuor bairn is samtrer tahn you tnhik» Ruby Object Oriented
Aoccdrnig to a rscheearch at Cmabrigde Uinervtisy, the oredr of letetrs in a wrod dosen't mttaer, the olny thnig thta's iopmrantt is that the frsit and lsat ltteer of eevry word is in the crcreot ptoision. The rset can be jmbueld and one is stlil able to raed the txet wiohtut dclftfuiiy. Tihs is bcuseae the [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:02 Rails and MySQL» Riding Rails - home

The MySQL-dump blog posted on some observed rubyisms while evaluating a large ruby application. He highlights some potential problems with ActiveRecord that may come up, such as using “SELECT *”, character sets, unsigned integers, and constraints.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Fri 20 July, 2007

Click here to bookmark this link.Channel Image23:15 日曜日» Matzにっき
次女が聖餐会でお話をしてくれる。 かなり照れながらも一生懸命に話す姿が好ましい。 日曜学校では教師。 ビショップリックが毎週日曜学校教師をしなければならない 人手不足が嘆かわしいと思う半面、 結構教えるの好きだから楽しいと思うところもある。 でも、くたびれた。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image23:15 富士通、島根でもノートパソコン組み立て教室を実施 | パソコン | マイコミジャーナル» Matzにっき
おおっ、近所だ。行くか。 と思ったが、この日は「LL魂」の日である。ちょっと無理だな。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image23:15 Java and K» Matzにっき
スクリーンキャスト。JavaとK(APLの末裔)の比較(英語)。 まあ、このタスクが圧倒的にK向けということを置いておいても、 ベクタを扱うプログラムにおけるAPL系言語の生産性は間違いない。 ある程度はRubyにも取り込みたいんだけど、 どういうAPIにするのが良いかなあ。 まずは複数のベクタ(配列)の各要素に対して処理する(APLでいう v1 + v2 でv1とv2の各要素を加算した配列を得るような)メソッドをEnumerableに加えればよいのかな。 良い名前が思いつかないけど。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 选取随机的记录的几个方法汇总» Ruby On Rails Techlogs --1ster..!
有的时候,我们可能想吧满足某个条件的记录随机的选几条出来,比如用户查看一篇文章的时候,我们想再旁边随机的列出与这个文章相关的几篇文章,我们就有如下几个方法: *1.在Ruby中一次实现* things = Thing.find(:all) random_things = [] 3.times do random_things << things[rand(things.size)] end 上面这个方法是可以的,但是有个缺点,它把整个表都查询出来,再随机的取三个,缺点很明显,如果数据库表太大,效率很差(内存等消耗很大);且可能取出两条相同的记录(尽管概率不大),第二个问题比较好修复,如下代码即可解决: things = Thing.find(:all) random_things = [] while random_things.size < 3 random_things |= things[rand(things.size)] end *2.Ruby查询两次* thing_ids = Thing.find(:all, :select => 'id').map(&:id) random_ids = [] while random_ids.size < 3 random_things |= things[rand(things.size)] end random_things = Thing.find(:all, :conditions => ['id IN (?)', random_ids]) 这个方法只是先随机取出ids较,然后再取ids对应的记录,比前面说的那个有个好处就是不会消耗太多的系统资源,比起第一种方法会快很多。 *3.在数据库层面上做* random_things = Thing.find(:all, :limit => 3, :order => 'random()') 是不是神奇呢,我们直接把:random(如果是MySQL则需要使用 rand()) 传给Find方法就可以了,这个方法看似比较好,其实不然,其构造出来的SQL比较变形,且对于不同的数据库不能通用。且类似与order by rand() limit 1这样的语句是很畸形的。 *4.使用offset进一步改进* Thing.find :first, :offset => rand(Thing.count) 上面这个方法好多了,但是只能取一条,你可以按照第一种办法构造一个取多条的,页很简单,不是么? 以上四个方法,请按照自己的实际情况使用,对于不同的需求,效率是不一样的,如果你有更好的方法,欢迎留言讨论。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 话题广告测试~» Ruby On Rails Techlogs --1ster..!
feedsky的话题广告 测试下1ef0baf2
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 警惕rails中的保留字带来的问题~» Ruby On Rails Techlogs --1ster..!
这个问题还真一直没有关注过,只是晓得rails和ruby中有些关键字、保留字,也没太注意,昨天开始遇到一个很奇怪的问题,我建立了一个用来存放友情链接的表links,里面有title,desc,*type*,created_at等字段,然后在controller中取记录的时候类似如下语句: @friend_links = Link.find(:all, :conditions => { :type => 1, :visible => 1 }) 貌似一切都很平常,却发生如下的错误: compile error D:/soft/ruby/lib/ruby/gems/1.8/gems/activerecord-1.15.3/lib/active_record/base.rb:1358: syntax error Object::1 一切都很平常呀,试着换个find的写法,还是一样出问题,真是够邪门的~! 然后今天问了几个朋友,也说奇怪,没有遇到过,还好google还是找到了这个问题的根源:保留字。 请注意,这里我使用了一个保留字*type*做为字段名,导致这个错误的发生,就像一个朋友这样解释的一样: Its because *type *is a reserved word, so you'll have to change that column's name (perhaps to kind or something). Otherwise you're code looks fine wink. 大家以后一定要注意,这个小问题浪费了不少时间~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 自动备份数据库的脚本» Ruby On Rails Techlogs --1ster..!
一个WEB应用,基本上是不能保证其100%安全的,网络安全、系统的稳定性都可能在某个时间突然发生,您辛辛苦苦写的文章,收集的资料,很可能在瞬间消失,再也找不回来;数据真的是越来越重要了;另外,你可能想把一个WEB迁移到另外一台主机上等等,这个时候,数据库的备份就显得各位的重要。 ROR应用中,使用的最多的是MYSQL数据库了,一直都没有找到比较好的、方便的方来来备份数据,上次自己写了一个备份到YMAL文件的,使用起来比较慢,导出来的格式也不是很好,所以也就没有发布出来,如果有人对这个比较感兴趣,可以mail我。 今天说的是另外的一个备份的工具(*AutoMySQLBackup*),在COR上看到的链接,脚本是个老外写的,主要使用的是mysqldump来定时备份数据,下来简单的配置试了下,果然好用,你使用的时候,需要修改你需要备份的数据库名、连接用户、密码和主机地址,另外如果你是在虚拟主机上的,则需要修改备份目标文件夹,如+BACKUPDIR="./backups"+(需要加上*./*,否则你可能会得到目录拒绝写操作的提示);另外,还可以配置邮件,使得备份以后会把其压缩后的文件发送到你的邮箱(这个大小受到邮件附件大小的限制),可以定时(天、周、月)来备份。 值得一提的是采用的是增量备份,非常方便。 详细的介绍页面你可以参考:http://www.debianhelp.co.uk/mysqlscript.htm 或者直接下载脚本程序(里面有说明的)
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 用图片代替link_to中的文字» Ruby On Rails Techlogs --1ster..!
link_to大家都会用吧,也有人用户把image_tag和link_to结合起来使用过吧,是不是觉得很长很不干净呢,不用怕,我们其实可以在link_to中直接使用图片来替代文字的,如下: <%= link_to image_tag("search.gif", :border=>0), :action => 'show', :id => user %> 注意里面的:border=>0是为了去掉图片四周那个无聊的框框的,需要加上哦~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 理解REST软件架构» Ruby On Rails Techlogs --1ster..!
*导读:* infoq上的这篇REST构架分析的文章还是不错,从HTTP协议开始介绍了REST的构架理念,值得看看,再花点时间好好理解下REST。 一种思维方式影响了软件行业的发展。REST软件架构是当今世界上最成功的互联网的超媒体分布式系统。它让人们真正理解我们的网络协议HTTP本来面貌。它正在成为网络服务的主流技术,同时也正在改变互联网的网络软件开发的全新思维方式。AJAX技术和Rails框架把REST软件架构思想真正地在实际中很好表现出来。今天微软也已经应用REST并且提出把我们现有的网络变成为一个语义网,这种网络将会使得搜索更加智能化。 详细内容,请查看:http://www.infoq.com/cn/articles/rest-architecure
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 清除HTML标签中的危险字符» Ruby On Rails Techlogs --1ster..!
很多时候,我们需要处理用户输入,为了适合WEB2的特性,做为开发者我们也会设计很对个途径让用户参与进去,但是“盖茨”大叔说得很对:*凡是用户的输入都是有害的!*一点不假,有时候用户可能是无意的或者一些不怀好意的用户会输入一些我们并不想让他们输入的东西,以防止破坏页面结构或者造成其他的危害(比如SQL注射和XSS攻击),所以我们需要对用户的输入认真的检验和过滤。 在页面上显示的时候,我们可以选择+h()+或者+sanitize+或者+strip_tags+等等rails提供的方法进行过滤,但是这些危险的字符还适度会存在数据库,或许有一天就会引爆了呢,所以呢,最好的办法是在存入数据库的时候就做一些过滤或转换,一下一点点代码段只是一个小例子,真实世界中需要过滤和清除的危险字符是很多的,大家注意主机收集和完善,也希望大家一起来实现这个功能,做一个通用的 helper方法。 def stripped_html(html) # this is a copynpaste of the routine in article.rb # so the one in article.rb can change w/o breaking this. self.html.gsub(/<[^>]*>/,'').to_url end 对于HTML标签的过滤和清除,你有什么好的方法么?欢迎分享!
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 来,Rubyize你的代码~» Ruby On Rails Techlogs --1ster..!
了解Ruby语法的朋友应该对Ruby的语法和表达形式很惊叹,这都要归功与Ruby强大的表达能力,有的时候,把以前的写的不完善的代码Ruby化不仅能加深对Ruby的理解,还能提高代码质量,更加可读,或者说更加Ruby一些~ 好,下面举个例子来说明一下,希望有见解的朋友能分享你的写法。 def manage_ducks(ducks) if ducks == nil ducks = fetch_some_champions else unless ducks.won_stanley_cup? ducks = fetch_some_champions end end ducks.beat_random_opponent end 如果是刚刚解除Ruby的话,上面这段代码可能就是你写出来的,她虽然可行,但是一点都不符合ruby的风格,你将怎么改呢~请留言分享~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 本站可以订阅啦~» Ruby On Rails Techlogs --1ster..!
很多朋友说喜欢在googleReader里面看文章,希望我提供XML的订阅功能,其实这个feed早就有了,细心的朋友可能已经找到了,呵呵,在左下角的# RSS、# Comments RSS,是可以直接订阅的。 有朋友推荐feedburner,说更加方便、也适合自己做统计,于是就添加了这个功能,在右边可以看到有个大大的订阅图标啦,其地址是http://feeds.feedburner.com/1stlog,大家可以使用这个来订阅啦。 我会写出更多的Rails方面的文章,欢迎讨论~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 日期上的迭代问题» Ruby On Rails Techlogs --1ster..!
给定一个时间点,希望得到其他时间点的解决方案如下,Ruby 的所有时间对象都可像数字一样用在值域中。Date和DateTime对象按天递增,而Time对象按秒递增: *例子* require 'date' (Date.new(1976, 7, 2)..Date.new(1976, 7, 4)).each { |x| puts x } 1976-07-02 1976-07-03 1976-07-04 span = DateTime.new(1776, 7, 2, 1, 30, 15)..DateTime.new(1776, 7, 4, 7, 0, 0) span.each { |x| puts x } 1776-07-02T01:30:15Z 1776-07-03T01:30:15Z 1776-07-04T01:30:15Z (Time.at(100)..Time.at(102)).each { |x| puts x } Wed Dec 31 19:01:40 EST 1969 Wed Dec 31 19:01:41 EST 1969 Wed Dec 31 19:01:42 EST 1969 Ruby 的Date类定义了*step*和*upto*两种方便的由数字使用的迭代器: the_first = Date.new(2004, 1, 1) the_fifth = Date.new(2004, 1, 5) the_first.upto(the_fifth) { |x| puts x } 2004-01-01 2004-01-02 2004-01-03 2004-01-04 2004-01-05 *讨论* Ruby的日期对象在内部被存储为数字,并且一定范围的这种对象可被视为一定范围的数字。对于Date和DateTime对象而言,内部表示是儒略历日期:每次在一定范围的这种对象上累加一天。对于Time对象而言,内部表示是自Unix 纪元以来的秒数:每次在一定范围的Time对象上累加一秒。 *Time*没有定义step和upto方法,但添加它们也很简单: class Time bq. def step(other_time, increment) raise ArgumentError, "step can't be 0" if increment == 0 increasing = self < other_time if (increasing && increment < 0) || (!increasing && increment > 0) yield self return end d = self begin yield d d += increment end while (increasing ? d <= other_time : d >= other_time) end def upto(other_time) step(other_time, 1) { |x| yield x } end end the_first = Time.local(2004, 1, 1) the_second = Time.local(2004, 1, 2) the_first.step(the_second, 60 * 60 * 6) { |x| puts x } Thu Jan 01 00:00:00 EST 2004 Thu Jan 01 06:00:00 EST 2004 Thu Jan 01 12:00:00 EST 2004 Thu Jan 01 18:00:00 EST 2004 Fri Jan 02 00:00:00 EST 2004 the_first.upto(the_first) { |x| puts x } Thu Jan 01 00:00:00 EST 2004
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 敏捷软件开发宣言» Ruby On Rails Techlogs --1ster..!
觉得敏捷开发模式就是我们目前追寻的理想开发模式,配合RoR的灵活,足以使得更加敏捷~ 于是给这个blog重新添加了一个“敏捷开发”的分类,记录该类的读书感受等等,以下便是大名鼎鼎的敏捷宣言! *敏捷软件开发宣言* 个体和交互 胜过 过程和工具 可以工作的软件 胜过 面面俱到的文档 客户合作 胜过 合同谈判 响应变化 胜过 遵循计划 虽然右项也有价值,但是我们认为左项具有更大的价值。 PS:发现个37的那本Getting Real里面宣称的几乎完全一致!
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 提交多个check_box的写法-check_box_tag.» Ruby On Rails Techlogs --1ster..!
有的时候可能需要有这样的需求,发一篇文章的时候,需要选择多个tag,我们把Tag取出来后就可以循环显示,但是注意应该是使用check_box_tag,如下是几个例子: <% Business.find(@know.business_id).know_tags.each do |t| %> <%= check_box_tag('know[know_tags_ids][]',t.know_tag_id,@know.know_tags.include?(t))%> <%= t.name %> <%end %> -------------- <% @know_tags.each do |t| %> <%= check_box_tag('know[know_tags_ids][]',t.know_tag_id,@know.know_tags.include?(t))%> <%= t.name %> <%end %> --------------- <% @tags.each do |tag|%> <%= check_box_tag ("topic[tags_ids][]",tag.id)%><%= tag.name %> <% end %> 我想上面几个例子,大家应该明白了吧?
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 完善你的URL显示信息» Ruby On Rails Techlogs --1ster..!
当你允许用户评论的时候,可能需要他们输入主页等URL,你以为用户会很认真的写上*http://*,现实是用户很多时候懒得写,只写www.1ster.cn这样的,你可以在接收数据的时候或者JS处理一下,如果没有http://就加上,但有的时候,面对一些历史数据或者你不想在接收的时候处理,可以按照下面这个来处理。 def url=(addr) super (addr.blank? || addr.starts_with?('http')) ? addr : "http://#{addr}" end 当然,你也可以按照这个思路在你接收数据的时候处理。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 安装mongrel服务器» Ruby On Rails Techlogs --1ster..!
需要安装这个的很简单,下面就是我在自己机子上安装的时候的过程演示,比起Apache等的配置,这个东西好多了。 D:\>gem install mongrel Select which gem to install for your platform (i386-mswin32) 1. mongrel 1.0.1 (mswin32) 2. mongrel 1.0.1 (ruby) 3. mongrel 1.0 (mswin32) 4. mongrel 1.0 (ruby) 5. Skip this gem 6. Cancel installation > 1 Install required dependency gem_plugin? [Yn] y Install required dependency cgi_multipart_eof_fix? [Yn] y Successfully installed mongrel-1.0.1-mswin32 Successfully installed gem_plugin-0.2.2 Successfully installed cgi_multipart_eof_fix-2.1 Installing ri documentation for mongrel-1.0.1-mswin32... Installing ri documentation for gem_plugin-0.2.2... Installing ri documentation for cgi_multipart_eof_fix-2.1... Installing RDoc documentation for mongrel-1.0.1-mswin32... Installing RDoc documentation for gem_plugin-0.2.2... Installing RDoc documentation for cgi_multipart_eof_fix-2.1... D:\>
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 安装SSH库的时候出现问题的修复» Ruby On Rails Techlogs --1ster..!
在使用SSH的时候,需要另外安装SSH的库,但是我按照官方上的方法无论是远程安装还是本地安装都出现错误,如下: D:\>gem install net-ssh --include-dependencies ERROR: While executing gem ... (Zlib::BufError) buffer error 查了下资料,貌似问题是出在Windows版本上的RUBY有点问题,可以按照下面的进行修复: 1.修改ruby的安装目录下(c:\ruby\lib\ruby\site_ruby\1.8\rubygems\package.rb)的package.rb文件,在 618 行,把1.2.1修改为 1.2.3。 2) removed the line ssh 22/tcp #SSH from file %systemroot%\system32\drivers\etc\services
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 如何快速统计RoR网站的访问量» Ruby On Rails Techlogs --1ster..!
本文来源JavaEye,由于没有提供单篇RSS,我就全部转过来了,版权所有规robbin所有。 链接地址:http://robbin.javaeye.com/blog/97287 统计网站的访问量有很多专业的第三方工具,例如Google Analytics,提供强大,而且详细的统计功能。当然,也许不是每个人都需要这么复杂而且操作麻烦的工具,如果你只是需要大概了解一下网站的访问量和访问URL的比例,那么让我们看看最简单最容易的统计工具:Unix Shell。 一个RoR网站的访问纪录,Web Server(Apache or lighttpd)会记录所有的访问请求,包括动态请求和静态请求,但大量图片,JS,CSS的请求对我们没有太大的统计价值,因此web server的日志参考价值就不大。 RoR会记录所有动态请求日志到log/production.log里面,我们要做的就是让RoR进行日志交换,每天产生一个新的日志文件。很简单,修改config/environment.rb RAILS_DEFAULT_LOGGER = Logger.new("#{RAILS_ROOT}/log/#{RAILS_ENV}.log", "daily") 那么每天就会产生一个诸如+production.log.20070702+这样的日志文件。 *一、统计每日动态请求处理总数* cat production.log.20070702|grep "200 OK"|wc -l 打印日志文件,挑选正确处理的请求行,统计行数,一条shell命令就搞定了网站处理的动态请求数量。虽然动态请求数量不等于网站访问量,但是可以作为一个重要的参考指标。 *二、统计URL的访问频度* 网站管理员都很希望知道哪些频道受欢迎被访问的频繁,哪些URL格外受到关注,不必寻求专业的网站流量统计系统,一条shell命令就搞定了: cat production.log.20070702 |grep "200 OK" | awk '{print $17}'|sort|uniq -c | sort -r -n > stat.log 打印日志文件,挑选正确处理请求行,把第17列即URL那一列挑出来,排序,统计唯一URL出现的次数,按照URL次数倒序输出到stat.log文件里面,让我们看看stat.log是什么: 10096 [http://www.javaeye.com/] 3590 [http://www.javaeye.com/forums/index] 3446 [http://www.javaeye.com/forums/board/Java] 3300 [http://www.javaeye.com/index/rss_index_topics] 2477 [http://www.javaeye.com/forums/board/Life] 1605 [http://www.javaeye.com/forums/board/AJAX] ......... 网站首页被访问了10096次,论坛频道首页被访问了3590次,...... 是不是很爽?我们用一条shell命令可以做简单的网站访问统计系统了。那么用Java做的系统,能不能这样统计呢?其实照样可以。你可以在tomcat的配置文件里面设置输出详细的日志信息,然后照样用shell命令搞定。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在windows上安装RMagick» Ruby On Rails Techlogs --1ster..!
看到网上很多人说再WIN下安装RMagick的方法都是这样的,gem install ImageMagick-6.3.0-7-Q8-windows-dll.exe,这样我感觉谁有问题的,至少我这样安装的时候是有错误的,如:D:\gem\RMagick-1.14.1_IM-6.3.0-7-Q8>gem install ImageMagick-6.3.0-7-Q8-windows-d ll.exe ERROR: Error installing gem ImageMagick-6.3.0-7-Q8-windows-dll.exe[.gem]: strin g contains null byte 所以正确的应该是用gem包来安装,如下: D:\gem\RMagick-1.14.1_IM-6.3.0-7-Q8>gem install rmagick-1.14.1-win32.gem Successfully installed rmagick, version 1.14.1 看看是不是安装上了: D:\gem\RMagick-1.14.1_IM-6.3.0-7-Q8>gem list rmagick (1.14.1) RMagick is an interface between the Ruby programming language and the ImageMagick and GraphicsMagick image processing libraries.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在rails中实现跟踪记录每个用户的最近十条记录» Ruby On Rails Techlogs --1ster..!
有的时候,你可能想显示给每个用户他最近浏览的页面,这个时候的一个很自然的想法就是使用数据库来存放,但是这样如果你的用户足够的多,而且页面的读取数据库又很频繁的话,就会对性能造成很大的影响,换个思路,我们可以在session里面存取,示范代码如下: class ApplicationController < ActionController::Base before_filter :add_to_history before_filter :page_title ### def add_to_history session[:history] ||= [] ## if File.exists?("#{RAILS_ROOT}/app/views/#{self.controller_name}/#{self.action_name}.rhtml") && session[:history].empty? || session[:history].first['uri'] != @request.request_uri session[:history].unshift({ 'uri' => @request.request_uri, 'name' => page_title }) session[:history].pop while session[:history].length > 11 end end ### #### # This bit came from Peter Cooper's snippets source and was moved into the application controller: ### def page_title case self.controller_name when 'tag' title = "Tags » " + @params[:tags].join(" > ") when 'user' title = "Users » #{@params[:user]}" when 'features' case self.action_name when 'show' then title = "Feature » #{Feature.find(@params[:id]).title}" else title = APP_CONFIG["default_title"] end else title = APP_CONFIG["default_title"] + self.controller_name + ":" + self.action_name end end helper_method :page_title ### ... end 然后在页面上就可以这样显示了:

User History

<% for cur in session[:history][0..9] -%>

"><%= cur["name"] %>

<% end -%>

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在rails中使用POP3接收邮件» Ruby On Rails Techlogs --1ster..!
上次我们写了如何在rails中发送email,自然接收email也是常常需要的功能,今天给出一段代码实现在rails中接受并处理email,代码如下: #!/usr/bin/env ruby require 'net/pop' require File.dirname(__FILE__) + '/../config/environment' logger = RAILS_DEFAULT_LOGGER logger.info "Running Mail Importer..." Net::POP3.start("localhost", nil, "username", "password") do |pop| if pop.mails.empty? logger.info "NO MAIL" else pop.mails.each do |email| begin logger.info "receiving mail..." Notifier.receive(email.pop) email.delete rescue Exception => e logger.error "Error receiving email at " + Time.now.to_s + "::: " + e.message end end end end logger.info "Finished Mail Importer." 做些说明:你需要在*Net::POP3.start*这行写上你要接收的邮箱的服务器地址以及你的用户名密码,如上配置好了,你就可以在cron中配置调度这个任务了,至于调度的频度你可以按照自己的需求来设定了。 如何,还算简单吧。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在bluehost上部署ROR应用1stlog.» Ruby On Rails Techlogs --1ster..!
前段时间搞了个bluehost,看他支持ror,一直不敢用,今天部署了套1stlog,还真不简单,总结下下遇到的困难和应对的措施。 *1.绑定域名* 我把1stlog.1sters.com这个二级域名绑定到bluehost上,很快就生效了。 *2.添加域名绑定* 把前面我指向的1stlog.1sters.com绑定进去。 *3.建立数据库和用户* 在bluehost的控制面板上创建MYSQL数据库和用户,注意要给该用户赋权。 OK,准备好了,我们开始安装吧。 *4.dispatcher配置* 首先遇到的就是dispatcher路径(/public/dispatch.rb) Set dispatcher path in "typo/public/dispatch.rb" 把 #require "dispatcher" 修改为: #require "/usr/local/lib/ruby/gems/1.8/gems/rails-1.1.4/lib/dispatcher" *5.遇到的是数据库编码* 由于必须使用UTF-8,而在它的控制面板里面创建的数据库默认是latin1_swedish_ci的, 找了一会,发现可以在phpMyadmin里面进行修改(幸好还有phpmyadmin)。 点上面的“操作”标签,然后选择最下面的“整理”,选择utf8_unicode_ci就可以了。 *6.配置FastCGI* 紧接着来的是FastCGI的配置(在public/.htaccess),需要修改如下几个地方: AddHandler fastcgi-script .fcgi RewriteRule ^(.*)$ dispatch.fcgi [QSA,L] 添加一行: SetEnv RAILS_ENV production *7.dispatch.fcgi修改* 确认 #!/usr/bin/env ruby *8.然后给dispatch.fcgi执行权限*。 这个很容易遗忘。。 *9.初始化数据库* rake db:migrate VERSION=0 *10.安装RedCloth* 这个竟然默认是没有安装的,只能自己来装了,先下载(wget或者你用FTP传上去) gzip -d RedCloth-3.0.4.tar.gz --解压 tar xvf RedCloth-3.0.4.tar --解tar mv RedCloth-3.0.4 redcloth --改个名字(可以不做) 然后需要自己加载: 在environment.rb里面加入: config.load_paths += %W( vendor/redcloth/lib ).map {|dir| "#{RAILS_ROOT}/#{dir}"}.select { |dir| File.directory?(dir) } require 'redcloth' *11.把log和tmp目录及其子目录属性修改为777* 恩,差不多了吧,应该没有忘记什么吧:)
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在Rails中用Gmail发送邮件» Ruby On Rails Techlogs --1ster..!
在rails中配置发送邮件还是比较简单的,但是由于rails还不支持TLS,也就是说默认的情况下是不可以通过gmail来发送邮件的,还好,老外改写了一个类库,使得我们可以使用gmail来发送了。 步骤如下: 1、把附件smtp_tls.rb放在你的/lib/smtp_tls.rb下。 2.然后在你的environment.rb中添加require ‘smtp_tls’ 3.配置邮件服务器 ActionMailer::Base.server_settings = { :address => "smtp.gmail.com", :port => "587", :domain => "localhost.localdomain", :authentication => :plain, :user_name => "someusername", :password => "somepassword" } 需要注意的是,该版本只支持ruby1.8.4及其以上版本。 参考:http://blog.pomozov.info/posts/how-to-send-actionmailer-mails-to-gmailcom.html
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 在ROR中实现验证码需要注意的地方» Ruby On Rails Techlogs --1ster..!
开始以为没有什么难得,参考了http://www.blogjava.net/killme2008/archive/2007/04/09/109456.html和JAVAEYE上的一些文章,其实大家说的都差不多的,都是说win下注意的事情,我在lunix上怎么就是跑不起来,一直报告Missing model noisy_image.rb这个错误,后来看到http://wiki.rubyonrails.com/rails/pages/HowtoSecureFormsWithNoisyImages这个文章,恍然大悟。 class NoisyImage require 'RMagick' include Magick 注意这个*require 'RMagick'*是放在class里面的,如果放在外面,就会报我上面说的那个错误。 PS:刚刚给1stlog加上了验证码,也是最后一个功能点了。明天找时间整理下文档就可以开源了。真开心~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 关于rails启动报500错误的可能问题点» Ruby On Rails Techlogs --1ster..!
当你启动rails的时候可能会遇到500错误“500- Premature end of script.”或者类似的错误,使得程序跑不起来~问题可能出在两个地方: 1、 The file permissions are not set to allow the dispatch.cgi to execute properly. Chmod the dispatch.cgi to +0755+. 2、The path to Ruby is is incorrect in the dispatch.cgi file. The first line of the file is called the shebang-- it sets the location of the intrepretor (in this case ruby). Change the shebang to the correct path to Ruby (/usr/bin/ruby). The first line of the dispatch.cgi file should look like this: #!/usr/bin/ruby
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 关于HAML的一点点想法~» Ruby On Rails Techlogs --1ster..!
大清早的,CFC就给我推荐HAML,说未来必将流行,这个东西以前我关注过,无非是使用一种规定的标记来替代RHTML,在显示的时候反向解析(这是我的理解),CFC给我看了他写的一篇文章(没有找到单篇的RSS,只能COPY过来啦=="),内容如下: --------------------------- 最近開始接觸HAML 在Rails中,預設使用ERb來當作模板描述語言,可是這樣寫個人認為非常醜也非常累... 而之前看到HAML時感覺到那東西似乎沒有太大的可用性,難道要Designer也學Ruby嗎? 不過後來我想通了.. 架構這部分可以給Coder作,Designer乖乖設計CSS就夠了.. 來看看底下這個Sample吧: *這是rhtml*

Welcome to our site!

<%= print_information %>

<%= render :partial => "sidebar" %>
*這是HAML* #content .left.column %h2 Welcome to our site! %p= print_information .right.column= render :partial => "sidebar" 看!少了多少行? 可以讓開發速度變快耶= v =... 最主要的是,看起來也比較美觀了! -------------------------- 说说偶的看法:(基本上是不推荐的) 1、多了一次解析反解析,效果难道不受影响(除非是直接解析成html) 2、难道要Designer也學Ruby嗎?同问? 3、我把RHTML分成 局部模板,单个文件就不会很大,也很简单。 4、美观么?ruby本来是不强制缩进的,这个东西还要求缩进~=_=~ 有谁再给出一些理由呢?
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 使用check_box_tag时需要注意的» Ruby On Rails Techlogs --1ster..!
*check_box_tag*这个辅助方法,不晓得是rails自己的Bug还是其他的原因,按照道理来说,应该是和*check_box*这个辅助方法差不多的才对呀,但是在使用过程中发现有些问题,提醒各位下: check_box是可以自动生成*hidden_field*区域的代码的,这样选中或者不选中的时候,都可以正常工作; 但是check_box_tag这个东西却没有那么好,它不会自动生成+hidden_field+的代码,所以使得你在不选该复选框的时候,其值是不会送到服务端的。必须手工添加以下代码: <%=hidden_field_tag item.name, 0 %> 切忌切忌哈~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 使用Jsonifier在rails中生成json» Ruby On Rails Techlogs --1ster..!
由于一个系统需要对外提供数据,自然使用widget来实现,JS中自然是对json支持最好,也是就可以吧数据组装成json格式的,再用JS解析显示,于是就有了这个需求:在rails中生成JSON,尽管rails1.1版本就增加了对json的支持,但要想更加灵活,自然使用插件来实现了,而Jsonifier 正是我们需要的。 看看Jsonifier的自我介绍: Jsonifier is a Rails plugin that adds options to the ActiveRecord#to_json method similar to ActiveRecord#to_xml. It's time to treat the JSON encoding of AR objects with more respect ;) The :only, :except, :methods, and :include options are supported. Check out the examples below. *安装:* 很简单,script/plugin install svn://svn.codefront.net/jsonifier/trunk *使用:* david = User.find(1) david.to_json # {id: 1, name: "David", awesome: true, created_at: "07/01/2007"} david.to_json(:only => :name) # {name: "David"} david.to_json(:only => [:id, :name]) # {id: 1, name: "David"} david.to_json(:except => :created_at) # {id: 1, name: "David", awesome: true} david.to_json(:except => [:id, :created_at]) # {name: "David", awesome: true} 很简单吧~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 使用ActionMaile发送邮件实例» Ruby On Rails Techlogs --1ster..!
来源:http://www.javaeye.com/topic/40778 更改config目录下的配置文件*environment.rb* 在最下面追加一段: ActionMailer::Base.delivery_method = :smtp #以简单邮件传送协议发送邮件 ActionMailer::Base.default_charset = "GBK" #设置邮件的默认编码为国标码否则发送的邮件主题可能会乱码 ActionMailer::Base.server_settings = { :address => "192.168.1.110", :port => 25, :domain => "xxx.com", :authentication => :login, :user_name => "xxx", :password => "xxx", } 1、:address => and :port => 决定你将使用的SMTP的地址和端口。这些缺省值分别为localhost和25。 2、:domain => 当识别自己是服务器时 mailer应该使用的域名。这是对HELO(因为HELO是命令客户端发送服务来启动一个连接)域的调用。你通常应该使用顶级域名机制来发送e-mail,但这依赖于你的SMTP服务的设置(some don’t check, and some check to try to reduce spam and socalled open-relay issues) 3、:user_name => and :password => 如果:authentication被设置则要求有此。 4、:authentication => :plain,:login,或:cram_md中的一个。你的服务器管理员将帮助选择正确的选项。当前没使用TLS(SSL)来从Rails连接邮件服务器的方式。这个参数应该被忽略,如果你的服务器不要求确认。 创建一个mailer的models class OrderMailer < ActionMailer::Base def signup(domain, sent_at = Time.now) @subject = 'Welcome to Beast' @body = "hello world" @recipients = "yyy@yyy.com" @from = 'yyy@yyy.com' @sent_on = sent_at @headers = {} end end @subject:邮件标题 @body:邮件正文可以使用html标签但需要设置参考下面 @recipients:收件人可以接收数组进行群发 多人发送:@recipients = [ "1@a.com","2@b.com"] @from:发件人 @sent_on:用于设置邮件 Date: header的Time 对象 @headers:一个header name/value 对的哈希望表,用于添加任意header行给邮件 如:@headers["Organization"] = "Pragmatic Programmers, LLC" 既要使用HTML格式发送邮件又要增加附件的话,需要在model里就对content-type进行设置 @content-type=”text/html” *创建一个controller 用于发送邮件* def send_mailer email = OrderMailer.deliver_signup(request.host_with_port) Puts email.encoded #邮件内容打印 #email = OrderMailer.create_signup(request.host_with_port) #email.set_content_type("text/html") 可在模型中设置 #OrderMailer.deliver(email) #发送HTML格式的邮件的设置 end *发送HTML模板邮件* 在views中创建一个模板:_mail_content.rhtml …… model中的mailer类改成如下: def signup(domain,content,sent_at = Time.now) @subject = "xxx" @body = content @recipients = "xxx@xxx.com" @from = 'xxx@xxx.com' @sent_on = sent_at @headers = {} end controller中更改发送方法: def send_mail content = render_to_string :partial=>" mail_content " email = OrderMailer.create_signup(request.host_with_port,content) email.set_content_type("text/html") OrderMailer.deliver(email) render :text=>"发送成功" end render_to_string方法返回的是String 与render不同的是它返回后不会发送给客户端。 *发送附件* 修改model中的mailer类,如下: def signup(domain,content,sent_at = Time.now) @subject = "xxx" @body = content @recipients = "xxx@xxx.com" @from = 'xxx@xxx.com' @sent_on = sent_at @headers = {} @data = "" File.open("D:\\Tools\\FastAIT.rar", "rb") { |fp| @data< } #参数的含义rb表示只读并且以二进制方式创建一个file对象 #不写r会出现丢失数据的问题,发送的附件也就被破坏了 ``r'' Read-only, starts at beginning of file (default mode). 只读,清除原有内容(默认方式) ``r+'' Read-write, starts at beginning of file. 读写,清除原有内容 ``w'' Write-only, truncates existing file to zero length or creates a new file for writing. 只写,创建一个新的文件覆盖旧的 ``w+'' Read-write, truncates existing file to zero length or creates a new file for reading and writing. 读写,创建一个新的文件覆盖旧的 ``a'' Write-only, starts at end of file if file exists, otherwise creates a new file for writing. 只写,追加 ``a+'' Read-write, starts at end of file if file exists, otherwise creates a new file for reading and writing. 读写,追加 ``b'' (DOS/Windows only) Binary file mode (may appear with any of the key letters listed above). *二进制模式* attachment :content_type => "application/rar", :filename => "FastAIT.rar" , :body => @data end 邮件附件的content_type(内容类型表) ".asf" ContentType = "video/x-ms-asf" ".avi" ContentType = "video/avi" ".doc" ContentType = "application/msword" ".zip" ContentType = "application/zip" ".xls" ContentType = "application/vnd.ms-excel" ".gif" ContentType = "image/gif" ".jpg", "jpeg" ContentType = "image/jpeg" ".wav" ContentType = "audio/wav" ".mp3" ContentType = "audio/mpeg3" ".mpg", "mpeg" ContentType = "video/mpeg" ".rtf" ContentType = "application/rtf" ".htm", "html" ContentType = "text/html" ".txt" ContentType = "text/plain" ".pdf" ContentType = "application/pdf" 其他 ContentType = "application/octet-stream"
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 乱码,警惕编辑器的编码~» Ruby On Rails Techlogs --1ster..!
今天没什么事情,写个小的问题分析系统,在数据库初始化的时候,用了 def self.up create_table :priorities do |t| t.column :name, :string, :default => "" t.column :desc, :string, :default => "" end Priority.new(:name=>"一级",:desc=>"很紧急,4-8小时完成").save Priority.new(:name=>"二级",:desc=>"紧急,8-24小时完成").save Priority.new(:name=>"三级",:desc=>"一般,24-48小时完成").save Priority.new(:name=>"四级",:desc=>"不紧急,48小时以上").save Priority.new(:name=>"不详",:desc=>"不详").save end 遇到下列错误 bq. ./db/migrate//003_create_priorities.rb:10: Invalid char `\274' in expression ./db/migrate//003_create_priorities.rb:10: Invalid char `\266' in expression ./db/migrate//003_create_priorities.rb:10: Invalid char `\262' in expression ./db/migrate//003_create_priorities.rb:10: Invalid char `\273' in expression ./db/migrate//003_create_priorities.rb:10: Invalid char `\275' in expression ./db/migrate//003_create_priorities.rb:10: syntax error, unexpected tIDENTIFIER, expecting kEND Priority.new(:name=>"四级",:desc=>"不紧急,48小时以上").save 真是ft,感觉是编码的问题,我数据库用的是UTF-8呀,我在environment.rb也加了$KCODE = 'u' require 'jcode'了呀,我在application.rb也写了:configure_charsets了下,我在数据库配置文件也加了encoding: utf8了呀。 这个问题搞得我一肚子火,最后想到了,还有一处编码需要注意,那就是文件的编码,也就是把radrails的editor默认字符集改成utf-8。 寒~真是ft,大家遇到类似问题千万记住呀,需要检查下面几个地方~ # 数据库编码 # application.rb # environment.rb # database.yml
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 一个很棒的Find方法!» Ruby On Rails Techlogs --1ster..!
今天CFC问我有没有用过find(:all, :select => )这个用法,别说,还真没有用过,直接告诉我应该是可以取指定的字段。 果不其然,比如我要取Contact表的id和name两个字段,可以有兩種寫法,一個是find,一個是find_by_sql,如下: Contact.find(:all, :select => "id, name") Contact.find_by_sql("SELECT id, name FROM `contacts`") 这两种写法效果是一样的,怎么样,是不是比较棒呀?可能你还要问这个写法有什么好处呀?写过rails的朋友应该对它的Find方法很熟悉,但是Find是一次吧所有字段都取出来,如果字段内容比较多,会耗费很多的内存的哦,这样的话,我们只取需要的字段就OK了。 你还有什么想法,欢迎留言讨论~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 ruby对RSS(XML)的实例解析» Ruby On Rails Techlogs --1ster..!
有时候你可能想备份下原来的博客,或者对写的文章做些备份之类的,用RUBY很间就可以实现,下面是我的这个应用中所用的,针对用户推荐的文章,给出文章的RSS地址,然后写些自己的感受或者评论,就可以把提交的那个RSS文章取过来的。 下面是代码: @topic.body = '引言:' + @topic.body + '
' feed = RSS::Parser.parse(open(params[:uri]).read, false) @topic.body += '
*来源:*' + feed.channel.title @topic.body += '
*地址:*' + feed.channel.link feed.items.each do |item| @topic.body += '
*标题:*' + item.title @topic.body += '
*内容摘要:*
' + item.description end
对了,你还需要在前面加上对库的引用,如下: require 'rss/2.0' require 'open-uri' 另外,刚刚看到Javaeye上一个老兄写了一个差不多的,我就不多写了,大家可以参考下,地址如下:http://www.javaeye.com/blog/57538
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 ruby中的方法调用» Ruby On Rails Techlogs --1ster..!
引言:张雪同学blog上的这个文章很是不错,从一个侧面展示了Ruby的一些和别的不一样的特性,显出了其灵活和强大,很值得仔细看看~会使得你对ruby中的方法调用更加理解~

*来源:*for each_day in life: ruby中的方法调用
*地址:*http://blog.snowonrails.com/articles/2007/05/15/ruby%E4%B8%AD%E7%9A%84%E6%96%B9%E6%B3%95%E8%B0%83%E7%94%A8
*标题:*ruby中的方法调用
*内容摘要:*
和我一样许多习惯了java的程序员在刚刚开始接触ruby的时候对ruby当中的方法声名以及调用的方式会感到非常的奇怪和别扭。比如我们在ruby当中经常可以看到类似的方法声名 method(arg1, *args), 又如这样的方法 method2(arg2, &block), 等等。相比于java那明确简单的方法声名方式,ruby中的方法声名要灵活许多,下面就ruby当中常见的几种方法声名的形式,以及方法调用的方式做一个简要的总结: 1. 首先,不同于java的方法声名,ruby中的方法可以接收的参数是可变的,而不是像java那样必须和方法声名中的参数类型相等,个数相等。当你希望ruby方法接收一个或者多个参数的时候,可在普通的参数名前放置一个星号(*),比如:
def varargs(arg1, *rest)Received #{arg1} and #{rest.join(', ')}”
end

varargs("one") #=>"Received one and "
varargs("one","two") #=>"Received one and two"
varargs("one","two","three") #=>"Received one and two, three"

以上代码出自《programming ruby 中文版》p80
在这里,varargs方法的第二个形参前有一个星号,表示将方法中第二个以后的所有参数都装到一个数组当中,然后赋值给rest. 所以当方法声名的参数前边又一个*的时候,代表:将方法调用时传入的所有除之前已匹配完毕的参数外的剩余参数放入一个Array并将其赋值给*后边的形参。 2. 我们也经常会见到在方法声名的参数当中有“&args”的形式,比如
class TaxCalculator
  def initialize(name,&block)
    @name,@block = name, block
  end
  def get_tax(amount)
    "#{@name} on #{amount} = #{@block.call(amount)}"
  end
end
tc = TaxCalculator.new("Sales tax"){|amt| amt * 0.075}
tc.get_tax(100) #=>"Sales tax on 100 = 7.5"
tc.get_tax(200) #=>"Sales tax on 250 = 18.75"

以上代码出自《programming ruby 中文版》p81
当方法的最后一个参数前缀为&,那么改方法调用的后边可以跟一个block,同时方法会将block转换为一个Proc对象,然后赋值给该参数。 3. 我们经常可以在rails的文档中看到这种方法声名:
def method(id,option={})
  ...
end
然后我们调用的时候可以以任意的顺序传入key=>value hash pair 如:
method(5,key1=>value1,key2=>value2,...)
在参数列表中,当hash参数在正常参数之后,并且位于任何数组或block参数之前,我们就可以直接用key=>value对,而不用加{}。所有的这些key=>value对会被集合到一个hash,然后赋值给形参,传入方法。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 ruby中一个方法返回多个结果的实例» Ruby On Rails Techlogs --1ster..!
大家知道,在一般的编程实现中,一个method只能返回一个结果,如果想实现返回多个结果,java中可以使用VO来实现,但是ruby借助其灵活的语法,我们可以一次返回多个结果,我记得前些时候还不晓得这么做,问了几个人貌似也没有提到,今天五一看到了这个实现,分享给大家: 首先,按照这个需求,你可能会写出类似下面的这段代码来检验,如下: def a_method_to_insult_innocent_people error = compute_error if error == :stupid return false, "You made a stupid error" elsif error == :ridiculous return false, "You made a ridiculous error" elsif error == :worst_of_all_time return false, "You made the most idiot error in history. Way to go…" else return true, "You made no error, you are still an idiot" end end success, msg = a_method_to_insult_innocent_people do_something_with_success(success) destroy_hateful_words!(msg) 但是这段代码还是只能返回一个结果,如何实现返回多个值呢,很简单,使用数组来实现,只要把上面这段代码中的- return false, "you made a stupid error"- 修改为 *return [false, "you made a stupid error"]*就可以了。 记录记录以备不时之需。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 rails实现下载文件的小技巧» Ruby On Rails Techlogs --1ster..!
有的时候,如果你把需要下载的文件放在public目录或者其子目录下,是可以通过URL直接下载的,但是有的时候,你可能想把文件存放在别的目录以保证不会被爬虫或者其他恶意的人下载到(比如你写的电子书或者好的资料等等.),这个时候Rails的send_file函数就显得很好用,它每次发送4096byte,所以发送文件会很快,下面是个例子: send_file '/path/to.jpeg', :type => 'image/jpeg', :disposition => 'inline' 这里只是一个例子,真实的使用中,你可以把一个文件的信息存放在数据库里面,然后下载的时候就可以根据每个文件来指定上述的值了,如下: def attachment @attachment = Attachment.find(params[:id]) @attachment.update_attribute(:downloads,@attachment.downloads+1) send_file @attachment.filepath, :type => @attachment.filetype, :disposition => 'inline' end 很棒,不是么~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 mini_magick 1.2.2 Released» Ruby On Rails Techlogs --1ster..!
*mini_magick* version 1.2.2 has been released! RMagick是大家用的最多的图片处理类库,但是它台复杂了,消耗太多的内存,比如下面这段最简单的代码都会吃掉100M的内存: Magick::read("image.jpg") do |f| f.write("manipulated.jpg") end *mini_magick*是把ImageMagick进行的一次封装,使得可以很方便的使用MiniMagick的commandline,可以在http://www.imagemagick.org/script/mogrify.php 查看可耕多的ImageMagick has 信息。 *mini_magick*1.2.2包含如下更新: # 1.) all image commands return the image object (The output of the last command is saved in @output) # 2.) identify doesn't trip over strangley named files # 3.) TempFile uses file extention now (Thanks http://marsorange.com/archives/of-mogrify-ruby-tempfile-dynamic-class-definitions) # 4.) identify commands escape output path correctly
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 days_in_month函数介绍» Ruby On Rails Techlogs --1ster..!
days_in_month 这个函数返回给定的年月的月的天数,对于写阴历什么的很有帮助,下面是英文的介绍。 Description days_in_month(month, year=nil) Return the number of days in the given month. If a year is given, February will return the correct number of days for leap years. Otherwise, this method will always report February as having 28 days. 1. >> Time.days_in_month(4) => 30 2. >> Time.days_in_month(4,2006) => 30 3. >> Time.days_in_month(2,2006) => 28 4. >> Time.days_in_month(2) => 28 5. >> Time.days_in_month(2,2008) => 29
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Textile Editor Helper» Ruby On Rails Techlogs --1ster..!
*Textile*是一种语言标记格式,目前在ROR领域用的相当多,本着简洁好用的原则,这套规则就像PHP领域内的BBCODE一样流行,但是一直一来,都是靠手工去写这些标识符号,很不方便,也曾萌发了写一套可视化的东西来,可惜一直没有时间和精力,今天看到slate blog的blog上有关于这个的东西,感觉就是自己想实现的那个,看了下视频(http://www.youtube.com/watch?v=wQYedmbsJf4)和DEMO(http://slateinfo.blogs.wvu.edu/plugins/textile_editor_helper/demo),果然是的,试用了下,很方便,效果很好,再各种浏览器下都表现不错,推荐给大家。可以先看下它的功能: 安装也挺方便的: +script/plugin install http://svn.webtest.wvu.edu/repos/rails/plugins/textile_editor_helper/+ 使用: bq. # 1. run rake textile_editor_helper:install 2. for the textarea(s) that you want to add the TEH toolbar to replace the text area tag(s) with: <%= textile_editor 'object', 'field' -%> just like writing a text area tag, same options 3. at the end of your form put in the following code: <%= textile_editor_initialize -%> Important! 4. save your view and check it out *注意*:To use Textile, you must install the RedCloth gem first.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Ruby版的YouTube库接口» Ruby On Rails Techlogs --1ster..!
YouTube的快速窜红,得到很多人的喜爱,加上被google收购以后,直觉告诉我们,肯定会推出类似google其他产品的API,果不其然,马上就推出了YouTube REST API,然后在rubyforge看到支持这个API的Ruby库,试了下,很简单好用,如下: 1.先要安装 % gem install youtube Bulk updating Gem source index for: http://gems.rubyforge.org Install required dependency xml-simple? [Yn] y Successfully installed youtube-0.8.6 Successfully installed xml-simple-1.0.11 Installing ri documentation for youtube-0.8.6... Installing RDoc documentation for youtube-0.8.6... 2.申请developer id 到http://youtube.com/my_profile_dev申请一个developer id。 3.使用 如下展示的是他的一个例子,很简单哈~ require 'rubygems' require 'youtube' youtube = YouTube::Client.new 'DEVELOPER_ID' profile = youtube.profile('br0wnpunk') puts "age: " + profile.age.to_s favorites = youtube.favorite_videos('br0wnpunk') puts "number of favorite videos: " + favorites.size.to_s friends = youtube.friends('paolodona') puts "number of friends: " + friends.size.to_s puts "friend name: " + friends[0].user videos = youtube.videos_by_tag('iron maiden') puts "number of videos by tag iron maiden: " + videos.size.to_s videos = youtube.videos_by_user('whytheluckystiff') puts "number of videos by why: " + videos.size.to_s puts "title: " + videos[0].title videos = youtube.featured_videos puts "number of featured videos: " + videos.size.to_s puts "title: " + videos[0].title puts "url: " + videos[0].url puts "embed url: " + videos[0].embed_url puts "embed html: \n" + videos[0].embed_html details = youtube.video_details(videos[0]) puts "detailed description: " + details.description puts "thumbnail url: " + details.thumbnail_url 附件是这个lib包。 更多信息请参考: RDOC : http://youtube.shanesbrain.net/
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Rails4Days中文翻译版» Ruby On Rails Techlogs --1ster..!
这个是我很早前开始接触ROR的时候翻译的,也有不少人看了,很是欣慰,今天1stlog加上了附件上传下载功能,顺便吧这个PDF发上来,需要的朋友可以在这里下载了。 写在前面的话: 自己正在学习ROR,鉴于关于ROR的中文资料比较少,虽然自己E语不怎么样,但是每次看到E 文资料都尽力翻译过来。一来方便自己日后回头看这些资料比较方便;二是这样可以使自己看 的比较认真,仔细揣摩原文的意思;还有一点就是尽量为后来的学习者提供一些关于ROR的中 文资料。 一边看一边翻译记录,没有仔细校核,如有不妥,还望海涵,如能指出,不甚感激!
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Layout in Rails(三种方法)» Ruby On Rails Techlogs --1ster..!
Rails里面的layout的主要思想是template的merge机制 — 即在布局中留下若干占位符。当HTTP请求过来,响应页面将具体内容插入到对应的占位符合并而成完成的内容,站在具体响应页面的角度看,当然“推”的处理方法项目可维护性更好。下面我们主要说说在Rails的controller中对layout的控制范围。 *1. method级别的控制*。在某些特定的请求(对应rails controller里面一个method)需要特定的layout, 这时候可以 class ExampleController < AppplicationController def index render :layout => ‘my_layout’ end def list end end *2. controller级别的控制*。很多情况下,需要对同一个controller中的所有或者大多数method应用一个layout。那么我们可以在controller级别上来定义layout class ExampleController < AppplicationController layout 'my_layout', :except => rss # layout :my_def_layout # layout proc{|c| …} def index end def list end end 我们可以使用layout函数的三种方式来处理对应的情况。 *3. application级别的控制*。因为所有的controller都是继承于ApplicationController, 所以要在application的级别控制layout, 我们只要把2中的layout定义上升到ApplicationController class。比如对于应用程序而言,XMLHttpRequest不需要layout, 那么 class ApplicationController < ActionController::Base layout proc{ |c| c.request.xhr? ? false : "application" } end 在以后我们将说说在layout中怎么插入多部分内容。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Introduction to ActiveMessaging for Rails» Ruby On Rails Techlogs --1ster..!
ActiveMessaging是个感觉很不错的一个插件,通过它你可以发送、接收MO,总得来说很有诱惑力,还没有看完,下面这篇文章对这个东西做了详细的介绍,感兴趣的可以自己去看看,我就不翻译了,等我自己试用后,可以再些些心得什么的。 *introduction* Rails has already planted its flag firmly in the ground of database driven web applications. *ActiveMessaging*is a Rails plugin framework that extends the borders of Rails territory by adding simplified messaging integration. With ActiveMessaging and Rails now you can loosely integrate with systems as disparate as mainframes sending MQ messages or J2EE webapps, offload processing long-running tasks, or create applications with event or message-driven architectures. As others have put it, ActiveMessaging is trying to do for messaging what ActiveRecord does for databases. This article will introduce you to ActiveMessaging and related technologies, and get you started using it in your Rails applications now. http://www.infoq.com/articles/intro-active-messaging-rails
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 How to Transfer Files using SSH and Ruby» Ruby On Rails Techlogs --1ster..!
老外(Matthew Bass)写了一篇文章*Automating File Uploads with SSH and Ruby.*放在InfoQ上,其说明了如何使用Net-SSH 和 Net-SFTP 库实现了使用SSH备份文件到远程主机上的Ruby实现,如果你有类似方面的需求,可以好好看看这篇文章,地址在:http://www.infoq.com/articles/ruby-file-upload-ssh-intro
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 Dir.glob基本操作» Ruby On Rails Techlogs --1ster..!
使用*Dir.glob*可以方便的进行目录遍历,如下的例子是查找D:/gem的子目录中所有包含readme.txt文件的子目录。 themes_root = "D:/gem" glob = "#{themes_root}/[a-zA-Z0-9]*" @theme_cache = Dir.glob(glob).select do |file| File.readable?("#{file}/readme.txt") end.compact p @theme_cache 还有一系列的延伸,请参考ruby手册。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog演示环境搭建好了» Ruby On Rails Techlogs --1ster..!
在bluehost上搭建了一套演示环境,欢迎大家使用,体验,谢谢~ 演示地址:"1stlog":http://1stlog.1sters.com/ 管理登录:"1stlogAdmin":http://1stlog.1sters.com/index/login 登录帐号:1stlog 登录密码:1stlog 请大家不要修改密码,数据库定时清空,谢谢~ 如果发现哪里用着不爽或者bug,欢迎提出,我尽快修改,谢谢~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog插件开发指南» Ruby On Rails Techlogs --1ster..!
一、什么是1stlog 1stlog是由1sters.com开发的一款基于RubyOnRails的博客系统,主要针对中国用户,符合中国用户的使用习惯,功能强大,结构合理,易于扩展和定制,是一款很有前景的博客系统。 二、为什么要开发插件 插件是对原有功能的扩充,以集成实现更多的更有特色的功能,主版本保证可扩展性,提供扩展的方法,制定开发规范和流程,方便不同需求的人可以快速的开发自己需要的插件;也可以把自己的插件分享给别人使用,甚至被1stlog开发官方收录,进入正式版本,为开源的RoR做出自己的贡献。 三、怎样开发插件 1stlog是基于RubyOnRals开发,严格遵循MVC构架思想,本着数据层和表现出分离的原则,使用RoR的组件原理,可以很方便的开发插件,且整合使用简单,下面将就一个具体的例子说明如何进行插件开发。 四、插件开发实例解析 目标:下面将实例说明如何进行插件的开发,我们的目标是使用Youtube提供的API,结合一组Youtube的Ruby代码lib,在1stlog上扩充一个展示您在Youtube上视频的小插件,该插件可以根据提供的USERNAME取其在Youtube上收藏的影片。 详细指南请参考附件, 或者到如下两个URL查看: http://code.google.com/p/1stlog/wiki/CreatePluginFor1stlogGuide http://docs.google.com/View?docid=dhf86kr9_28g7jthk
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog Version: 1.0.0即将发布!» Ruby On Rails Techlogs --1ster..!
很高兴的告诉大家,1stlog的第一个版本马上就可以发布了,从规划到实现、测试大概有一个月的时间,谢谢朋友们的支持和帮助,谢谢! *1stlog诞生的背景* 大家知道,PHP的领域中,被广泛使用的博客系统应该是WP了;Rails版本的blog系统现在用的比较多的应该是typo和simplog了,这两个也有不少人使用了。但是我用了后觉得不是很符合国人的习惯,很多地方用着感觉很别扭,于是打算自己动手写一个用着习惯的blog系统。 *1stlog规划* 做为一个blog系统,需要很好的通用性和易用性,我们平衡两者的关系,通过研究现有blog的特点,规划了1stlog的大部分功能,简单灵活、可扩展。 *1stlog的命名* 我们是1sters.com团队开发设计开发的,又是一个blog系统,所以定其名字为1stlog,很合理,不是么,:) *1stlog的功能点* 功能点还是很多的,包含但不限于以下列举的这么多。 * 安装方便,不需要重新编译 * Type / Categories / Tags 的管理 * 日志的发表 编辑 删除 * 评论及其评论管理 * 支持Textile可视化和tiny_mce可视化编辑器(简单、高级两种) * Trackback 及其防spider以及灌水机 * 基于Ajax的search和Trackback地址生成 * 文章 / 评论的feeds * 按照分类或者性质的feeds * 单篇文章的feeds输出 * 个性化展示配置 * 自定义显示模板 * 验证码 * 上传下载文件 * 选择自己需要的显示模块 * 可配置每页显示的篇数等显示数目 * 可以选择自己喜欢的显示模板 * 用户管理 * 友情链接 * 定时备份数据库 等等等。。。 *搭建1stlog需要* * mysql4.0及其以上版本数据库 * rails1.2.3及其版本 * ruby1.8.4及其以上版本 * RedCloth * RMagick *演示* www.1ster.cn就是以这个系统搭建的。 *安装演示* 稍后给出~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog Version1.0.1可以下载了!» Ruby On Rails Techlogs --1ster..!
不好意思,今天出去有点事情,回来晚了点,结果就没能赶在0点之前发布,对不起了~ 现在可以下载了,为了保持1ster的ROR技术笔记氛围,不在这里提供下载了,将下载统一转到*1sters.com*站上,请大家前去下载,谢谢~ 为了再以后发布新版本的时候能迅速通知到大家,这次要求要下载的朋友提供邮箱,下次发布将第一时间通知各位,谢谢~ 下载页面:http://www.1sters.com/download 谢谢大家支持~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog Version1.0.1即将发布~» Ruby On Rails Techlogs --1ster..!
1stlog Version1.0.1即将发布~ 1、添加一些必须的数据库初始化脚本 2、完善定制模板的实现原理 3、修复文件拷贝在UNIX下不工作的 4、后台界面修改为中文的 5、添加了一个Youtube的组件 6、修改了模板定制的规范 7、增加初次安装注册管理员 8、制定组件编写规范 包和文档都整理好了,实在太困了,明天发布吧~
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog Version1.0.0安装部署文档» Ruby On Rails Techlogs --1ster..!
1stlog的安装部署文档,是基于51boo提供的空间做的演示,如果你是使用51boo的用户应该比较容易理解,如果你还没有ROR空间,建议你去51boo.com看看有没有合适你的产品,如果你有自己的服务器,那就不用我教了,部署方法和其他Rails部署基本上是一致的。 需要提醒大家的是,搭建1stlog需要如下基本条件: mysql4.0及其以上版本数据库 rails1.2.3及其版本 ruby1.8.4及其以上版本 RedCloth RMagick 详细的安装部署步骤在附件,请先自行下载查看,源文件将在晚上24点提供下载,请关注!
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image20:51 1stlog Version1.0.0发布啦!» Ruby On Rails Techlogs --1ster..!
很高兴的和大家说,做为*1sters.com*的第二个开源产品*1stlog*终于发布了,谢谢这么多朋友的关心和鼓励,谢谢你们大家的帮助,谢谢所有帮助、鼓励、支持我的朋友们! 做为第一个对外发布版,从规划到实现,测试,到一步步的修正bug,一个来月的*“业余时间”*或许真的不算多(我白天是需要上班的,都是下班晚上写的代码),并且经常有其他的事情打扰,说真的,时间真的比较紧张。 其实开源是需要勇气的,特别是对于我这样还没有多少经验和资本的时候,开源真的需要勇气,有的时候真的怕一个用户接二连三的抱怨或者漫骂,虽然做为开源的东西,做为作者的我并没有多少责任去满足每个用户的需求,但是从一个产品的开发者角度,我还是害怕大家用那种鄙视的目光,或者那种类似“就他也配开源”等等的话语,但是无所谓了,从开始规划1stlog我就打算开源了,我不能失约于关心我的朋友们。 于是,狠狠心,咬咬牙,开源吧... 或许还有很多的不足,还有很多的地方需要优化,很多地方需要调整和优化,等不及了,做为第一个版本,我想现在的功能已经足够丰富了。持续的改进,修复,优化将在后续版本继续吧。 如果您使用或者借鉴了1stlog,如果有时间,可以发个mail什么的鼓励、感谢下我,也算对我心灵的犒劳;如果你有什么建议、意见,或者对1stlog有什么看法,也欢迎发Email给我。也可以到我的公司的网页上提建议:www.1sters.com.. 我的邮箱是:+iceskysl@gmail.com+ 马上就到6.14了,一个很特殊的日子,1stlog开源了...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:56 pTAL,TAL,EpTAL,TNS,TNS/R,TNS/E» 404 梦想没找到
HP的这些东西太faint了,没人教,只能自己看,都是英文文档,根本看不过来。 这些概念也模模糊糊似懂非懂的。 pTAL 基于TAL HP Transaction Application Language。可以用pTAL 或 EpTAL 来编译pTAL源程序。 EpTAL 编译出来的代码都是TNS/E 的。 pTAL 编译出来的代码都是TNS/R 的。 TAL 编译出来的代码都是TNS的。 TNS architecture. NonStop 系列体系结构。HP计算机(NS系列)基于CISC技术,TNS体系结构实现了TNS指令集。 TNS/E architecture. NonStop Series/Itanium architecture.这是HP基于Itanium技术的计算机系统。 TNS/E体系实现了Itanium的EPIC(explicitly parallel instruction set computing)指令集,而且向上兼容TNS和TNS/R系统级别的体系结构。 TNS/E native object code. 由支持Intel Itanium 指令编译器编译成的对象,TNS/E native object code只能在TNS/E系统上运行,不能在TNS和TNS/R上运行。 TNS/R architecture. NonStop Series/RISC 结构,如R所示,这是基于RISC指令集的HP计算机系统。向上兼容TNS系统。 TNS/R native object code. 由支持MIPS RISC 指令集的编译器编译成的代码,同样,他也只能运行在TNS/R系统上,而不能运行在TNS或者TNS/E系统上。 release version update (RVU).一组对NonStop OS系统软件的修正,用RVU ID来标识,以这为单位发售和提供支持。RVU包括对象文件,支持文件,文档等。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image09:15 group_concat» Ruby Object Oriented
CREATE TABLE `eats` (   `id` int(11) NOT NULL auto_increment,   `person_id` int(11) default NULL,   `eat_type` varchar(255) default NULL,   `value` varchar(255) default NULL,   PRIMARY KEY  (`id`) ) ENGINE=InnoDB ;     INSERT INTO `eats` (`id`, `person_id`, `eat_type`, `value`) VALUES  (1, 1, '早餐', '包子'), (2, 1, '午餐', '米饭'), (3, 2, '晚餐', '面条'), (4, 3, '早餐', '豆浆'), (5, 1, '早餐', '混沌'), (6, 2, '午夜', '大鱼大肉'), (7, 3, '早餐', '韩国料理'); select person_id,group_concat(concat(eat_type,'(',value,')')) as eateds from eats group by person_id
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image08:45 不用如果» Ruby Object Oriented
把生米煮成熟饭,用事实削除假设.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:17 Chained Builds in CruiseControl.rb» Lovable Lyle
The good news is that there is some code in the trunk for CruiseControl.rb that addresses the need for chained builds. If you’re using that version, you can for example specify that a successful build of ProjectA should trigger a build of ProjectB. # cruise_config.rb for ProjectB Project.configure do |project| project.triggered_by 'ProjectA' end The bad news — which [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:38 Ruby.NET open-source project» James Britt - Code, Content, Caffiene

The Ruby.NET project has been relocated to Google code, under a BSD license.

The Ruby.NET project’s goal is to create a compiler for the Ruby language that targets the Microsoft .NET CLR. There is currently support (at various stages of maturity) for the core language, including the built-in Ruby classes such as Class, Object, Array, String and the built-in Ruby modules such as Math and Kernel. However other Ruby libraries that commonly ship with the Ruby distribution, such as CGI and DBM are yet to be implemented.

There is also a mailing list , where a recent thread explored some of the differences between this project and Microsoft’s IronRuby. Perhaps the most notable is that you, dear coder, can contribute to Ruby.NET.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Thu 19 July, 2007

Click here to bookmark this link.Channel Image23:35 Matz, Koichi访谈(二):JRuby及其它» LetRails
问:最近Ruby社区出现了一些令人激动的新实现,如JRuby,Rubinius等,你们能谈谈这些新实现对Ruby的官方发布版本有什么影响? Matz:我很高兴看到有这么多的新实现出现,因为这意味着Ruby已经...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image22:50 Ruby なんて遅くて使えないよねって言ってみる - Akasata's Page(あかさたのページ)» Matzにっき
タイトルは「遅くて使えない」となっているが、 実際に呼んでみると「使えないわけではない」というような論調。 いや、別に「Rubyが遅い(特に1.8が遅い)」って言われても、 「はぁ、そうですか」としか思わないんだけど(性能を目指して実装してないし)、 パフォーマンスと言うのは非常にFUDに満ちあふれた分野であるので、 誰かが「遅い」とか「遅くて使えない」と言った場合には、 その真意を見極める必要がある。 で、「遅くて使えない」って言った人が、 その根拠にGreat Language Shootoutを 持ち出してくるようなら、その人の言うこ..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image22:50 BabelStone: What's new in Unicode 5.1 ?» Matzにっき
2008年以降の「いつか」にリリースされるUnicode 5.1で増えるもの。 これによって総文字数は100,823文字とはじめて10万文字を越える(5.0は99,024文字)。 誰だよ、65536文字表現できれば十分だなんて言ったのは。 とはいえ、もうこのレベルになると追加されるのはもうほとんど使われないような文字ばかり。 特に台湾から来たものとかは「ある特定の個人の名前に使われているだけ」とか ちょっとどうなのよ、というものもある。その人が死んだらもう歴史的文字になっちゃうね。 自分が死んだ後に歴史に名を残すのはなかなか難しいことで、 ..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image22:47 TAL的Hello World程序» 404 梦想没找到
The Transaction Application Language (TAL) 是hp NSK上一种编程语言,如果分类,应该算过程式。 ,而且也需要编译为可执行文件。 Tal不区分大小写,但是在C语言里调用Tal过程时过程名(函数名)一定要全用大写。 注释有两种,一个是两个横线–,直到行末有效,另一个是感叹号!,直到行末有效,或者到下一个感叹号,比如 CALL PROC1(p1,!p2!,p3) –p2 is not provided 这个调用和 PROC1(p1,,p3)是等价的,但是如果在第二个参数出写个那样的注释,非常好理解。 下面来写个Hello World 其实无论是c,java,ruby,都很简单,但是Tal可就复杂了。 首先,需要定义一个主过程,着类似c的main函数。 PROC myproc MAIN; 这个myproc是名字,PROC标识他是一个过程,MAIN表示是程序开始执行的入口点。 然后就可以打印了。Printf,没找到个函数。当然,人家凭什么给你。 最后找了一下,发现是这样的。 首先,执行编译好的程序是从TACL启动的,注意是TACL,不是Tal,完全不同的东西。 如果要打印,则需要往TACL进程里写东西,TACL才能打印到标准输出。也可以把我们要执行的程序看作TACL的子程序。 TACL用RUN启动一个程序的时候,会有一个500多个字节(word?)的message送给被启动的进程,包括id,卷标,输入输出,参数等,我们就可以从这个message里取得输出的。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 When is 12 mpg better than 100 mpg?» John Lam on Software
Ian Wright changed the way that I thought about fuel efficiency in motor vehicles. And I suspect that he changed the minds of a few other folks at Foo camp as well. The math is pretty simple (but totally not...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Vibrant Ink, Visual Studio and Vim settings» John Lam on Software
I'm a big fan of the Vibrant Ink theme for Textmate. I spent some time last year porting the color scheme to both vim and Visual Studio - that's what you can see in the screenshot. I'm releasing my _vimrc...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 VMWare Fusion Rocks» John Lam on Software
I've been a loyal Parallels User for their first two versions. However, there are two things that drive me crazy with Parallels: 1) Too many keystrokes are passed back to Mac OS while running in full screen mode. For example...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Steve Yegge ported Rails to JavaScript» John Lam on Software
One of the first talks that I went to at Foo Camp was called "Google Rails Clone" by Steve Yegge. With a title like that, how could I resist? Google uses four different programming languages: C++, Java, Python, and JavaScript....
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Outlook Zen» John Lam on Software
I spent some time this week pimping out (actually whatever the opposite of pimping out is) Outlook to try and improve my workflow. I did my usual remove all toolbar / status bar trick, so Outlook now looks like this:...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Modular Architectures with Ruby» Articles published in Ruby Code & Style
A modular architecture allows users to create modules that conform to well-described APIs and plug them into the application to extend the functionality. This article shows one way to create a modular API in Ruby.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Microsoft Surface» John Lam on Software
It's one thing to see one of these things on YouTube, it's another thing entirely to see one running in front of you. This morning, I went over to Building 33 to see a demonstration of a Surface computer. Wow....
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Linux Clustering with Ruby Queue: Small is Beautiful» Articles published in Ruby Code & Style
Ruby Queue software package lowers the barriers scientists need to overcome in order to realize the power of Linux clusters. The toolset is designed with a K.I.S.S, research focused, philosophy that enables any ordinary (non-root) user to set up a zero-admin Linux cluster in 10 minutes or less.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Links for 2007-07-11 [del.icio.us]» John Lam on Software

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Links for 2007-07-08 [del.icio.us]» John Lam on Software
  • Madonna's got a blog?!
    I should have expected this, but I'm still blown away that she's got a blog. I found it when I was looking for some more info about Hey You.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Links for 2007-07-05 [del.icio.us]» John Lam on Software

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Links for 2007-06-27 [del.icio.us]» John Lam on Software
Click here to bookmark this link.Channel Image19:17 Links for 2007-06-26 [del.icio.us]» John Lam on Software

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Links for 2007-06-22 [del.icio.us]» John Lam on Software

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 JRuby Goes 1.0!» John Lam on Software
Congratulations to Charlie, Tom, Ola, Nick and the rest of the JRuby dev team for getting to 1.0! I hope you guys are gathering together somewhere nice to celebrate the accomplishment!...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 IronRuby plans revealed on .NET Rocks» John Lam on Software
Richard and Carl interviewed me a few weeks ago on .NET Rocks! We had a fun discussion about a whole range of topics from my experience emigrating to the Republic of Microsoft to why Ruby the language is important. The...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 If It's Not Nailed Down, Steal It» Articles published in Ruby Code & Style
There's a whole world of language features that we sometimes miss out on as Rubyists, such as pattern matching, S-expressions, and external domain-specific languages. But the good news is that we can have them, too, as long as we're not afraid to steal a few things first.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Foo Camp can influence you before you go» John Lam on Software
It should be a fun weekend at Foo Camp. I attended one of the first Bar Camps in Toronto in January of 2006, and I really liked the un-conference style. I even sponsored it through ObjectSharp, the company I was...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Foo Camp + electric car == fun» John Lam on Software
One of the highlights of Foo camp was a ride in Ian Wright's X1: The electric motor in this supercar puts out 1500 ft-lbs of torque at the rear wheels. We pulled 0.83g on acceleration, 1.30g on the right hand...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Creating Printable Documents with Ruby» Articles published in Ruby Code & Style
In this article, Austin Ziegler introduces the creation of a variety of types of documents with PDF::Writer for Ruby. This introduction covers basic creation, partial document generation and customization, and Rails-generated documents.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 Creating DSLs with Ruby» Articles published in Ruby Code & Style
Broadly speaking, there are two ways to create a DSL. One is to invent a syntax from scratch, and build an interpreter or compiler. The other is to tailor an existing general-purpose language by adding or changing methods, operators, and default actions. This article explores using the latter method to build a DSL on top of Ruby.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:17 (A Belated) Welcome to Ruby Code & Style» Articles published in Ruby Code & Style
James Britt welcomes all to Ruby Code & Style and offers his views on what makes it so special.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Two Years of Rails Podcasting» Riding Rails - home

Two years ago today, Scott Barron published the first episode of the Ruby on Rails Podcast. —Geoffrey Grosenbach

Wow, has it been two years already? Geoffrey’s been a major positive force in the Rails community even longer then that, starting with the humble Pluralizer, which helped us all figure out what table names our ActiveRecord models were supposed to be using. For his next podcast, he’s turning the tables and letting himself be interviewed by Dan Benjamin. Be sure to send in some challenging questions (see Geoffrey’s blog post for details).

Congrats on the milestone, Geoffrey, Scott, and everyone else that’s been involved with the Rails Podcast!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Summer of Hack, 2007» Riding Rails - home

The hackfest is back! In sleek new form, the ‘fest runs monthly, starting now.

Without further ado: it’s on. Two weeks to go. Sprint!

Thanks to Working With Rails for making this an integral part of their site; thanks to O’Reilly for signing on as the first sponsor (first prize is a free pass to RailsConf Europe); and thanks to you for contributing the patches and bugfixes that keep Rails at the top of its game.

Go, go!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Subversion Browser on Rails» Riding Rails - home

ActiveReload has just released Warehouse, a simple subversion browser written using Rails. It sports a beautiful UI and can handle the mundane task of user and permission management for you. It’s also being distributed in a unique fashion for most Rails applications. Instead of being hosted, it is sold and downloaded to be installed on your own server.

If you’re interested, check us out at the Warehouse site.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Research on why and how adopts Rails» Riding Rails - home

Michel Barbosa has completed his bachelor thesis Delivery of the Key Adoption Factors and Key Characteristics of Companies Using Ruby on Rails. It presents research he has done and conclusions the why and who of switchers.

I’m happy to see that “Joy in Development” was a key adoption factor for 92% of the people interviewed.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 RailsForge?» Riding Rails - home

Jason Perry has started a survey at http://railsforge.com/, asking for community feedback on whether a Rails-specific forge-site would be useful or not. What are your thoughts? Head on over and let him know!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 RailsConf Europe 2007 in Berlin» Riding Rails - home

Registration for RailsConf Europe 2007 has opened up. It’s all going down in Berlin, Germany from September 17th through 19th. There’s a ton of great speakers lined up, so we’ll undoubtedly have one heck of a party there. Really hope to see as many as possible there.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Rails to Italy in Pisa in October» Riding Rails - home

Rails to Italy is gathering the Italian Rails community in Pisa from October 26th through 27th. They’re open for registration and are still looking for speakers. The price to participate is €89 for registrations done before August 1st.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 PhD study on innovation with open source» Riding Rails - home

Zilia Iskoujina is a PhD student from the UK who’s doing research on Knowledge management and innovation in virtual organisations. As part of that, a questionaire for people working in open source has been created. If you have 15 minutes, consider filling it out.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Haml 1.7» Riding Rails - home

The Haml team recently announced the release of Haml 1.7, which is an alternative markup system that you can use in Rails, instead of the default ERb-based markup. Version 1.7 is significantly faster than previous releases (and is almost as fast as Rails’ default system, now!). There are a few other new features, too: read all about it in the release notes. Great work!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Capistrano 2.0 Preview 4» Riding Rails - home

I am such a chicken. I very much wanted the next release of Capistrano to be the official “Capistrano 2.0” release. But as I watched the changelog grow, I started to get cold feet.

Thus, tonight I announce the fourth (and final, hopefully!) preview release of Capistrano 2.0. As before, you can grab it from the Rails beta gems server:

gem install -s http://gems.rubyonrails.com capistrano

(What is Capistrano, you ask? Allow me to direct your attention to http://www.capify.org...)

The following items are just some of the changes new in preview #4:

  • The deploy:symlink task works correctly now when run by itself.
  • Synchronously instantiate the gateway to prevent it being instantiated multiple times.
  • Use “which” instead of “test -p to test whether a command exists on the path.
  • The :hosts and :roles keys can now accept lambdas, to lazily select which hosts or roles a task uses.
  • Versions of Net::SSH prior to 1.1.0 work with Capistrano again.
  • Variable accesses are now thread safe.
  • The deployment code is now locale-independent, so that the revision is parsed correctly even if your computer is using a non-English locale.
  • You can now pass :on_error => :continue when defining a task, so that any connection or command errors that occur during the task’s execution will be ignored, allowing the task (and subsequent tasks) to continue.

You can see the entire list of changes in the CHANGELOG.

So, give it a go. Try it out. Post your feedback to the Capistrano mailing list. I’d love to release cap2 final next week!

P.S. If you are on a Windows machine, and you get Zlib errors trying to install the Capistrano gem, try this. Find the rubygems/package.rb file (wherever it happens to be in your Ruby installation), open it up, and find the zipped_stream method. Then, replace it, wholesale, with the following:

def zipped_stream(entry)
  entry.read(10) # skip the gzip header
  zis = Zlib::Inflate.new(-Zlib::MAX_WBITS)
  is = StringIO.new(zis.inflate(entry.read))
ensure
  zis.finish if zis
end

That seems to do the trick for me; let me know if it doesn’t work for you.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Capistrano 2.0 Preview 3» Riding Rails - home

Alright, we’re nearing the finish line! Capistrano 2.0 Preview Release #3 is now available.

Capistrano is a utility for automating the execution of tasks on one or more remote machines. You can read all about it at www.capify.org.

To install Preview #3, you’ll need to grab it from the Rails beta gem server:

gem install -s http://gems.rubyonrails.org capistrano

Accompanying PR3 is a new page of documentation on the capify.org site: Capistrano Basics. This walks you through the major features of Capistrano, but does not touch on deployment. This makes it a great introduction for those wanting to use Capistrano in non-deployment scenarios.

Preview #3 includes the following changes and enchancements:

Feature: Mercurial and CVS are now supported out of the box. Just set your :scm variable to :mercurial or :cvs, like so:

set :scm, :mercurial
# or
set :scm, :cvs

Thanks to Tobias Luetke and Matthew Elder for the Mercurial module, and Brian Phillips for the CVS module.

Feature: There is now a :default_environment variable, which is a hash that can be used to set environment variables that should be present for all commands that are executed. For instance:

default_environment["PATH"] =
  "/bin:/usr/bin:/usr/local/bin:/home/jamis/bin" 

Feature: All commands are now explicitly invoked via “sh”, which means that even if your default user shell is non-POSIX (e.g., tcsh, csh, etc.), you can use Capistrano just fine. Note that if you were using tcsh or csh syntax in your Capistrano scripts, you now need to set the :default_shell variable to use your (non-POSIX) shell of choice:

set :default_shell, "/usr/bin/tcsh"

Feature: You can declare empty roles, and Capistrano won’t complain. This is useful for predeclaring roles that need to exist (because task definitions depend on them), but which might not have any servers in them (depending on runtime conditions).

Feature: A username and port specified with the server definition (e.g., “fred@some.server.com:1234”) now take precedence over the :username and :port settings in the ssh_options hash, rather than the other way around. This lets you set a general default via ssh_options, and override on a per-server basis in the server definitions themselves.

There are several other minor changes and fixes as well; you can read the CHANGELOG for all the gory details.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Bratwurst on Rails at RailsConf Europe» Riding Rails - home

The Berlin Ruby User Group is throwing a pre-RailsConf party under the banner of Bratwurst on Rails.

The Ruby User Group Berlin is one of the biggest in Germany and therefore we’re pleased to organize an event on the night before the RailsConf Europe. In the tradition of last year’s “Pizza on Rails” the event is called “Bratwurst On Rails.”

The event is an opportunity to socialize and meet the conference participants in a relaxed atmosphere, and to make your name or brand known amongst them. Tighten your knots with the community by becoming a sponsor.

The venue will be in the heart of Berlin, close to the conference venue. Entry will be free, as will the food. (If you’re interested in sponsoring, have a look at our sponsoring packages and feel free to contact the organisation board via sponsoring@bratwurst-on-rails.com).


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 1 million yen with Award on Rails» Riding Rails - home

A million yen ($8,300) is the first price for a new application competition called Award on Rails that starts tomorrow. The competition is sponsored by DRECOM and will run from July 2nd until September 25th. While the show is based in Japan, they’ll be accepting entries from all over the world. Read all about the rules and the sponsors or sign up to participate. Good luck!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 絶望した» 青木日記
味噌汁つくったのに味噌がない!!! (02:45)
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Debian で Java» 青木日記
Debian で Java 使うのはすげー楽になったなあ。 aptitude install sun-java5-jdk で終わってしまった。 ant とか junit も一発で入るし、すげー楽だ。 どっちかというと、その前に 32 ビット環境を作るほうが面倒だったりした。 AMD64 なので。 (05:05)
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Cflat コンパイラ Java 版» 青木日記
ようやく Hello, World コンパイルできた。 tukumo:~/c/stdcompiler/src/test % cat test1.cb import stdio; int main(int argc, char **argv) { printf(Hello, World!\n); return 0; } tukumo:~/c/stdcompiler/src/test % cat stdio.hb extern void printf(char *fmt, ...); extern void puts(char *str); extern void putc(int c); extern int getc(void); tukumo:~/c/stdcompiler/src/test % ./cbc test1.cb as finished; status = 0 tukumo:~/c/stdcompiler/src/test % ./a.out Hello, World! あー、なんかめっちゃ苦労した……。 (06:..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 uncov FTW» James Britt - Code, Content, Caffiene

uncov is a consistent source of heavy mirth.

From today’s post:

Ikan claims that their product will revolutionize your grocery shopping. I have done this once before, but let’s talk one more time about the definition of “revolutionary”:
  • Modern pesticides: revolutionary
  • Automated crop irrigation systems: revolutionary
  • Worldwide shipping networks that make all vegetables “in-season” regardless of where you are on the planet: revolutionary
  • Making a grocery list by scanning barcodes and shit: NOT REVOLUTIONARY.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 and then they call them "Help Vampires"» James Britt - Code, Content, Caffiene

I found this by way of the Haskell Cafe list: How to Help Mailing Lists Help Readers

Interesting observations on helping newbies in a programming community.

Shame he didn’t survey the ruby-talk list; he would have found a much higher level of newbie support


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Without a Cause» James Britt - Code, Content, Caffiene

I like a good amount of what Lennon did, but this quote from This idiocy is all John Lennon’s fault is dead on:

Lennon invented the pop star as conscientious rebel, a fog that has enveloped others in the years since. In fact, pop music, rock music, call it what you will, is essentially conservative. People conform to certain types, and one of those types is “the rebel”, who considers himself to be some sort of anti-establishment character because he wears a leather jacket, drops his Hs, and swears in interviews.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Why there's no Rails Inc» Loud Thinking by David Heinemeier Hansson

IDC predicts the market for open-source software will reach some six billion dollars in 2011. No wonder the VCs are getting anxious to play on that roulette.

Which brings me to why there's no Rails Inc. It certainly isn't for lack of VCs wanting to fund. I've had more than a handful conversations with various outfits eager to pour big money into such an operation, but I'm just not interested.

There are many reasons not to be interested in VC money these days, but let's just give two specific ones for Rails.

First, Rails is not my job. I don't want it to be my job. The best frameworks are in my opinion extracted, not envisioned. And the best way to extract is first to actually do.

That's really hard if your full-time job is just the extraction part since you now have to come up with contrived examples or merely live off the short bursts of consulting. For some that might work, but I find that all my best ideas and APIs come from working on a real project for a sustained period of time.

Second, the growth of the Rails ecosystem has been staggering. There are so many shops out there offering Rails consulting and training. I believe part of that proliferation is due to the fact that there's no core-group monopoly that can dominate the market.

I believe a Rails Inc consisting of a large group of core committers would have an unfair advantage in the training and consulting space — easily siphoning off all the best juice and leaving little for anything else. There are plenty of examples in our industry of that happening around open source tools.

It's much more satisfying to see a broader pool of companies all competing on a level playing field.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 While we're hoping that the backups are good» Loud Thinking by David Heinemeier Hansson

Loud Thinking is down for the count while the server that held it up for the past six years is in ICU. Hopefully it'll make it through and allow the archives to appear unscathed. But if not, we'll deal with that too. Currently I have from June '05 and backwards recovered..

Nothing like a little forced Spring cleaning to get the cruft moved out.

But if you sent me any email to the loudthinking address over the past 3-4 days, it might not have made it. So if it was important, please do shoot it over again.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 What a Lovely Christian» Joey Gibson's Blog

There are some "Christians" who give the rest of us a bad name. Some TV-preacher jack-ass called Bill Keller is one of them. He's going off on Mitt Romney for being a member of a "cult" and being evil and having a forked tongue, a bifurcated tail and carrying a hay-fork. Yeah, he doesn't like Mormons. I just love hearing so-called "Christians" joyously telling everyone who will listen how someone else is "going to hell."


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Vim-tab-a-licious» James Britt - Code, Content, Caffiene

I’ve tried using the built-in IDE for DrScheme but my fingers want to viminate the code.

To do the vim thing (gvim, actually), I first wanted to know how to call my scheme code from the command line.

A short Google, and presto:

     $ mzscheme -r   foobar.scm 

Next, because shifting from editor to terminal is suspiciously like work, I looked around for a nice way to map this to a keyboard command.

My first poke was something like this:

      map ss <ESC>:! mzscheme -r    %<CR>

That worked, but it wasn’t really making my day. I would prefer to have the results in a new buffer. I then found this on vim.org:

function! TabMessage(cmd)
  redir => message
  silent execute a:cmd
  redir END
  tabnew
  silent put=message
  set nomodified
endfunction
command! -nargs=+ -complete=command TabMessage call TabMessage(<q-args>) 

I combined that with the previous mapping to create this:

      map ss   <ESC>:TabMessage !  mzscheme -r  % <CR><ESC>:  % s/\r//g<CR>

(I needed that last part because I was seeing ^M in the results.)

Very cool. However, while vim7 has tabs, I’ve not gotten used to using them. I tend to just have many instances of gvim floating around. I think that’s because I’m used to navigating tabs a certain way in Firefox. And my vim habits started with vim5.

Given the “bang output in a tab” macro, I decide to go figure out the proper tab navigation commands and just make myself learn them. But, no need: Kim Schulz wrote up mappings to do Firefox-style tab-nav in vim:

" tab navigation like firefox
:nmap <C-S-tab> :tabprevious<cr>
:nmap <C-tab> :tabnext<cr>
:map <C-S-tab> :tabprevious<cr>
:map <C-tab> :tabnext<cr>
:imap <C-S-tab> <ESC>:tabprevious<cr>i
:imap <C-tab> <ESC>:tabnext<cr>i
:nmap <C-t> :tabnew<cr>
:imap <C-t> <ESC>:tabnew<cr> 

Quite the slickness.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Vids from Seattle Conference on Scalability» James Britt - Code, Content, Caffiene

Fellow Zonie Robin Harris, who writes the excellant Storage MoJo blog, has posted links for the videos from the recent Seattle Conference on Scalability .

I’ve read good things about what was presented there and look forward to watching these (though it seems that not all the presentations are up on Google video).


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 UIGEA Repeal Bill Introduced» Joey Gibson's Blog

I never thought I'd be cheering for Barney Frank, but the Congressman has introduced legislation that would make the UIGEA unenforceable. For those of you who haven't been following this, the UIGEA is a law that was passed last year that effectively killed online poker in the US. The august Bill Frist snuck the UIGEA on the tail-end of a must-pass "port security" bill and thus it was passed without any discussion. What an ass-clown. So now Frank has introduced legislation that, if passed, would bring online poker back to the US.

Let's hope it passes. I'm not sure how much of a chance it has, but it's at least forward progress.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Third Time's The Charm on Mac RAM — I Hope» Joey Gibson's Blog

Being at the end of a UPS route is hard. Tuesday morning I saw from the UPS website that my third set of RAM from Crucial was "out for delivery" from the local hub. What this means is that it's on a truck, heading for my house. Unfortunately, we're at the tail-end of said route, and I have yet to receive a UPS delivery before 4:00 PM. We were going to be leaving around 5:00 and since UPS is a "drop and run" courier, if it got there after we left, it would have been sitting on the porch for several hours until we got home. Fortunately, it arrived about 4:45. So it got inside the house, but wouldn't get inside the Mac until later.

When I got home Tuesday night, I installed the RAM. So far, it's working perfectly. Of course, the first set worked perfectly for a week or so, so I'll have to just keep an eye on it. Thus, once again, my Activity Monitor looks like this


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Value of Being Open» Joey Gibson's Blog

There's a little golf store near my house. I've now tried three times to patronize them, but each time I've been thwarted. The first time I tried to visit them, was on a Monday. When I got there, I discovered that they were closed on both Sunday and Monday. Strike 1. The second time, I went on a Wednesday. They closed at 6:00PM. Who closes that early any more? Strike 2. Today, I tried again. I got there at 12:30, only to find a hand-written sign taped to the glass: Bank + Lunch. Back 1:45 - 2:30.

Strike 3.

I guess I'll just have to keep schlepping over to the PGA Tour Superstore for my golfing needs.

The lesson here is this: if you have a business you need to be open when your customers try to visit. I don't care how good the store is, I'm not going to try a 4th time to visit them.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Amnesty Bill Is Dead» Joey Gibson's Blog

Great news! According to this story the Amnesty Bill is dead. Ted Kennedy said the defeat was "enormously disappointing for Congress and for the country." I have to say that anything that is disappointing for Kennedy is good for the rest of us.

Kennedy then added "We will be back. This issue is not going away." We need to remember this threat. Bush and Kennedy will not be happy until this monstrosity is law, and the hordes of illegal Mexicans are welcomed as citizens.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Scaling to multiple databases with Rails» Loud Thinking by David Heinemeier Hansson

Remember that point about Rails lacking an easy-to-use way of dealing with multiple read/write databases? Strike that. Nic Williams has released Magic Multi-Connections. It makes it dead easy to use a cluster of databases to scale read and write speeds higher than a single connection would ever allow.

That in itself is wonderful. Williams let code be his reply to the discussion of Twitter's woes on scaling the database. I would of course rather have seen this work come out of Twitter, but I'm happy that they got a free offering handed to them regardless. They didn't even have to pass step 1 in Brian McCallister's road map for getting stuff fixed in open source. And the turn-around time was within the same day of this whole thing blowing up.

Now how could this be. How could Nic fix such an apparent "critical flaw", as others have billed the lack of this facility in Rails, in such a short time? Simple, he did it in less than 75 lines of Ruby as a plugin for Rails. Less than 75 lines.

In my mind, that's the crux of the story. That extending Rails to do what you want is often much simpler than you think. That you can't compare extending a high-level framework written in a language like Ruby to, say, patching Apache or MySQL. The barriers of entry are simply not in the same sport.

So let's use this occasion to celebrate the wonders of open source ("some times you can just ask and you will receive"), but at the same time keep the effort involved in this example as a guidance for the future ("maybe next time, I could just have a look at how hard it would be to fix myself"). And of course, a big thanks to Nic Williams to making a big fuss a non-issue.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Rowan Atkinson's Amazing Jesus» Joey Gibson's Blog

If you don't like things that mix religion and humor, then don't watch the video below. If you do have a sense of humor, then press on. It's hilarious.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Rising» James Britt - Code, Content, Caffiene

I’ve mentioned it to some people in the Phoenix tech crowd, but thought I should mention it here, too.

I’m quite pleased to say that I’ve joined Rising Tide Software.

If you’re curious, you can get an idea of the culture behind the company from David’s recent post.

We’re a wicked cool team of skilled, smart people, so keep an eye on future announcements.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Registration open for RailsConf Europe 2007» Loud Thinking by David Heinemeier Hansson

I've actually never been to Berlin before, so I'm excited to get the chance to not only see one of the great cities of Europe, but at the same time share in a meeting with the Rails community in Europe and around for RailsConf Europe 2007. The doors for registration have just been opened and until August 6th, the price is €645 (after that, it jumps to €795).

I really had a smashing time last year in London. There was somehow more time to get into more discussions with people than the more hectic version in the US. And I got to premiere a bunch of new Rails features I had been working on over the Summer.

So I hope to see a lot of the familiar faces from last year and new ones too when we convene from September 17th through 19th in Germany.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Phoenix Dev House» James Britt - Code, Content, Caffiene

Super happy Phoenix Dev House has arrived.

Sweet logo. ;)

Saturday August 4th, 2pm – 1am

21469 East Lords Way, Queen Creek AZ

Only an hour drive from my home.

Phoenix Dev House hopes to become the greater metro Phoenix premier hackathon event mimicking the now famous Bay Area SuperHappyDevHouse.

We’re about rapid development, ad-hoc collaboration, and cross pollination. Whether you’re a l33t hax0r, hardcore coder, or passionate designer, if you enjoy software and technology development, Phoenix Dev House is for you. Code in Ruby? PHP? Java? .NET? Perl? It doesn’t matter.

Phoenix Dev House is not a marketing event. It’s a non-exclusive event intended for passionate and creative technical people that want to have some fun, learn new things, and meet new people. In this way, we’re trying to resurrect the spirit of the Homebrew Computer Club. We also draw inspiration from the demoscene as one of the only intentional getting-things-done computer events in the world.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 My Second Game, Now With New-and-Improved Grips» Joey Gibson's Blog

Three friends and I went up to the Chateau Elan, Par 3 yesterday for my second golf outing. While my score didn't improve that much (a 51, down from 53), I felt like I played better, in terms of mechanics. I had just as much fun as the first time, even though it was about 8 degrees hotter.

Also of note is that I was playing with new grips on my irons. As I mentioned before I took my clubs to the PGA Tour Superstore and got some pretty, red Lamkin Crossline grips put on, which made a nice change. It was almost like getting a new set of clubs, at a fraction of the cost. Here's what it looks like

I'm playing this same course again tomorrow (Tuesday), so maybe I'll shave a few more strokes off my score.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 My Mac Pro Goes Boogety Boogety-er» Joey Gibson's Blog

I said before that my Mac Pro was fast. But lately it's been bogging down a bit when I have lots of apps open. Especially if I am using Parallels.

But UPS just arrived with a little shipment from Crucial: another 2GB of RAM. O, glorious day! Notice the screenshot of my activity meter:


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 My First Golf Game In Nearly 20 Years» Joey Gibson's Blog

I played golf last Sunday for the first time in many years. We went to the 9 Hole, Par 3 course up at Chateau Elan and had a great time. I shot nearly 2x par, but for not having played in so long, I think that qualifies as "not that bad." Here's the score card:


The 9th hole was the fun one. You have to hit over a lake to get to the green. The first shot each of us took, we put the ball straight into the water. My second shot, with a 3 wood, was beautiful: straight, high and long. The ball landed on the green, about 20 feet from the hole. Putting was another story, but it was fun to make such a nice tee shot.

The hardest hole was 5. You have to skirt a lake, and that wasn't easy. I lost three balls in that lake.

I went to the PGA Tour Superstore in Duluth on Saturday and bought a new golf bag. It's quite nice, with lots of pockets and dividers and such, and these auto-retracting legs for standing it up. It was on sale, which makes it even better. I also looked at grips and talked to the guy in the club-building department about getting mine regripped. I'm going to take them up there this week to get some new grips put on them, since mine are old, wrapped leather that have slipped and turned.

I can't wait to play again.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Multi-core hysteria and the thread confusion» Loud Thinking by David Heinemeier Hansson

New CPUs are growing in cores and not in GHz. That's a tough problem for applications that have been traditionally single-threaded, like games. They have to learn all new techniques and rework their thinking to get the most out of the next-generation platforms.

But the fear of that transition has bled into places where it's largely not relevant, like web-application development. Which has caused quite a few folks to pontificate that the sky is falling for Rails because we're not big on using threads. It isn't.

Multiple cores are laughably easy to utilize for web applications because our problems are rarely in the speed of serving 1 request. The problem is in serving thousands or tens or hundreds of thousands of requests. Preferably per second.

Threads are not the only way to do that. Processes do the job nearly as well with a drop of the complexity. And that's exactly how Rails is scaling to use all the cores you can throw at it.

The 37signals suite is currently using some ~25 cores for the application servers that all the applications have dips on. We'd welcome a 64-core chip any day.

Read more: A good summary of a discussion on multi-core programming in general.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Mac Pro RAM Woes» Joey Gibson's Blog

You may remember how excited I was about a month ago when I got the 2GB RAM upgrade from Crucial for my Mac Pro. Well, about two weeks ago I happened to notice in Activity Monitor that I only had 3GB of RAM. That wasn't right; I had 4GB. I started testing, and discovered a problem with the RAM. System Profiler was reporting 6 512MB sticks of RAM, instead of 4 512MB and 2 1GB sticks. I tried moving the sticks around to various banks, but never got it to see more than 3GB. Also, there are four LED's on each of the risers that correspond to the four RAM banks. When you boot the system, these lights come on for about 2 seconds, then go out. There was one Crucial stick whose LED stayed on. No matter which bank I put that stick in, its light stayed on.

Saddened by this, I called Crucial. I spent just a few minutes on the phone with them before they agreed that there was clearly a problem, and that they would replace them. They have excellent customer and technical support. I shipped the two sticks back to them and waited.

Two days ago UPS arrived with my replacement sticks. I shut down my Mac and put the two new sticks in banks 3 and 4 of riser A, leaving the 512MB sticks in banks 1 and 2 of risers A and B, and booted. I logged-in, brought up Activity Monitor, only to see 3GB reported. System Profiler says 6 512MB sticks, just like before. The new RAM is doing exactly what the first set of RAM did. I tried every combination of placement of the sticks I could think of, including removing ALL the Apple RAM, and just putting the Crucial sticks into banks 1 and 2 of riser A. In that case, the Mac only saw 1G of RAM.

So it was back to Crucial tech support. They agreed it sounded like a bad stick (again) and are going to replace them again. I just shipped back the two latest sticks, and am once again waiting on a shipment from Crucial. I hope this one works. If it doesn't, I'm just going to pony up the 2x extra and buy direct from Apple.

The Crucial guy said it was "hard to believe" that I got two bad sticks in a row, and I agree. But what else could it be? If I only had two banks for RAM in the computer, then you could blame it on the computer itself. But I've got eight banks to play with, and have tried them all. I don't think it's a problem with the Mac itself. I could be wrong, but I don't think so.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Liberals Hate Context» Joey Gibson's Blog

Last night I saw a link to a clip of Ann Coulter apparently saying very nasty things about John Edwards. After watching it, I was fully prepared to write her off as having gone from being edgy, to going over the edge. The Internet is aflame today with liberals in shock and amazement at what Ann "said." According to the, in this case, apt-named Crooks and Liars

And Coulter herself said, "if I'm going to say anything about John Edwards in the future, I'll just wish he had been killed in a terrorist assassination plot."
Based on that statement, it sure sounds like Ann has gone over the edge and should be denounced by everyone. I had my pitchfork ready to go.

But not so fast. Today, I found the full interview that provides the context for her apparently-insensitive statement. Go watch both and come back. I'll wait.

[Time passes.]

Notice the really important line of context leading up to the "slur?" The full quote is

... but at the same time, you know Bill Maher was not joking and saying he wished Dick Cheney had been killed in a terrorist attack. So I've learned my lesson, if I'm going to say anything about John Edwards in the future, I'll just wish he had been killed in a terrorist assassination plot.
That context changes things, doesn't it? It always does.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Learn the Bible in 24 Hours? Sure...» Joey Gibson's Blog

I was at Borders the other day, and I happened to see a book called Learn the Bible in 24 Hours. Yeah, I'm sure that's possible.

Anyway, I was discussing it with my friend Fred and we started coming up with other funny "learn the Bible" book titles, such as

  • The Bible for Dummies, Evangelical Edition: The Book of Romans, Throw the Rest Away
  • The Jehovah's Witness Edition: It's All About John 1:1c
  • The Mormon Edition: Read the Sequel
  • The Catholic Edition: All Your Saint Are Belong To Us
  • The Muslim Edition: The Bible, That Work of Fiction by Jews and Christians
I especially like the Catholic one, of course, that was one that I came up with...


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Kelly Willis' New Record is Out... And Good» Joey Gibson's Blog

It's just after midnight on June 26. Kelly Willis' new album, Translated From Love was just made available on the iTMS, and since I pre-ordered it, it was a-waiting for me to download it. Oh, yeah. I'm four songs into it, and it's really good. I have all of Kelly's stuff, but the last two, Easy and What I Deserve, have been my favorites. Based on what I've heard so far, they may have some competition with this album.

Kelly's voice is just as smooth and luscious as always. She has that Austin twang, and her music is about as far as you can get from the "pop country" that passes for C&W these days. Kelly, Mindy Smith and Neko Case are my favorite ladies. You should check them out.

Kelly is coming to Atlanta on July 7! I went ahead and bought my ticket the other day, after I got hosed on the Mindy Smith show selling out. I was not pleased about that. I love both these ladies' music, and I really wanted to see Mindy. Oh well, at least I'm assured of seeing Kelly.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 It's My Birthday» Joey Gibson's Blog

Today's my birthday, and now I can truthfully quote Dennis from Holy Grail

I'm thirty-seven; I'm not old!
That should make for hours of entertainment.

I last played golf about 20 years ago. For some reason, about six weeks ago, I started having the urge to play again. So, using money given for my birthday, I'm going to get me some golf schoolin'. My first lesson with the local golf pro is Saturday. I am supposed to play with some friends later in the month at Chateau Elan and I'd rather not look like a complete idiot. Hopefully the lessons will prevent that. :-)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 It's DCE, not DRM» Joey Gibson's Blog

George Orwell would be so proud of this. HBO's CTO recently said he no longer wants to use the term DRM, Digital Rights Management, for how they copy-protect their content. Instead, he prefers the term DCE, Digital Consumer Enablement (emphasis mine). Referring to a technology that limits what I can do with content as something that "enables" my use... well... that's just double-plus good, isn't it?


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 I Had My First Golf Lesson» Joey Gibson's Blog

I had my first golf lesson on Saturday. It was fun, and I wasn't starting out as terrible as I had imagined. We started out working on swing mechanics without a ball present, but once we moved up to using a ball, only once did I swing and completely miss the ball. Every other swing made contact; it was just the quality of the hit that changed. There were a few rollers and a few "D'oh!" moments, but for the most part, I got some good hits.

My right biceps is still sore from Saturday, too. I need to stretch out before-hand next time more. Bob showed me some stretching exercises to do, I just didn't take the time to actually do them so they could stretch me out. I'll know better next time.

The clubs I have are a mixture of ancient and not-quite-so-ancient. The two woods I have are from a set my parents gave me back in the mid-eighties. The irons are some that my wife bought from a neighbor's yard sale a few years ago. Bob said that the irons (Ram) were quite good, but the woods were "going to put you [me] at a disadvantage." The problem, he said, was that the faces on them were so small that you get no margin for error. He said that modern woods are three to four times as large, and he would recommend getting something else. We did hit some with the driver, but he was right about margin for error. So yesterday I went to my local Play It Again Sports store and picked up a new 1 and 3 "wood" that had enormous faces and heads that are far, far larger than my old ones. I'll give them a try tonight. And I put "wood" in quotes because there's not a scrap of anything resembling wood on them. It's all aluminum and carbon and such. Or something. I don't know what they really are made of, but it's definitely not wood.

I've got a second lesson scheduled for this Saturday and I need to practice some this week. I'm going to try to get to the driving range tonight and at least one more time before Saturday.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Hot Air» James Britt - Code, Content, Caffiene

Reading about the carbon footprint of those participating in the Live Earth concerts makes me think that it’s a bit like PETA holding a promotional barbecue.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Getting back to the foil» Loud Thinking by David Heinemeier Hansson

I used to fence in high school. It's such an elegant sport. Yes, stamina, agility, and even strength are elements, but fencing foil is so much more about technique. A small rotation of the wrist is all it takes to parry an attack and you're all set for riposte.

I relearned that last Wednesday when I went my first fencing class in more than a decade. Most of the footwork was still imprinted in my memory, but that was the easy part. The hard part was realizing just how much technique I had lost as I was getting schooled by a 7 year-old girl.

Which is of course also one of the wonders of fencing. It allows for such a wide range of physical attributes to enjoy it together. In the small group that was at the session that night, it ranged from Alexa, 7 to a 50-something Argentinean. With a few teenagers and me in between.

So lots of fun, but I'm also grateful that there's a full week between sessions on the beginner's team. It's taken at least half that to be able to walk without pain again. Nothing like exercising muscles that have laid dormant since Jurassic Park was a box office hit.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Exploding Soda» Joey Gibson's Blog

A few days ago I went by the grocery store. One of the things I picked up were some 12-packs of soda. I had three 12-packs in my cart when I went to check-out, and the clerk said that they had a special running: 4 12-packs for $10, and you got three 2-liters for free. It made sense for me to go get some more soda, so I did.

When I got home, I was able to get everything except two of the 12-packs in one trip, with the intention of coming back out for the other two. But something happened, and I never made it back out. The 2 12-packs in question were in the back floorboard, out of direct sunlight, so I didn't see a problem.

The next day, Thomas and I were going somewhere. I opened his door for him, and noticed that the 2 12-packs were obstructing his leg-room. I moved one of the 12-packs to the back seat, behind the passenger seat, and off we went.

On Friday morning, I needed to run an errand. I went out to my car, got in and started it up. I noticed a strange smell, but couldn't quite place it. I then turned around and saw a 12-pack of Pepsi One on the back seat. Actually, I should say I noticed the remnants of a 12-pack of Pepsi One on the back seat. Remnants, because the whole bloody thing had exploded all over the inside of my car. It was then that I noticed the brown spots all over the car: the ceiling, the sunroof, the back window, the side windows, the windshield, the back seat, the backs of the front seats. Yes, pretty much everywhere that could have gotten splattered did.

I got out, went back in the house and got Thomas to come out and see the carnage. He was amused. I have to say, I was, too. I just couldn't help but laugh at this absurd occurrence. I got the remnants out, and as I gently dropped it down onto the driveway, another can exploded. It missed me, but barely. There were three others that looked like they were near the bursting point, so I carefully knocked the side of each one against the edge of the driveway to puncture it in a "controlled" fashion.

So, of a 12-pack, 8 exploded in the car, one on its own, and three via "controlled detonation."

The lesson to be learned: if you live in the South, don't leave sodas in your car on hot Summer days.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Digesting RailsConf 2007» Loud Thinking by David Heinemeier Hansson

Going from five to sixteen hundred people is a big risk for a conference. There's so much to lose: The atmosphere, the coherence of content, and the interestingness of the people. But in my mind we didn't, RailsConf 2007 was a roaring success.

There were so many great debates going on, so much fascinating work happening, and so extraordinary tales of adoption. It was wonderful to meet up with people like Martin Fowler, Ward Cunningham, Tim Bray, Dave Thomas, Robert Martin, and other industry leaders.

But in many ways, even more wonderful was the level of involvement from everyone else. I remember RubyConf '03 when we just had a couple of people doing professional Ruby work. This year at RailsConf more than half the room raised their hand when I asked how many were working professionally with Rails. What a leap.

So many people doing applications in all niches and of all shades. Plenty of startups, naturally, but also plenty of so-called enterprise operations. From banks to insurance companies. ThoughtWorks announcing that 40% of all new business in the US is Ruby on Rails projects. Wow.

I loved the fact that it wasn't all about the nitty gritty stuff either. We had an Extra Action marching band that pushed the comfort level of many on the fun side of things.

And on the more serious side, Alan Francis explored the similarities between the Rails and XP movements on a higher plane of approach, angry teenager-tendencies, and peaks.

I also much enjoyed the fact that it was broader than just Ruby and Rails circle. That we had Avi Bryant talk to us about this magical parallel universe of Smalltalk. And that we attracted people like Scott Hanselman from the .NET world (and that he posed plenty of opposing opinion that we sorta captured in a podcast with Martin Fowler and me).

All in all, a spectacular extended weekend. It made me all the more excited for turning another chapter in the conference book in Berlin come late September with RailsConf Europe.

All photos by the always awesome James Duncan Davidson


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Desert CodeCamp 2007» James Britt - Code, Content, Caffiene

Planning is underway for Desert CodeCamp 2007. It will be held Saturday, September 15th, 2007, at the University of Advancing Technology in Tempe. Presentation proposals are being accepted now (see previous link).

I’d like to give talk, but I’m not sure what I want to talk about.

Here’s what’s running through my mind:

  • Trac: A Crash Course
  • Beyond Ruby: A Potentially Hasty Intro to Haskell, Erlang, and Io.
  • Nothing. Be a spectator and razz Josh and David

Comments and suggestions invited.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Cranking up the machinery» Loud Thinking by David Heinemeier Hansson

So I finally had a few spare moments to work on the Loud Thinking machine again. Instead of going with one of the million packages out there, I decided to eat some dog food and just roll my own.

Yes, yes, terribly inefficient from a productivity perspective, but I indulged myself with a learning experience on how it feels to setup a small Rails application from scratch using Ubuntu Fiesty, nginx, Mongrel, and SQLite3.

As a side-effect, I haven't bothered implementing comments for my little machine just yet. And I'm thinking that's actually a blessing in part disguise. I think I'll be happy with the tranquillity for a while.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Cold Turkey @ Trax» James Britt - Code, Content, Caffiene

Saturday, July 7, 2007.

Show time: 9:00pm. Or so they say.

Well worth your time and trouble to party hearty with the desert rock masters.

Really, how could you pass on this:

Another booty-rockin’, smack-talkin’, party-like-you’re-Christopher-Walken good time from your favorite degenerates at Cold Turkey. Playing with us also is our friends in rock from Rudy’s Arcade. Funkmaster Avedog will be flying all the way from Dallas to ensure the jam is properly funkified.

Nothing beats funkified jam.

Nothing.

July 7, 9pm, Trax, NW corner of 1st St. & Farmer in Tempe (right down the block form the secret liar of the mysterious Dr. Jumpbox), and NO COVER.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Capturing Middle-Mouse Click in Safari» Joey Gibson's Blog

I have been a consistent user of the nightly builds of the WebKit project for some time now. For those of you who don't know, WebKit is essentially the work-in-progress that will be the next production version of Safari. I like the nightlies because they are extremely fast, and while they occasionally have problems, that's OK.

The point of that discussion was to say that I have stopped using Firefox on my Mac, because the nightly builds of WebKit are so much faster. But there's one problem. In Firefox I could click a tab with my middle-mouse button, and it would close. Safari doesn't have that feature, and that's the one feature from Firefox that I really miss.

So, I've been trying to solve this problem using SIMBL. What SIMBL does is let you write a standard Cocoa bundle and have it load into another program, like Safari. Once loaded, you can replace methods in the application with your own versions, in a way known as "method swizzling." I have successfully written a Cocoa bundle, made the approrpriate changes to make it loadable by SIMBL, and have loaded it into Safari/WebKit. I have logging statements at various points in the bundle, and I can see these on the system console, thus I know it's loading.

Once the bundle was loading, I needed to pick the objects and their methods that I thought would be most likely to let me do what I needed, and then swizzle in my changes. Using F-Script Anywhere I was able to identify a single tab as an instance of TabButton. Using class-dump I was able to generate header files for Safari that would let me see the methods on TabButton and it's parents. My first thought was to override mouseUp:. This works, and I can now trap mouse events when you click on any tab. According to the Apple docs, once I get a mouse event, I should be able to call [theEvent buttonNumber] to figure out which button was pressed. Well, maybe. No matter if I clicked with the left- or middle-mouse button, [theEvent buttonNumber] always returned 0. Further digging in the docs turned up an event called NSOtherMouseUp that is sent when a button "other" than left- or right-mouse is clicked. Supposedly, I should be able to override otherMouseUp: to get those events. I have successfully swizzled this method, but it never gets called. I know that TabButton had a version of this method, because when I swizzle, I can tell if there was already a method there, and there was. I'm just not sure why it isn't being called.

So what did I get working? Well, after working a long time trying to get the middle-mouse detection working, I decided to punt for the moment. I added some code to the mouseUp method to check the event for modifiers and if the user held down Command while clicking, then I will close the tab. This is close to what I want, but nearly as sexy as just middle-mouse clicking. In case you're interested, my TabButton.m looks like this:

	 1 #import "TabButton.h"
	 2 #import "WebKit/WebKit.h"
	 3 
	 4 @implementation TabButton (MCCSwizzle)
	 5 - (void)_mcc_mouseUp:(NSEvent *) theEvent
	 6 {
	 7   NSLog(@"_mcc_mouseDown");
	 8   int buttonNumber = [theEvent buttonNumber];
	 9 
	10   NSLog(@"buttonNumber: %d", buttonNumber);
	11   NSLog(@"type: %d", [theEvent type]);
	12   NSLog(@"modifierFlags: %d", [theEvent modifierFlags]);
	13 
	14   if ([theEvent modifierFlags] & NSCommandKeyMask) {
	15     NSLog(@"Cmd-Click!");
	16     [self closeTab: theEvent];
	17   } else {
	18     [self _safari_mouseUp: theEvent];
	19   }
	20 }
	21 @end
	
and then the swizzling looks like this:
	 1 #import <WebKit/WebKit.h>
	 2 #import "AppController.h"
	 3 #import "MiddleClickClose.h"
	 4 
	 5 typedef struct objc_method *Method;
	 6 
	 7 struct objc_method {
	 8   SEL method_name;
	 9   char *method_types;
	10   IMP method_imp;
	11 };
	12 
	13 BOOL MCCRenameSelector(Class _class, SEL _oldSelector, SEL _newSelector)
	14 {
	15   NSLog(@"OLD: %s", _oldSelector);
	16   NSLog(@"NEW: %s", _newSelector);
	17 
	18   Method method = nil;
	19 
	20   // Look for the methods
	21   method = (Method)class_getInstanceMethod(_class, _oldSelector);
	22   if (method == nil)
	23     return NO;
	24 
	25   // Point the method to a new function
	26   method->method_name = _newSelector;
	27   return YES;
	28 }
	29 
	30 @implementation MiddleClickClose
	31 + (void) load
	32 {
	33   int rc;
	34 
	35   rc = MCCRenameSelector([TabButton class], @selector(mouseUp:),
	36                                    @selector (_safari_mouseUp:));
	37   NSLog(@"RC: %d", rc);
	38 
	39   rc = MCCRenameSelector([TabButton class], @selector(_mcc_mouseUp:),
	40                                                  @selector(mouseUp:));
	41   NSLog(@"RC: %d", rc);
	42 
	43   rc = MCCRenameSelector([TabButton class], @selector(rightMouseUp:),
	44                                    @selector (_safari_rightMouseUp:));
	45   NSLog(@"RC: %d", rc);
	46 
	47   rc = MCCRenameSelector([TabButton class], @selector(_mcc_rightMouseUp:),
	48                                                  @selector(rightMouseUp:));
	49   NSLog(@"RC: %d", rc);
	50 
	51   NSLog(@"MiddleClickClose loaded");
	52 }
	53 
	54 + (MiddleClickClose*) sharedInstance
	55 {
	56   static MiddleClickClose* plugin = nil;
	57 
	58   if (plugin == nil)
	59   {
	60     plugin = [[MiddleClickClose alloc] init];
	61   }
	62 
	63   return plugin;
	64 }
	65 @end
	
Line 35 renames Safari's original mouseUp: method to _safari_mouseUp: and then line 39 renames my _mcc_mouseUp: method to mouseUp:. The otherMouseUp: method is handled on lines 43 and 47, but as I said otherMouseUp never gets called.

What's especially frustrating about this is that I know Safari knows how to bag a middle-click, because I frequently will middle-click on a link in a web page, and Safari will open that link in a new tab. So, why can't I get a middle-click in the TabButton instance? Does anyone have any ideas on this? I'd appreciate any pointers. I feel like I'm thiiiiiiiiiiis close to getting this working, but there's some small piece of info that is eluding me.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Back Up, Once Again» Joey Gibson's Blog

In case you've missed me, I'm back. The site has been down for a week and a half due to server problems. I host this site in the same rack as my company, on one of the spare machines, but last monday we lost a drive in our database server. I started moving the data to the spare machine, but while doing so, that drive also failed, taking with it my blog. Today I upgraded my test machine from an older copy of SuSE Linux to Ubuntu Fiesty (which is what all the machines are now running), and now the blog is back. Hooray!

For good, I hope.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 AppleScript and iTerm: Sweet!» Joey Gibson's Blog

I use iTerm for all my command-line needs. I really like it, especially the tabbed interface. I typically have two to three terminals open for my local box, plus two to three for various systems in the company rack. iTerm has a nice bookmark feature that lets you save commands (like ssh me@foo) to open these various windows, but it's not exactly what I want. The reason for this is that I either have to leave the bookmark drawer open all the time, or I have to click to open it, then double-click the bookmark I want to launch, then close the bookmark drawer. And that's a real drag for me, because I'm not really a mouse guy.

So yesterday I started thinking that it had to be possible to do this using AppleScript, and indeed it is. My solution is not optimal, as I had to use two files, but it's close to optimal. It's approaching optimal. Here's the AppleScript file, which is called it.scpt:

		    1 on run argv
		    2     tell application "iTerm"
		    3             activate
		    4 
		    5             tell the first terminal
		    6                     launch session (item 1 of argv)
		    7             end tell
		    8     end tell
		    9 end run
	
Next is a regular shell script, called it that calls it.scpt:

		    1 #!/bin/bash
		    2 
		    3 if [[ $# == 0 ]]
		    4 then    
		    5     echo "Usage: it <session_name>"
		    6     exit
		    7 fi
		    8 
		    9 osascript ~/bin/it.scpt $*
	
You can see that the shell script checks to see if you've specified a bookmark name to launch. If you haven't, it tells you how to run it. Once it's established that you have specified a name, it calls the AppleScript file it.scpt, which I've placed in ~/bin for convenience. (Both files are in ~/bin on my system.) The AppleScript tells the currently-running iTerm to activate (probably not needed) and then tells it to launch the requested bookmark in a new tab. I don't need to worry about the case where iTerm isn't running, because I would execute this script from within iTerm. If you specify a non-existent bookmark, it just opens a new shell on your local system, which is OK, I guess.

So, to run it, I would type something like

it web1
to open the bookmark called "web1." And that's what I wanted.

I was a bit surprised that I was unable to just have one file. I should have been able to put a she-bang line in it.scpt and have it work. In other words, I should have been able to have

		    1 #!/usr/bin/osascript
	
and then the rest of the script, but I got an error when I tried that.

If anyone knows an easier way to do this, please let me know.

04/11/2007 14:20 Update: A reader sent in how you can combine the two scripts into one, using osascript's -e switch. I knew about this switch, which let's you specify the program on the command line, but I've seen so many horrible (ab)uses of the same option in Perl that I didn't even try it. What I didn't know was that you can have embedded line feeds inside the quotes, so you can still have a nicely formatted script. Here's the new and improved, single-file version of it:

		    1 #!/bin/bash
		    2 
		    3 if [[ $# == 0 ]] ; then
		    4     echo "Usage: $0 <session_name>" >&2
		    5     exit 1
		    6 fi
		    7 
		    8 osascript -e 'on run argv
		    9     tell application "iTerm"
		   10             activate
		   11 
		   12             tell the first terminal
		   13                     launch session (item 1 of argv)
		   14             end tell
		   15     end tell
		   16 end run' $@
	

04/12/2007 11:46 Update: This tip got posted over at MacOSXHints.com and has gotten some comments. Based on those comments, below is the latest version, which includes the ability to get a list of available bookmarks to launch by typing it list. Here it is:

		    1 #!/bin/bash
		    2 
		    3 if [[ "$#" = "0" ]]; then
		    4     echo "Usage: 'it bookmarkname' or 'it list'" && exit 1
		    5 elif [[ "$1" = "list" ]]; then
		    6     defaults read ~/Library/Preferences/iTerm|grep Name
		|grep -v NSColorPicker|awk '{$1="";$2=""; print $0}'|tr -d ';'
		    7 else 
		    8 osascript <<ENDSCRIPT
		    9 on run argv
		   10   tell application "iTerm"
		   11     activate
		   12     tell the current terminal
		   13       launch session "$1"
		   14     end tell
		   15   end tell
		   16 end run
		   17 ENDSCRIPT
		   18 fi
	


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 [ANN] Wee 0.7.0 + Tutorial Videos» Mike's Weblog
Click here to bookmark this link.Channel Image19:16 Why Japan is Great» Mike's Weblog
  • Dir en grey, the greatest hard-rock band on earth. "Crazy Kyo" & Co now coming to Berlin ;-)
  • Ruby, my favourite programming language.
  • Haruki Murakami, a great author of novels.
  • Sushi. mhmmm ^__^

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 What Should flexmock(real_obj) Return?» { | one, step, back | }

Bruce Williams asked this question at RailsConf, and I am soliciting feedback.

Background

First, a little background. There are two possibilities when calling flexmock(). First, you are creating a full mock object:

# Example 1
mock = flexmock("description")
mock.should_receive(...)

A full mock fulfills two roles: (1) it is a target for should_receive to define expectations, and (2) it is a target for normal domain messages when testing.

The other possibility is that you are creating a partial mock (i.e. a regular Ruby object with just a few mocked methods):

# Example 2
real_obj = RealObject.new
proxy_mock = flexmock(real_obj, "description")
proxy_mock.should_receive(...)

The object returned from the flexmock() method is actually a proxy object that can accept should_receive() messages to define the expectations, but does not handle normal domain messages. After all, we have a real object that that handles domain messages.

Partial Mocks

It is clear that when creating a partial mock using the non-block form of flexmock(real_obj), we must return the proxy, else there would be no way to add expectations. But the return value for the block form of flexmock is not so clear.

Consider the following code:

# Example 3
real_obj = RealObject.new
result = flexmock(real_obj) do |mock|
  mock.should_receive(...)
end

Here the proxy object is passed as the block argument. All the expectation setup is done within the block. It is very tempting to write this code as:

# Example 4
result = flexmock(RealObject.new) do |mock|
  mock.should_receive(...)
end

But here is the problem: in example 4 we no longer have a reference to the RealObject instance. The flexmock() method returns the proxy object, not the real object; just as it does in the non-block form.

Bruce’s Suggestions

Bruce suggested changing the block version of flexmock() to go ahead and return the real object. Since the proxy is used in the block, there is no real need for it outside the function. And, I will admit, example 4 is short and relatively clear, especially with those familiar with the returning idiom used in Rails.

The Dilemma

So here is my dilemma. Changing FlexMock so that example 4 works properly is attractive. And I suspect that the return value of flexmock(real_obj) is not ever used in a significant way in existing code, so backwards compatibility should be be only a minor concern. However, changing the return object based on whether or not the method has a block just seems … wrong.

There is precedent for this. In the standard Ruby libraries open(fn) and open(fn) { ... } return different things (an open file for the former and the value of the block for the latter). I’ve never had problems with this behavior in open, so perhaps I am just being over sensitive here.

I told Bruce I would blog the issue and consider the feedback received. So let me know what you think. Should flexmock() be modified to return the real_object when defining partial mocks using the block form?

You can email me (jim@weirichhouse.org) or add a comment using the comments link below.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Trouble with MacPorts» { | one, step, back | }

This happened to me just this past week.

Trouble Installing Packages with MacPorts?

If you are having problem installing packages with the macports port command, double check that you have the latest version of Xcode installed (version 2.4.1 at this point in time). A number of packages install with much less hassle when you are up to date.

Just speaking from experience.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Thunderbird: Use Konqueror as browser » Mike's Weblog
Edit your prefs.js file located somewhere inside the .thunderbird directory, and add or modify the following two lines:
  user_pref("network.protocol-handler.app.http", "/usr/local/bin/konqueror");
  user_pref("network.protocol-handler.app.ftp", "/usr/local/bin/konqueror");

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Zak Mandhro Answers» { | one, step, back | }

With the erubycon quickly approaching, I have sent a list of 5 questions to several of the erubycon speakers. As their responses come back to me, I’ll publish them here.

Enjoy!

—Jim Weirich

Zak Mandhro Answers

Zak Mandhro is a Senior Manager of Information Management Solutions for BearingPoint (http://www.bearingpoint.com). He is the first of our erubycon speaker interviews.

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I am a Senior Manager at BearingPoint, a global consulting company. My background is custom Enterprise Solutions that utilize JavaEE, .NET, SOA, Portals and Business Intelligence. I came across Ruby while exploring dynamic languages in 2004. I started using Ruby actively after Rails 1.0 release (outside of BearingPoint). We are currently using Ruby for a requirements DSL (http://rubyforge.org/projects/rdil) at a major federal client.

Q: What unique opportunities do you see for Ruby in the enterprise?

Short answer: The bottom-line is richer application at lower cost with faster time-to-market. At the moment, I see two areas where Ruby and Ruby on Rails are particularly attractive. (1) Building departmental database-driven applications, the type that are being serviced by VB, Access and ColdFusion today, and (2) Web services and SOA glue code.

The long answer is here: http://www.sdtimes.com/printArticle/column-20070101-01.html

Q: What obstacles do you see to getting Ruby used more in enterprise software?

We need to have a better deployment and infrastructure story for Rails. Unlike the shared hosting and VPS market, terms like monit, lighty, mongrel and fastcgi are alien to Enterprise data centers. There’s isn’t much in the “Enterprise”-press that would give these products credibility, let alone coverage. Lack of management tools is another area of improvement. We need to get to a point where systems integrators and IT infrastructure staff are familiar and comfortable with Rails deployment. JRuby WAR deployments is one way to get there.

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

I think we are already in the midst of the next big thing. “Simplification of Enterprise Software”. Complex and high-priced proprietary Enterprise software will slowly but surely start to lose market share to simpler open-source alternatives. We are seeing a move to openness and simplicity with JavaEE. We are witnessing endorsement of dynamic languages (less code). Over the next 12 to 24 months, we’ll see more simpler alternatives pop-up, mature and become pervasive; hopefully without ending up becoming just as complex.

Q: What erubycon talk are you most interested in hearing?

Must I choose? Here are three quick picks (in no order):

- Security (CAS and OpenID)

- Mingle: Full-scale JRuby

- Keeping Tests Dry

Thank You

Thanks Zak. Folks can get more information about erubycon at erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Stuart Halloway Answers» { | one, step, back | }

Today we are publishing Stuart Halloway’s answers to our erubycon interview questions.

Stuart Halloway Answers

Stuart Dabbs Halloway is a co-founder of Relevance, LLC. Stuart is the author of Component Development for the Java Platform. He regularly speaks at industry events including the No Fluff, Just Stuff Java Symposiums and the Pragmatic Studio.

Here are Stuart’s answers:

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I have been doing enterprise software development since 1989. Four years ago Justin and I founded Relevance with a goal of raising the bar for how software is written. Ruby has been a great tool. In March 2005, we ported a project to Ruby and haven’t looked back.

Q: What unique opportunities do you see for Ruby in the enterprise?

Ruby is compelling for enterprises that embrace agility. Agile teams don’t aim to limit failure, they aim to enable success. Thus, they are willing to embrace open languages that give developers maximum power to get things done.

Q: What obstacles do you see to getting Ruby used more in enterprise software?

We need more knowledge transfer. Ruby embodies a ton of good ideas, and it will take people (and organizations) a while to explore them all.

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

We’re already there: Agile development methods and open languages.

Q: What erubycon talk are you most interested in hearing?

I’m looking forward to Muness’s report from the field on large Ruby projects.

Thank You

Thanks Stu.

For more information on the conference, see erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Muness Alrubaie Answers» { | one, step, back | }

Continuing with the erubycon speaker interviews, next we have Muness Alrubaie.

Muness Alrubaie Answers

Muness has over 10 years of experience in software development and teaching computer science. His development background has included working with various languages including Java, C#, Python, VB.Net, Perl and Javascript. Now, he is thrilled to be coding in Ruby. Muness is currently a software developer at ThoughtWorks.

Here are Muness’s answers:

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I’ve been doing software development since ‘97. I am currently an architect with ThoughtWorks. I first came across Ruby three years ago thanks to all the Rails hype.

Q: What unique opportunities do you see for Ruby in the enterprise?

I love Ruby for system with fast changing requirements. Its succinctness and readability make it especially attractive, for those properties make programs written in Ruby easier to write, maintain, and most importantly for me, evolve.

Q: What obstacles do you see to getting Ruby used more in enterprise software?

Half hearted attempts at Ruby. Let me explain: whenever a company tries something new and it fails, they blame the technology. This is a problem all new tools/languages face, but I think it’s especially relevant for Ruby.

To be harnessed properly, one has to approach Ruby with respect. In my opinion, using Ruby for large systems without the feedback supplied by an agile process, for example, is a recipe for disaster. Another example of the respect due Ruby is that it is drastically different than Java or C#. Writing Ruby without TDD or taking advantage of its features (dynamic typing and extensive metaprogramming support stand out) will ultimately disapoint both managers and developers.

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

Language oriented programming, aka, making better use of DSLs.

Q: What erubycon talk are you most interested in hearing?

I am looking forward to all the talks, and especially to Keeping Tests Dry and The Beauty of Ruby.

Thank You

Thanks Muness.

For more information on the conference, see erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Glenn Vanderburg Answers» { | one, step, back | }

Glenn Vanderburg is featured in today’s erubycon interview.

Glenn Vanderburg Answers

Glenn Vanderburg has over 20 years of experience as a software developer, working in diverse environments using a wide variety of languages and tools, including Java, C and C++, Perl, Tcl, and more. His career spans large enterprises, universities, and startups. He caught the Ruby bug in 2000, and has never enjoyed programming so much.

Here are Glenn’s answers:

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I’ve been a programmer for 20 years now, and I’ve worked in a wide variety of enterprises, with many different technologies. I’ve just hung up my independent consultant hat to join Relevance, LLC (where I’m be a semi-independent consultant).

In late 2000 I was a regular at a Dallas-area lunch discussion group focused on “Extreme Programming and related topics” (i.e., what we would now call agile software development). Dave Thomas was also a regular there, and he mentioned to us that he and Andy were working on a book about Ruby. I was able to go to the OOPSLA conference that year, where the first edition of the PickAxe was released, and bought a copy on release day. I was hooked immediately.

Q: What unique opportunities do you see for Ruby in the enterprise?

I blogged recently that I think Ruby and Rails help good programmers to become better—partly through just being well-designed and powerful, partly through providing good examples and assistance in doing the right thing, and partly through having a community and culture that values good design and clean, expressive code. I think good, solid design and code are crucial for enterprise software. Enterprises, however, have historically undervalued those things, largely because it’s been so tempting to believe that tools and technologies will solve all the problems. I think we in the Ruby community have a chance to bring much-needed simplicity back to enterprise systems, and remind enterprises that there’s no substitute for skilled people with good tools.

Q: What obstacles do you see to getting Ruby used more in enterprise software?

Large enterprises have a pretty solid division of labor between those whose job it is to get work done and those who are supposed to prevent mistakes. Those in the first group will be drawn to Ruby as a powerful tool that helps them work faster, but those in the second group always try to resist change. And to some degree they’re right to resist. But because they aren’t accountable for the work getting done, they might hold out much longer than they should, hurting the organization in the process. The best strategy against such resistance is for all of us to go public with our Ruby success stories (and there are a lot of them already).

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

There are a lot of people these days wondering whether Apollo or Silverlight will mean the end of web applications, but I don’t think that will happen. My prediction is that new kinds of devices (including smartphones, pads, multitouch screens, and even large- scale displays) will require revising our assumptions about user interfaces, and that will require developers (yes, even enterprise developers) to learn some new techniques. Two-handed input, pervasive animation, and other innovations will cause a lot of upheaval among application developers.

Q: What erubycon talk are you most interested in hearing?

I can’t wait to hear Neal Ford discuss Mingle.

Thank You

Thanks Glenn.

For more information on the conference, see erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Bruce Tate Answers» { | one, step, back | }

Bruce Tate is the second featured speaker to provided feedback on our erubycon speaker interviews.

Bruce Tate Answers

Bruce Tate is a kayaker, mountain biker, and father of two from Austin, Texas. An international speaker and respected author, Bruce’s primary focus through the years has remained steady: rapid application development of web applications. He specializes on putting highly effective teams on the most productive and most appropriate technologies.

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I have been programming for about 30 years, and programming for money for the last 25. I worked at IBM for a number of years, got bored, and left to work for a startup which immediately blew up. Then, I was an independent consultant, which was a little like saying “Unemployed, but with business cards.” I did Java development, training, mentoring, and consulting for five years or so, and began to think that things were getting too bloated, too complicated, and unsustainable. Dave Thomas challenged me to give Ruby a try, and I did, and loved it, and hated that I loved it. All of my reputation, my books, and my customers were all wrapped up in Java, but I knew it was not the right language for the types of problems I was trying to solve. I interviewed a bunch of people to understand what was happening, and then decided to write a book about the learning experience. That book, Beyond Java, caused a lot of controversy, but the stuff seems pretty tame these days.

Eventually, I shifted my consulting practice to Ruby full time. I later turned a consulting gig into a full time CTO position at http://ChangingThePresent.org, We’re building a charitable contributions portal. At ChaningThePresent, you don’t just make a donation. You get an hour of a cancer researcher’s time, you make a blind person see, and if you like, you can make that tangible donation in the name of another, and get a customized card to announce your donation. We hope to be the de facto resource for nonprofits on the web. We think we’re well on the way.

Q: What unique opportunities do you see for Ruby in the enterprise?

I do everything in Ruby. As computing power gets less expensive, we need to use more of that power, and let the base programming language do more of the work. Our infrastructure is just about all in Ruby these days.

Q: What obstacles do you see to getting Ruby used more in enterprise software?

We don’t see insurmountable obstacles. We do think tools have room to grow, especially in the area of refactoring development environments. The dependence on so many C libraries, like ImageMagic, is a pain for deployment. And we use Rails, which has its share of warts. Caching in the persistence layer is harder than it needs to be. Migrations don’t scale beyond small teams. But none of these things even dent the long term productivity that we experience. Any framework will lead to its share of technical debt. Rails is no exception. All in all, it’s a fantastic framework.

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

I always get in trouble for doing this, but I’ll bite. From a language perspective, we seem to be getting closer and closer to a functional language. Ruby is just one step in that direction. We won’t see major movement in the core language for another 10 years, though… we’re locked pretty hard into a 10 year programming language cycle. I think we’ll continue to converge on a set of frameworks that is over HTML and JavaScript. You can easily imagine one of the HAML-like languages putting a dent in HTML, and one of the AJAX frameworks, either in JavaScript or a langauge that composes it, providing a layer over the browser. It’s becoming clearer that HTML isn’t enough, and JavaScript needs layers on top to be everything we need.

Domain specific languages will be unleashed, and driven from things like IDEA’s language workbench and programming languages and concepts in Ruby. This will take us closer to functional programming languages than we’ve ever been.

From a language and feature standpoint, we’ll see continuations play a bigger role. AJAX is complicating web development again, and we’re going to have to make some simplifying assumptions. AJAX tripped up continuation based models for a little while, but I can easily see an abstraction with better encapsulation that lets AJAX play.

So those are three things that I see in the 5-10 year window. In the more immediate timeframe, we’ll see Ruby continue to push Java on the applications end. No single language will dominate, but a bunch of us have already moved beyond Java. There’s still a place for Java, and C++ or COBOL for that matter. But mind share is moving on. It’s inevitable.

Q: What erubycon talk are you most interested in hearing?

It’s an incredible docket. I can’t pick just one.

Thank You

Thank you Bruce. Folks can get more information about erubycon at erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The erubycon Interviews: Anthony Eden Answers» { | one, step, back | }

Anthony Eden’s answers to the erubycon interview questions make up the third installment in this series.

Anthony Eden Answers

Anthony Eden has more than 10 years of experience developing web applications, first with Perl, then Java and now Ruby on Rails. Anthony has developed numerous open source projects over the last 5 years in both Java and now in Ruby. Anthony is currently a project manager and technical lead with Camber Corporation, a government contractor and runs his own company, Aetrion LLC, a data warehouse development company.

Here are Anthony’s answers:

Q: Tell me a little about your background, where you are working and how did you come to start using Ruby?

I am a software developer/project manager with Camber Corporation, a 1400-employee consulting company that services the military and US Government as well as other nations. I also run my own business on the side developing Ruby-based data warehouse solutions for small businesses. I began with Perl in ‘95, started using Java in ‘96, used Python along the way and am now doing Ruby almost exclusively (except for some interest in Erlang). I came to Ruby via Rails and I was skeptical at first, but within a couple of months of using Ruby I became convinced that it could greatly improve my productivity, my team’s productivity and the overall joy of developing software.

Q: What unique opportunities do you see for Ruby in the enterprise?

The prime opportunity is to reduce the amount of code and amount of effort that goes into operating and maintaining various systems used to support Enterprise organizations. The larger an application is the harder it is to maintain. My hope is that the elegance of the Ruby language is seen as an enabler for smaller, easier to maintain enterprise applications that work together, rather than monolithic beasts that can’t be integrated.

Q: What obstacles do you see to getting Ruby used more in enterprise software?

Lack of quality documentation about Ruby and its associated libraries, that is easy to find, for one. Development tools are still an issue, but I actually see Ruby as a catalyst for new development tools that can take advantage of the dynamic nature of scripting languages, rather than something which is seen as an obstacle.

Q: Play oracle for a moment and tell me what you see as the next “Big Thing” in software development.

Distributed parallel processing. A few days with Erlang opened my eyes to the potential of direct support for parallel processing in a language and made me realize that parallel processing is going to be the only way to process the huge amount of data that is becoming available thanks to the “opening up” of a lot of web sites. Google and Amazon are really leading the way here and are representative of where we can go with applications and data integration on a large scale.

Q: What erubycon talk are you most interested in hearing?

- Ruby on Rails with Large Teams

- Stretching ActiveRecord

Thank You

Thanks Anthony.

For more information on the conference, see erubycon.com.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Some Wee and Nemo screenshots» Mike's Weblog
This night, I hacked up a Table and a Pager component for Wee. The Table component is 140 lines of code (including all HTML generation, nothing else except CSS styles are required), the Pager is 100 lines long.

Some days ago, I wrote an OgScaffolder component. It’s damn easy to use. Just pass an Og domain class to OgScaffolder.new, and what you get is a regular Wee component. Look at the screenshot below.

Below I’d like to show some Nemo screenshots, to show it’s potential. Note that the whole generic editor component (the first screenshot) is less than 200 lines very clean Ruby code! Thanks Kevin ;-)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Simplicity via Complexity» Siaris.net
byline: Andrew L. Johnson

…If you aim to dispense with method, learn method
…If you aim at facility, work hard
…If you aim for simplicity, master complexity
   — Lu Ch’ai (Wang Kai), [chinese painter, ca 17 century]

The economy and simplicity of traditional oriental painting is not arrived at by squinting at the subject in order to blur or filter out the complexity — subjects are studied in detail (with both eye and mind). The simplicity and elegance are distilled from the far side of that process.

Consider the tale/fable of the gentleman who entered a well known chinese painter’s shop and described a painting he would like to have painted. The painter talked the painting over with him over a cup of tea, thought for a few minutes and said he could do such a painting but he wouldn’t have it ready for a year. The gentleman frowned at such a delay, but this painter came highly recommended, so he paid a downpayment and left the shop.

A year passed and the gentleman returns and asks the painter if his painting is ready. Without a word, the painter rolls out a new length of rice paper, grinds some fresh ink, and proceeds to paint the picture before the gentleman’s very eyes. In a few minutes he is finished. The gentleman is stunned, and quite impressed that this picture, painted in just a few minutes, captured exactly what he had wanted. "Don’t get me wrong", the gentleman spoke, "the painting is exquisite. But it took you less time to paint than we spent drinking tea a year ago, could you not have found the few minutes needed to paint it any sooner?"

The painter went to a cupboard and retrieved a large box full of hundreds of discarded versions of the masterpiece now drying on the table. "Which of these", the painter replied, "would you have wished to have sooner?"

Well, there may be as many versions of this fable as there were discarded paintings in the box, and, Damn, could that painter estimate a project or what!? But project estimation isn’t my point. Try this one:

I would not give a fig for the simplicity this side of complexity,
but I would give my life for the simplicity on the other side of
complexity.    — Justice Oliver Wendell Holmes (1809-1894)

I think we can all recognize a certain Truth in these quotes that applies to any human activity — and certainly to software development. Getting over the complexity divide takes work. You can’t just skirt around it, and you shouldn’t fear it.

Behind complexity, there is always simplicity to be revealed. Inside simplicity, there is always complexity to be discovered.   — Gang Yu

__END__


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Remote Disk Copy» Mike's Weblog
How to copy the files of a hard-disk from one computer to another, across a network, without loosing file attributes? That’s kind of easy using pax and ssh (pax is probably only available on BSD. cpio on others will do fine, too):
  cd directory/to/copy
  pax -w -x sv4crc . |
    ssh root@remotehost "cd directory/to/copy/into && pax -r -p e"

You should use "root", to maintain correct ownership of files. Use format sv4crc, as most other formats are limited to a path-length of 255.

To double-check that all files were transfered correctly, make use of mtree:

  cd directory/to/copy
  mtree -c -k md5digest -p . |
    ssh root@remotehost "cd directory/to/copy/into && mtree -k md5digest -p ."

If there’s no output, everything is OKAY!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Public Todo list for Wee » Mike's Weblog
I can’t write all Wee code on my own. So here is a list of things that needs to be done:
  • Make session-id cookies available to both Wee::Request and Wee::PagelessRequest, controlled by an application-wide setting.
  • Finish the implementation of pretty-URLs (this rulez!). Thanks to Joao Pedrosa who is working on this.
  • Implement a FilterDecoration and it’s subclass AuthorizationDecoration (that’s very easy, ~20 lines of code).
  • Implement a Seaside-like root_for traversal, which allows each component in the tree to add stuff inside the <head> tag. This is triggered by the root-component from it’s render method.
  • Refactor the Wee::Session class and it’s subclasses.
  • Implement further adaptors, most useful would be a FastCGI adaptor. This would need to factor out the WEBrick dependent parts.
  • Implement ResouceHandlers, which make it possible to generate images (or other external resources) from within your components.
  • Use it in your projects and write tutorials ;-)

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Präsentation: Autonomes Grid Computing» Mike's Weblog
Letzten Freitag hab ich im Rahmen des Seminars Selbstorganisierende Rechnersysteme meinen Vortrag über Autonomes Grid Computing gehalten.

Folien als PDF

Alles im ViewCVS


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Oniguruma (Ruby with Demon wheels)» Siaris.net
byline: Andrew L Johnson

Oniguruma is a regular expression C library you can use in your own projects under the BSD license, or you can install it as Ruby’s regular expression engine (in which case it falls under the Ruby license). Oniguruma may be translated to English as Demon Wheel (or something along those lines).

Oniguruma is slated to become Ruby’s default regular expression engine, and Ruby 1.9 already has it included. But you don’t have to wait to try it out — it is easily incorporated into 1.8* ruby builds and basically just involves:

  1. downloading and unpacking the latest oniguruma sources for Ruby
  2. configure oniguruma with your Ruby source directory
  3. make oniguruma (which applies the patches to the Ruby sources)
  4. rebuild and test your ruby (make clean;make;make test) in Ruby directory
  5. test oniguruma (make test) in oniguruma directory

The only danger in doing this is forgetting that oniguruma is not yet standard Ruby and shouldn’t be a dependency in released code. You might want to build both a standard ruby and an oni-ruby (or perhaps guru-ruby).

Oniguruma brings several features to Ruby’s regexen, notably:

  • positive and negative look-behind
  • possessive quantifiers (like atomic/independent subexpressions but as quantifier)
  • named backreferences
  • callable backreferences

Look-behind and callable backreferences are probably the main reasons you’d want to install oniguruma.

Look-Behinds

Look-ahead assertions have been around for some time, in many regular expression flavors. Look-behind assertions are less prevalent. Oniguruma brings positive and negative look-behind assertions ((?<=…) and (?<!…) respectively) to Ruby. Just like look-ahead assertions, these are zero-width assertions — they match the current position if the assertion about what follows (look-aheads) or precedes (look-behinds) is true. They do not consume any part of the string.

Unlike look-ahead assertions, look-behinds must contain fixed-width patterns which means: no indeterminate quantifiers. However, alternation is allowed at the top level of the look-behind, and the alternations need not be of the same fixed width. Capturing is allowed within positive look-behinds, but not in negative look-behinds (which makes sense).

Callable Backreferences

Callable backreferences give us recursively defined regular expressions, which allow one to match/extract arbitrarily nested balanced parentheses (or other delimiters).

  # to match a group of nested unescaped parentheses:

  re = %r/((?<pg>\((?:\\[()]|[^()]|\g<pg>)*\)))/
  s = 'some(stri\)\((()x)(((c)d)e)\))ng'
  mt = s.match re
  puts mt[1]

    ==> (stri\)\((()x)(((c)d)e)\))

Difference between Oniguruma and Standard Ruby Regular Expressions

The main behavioral difference I’ve noted between the two regular expression engines involves capturing with zero-length subexpression matches. In the following, sruby is standard ruby, and oruby is compiled with oniguruma:

  $ sruby -e '"abax" =~ /((a)*(b)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  aba::a:b
  $ oruby -e '"abax" =~ /((a)*(b)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  aba::a:b

No difference there, but note that Perl handles this differently (and, IMHO more correctly):

  $ perl -e '"abax" =~ /((a)*(b)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  #{aba}:#{}:#{}:#{}

In my mind, with nested capturing such as this I would expect that the contents of $2 and $3 would be substrings (even if only empty strings) of $1 — like Perl handles it. However, Ruby isn’t alone in that Python and the pcre both handle it as Ruby does.

If this behavior doesn’t seem strange, consider this more obvious example:

  $ sruby -e '"ba" =~ /((a)*(b)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  ba::a:b
  $ oruby -e '"ba" =~ /((a)*(b)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  ba::a:b

I understand the interpretation, I just don’t think it is the most correct interpretation to follow.

The difference between Oniguruma and Ruby becomes apparent in the following example, when the subexpressions themselves may be zero-length:

  $ sruby -e '"abax" =~ /((a*)*(b*)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  aba::a:b
  $ oruby -e '"abax" =~ /((a*)*(b*)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  aba:::
  $ perl -e '"abax" =~ /((a*)*(b*)*)*/; print "#{$&}:#{$1}:#{$2}:#{$3}\n"'
  #{aba}:#{}:#{}:#{}

Here, Oniguruma sides with Perl instead of Ruby, and all the captured subexpressions are the empty string. However, pcre agrees with standard Ruby on this one, and Python won’t even compile the regular expression.

  Versions used in testing:
    sruby       => Ruby 1.8.4 (2006-01-21)
    oruby       => Ruby 1.8.4 (2006-01-21) with Oniguruma 2.5.2
    Perl 5.8.7
    Python 2.4
    pcre 6.3

__END__


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Looking at darcs » Siaris.net
byline: Andrew L Johnson

I like simple, so when I heard that darcs is a simple (but rich) distributed version control system, I had to take a look.

darcs is a relatively new entry on the version control landscape, officially announced in April of 2003 it passed the 1.0.0 milestone in November of 2004 and now sits at 1.0.1. It is written in Haskell, and you’ll need the Glasgow Haskell Compiler (GHC) to build it from source, but there are binaries available for many platforms. The linux static binary worked out of the box.

What makes darcs different is that you don’t check out working directories, but rather fully functional repositories — essentially branches — without any of the fuss or administrative overhead of setting up local branches / repositories that some other version control systems require.

So, if I do

  darcs get http://www.abridgegame.org/repos/darcs

I wind up with a full repository of the darcs sources — in which I can make changes, record, unrecord, revert, pull down new patches, or create patches to apply back to the "main" repository (using darcs push if I had write access to the that repository, or darcs send to send via email where they might either be manually or automatically applied). Of course, I could share my patches directly with another developer equally as easily if we both working on some fix or feature.

(Note: darcs get —partial … is recommended if you don’t really need the entire patch history of the project — it will just fetch the patches since the last ‘tagged’ version and build your repository based on that. Currently with darcs, that’s the difference between getting some 2500+ patches or just getting and applying few hundred).

This tutorial illustrates how easy using darcs is, and the manual itself is a well written guide and reference (which also discusses the underlying Theory of patches of darcs). So I won’t duplicate that material here.

I will mention one experience I had with darcs itself. I decided I’d rather build darcs from source rather than rely on a binary, so I downloaded a binary install of GHC, used my binary of darcs to get the darcs repository, and built my own version. Unfortunately, the GHC I installed was broken on my system, and any system() calls failed (and darcs uses system() calls in a few places such as bringing up your editor to write long log messages, or for running automated test commands). My first attempt to build my own GHC from source also failed.

So I dove into the darcs sources (without ever having looked at Haskell code before) and was able to come up with a workaround patch that replaced any system() calls in darcs with an execvp based alternative — this solved my immediate problem, and everything worked fine.

Now I wouldn’t expect a patch for my isolated case to be incorporated into darcs, especially since my real problem was the GHC compiler and not darcs. But then, I do have my own fully functioning branch right here which I can still keep up to date by pulling down new patches from the main repository (resolving any conflicts if they arise). In fact, a couple of new patches were added to the repository, and I just did:

  darcs pull

within my own repository and it interactively asked me about applying each patch in turn (I could have had it not ask), applied them, and I recompiled — no problem, no headache.

That was quite nice to know. Fortunately, I did manage to get a working version of GHC compiled on my machine (with a little baby-sitting during the compile), thereby solving my real problem and allowing me to unpull my specialized patch from my repository. Cool.

In reworking the code section of this site, I decided to make the few small Ruby and Perl projects currently there available as darcs repositories (along with tarballs).

A couple of other darcs features:

  • atomic commits
  • file and directory moves handled
  • token-replace patches
  • symmetric repositories (full darcs power in any copy)

But the number one feature I like is that it is damn easy to use without sacrificing power.

However, it’s not all roses and there are a couple of caveats:

  • a repository costs 2 source-trees plus in disk-space (at the present time — though hard-linking is done when possible between copies on local filesystems, and besides, diskspace is cheap)
  • Large source trees with many changes can be slow to fetch, and require lots of memory (but memory is cheap too).
  • Really complex merges may take a long time (exponential algorithm).

Work is being done to address the above issues, and in the meantime, darcs is cetainly capable of handling small to medium projects (say perhaps, into the 10’s of thousands of LOS[1] range). Darcs is self-hosting and runs some 28,000+ LOS.

FeedBack

__END__

  [1] LOS = Lines Of Stuff

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Embed a MicroBrowser on Your Webpage» Siaris.net
byline: Andrew L. Johnson

Browsers can display webpages, and now webpages can display browsers (which can display …).

For a quick demo, I created a Ruby mashup of a different sort (javascript required) — one webpage displaying four embedded bitty browsers, each an independent, functional browser. Each is initialized with a different Ruby feed. Kind of cool, really … and its even possible to have a bitty browser in a bitty browser (though the recursion isn’t infinite).

I was thinking this would be a dead simple way to add a "Recent Posts" sidebar, just slot in a bitty browser with my site’s rss feed. I’ve even got a couple different layouts that work pretty well — but the bitty browsers themselves are, imho, ugly; so for now, those layouts are staying in my development pool.

__END__


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Do NOT Reverse Lookup» Mike's Weblog
For all of you that experience slowliness with any type of application that uses sockets in Ruby (e.g. WEBrick), try this:
  Socket.do_not_reverse_lookup = true

I’ve now enabled this by default for my Wee::WEBrickAdaptor class, which results in a huge difference in performance.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Comparing the underlying models of Wee and Rails» Mike's Weblog
I’m trying to marry my child Wee with some of Rails features, mainly REST-like, pretty URLs. But before, I have to understand the differencies in how they work.

Disclaimer: This is my understanding of how Rails work. I might be wrong.

Rails

Rails model is very simple compared to that of Wee. The controller class and the method to invoke is extracted directly from the URL. For example:

  /blog/show

would invoke BlogController#show. Now imaging the following URL:

  /blog/show/4

This would invoke BlogController#show with @params = {‘id’ => 4}. I don’t know how Rails knows that 4 maps to the ‘id’ key, but that’s another story.

So you have these parts of a URL:

  /controller/action/arguments

In Rails, there’s also no (conceptual) distinction between performing an action and rendering, as is the case in Wee. Both are inseparable from each other (in Rails).

Another difference to Wee is, that the controller classes are stateless, and instances of it might be reused (pooling). On the other hand this implicates that you can’t store information inside a controller instance across requests.

Wee

In Wee, we differenciate between an action phase, where callbacks are invoked and as such possibly modify the state of components, and a render phase, which ideally is side-effect free and whose sole purpose is to render the component to HTML (or whatever format you like).

Imagine you look at a simple Wee application which displays an HTML anchor tag. If you click on that anchor, you’ll trigger an action phase, which eventually will find the registered callback associated with the anchor you have clicked on and invokes it. At the end of the action phase, Wee will forward you to a new (automatically generated) URL, which when requested by your browser, will trigger the render phase. This in turn renders the whole component tree. "Why redirect", you might ask. Well, this simply avoids that the same callback will be invoked again if you hit your browsers reload button. Whenever you hit on reload, this will only trigger a render phase event.

Additionally, at the end of each action phase, a snapshot of the component tree is taken, so that you can go back to older states (called back-tracking). The information about which state of the component tree we refer to, is stored as page_id inside the URL. This page_id increases whenever an action phase is performed.

So, an URL in Wee basically consists of the following parts:

  session_id page_id [callback_id]

where callback_id is optional. If it is given, the URL triggers an action phase. Otherwise, a render phase.

Compared to Rails controllers, Wee’s components are composites, meaning that they may contain sub-components which itself might contain sub-components and so on. And in Wee there’s only ever one root component, whereas in Rails there are usually multiple controllers. All this makes it nearly impossible to have REST-like URLs in Wee. Also due to the reason that a sub-component cannot be rendered on it’s own, whereas a controller in Rails builds a whole page. So it does not make sense to have URLs in Wee like:

  /1.2.3
  # == @root_component.children[1].children[2].children[3]

Marrying Wee and Rails aproaches

The concept of multiple top-level controllers can be easily added onto Wee by using the following RootComponent class:

  # NOTE: not fully functional code!

  class RootComponent < Wee::Component
    def initialize
      super()
      @controllers = {
        'blog' => add_child(BlogComponent.new),
        'list' => add_child(ListComponent.new)
      }
    end

    def render
      controller = # extract information from URL
      r.render @controllers[controller]
    end
  end

This RootComponent merely acts as a dispatcher. It looks at the URL and extracts the desired controller out of it and then forwards to it.

Likewise, we could map the Rails action part (the "show" in "/blog/show"), to invoke render_xxx (e.g. render_show) of the controller-component (I use this term now, to distinguish it from a "regular" Wee component and to mark the similarity with a Rails controller):

    def render
      controller = # extract information from URL
      action = # extract Rails action part from URL

      component = @controllers[controller]

      component.with_renderer {
        component.send("render_" + action)
      }
    end

And even further, we could also extract the additional arguments of the URL for use inside the called render method. We could use a custom parse_arguments method here in each controller-component.

Now lets look at a simple example:

  class BlogController < Wee::Component
    def parse_arguments(str)
      # for /blog/show/5, str would be "5"
      @params = ...   # e.g. {'id' => 5}
    end

    def render_show
      entry = BlogEntry.get(@params['id'])
      # render it
    end

    def render_list
      BlogEntry.find_all do |entry|
        # render it
      end
    end
  end

What else would be needed is to tell which controller/action pair should be used. This could for example be specified each time when generating an anchor or form tag:

  r.anchor.controller('blog/show/5').callback { .... }.with('show')

Note that this would first invoke the callback and then render ‘blog/show/5’. Of course you could ommit in this case the callback. But specifying the controller/action pair each time is tedious, as this would have to be done in each sub-component, too, which completely breaks the concept of a component. So the second approach is much better:

  r.anchor.callback {
    ... do something
    request.controller = 'blog/show/5'
  }

where the request.controller setting is carried inside the URL as long as you assign a new value to it.

Note that you can still use sub-components with this approach, but they would no longer be subject of REST-like URLs.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Chicago RailsEdge Sessions Posted» { | one, step, back | }

Rails Edge

I’ve been meaning to post about this for a couple of weeks, but with everything going on, there just didn’t seem to be time.

Here’s the news. Registration is open for the next RailsEdge conference in Chicago (August 23-25). Mike and Nicole have posted the session list for Chicago and there are some really great talks lined up for this time around, including a number of new talks that we haven’t done before.

New talks

Chad Fowler will be speaking on ”Quick and Clean: Well-Factored Rails”. I really like the emphasis in the Rails community on keeping your code clean (and still beating everyone to market).

Stuart Halloway is adding a talk on Domain Driven Design. Good design is critical to producing a system that flexible and maintainable. Looks like Stu is going to give us the goods on how to do just that.

Justin Gehtland will be talking about JRuby. I was in the JRuby tutorial at RailsConf and the JRuby guys are doing a bang up job of bring JRuby up to speed as a solid platform for rails. If you are in a place that already has Java deployed, then deploying a Rails app has suddenly become as easy as dropping a WAR file on the server. Cool stuff.

And it looks like I will be able to reprise my ”DSL: Speaking the Lingo” talk from RubyConf a couple years ago. If anything, the DSL story in Ruby has gotten even stronger than before. And in addition to juggling and Rubiks Cube from the original talk, I have a little extra surprise just for the Chicago crowd.

New Speakers

In addition to all the new talks, we have several new speakers featured at the Chicago venue.

Ezra Zygmuntowicz will be speaking on ”Mongrel: Learning how to walk the dog” and ”Xen and the Art of Rails Deployment”. Deployment issues seemed to be at the top of the list of concerns at RailsConf and Ezra will help set us straight.

At past RailsEdge conferences, the feedback was strong about having more coverage on the topic of testing. So as not to disappoint, we will have David Chelimsky talk about ”RSpec: Behavior Driven Rails” and Mike Mangino will cover ”Testing in the Real World”.

See you there

That’s just the new stuff for Chicago. We still have a great selection of topics from previous RailsEdge conferences. See the current schedule for a complete list of topics.

All in all, it looks like a really great lineup of speakers and topics. I hope to see you there.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 By way of Introduction» David Naseby's World

Welcome to my blog, dear reader. I can only assume that you are going back over the archives, searching desperately for something interesting, or you are some poor bastard who had the site foisted upon them by me personally. Either way, well met. Hopefully one day this will be an interesting place.

But first, thanks and acknowledgements. The blog is, at this time, powered by the unfortunately named diaria, by ozten. Its powered by Ruby, which is a language that will probably get some airtime on this blog. The site design was a homage of glish.com's css site. By homage, I mean direct ripoff, of course.

Diaria is convenient for me, as I have nothing active that I can play with on the server, so client-side generation is a must. Its a very pragmatic little program - spartan, even. I tried to write my own several times, but kept on coming back to diaria as the simplest thing that could possibly work. And I need something to get me writing, even if there is no audience. Here it is. Hopefully, there'll be more coming.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Booting FreeBSD from external USB harddisk (without USB BIOS) » Mike's Weblog
I got my external USB-connected 300 GB Seagate harddisk today. The first thing I tried was to install FreeBSD 6.0 Beta-1 on it. I quickly recognized that my BIOS would not recognize the USB-connected harddisk to boot from. After some research I found this workaround:
  1. Boot from FreeBSD 6.0 CD-ROM.
  2. Escape to the boot loader and type set boot_askname.
  3. At the "mountroot>" prompt type ufs:da0s1a

And voila, it boots from the root partition of the first slice of da0. Note that the kernel will be loaded from the CD-ROM and not from the USB harddisk.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Bloom Filter» Siaris.net
byline: Andrew L. Johnson

I was recently looking up something in Knuth’s TAOCP vol. III, 2nd ed. and I came across mention of Burton H. Bloom and his data structure for set membership queries that now carries his name: Bloom filters. This structure has seen something of resurgence in the past few years, so I thought I’d contribute my own explanation and implementation.

Superimposed encoding techniques on secondary keys (attributes) had been around for quite some (manual card filing systems for example) when Bloom, in 1970, published an article that basically turned the idea on its side by considering an entire dataset as one record and the primary keys as the attributes. This provides the basis of a relatively compact structure (an m-bit field) that allows for fast membership queries on the primary with a probabilistically controlled rate of false positives.

What does that mean? Let’s start with something a little more concrete. We can simulate the stucture with a hole-punch, a strip of paper, and a Ruby irb shell open (to calculate a few numbers for us).

Let’s assume I want to make a set consisting of the names of myself and my three brothers: Andrew, Bradford, Gregory, and John. I can take a strip of paper with 12 small circles drawn on it numbered from 0 to 11 (this is a 12-bit field).

For each name, we will calculate two identifying numbers between 0 and 11 — for the purposes of this little simulation it will suffice to use Ruby’s String#sum and String#hash methods and use the modulo operator to reduce these to numbers between 0 and 11. For example, the two identifying numbers for my name in this situation are:

  "Andrew".sum  % 12    # => 9
  "Andrew".hash % 12    # => 7

We generally refer to such operations as hashing operations or functions — so our example is using two hashing functions. To add my name to the set, I just use my hole punch to punch out those two circles in the strip of paper:

And continuing by hashing Gregory, Bradford, and John we get

  "Bradford".sum  % 12    # => 0
  "Bradford".hash % 12    # => 5

  "Gregory".sum  % 12     # => 3
  "Gregory".hash % 12     # => 9

  "John".sum  % 12        # => 3
  "John".hash % 12        # => 4

And after a bit of hole-punching (some holes will have already been punched and that’s expected) we arrive at this strip of paper which represents our loaded Bloom filter:

Now, if I want to see if any old Tom, Dick, or Harry is in the Johnson Gang, I just calculate the 2 hashes for that name, punch out those two holes in a new strip of paper, then line it up with my master strip (the Bloom filter) and see if both holes align with existing holes in the master strip.

As we can see, neither Tom nor Harry are in the gang because at least one hole in each person’s strip doesn’t match up with a corresponding hole in the Bloom filter strip. However, Dick’s name just happens to hash to two holes in my Bloom filter. This is the false-positive problem mentioned earlier. In fact, using a 12-bit field to store 4 items by setting two bits per item results in a false positive rate of approximately 25%. Reducing this false positive rate is accomplished by increasing the size of the bit-field and utilizing more bits per item. For example, to get the false positive rate down to 10% we could use a 20-bit field with 3 hashes, and to reach 1% we’d use a 39-bit field and 7 hashes.

The way the math falls out for optimum performance with a given set size n and an acceptable rate err of false positives is to calculate the size of the bit-field and number of hashing functions as follows:

  m = (n * log(err) / log(1.0 / 2**log(2))).ceil
  k = (log(2) * m / n).round

Where m is the size of the bit-field and k is the number of hashes to use. So, for example, given n = 1000 here are a few data points for various error rates just to get a general idea of the relationships:

         err      m      k

        0.25     2886    2
        0.10     4793    3
        0.01     9586    7
        0.001   14378   10
        0.0001  19171   13

One of the assumptions is a good set of hashing functions — and MD5 or SHA1 (with various salts) are common choices — for a good random distribtion of the k-bits per key. However, a recent paper demonstrates that distributing k-bits using only 2 hashes and a simple cycling algorithm can achieve results comparable to using k high-quality hashing functions. This can lead to definite speedups as k grows and numerous keys are checked against the filter.

My Ruby implementation utilizes the above mentioned algorithm — the core of the implementation resides in the private bits_on method which takes a key and computes two hashes (aka MD5 digests) and then cycles through k bit positions yielding each position in turn. The add and has? methods call bits_on and supply blocks to set or test the bit positions respectively:

  def add(*keys)
    keys.flatten.each do |key|
      raise RangeError, "Too many keys" if (self.nkeys += 1) > capacity
      bits_on(key) {|pos| self.bv[pos] = 1}
    end
  end
  alias :insert :add

  def has?(key)
    bits_on(key){|pos| self.bv[pos] == 1 or return false}
    true
  end

  # yields each bit-position for a given key
  def bits_on(key)
    pos1, pos2 = salts.map{|s|Digest[s + key.to_s].hex % bits}
    hashes.times do |i|
      yield pos1
      pos1 = (pos1 + pos2) % bits
      pos2 = (pos2 + i)  % bits
    end
  end
  private :bits_on

On a simple test using a smallish dictionary of n = 38619 words and a false-positive rate of err = 0.0001, this implementation was better than an order of magnitude faster than the pre-existing Ruby version or the Perl version from which it was derived. I’ve run a number of ad-hoc tests and confirmed that the false positive rate does not appear to be affected by the dependency introduced in the k-bit positions.

Traditionally, Bloom filters were used in memory constrained applications, such as a spell-checker when available RAM couldn’t hold a dictionary of appreciable size. More recently, Bloom filters have found uses in network routing, cache-summary, and peer-peer applications (see this survey article, or read about loaf for a more specific example).

Further Resources

Here are a few further resources — my implementation drew heavily from the C# version given in the literate programming example at the end of the following links:

Feedback

__END__


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Another Rake Tutorial» { | one, step, back | }

Greg Pollack has written a Rake Tutorial.

A Rake Tutorial from the “Rails Guy”

Remember this (and this, this, and this)?

Gregg Pollack (the “Rails” guy in the above videos) has written a delightful little rake tutuorial that you might enjoy. You can find the tutorial at http://railsenvy.com/2007/6/11/ruby-on-rails-rake-tutorial.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 plist.xml parser for Ruby» not another ruby framework
To help with my AlbumData.xml parsing, I've thrown together a plist parser for Mac OS X plist.xml files. Api documentation: Plist::parse_xml( plist_xml_filename )

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 meat and gravy» not another ruby framework
In the other half of my day, I am a painter. For about half of a year, I've been capturing snapshots of my work on some digital prints. I've been just showing these running down a page, but I haven't been happy with it:

http://hexane.org/slider/artwork-old.html
Last night I pulled this work together using dHTML:

http://hexane.org/slider/artwork.html
The programming is nothing too exciting: script.aculo.us is cool, browsers are still annoying, but all it takes is a few hours of fiddling.



The insight for me was: given interesting enough data (meat), all you need is an evening of whiz-bang javascript (gravy) to put together something nifty.



Of course, if you prefer the running-down-the-page version, let me know. That way, I can go to bed earlier tomorrow night :-)

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 iPhoto2» not another ruby framework
Just released a library for parsing iphoto databases:





gem install plist

gem install iphoto2



iphoto = IPhoto2.new # path to AlbumData.xml is optional

iphoto.albums.each do |album|

album.each do |image|

puts image.path

end

end





There's more, but I'm tired now.



Update: oylenshpeegul pointed out a bug in the comments, I've put out another gem (iphoto2-1.0.1) to the problem with the Album#each. And he is correct, there is an Album#images accessor.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 iPhoto 2 database format» not another ruby framework
~/Pictures/iPhoto Library/



2006/01/07/fallow_keep.png.450x450.2005-12-04.jpg
original image


2006/01/07/Thumbs/7.jpg
a thumbnail


AlbumData.xml
plist file with all the goodies


Dir.data
binary


iPhoto.db
binary


iPhoto.ipspot
text, perhaps for spotlight indexing?


iPhotoLock.data
blank at the moment


Library.iPhoto
binary


Thumb32.data
binary


Thumb64.data
binary


ThumbJPG.data
binary






I kept the library pretty simple, to show the structure:





{

"Application Version" = "5.0.4 (263)";

"Archive Path" = "/Users/username/Pictures/iPhoto Library";

"List of Albums" = (

{

AlbumId = 999000;

AlbumName = Library;

KeyList = (7);

Master = 1;

PhotoCount = 1;

PlayMusic = YES;

RepeatSlideShow = YES;

SecondsPerSlide = 3;

SlideShowUseTitles = 0;

SongPath = "";

TransitionDirection = 0;

TransitionName = Dissolve;

TransitionSpeed = 1;

},

{

"Album Type" = "Special Roll";

AlbumId = 999001;

AlbumName = "Last Roll";

"Filter Mode" = All;

Filters = ({Count = 1; Operation = "In Last"; Type = Roll; });

KeyList = (7);

PhotoCount = 1;

PlayMusic = YES;

RepeatSlideShow = YES;

SecondsPerSlide = 3;

SlideShowUseTitles = 0;

SongPath = "";

TransitionDirection = 0;

TransitionName = Dissolve;

TransitionSpeed = 1;

},

{

"Album Type" = "Special Month";

AlbumId = 999002;

AlbumName = "Last 12 Months";

"Filter Mode" = All;

Filters = ();

KeyList = (7);

PhotoCount = 1;

PlayMusic = YES;

RepeatSlideShow = YES;

SecondsPerSlide = 3;

SlideShowUseTitles = 0;

SongPath = "";

TransitionDirection = 0;

TransitionName = Dissolve;

TransitionSpeed = 1;

},

{

"Album Type" = Regular;

AlbumId = 9;

AlbumName = "An Album";

KeyList = (7);

PhotoCount = 1;

PlayMusic = YES;

RepeatSlideShow = YES;

SecondsPerSlide = 3;

SlideShowUseTitles = 0;

SongPath = "";

TransitionDirection = 0;

TransitionName = Dissolve;

TransitionSpeed = 1;

}

);

"List of Keywords" = {};

"List of Rolls" = (

{

"Album Type" = Regular;

AlbumId = 6;

AlbumName = "Roll 1";

KeyList = (7);

Parent = 999000;

PhotoCount = 1;

}

);

"Major Version" = 2;

"Master Image List" = {

7 = {

"Aspect Ratio" = 1;

Caption = "fallow_keep.png.450x450.2005-12-04";

Comment = "";

DateAsTimerInterval = 158341389;

ImagePath = "/Users/username/Pictures/iPhoto Library/2006/01/07/fallow_keep.png.450x450.2005-12-04.jpg";

MediaType = Image;

MetaModDateAsTimerInterval = 158341439.728129;

ModDateAsTimerInterval = 158341389;

Rating = 0;

Roll = 6;

ThumbPath = "/Users/username/Pictures/iPhoto Library/2006/01/07/Thumbs/7.jpg";

};

};

"Minor Version" = 0;

}


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 continuations and state» not another ruby framework
Ruby continuations have been described as "going back in time" in your program, but that's not really true. You go back into the stack, but all your state remains the same. This ruby snippet:



state = "label 1"

continuation = callcc { |c| c }

puts "state: #{state}"

state = "label 2"

continuation.call if continuation




Will produce the following output:



state: label 1

state: label 2




Note that the state variable keeps it's value. This is how you can do useful programming with continuations, even though you've jumped "back in time."



The next wierd thing, is that we don't get stuck in a loop. Notice "if continuation"? The second time we try to call the continuation, it is nil.



If you want, you can make a loop by doing the assignment inside the callcc block:



state = "label 1"

continuation = nil

callcc { |c| continuation = c }

puts "state: #{state}"

state = "label 2"

continuation.call if continuation




That will give you this output:



state: label 1

state: label 2

state: label 2

state: label 2

... (ad nauseam)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Windows Ruby FastCGI notes» not another ruby framework
Just a few notes from working on supporting FastCGI on windows:
  • fcgi.rb is not compatible with Windows.
    • Simple incompatiblities include trapping undefined symbols on Windows.
    • $stdin is not always a socket on fastcgi on windows, so wrapping $stdin.fileno doesn't work
    • libfcgi has OS dependent code to handle various windows cases

  • compiling libfcgi for windows is difficult
    • Makefiles have a few syntax errors with nmake
    • assembling a free compiler enviroment on windows is a pain
      • MS VC Toolkit
      • MS Platform SDK
      • MS.Net SDK
      • ... or buy MS Visual Studio


  • isapi_fastcgi has alternate version of libfcgi, but with Visual studio build files (.dsp)

So I guess I need to get Visual Studio to properly support Fastcgi on windows.
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 When to Repeat Yourself» not another ruby framework
Flying over the Atlantic, I wondered about the reliability of the flight progress indicators. It's so hard to integrate software. How did the engineers pass the location of the plane to one critical system (autopilot) and one trivial system (cabin TVs) while ensuring that a short or other problem with the cabin TVs didn't knock out the autopilot. My memory of the East Coast blackout lingers.



My father-in-law is a process engineer and amateaur pilot. After landing, I asked him how the engineers did it. He explained that there most likely is just a second GPS for the cabin TVs. In fact, the electrical system for the cabin is probably completely separate from the avionics. The reward of sharing one component (the GPS) isn't worth managing the additional risk of merging the circuits.



Consider the different areas of a website, and the different divisions of a company. It isn't always worth allowing the marketing department to take risks that affect fulfillment. Especially if the code between business units is straightforward:

def fullname; firstname + ' ' + lastname; end
Having 2 copies of the above code doesn't hurt anyone.



Furthermore, given:

  • one web domain is one business
  • the one web domain is handled by one web application
  • that business employs a full time programmer
  • on some regular schedule, that programmer releases code to production
  • it is impossible to catch all bugs

On some regular schedule, the entire website is at risk. It frightens me -- the entire business as a single (failure prone) application.



On the other hand, if these are given:

  • the website is split into 5 web applications
  • on some regular schedule one of the web applications is updated
Then only 1/5 of the website is at risk at a release point. Even better from a risk management perspective, given this environment:

  • 500 unlinked php/coldfusion/asp scripts
Each update only puts one small fraction of the site at risk. My point is not that the 500 scripts is the optimum solution, but that linking code also links risk.



In my view, linking code is a bet that the benefits will outweigh the risks. There is nothing wrong with taking risks, but sticking to a simple rule like "Don't Repeat Yourself" can obscure the bets being made.



It is worth knowing when you are standing on the shoulders of giants, and when you are standing on thin ice.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 What's Wrong with Ruby? Hah Yeah, It's Me!» RedHanded

In an article posted entitled What’s Wrong With Ruby?, the author cites me as one of the main problems:

If I was put off Ruby by the hype, I was put off more by the many cutesy introductory tutorials I encountered when trying to get into it. Why’s (Poignant) Guide is a particular horrid example… I don’t want someone chatting away to me and telling me how “cool” it all is (I’ve lived long enough as a computer programmer to know it’ll never really be “cool” to be one). I just want the straight facts, plainly put.

These are such great points and so well-put. See, actually, I’ve known since birth that I’m a problem, so this is no surprise to me. As a child, I caused a giant meadow fire that all the dads had to go fix! Also, I broke a statue! And now I’ve ruined Ruby. Uh. Oh.

If I may build on his argument for just a sec.

The problem here is: the author of the article is trying to do academics, to gain knowledge, to build a career. And my cartoons and stories have patronized him, belittled him, by treating him as if he wasn’t a real professional. This is a terrible breach of conduct. He has accolades innumerable. He has done no small deed. His peers are all gathered around him, wishing him the best and swelling with nothing but respect and esteem for him. NOW WHAT IS THIS CARTOON BOOK DOING HERE??

Programming is for world commerce. It is like agriculture or fossil fuels. It is lot a like baling hay. I’ll give you an example: You wouldn’t write a cartoon book with a plot and running narrative just to show a guy how to bale hay! That would frustrate the guy! He would throw that book in the pig’s pen! He just wants to get straight to the nitty-gritty and, for once in his life, just bale hay, straightway!

Fortunately, as I’ve mentioned before, I have a strong feeling that I will die young without artifact. That I will make no lasting impression. This will be my avenue. So hold your horses, I just have a few more things to do in life and I’m sure I’ll be out of your hair.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Try It» Glenn Vanderburg: Blog
Two of my best friends in the Ruby community have suddenly gone all nyah nyah on us, and it’s time for a bit of reality. Neal Ford says static typing is communist bureaucracy, and Stuart Halloway (presumably trying to tone things down a bit) says it’s more like training wheels.

Being intentionally provocative to knock people out of old assumptions is all well and good … but even though I love Ruby, and am so glad to be working in it now after 11 years of Java, my perspective is more pragmatic.

There is no perfect world. You gain a lot by giving up static typing for dynamic typing, but you also give up some things. It’s six of one, a half-dozen of the other. Or maybe 9 and 3. Whatever. Whether the tradeoff works in your favor depends on a lot of things — the kinds of systems you’re building, the process and practices you use, how well you understand your domain, and other things. And folks like Tom Ball make great points when they point out some of those tradeoffs.

(Furthermore, "static typing" doesn’t necessarily mean "Java-style static typing." It’s just that the industry right now is all wrapped up in static typing done the wrong way, while ignoring static typing done the right way.)

In spite of all that, though, I do agree (mostly) with Neal and Stu. I, too, would rather write Ruby in vi (er … that is, emacs) than Java in IDEA.

If you’re still on the fence about this, or even downright skeptical, here’s my advice. Having been a static typing bigot for a very long time, I know all of the arguments from that side. I used them myself. And what I’ve learned is that you can’t figure this out by thinking about it. There are things about dynamic programming languages — and about how programmers work in those languages, and how systems are designed in those languages — that you don’t really understand until you’ve gained some real experience. It’s the Blub paradox at work. Knowing about the flaws in the language isn’t enough either. What’s important is knowing when they bite you, and how badly, and what you have to do to stay clear of them. Primitive types in Java represent one of that language’s worst flaws, but in my many years of Java programming I was impressed by how rarely they really got in my way. (They did get in my way, but not as much as I expected them to when I first learned Java.)

So just give Ruby (or Groovy, or Python) a try. Find a way to build a system of some reasonable size (a few thousand lines or so) in it. Give yourself time to get over the learning curve of syntax and names, and learn to think in the language. Decide based on experience, not fear or doubt.

Our field is at its worst when we act (when we teach, design, manage, plan, argue) as if we’ve got it all figured out, as if we’ve got it down to a science. Nothing could be further from the truth. Our field is one of creativity, experimentation, guesswork, hunches, and feedback. Above all, feedback.

Nothing blinds us and deafens us to feedback like being convinced we’ve found the one true way.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Original Fifty» RedHanded

Over the last two months, I have met a small group of friends online who helped me out with a new program. The fifty people in that group have made my life soooo wonderful!!

Brian DeLacey, who started teaching 3 of his kids to program and kept detailed notes on their good and bad times.

Leslie Wu, who has been all over FFSandbox and Hpricot. I am amazed by how she can look in any direction and then do exactly what she wants in that direction. I repeat: she’s been hacking the sandbox for me!!

RSL, who’s been a regular around here, was one of the 50 and I really like his Hacky Mouse kaleidoscope.

Harold Hausman, who started LittleCoder and hung out in the group to offer encouragement and ideas—we’re going to team up soon, Harold!

And I still gotta dig up some links for the rest of these folks. (Eli?)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Limits to Scaling Ruby» not another ruby framework
When discussing whether a web technology "scales", usually the conversation alternates between two basic questions:

  1. Does the implementation perform acceptably? Does it continue to perform acceptably as load is increased in orders of magnatude?
  2. Can the implementation be maintained and enhanced?
To show that a technology "scales", one must illustrate how both questions can be answered at the same time without sacrificing one for the other.



The simplest way to run Ruby from a web server to use CGI. Unfortunately, with CGI applications each additional request loads a new interpreter with a new instance of the program. This leads to the notoriously bad performance of CGI under increased load.



Ruby has several ways of serving web pages which offer better performance:

  • mod_ruby: embeds the interpreter into the Apache server
  • fastcgi: using the FastCGI protocol, scripts run in a loop and hang around to serve multiple requests
  • webrick / mongrel: 100% ruby web servers. Often these are integrated with a major web server like Apache or IIS via proxying.
Note that each of these implementation persists an interpreter across requests:

  • mod_ruby: one interpreter per Apache process
  • fastcgi: one pool (1-10) of interpreters per script
  • webrick / mongrel: one interpreter per "site", but different proxying strategies can lead to the interpreter being shared in various ways.

When the same interpreter is used across different requests, there are important consequences to the programmer:

  • require 'lib'

    The first call is processed, and the rest are skipped. If you are dynamically adjusting your load path, the question becomes: Which 'lib' was loaded?



  • overloading core methods

    Can one be sure that adjustments to the Array class are ok for every instance of an Array on the site?



  • global variables leading to memory leaks

    If it is possible for variables to be referenced between requests, these references can prevent garbage collection and lead to memory leaks
These concerns illustrate that when scaling ruby, your scripts have become an Application [1]. They also illustrate the difficulties that ISPs face when hosting Ruby, since for security reasons an ISP must force "Share Nothing" behaviour between users.



Scaling Ruby to provide performance forces a change in development mentality. This transition from writing scripts to writing applications increases the cost of maintenance. For this reason, I do not think that Ruby scales on the Web [2].



Luckily, I consider this to be a failure of the current Ruby web implementation, not a fact of the web development problem space. We have examples which can be followed.



The commercial web scripting languages (ASP and ColdFusion) allow casual "scripts" to perform well. A bit more useful example, PHP has implemented a web scripting language which performs acceptably without requiring developers to go into "Application Mode."

  • All caching is performed by the implementation under the covers. It is impossible for hosted code to share anything between requests.
  • Every request is given a fresh and identical operating environment, regardless of webserver.
It's worth dwelling on PHP for a moment longer. In PHP, it is possible for a novice to deploy multiple large-scale multi-developer projects (PHP-BB, WordPress, Drupal) on the same $4/month shared hosting environment.



It is imperative for the future of Ruby that we recognize how the implementation of PHP has lead to dominance of the Web scripting market [3]. Ruby must outgrow its Perl roots and discard the notion that large-scale web programming requires the "sobriety" of Application development.





Footnotes

  1. Note that the change in developer mentality has also been observed in mod_perl development.
  2. There's another insiduous property to Ruby's implementation. Not only does the implementation push developers to think in Application Mode, it also pushes developers to choose one Application Framework per web server. The forthcoming arguments of Rails vs XXXX vs XXXX will be a waste of time.
  3. Even though the (easy) comparison to Java is a seductive angle, it is important to note that every other environment also shines when compared to Java. Tcl, Python, and now even mod_perl are niche markets. Ruby will remain a popular novelty unless it compares itself to the real competition.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 The Hpricot and Sandbox Mailing Lists» RedHanded

I know a lot of you have questions about how to use Hpricot. And I’d like to start helping with that a lot more. For example, did you know that XML files should be loaded with the Hpricot::XML() method? Oh, hey, that’s handy, right? That skips Hpricot’s HTML clean-up stuff.

So, I’ve started lists for both Hpricot and Sandbox, since both have had lots of good activity over the last little while.

To join:

  • Send a message to hpricot@code.whytheluckystiff.net.
  • Cc: why@whytheluckystiff.net.

For sandbox, the e-mail address is sandbox@code.whytheluckystiff.net. Please come along!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Textmate Footnotes» Glenn Vanderburg: Blog

For a while now I've been using Duane Johnson's TextMate Footnotes plugin with my Rails development. It's been the biggest boost to my productivity since I started using Rails. I kind of assumed that most Rails developers were using it, but apparently it's not as widely known as it should be.

I first learned about footnotes from Geoff Grosenbach, when he interviewed me last year for the Ruby on Rails Podcast. Geoff mentioned that it links lines from a Rails stack trace (displayed in the browser in development mode) so that clicking will open the appropriate file in TextMate, positioned to the correct line. Nice!

TextMate Footnotes links stack trace lines back to TextMate.

But it does more than that. When there is no error and your page renders correctly, the plugin adds "footnotes" to it: a little div at the bottom of the page with useful features for development and diagnosis:

TextMate Footnotes provides links to edit crucial files, and in-page diagnostic helps.

You can show the contents of the current session, current cookies, the parameters passed to the controller, and the last 200 lines of the Rails log. But the most useful things are the links that ask TextMate to open the controller, view, layout, and other important files that Rails used to build that page. (It only does all this when the app is running in development mode, of course.)

If you're doing Rails development on OS X, install it this way:

$ script/plugin install -x http://macromates.com/svn/Bundles/trunk/Bundles/Rails.tmbundle/Support/plugins/footnotes

If you aren't on OS X, I know there are ways to define URL schemes like the "txmt" scheme TextMate defines on OS X. What are you waiting for? Arrange for "txmt:" URLs to open your favorite editor appropriately, install footnotes, modify it (to remove the "only on OS X" code), and have fun!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Tell Me the Hashing Dangers» RedHanded
 class Symbol
 def hash; to_s.hash; end
 end

Someone explain why not.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Stream Copy YouTube, Revver, Etc.» RedHanded
Click here to bookmark this link.Channel Image19:16 Rubinius and Its Helpful Dev'il» RedHanded

Whoa, the rubini.us site is all fleshed out with forums and a wiki and the like.

What is Dev’il? The excellent Beast forum extended with tickets, pages, and source code changes.

What a fantastic little spook. Here’s Brian’s list of upcoming features.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Rehash of scaling limits discussion» not another ruby framework
This is a rehash of something I've written before, but I keep returning to this issue.



I wrote this in response to the ongoing post about PHP. This is in follow up to the pro-PHP rant closing the discussion.



Harry Fuecks is on target when he points to the execution model, but I think I can get more specific about two ways that PHP's execution model has made it successful:

  • Cheap Hosting (a short point)

  • It's Still a Scripting Language (a longer point)
Cheap Hosting



Fuecks points out how the execution model eliminates hard to debug user land memory leaks. He also points out how this makes PHP servers easier to administer.



I'd like to also point out that execution model has no dependency on a particular web server scaling model. This allows PHP to be ported to almost every existing web server.



By making PHP an easy business to manage, and by eliminating server/os specific niches in the hosting market, PHP hosting has become a cheap commodity. It's basically free.



It's Still a Scripting Language



Moving on to the rant. Basically, I'd like to raise awareness of this single point:

Scope management is as important as dynamic typing in the development of general purpose scripting languages.
Because I would really like to ruby online, but the architecture insists that I write fire breathing applications rather than the simple pet scripts that I prefer.



Aside from dynamic typing, I believe that the most distinctive feature of general purpose scripting languages (perl, python, ruby, etc) is the support for writing programs of a limited scope. I can write a script confident that it will only affect the problem at hand. For all inputs? Who cares, it only needs to work for this input.



Using ruby as my most familiar example, in a basic command line script I have a range of scopes available:



+ Create a ruby file (script)

+ Dynamically decide how to setup globals (per invocation)

+ Require a library in my home directory (user)

+ Use some standard libraries (ruby)

+ Install some gems (machine)



Just by installing ruby I can write little scripts focused on my problem while leveraging shared code from the larger community. And I am in control of when I pull in successively "more" global code.



But when I go online, I lose some of this control. The most common means of scaling general purpose scripting languages is to simply span the interpreter across multiple requests (with various tricks). I believe that this lazy route causes a loss of "scripting language" features. Continuing to use ruby as an example:



CGI: Create an interpreter per invocation



CGI has the same available scopes as the home directory, except that even a trivial web site will cause more invocations than one would see with a commandline script. It doesn't matter that I still have all these scopes available because the server dies of load.



FastCGI: Create 1 to 10 interpreters per script, reuse the interpreters



- limit on the number of scripts

All those interpreter instances will consume between 5 and 10 megabytes of memory. That overhead can add up, and is enough to discourage me from creating many scripts. Unfortunately, this loses a nice feature of scripting -- the ease of forking.



- per invocation scope lost

I get to worry about memory links since the interpreters are re-used. Another feature of scripting lost. Plus, I can't do any dependency injection tricks b/c I need to be careful about setting globals per invocation. This is 'free' in PHP and in commandline ruby, but for ruby online it's another feature of scripting lost.



Mod Ruby: Create 1 interpreter per web server process



- script scope lost

- per invocation scope lost

- user scope lost



Mod Ruby is quite bloody. Since the same interpreter is used across any requests to the web server, you lose scopes smaller than the machine. All development happens at the scope as the web server, which is usually on the machine level. You have the memory leak / globals issues of FastCGI made worse by the fact that now unrelated scripts will interfere with each other.



This doesn't sound like scripting at all to me :-)



Conclusion



As far as I'm concerned, ruby is not a web scripting language. Neither is perl, python, or tcl. Once used online, scaling these languages turns them into a variant of SmallTalk, i.e. a dynamically typed systems language. PHP is the only open source scripting language of which I am aware.



It's worth noting that Coldfusion (another horrid language with in-comprehensible success) does a good job of separating requests from each other. While there is a less than obvious auto-include of application.cfm files, requests are independent.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Random Number in a Feed (for Pipes Maybe?)» RedHanded
Click here to bookmark this link.Channel Image19:16 Okay, Which Browser Will Run This Code and Can You Get It Going?» RedHanded
Click here to bookmark this link.Channel Image19:16 Math (Eww?)» RedHanded

aparrish: How can you find fault in a programming tutorial that teaches you how to make a blog before it teaches you how to do arithmetic?

AtDuskGreg: So many people drone on boringly about how important it is for kids to learn computers, only to come up with curricula that focus on using a spreadsheet or writing a resume.

Paul Robinson: The first book I ever read on programming was on BBC Basic and was illustrated with pictures of robots in factories pretending to be FOR loops.

I have a solid four years of work ahead of me on Hackety Hack, which is in my mind a very primitive tool, but hey the discussion is igniting. And among people who I haven’t encountered before, yeahhh!! One common theme is: where do you start teaching someone? (Brian D. pointed out Constructivism on the HH mailing list.)

I’m not really sure, actually. Who really knows if H-ety H goes about things in a sensible way. I was a very bad student myself and am often occupied with ideas which are widely acknowledged as ill-conceived. So, today, I’m surprised at the feelings of goodwill pouring in for Hackety Hack, but I suspect waves of criticism are forthcoming, which will be quite stimulating indeed.


I designed HH with two of my very good friends in mind, Oliver Mooradian and A. Woolsey. The second friend, A., was taking a university beginning Java class. The culminating exercise of his class was to read a comma-separated address book into memory. His program was nearly one-hundred lines long. And he wrote it knowing that he would never use it again. As a reminder: it is the year 2007.

I didn’t think I had many strong opinions about the way things should be. But this infuriated me!! This is not programming!! It should not be acceptable in 2007 for students to write a program which isn’t somehow useful to them. Not when we all use computers and are already employing micro-hacks (emoticons, bbcode, email addresses, etc.) everyday.

A. was also subject to a lot of mathematical programs: drawing circles, computing distances, a lot of spreadsheet-style activity. This sounds like academic drilling. Surely this can wait until after you’ve tinkered with RSS feeds and written a blog.

I can’t say, though. I personally only really use math for pagination and pointer arithmetic. Tell me: are math and programming intertwined much these days??


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 MVC with ruby-web» not another ruby framework
You can get MVC action by combining two features of ruby-web. Before loading a page, ruby-web looks up the directory tree for an "application.rb" file. Then, in the application.rb file, you can define a Web::filter [1].



Let's use a basic hello.world.rb as an example:



#!/usr/bin/env ruby-web

puts "Hello World"



When you visit this cgi script, you'll get "Hello World". If you add this application.rb in the same directory as hello.world.rb:



Web::filter do |content|

"

#{content}

"

end



Visit the script again, and notice that Hello World is a bit louder. You can also have multiple chained filters:



Web::filter do |content|

"

#{content}

"

end



Web::filter do |content|

content.gsub(/Hello World/, "Hallo Welt")

end



Take that, Servlet API!





A few notes:



1. If you are running ruby-web 1.0.0, Web::ob_start is a more cryptic name for the exact same function. If you are running php, ob_start is also your friend :-)



2. I'm sorry that ruby-web scripts still run as basic cgi scripts. Alas, I have not yet written enough SAPI modules. One day I'll get them all done.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Know for yourself ...» Glenn Vanderburg: Blog
Greg Vaughn thinks there are only two people who read his blog. I’m pretty darn sure at least six read mine, so maybe I can quadruple Greg’s readership today.

I’m always interested in the things that other fields can teach us about my own field of programming. My blog on bridge building from a few weeks ago is one example; I also recall when Dave Thomas pointed out some relevant phrases from the U.S. Marine Corps’ document on Warfighting, and of course Dave and Andy learned about the Dreyfus Model of Skill Acquisition from reading about the nursing profession.

Now Greg’s found a delightful example from the world of woodworking. Read Greg's blog, and the short article it links to.

"So in your leisure or in your active moments, if you wish to advance, you must be alert."


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Keeping Track of Unimplemented Features» Glenn Vanderburg: Blog

I started a new Rails project last week. The customer had done an unusually good job of working out the site look-and-feel ahead of time, so my first day on the project I grabbed the HTML mockup of the first page we were going to implement and turned it into a Rails app. It was still static HTML -- there was no code at all in the application, and no database yet -- but the page was being rendered by the new Rails application. I carved the page up into a layout, main template, and appropriate partials, and got ready to start implementing features the next day.

But before I called it a day, I had an idea that seemed promising. I spent about 10 minutes (certainly not more than 15) going through that HTML looking for anything representing a feature that needed to be implemented. That meant links and buttons, plus anything that needed to be generated dynamically. Whenever I found something like that, I added a CSS class to the markup: "unimpl".

Then, using Chris Pederick's Web Developer Toolbar extension in Firefox, it became a simple matter to quickly highlight all of the not-yet-implemented features in the application:

The "Outline Custom Elements" feature in Chris Pederick's Web Developer Toolbar.

Just use CSS selector syntax in the dialog to select all elements with class "unimpl":

Choosing custom elements and outline colors in Chris Pederick's Web Developer Toolbar.

Here's what the result looks like (demonstrated with the Streamlined sample application rather than my current project):

Unimplemented features outlined in red (after manually annotating them with a ".unimpl" class).

(By the way, those features are really implemented in Streamlined; I just marked that application up as an example.)

This provides a great, easy way of keeping track of things that remain to be done. As I implement those features, I replace static HTML with generated HTML, and I just delete the "unimpl" class as I go. Sometimes I partially implement a large part of the page; in that case, I move "unimpl" from the surrounding element to the individual pieces inside that I haven't completed yet.

This is no substitute for requirements, or an issue tracking system, or anything like that. But it's already proven very convenient as I implement features, trying to decide what's next. It's particularly nice when I have just a few minutes available … maybe not enough time to tackle a big feature, but I can quickly scan to see if there are any small things I could fix.

It takes just a little bit of discipline and consistency on the part of the development team, but it was really easy to annotate that first mockup, and now that the layout and commonly used partials are done, doing subsequent mockups will be even easier.

This morning I became annoyed by the three-click process to highlight those elements using the toolbar (how lazy is that?) so I hacked TextMate Footnotes to add a quick toggle link in the footnotes div at the bottom of the page:

A hack to the TextMate Footnotes plugin adds a link that outlines elements with class="unimpl".

If you're interested in that, let me know. If it's useful to people, I'll polish it up and submit it for inclusion in footnotes.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Highlights from RailsConf 2007» Glenn Vanderburg: Blog
Chad’s opening call to change the way our community is perceived from the outside. Preach on, brother!

Hot on the heels of that, Chad strumming on his ukelele while Rich Kilmer gamely tried to deadpan through his introduction of David Heinemeier Hansson.

From David’s RailsConf keynote: "What we want to manipulate … is people." (With a little careful editing, you can turn a harmless quote into just about anything!)

Seeing Uncle Bob speak. He’s a master, and I haven’t seen him speak for about three years. The talk was about clean code, and I already understood about 48 out of the 50 minutes of material he presented—but as a speaker, watching the way he presents and works the audience is always fantastic and educational. (James' photo captures the magic perfectly.)

After being online friends since sometime in 1999 (when we met on Ward's wiki), Alan Francis and I finally got to meet in person.

Another quotable moment from David (this time with no editing required) during Alan’s talk: "People don’t stop doing stupid things because you make fun of them once."

Being blocked out of Adam Keys' standing-room-only talk. (Not a highlight for me, but I was thrilled for Adam, and it was great to see so many people interested in such an important but underemphasized topic.)

The accordion and ukelele duet.

Avi Bryant's wondefully articulated challenge for Ruby over the next few years to work toward turtles all the way down.

Ze Frank. ‘Nuff said.

My audience cheering wildly. I always thought you had to deserve something like that, but apparently you can just ask! I’ll try that again sometime. (But even though I got the cheers by cheating, it was nice to know everyone was on my side. :-)

James Adam is a great speaker, and his talk on "The Dark Art of Developing Plugins" was loads of fun.

Jeff Barczewski and Deb Lewis demonstrating MasterView at the lightning talks session. Deb told me about MasterView last year at OSCON when she and Jeff had just begun working on it. MasterView is an alternative templating system for Rails that’s HTML-centric, designed to allow page designers to use HTML editors like Dreamweaver within a Rails project. I was a bit skeptical of MasterView, because I’m most comfortable when the programmers are in control of HTML generation. But Deb and Jeff get it; MasterView works just like a Rails templating engine should. Reopen the page in Dreamweaver, edit things, save, and when you click refresh in the browser the changes are there. Great stuff.

The personal page editor demonstrated by the guys from Revolution Health. Impressive!

French programmer Fernand Galiana's "Pardon my French!" after he got a bit frustrated during his demo of the Mole plugin.

Rich and Marcel finally believing I wasn’t a werewolf.

Charles Nutter and Tom Enebo giving some really boring demos of JRuby. Boring is great for JRuby. It’s supposed to be just Ruby, on a different platform, and with Java integration that just seems natural. And it is! That was the challenge for them, to make JRuby boring, and they’ve done a great job.

Erik Hatcher’s fantastic talk about Solr on Rails, with demos of very cool things he’s doing with full-text search at the University of Virginia.

All of James' photos. He keeps getting better.

Beginning with many attendees at the Pragmatic Studio’s introductory Guidebook tutorial (but continuing throughout the week), the Ruby community raised (at last count) $26,000 for some excellent causes. (Update: over $33,000!)

Finally, Dave Thomas’ closing keynote was the perfect finish. Thanks so much, Dave.

But of course, at all of the really good conferences the best things happen in the halls and over lunch and dinner. I had the pleasant privilege of chatting with loads of great people—some old friends, and some new. I’m already looking forward to next year.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Hackety Org» RedHanded

Thankyou for enjoying The RedHanded Adventure Show. We have had the nth batmans galore!! I adore you. I will never forget you. I will especially not forget you if you follow me to Hackety Org.

Is this the first time a Ruby blog has closed?? No matter. There will three more by supper. I will enjoy those blogs as a plainclothes civilian. Tallyho.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Hackety Hack Events and Things» RedHanded

A few other H-ety H items you may be interested to hear of:

  • My friends Brian DeLacey, Eric Mill and Kevin Driscoll (all of the Original 50 Hackety Hackers) will be answering questions and catering to YOUR needs on Tuesday, May 8th from 7 to 9pm at 1 Broadway St, Kendall Square, Cambridge. I already checked: you have nothing else that night.
  • Also, Eli Brody has a blog. Eli was the leader in beating up HH and has a bunch of alterations to the chat program so you can send RedCloth and keep logs.
  • A good feeling is to see this on the Hackety Hack wikipedia entry: Developer: why the lucky stiff and 50 friends.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Growing Great Programmers» Glenn Vanderburg: Blog
Here’s another highlight from RubyConf 2007: watching Jamis Buck and Michael Koziarski give a terrific keynote based on their joint blog, The Rails Way. I leaned over to Alan Francis and mentioned how encouraging it is to see young programmers with a solid, confident grasp of design and development principles that I didn’t learn until I was much older. I don’t mean to embarrass either Jamis or Koz by this; I admire them greatly. They make me optimistic about the future of my profession. (And calling them young says more about me than about them, perhaps.)

It’s absolutely certain that the biggest factor in their early maturity as programmers is that they’re just very smart guys. I’m also sure they started programming at a younger age than I did.

But Alan and I think there’s a third factor: Ruby itself. Ruby helps to teach those good programming skills, and makes them easier to learn. I got the chance later to talk to Koz about it, and he enthusiastically agreed.

The first thing I said in my talk on Saturday was that Rails is like an instructional laboratory for how to build good software. I think that’s the thing I like most about Rails. A big part of that is Ruby itself. Ruby, its libraries, and its documentation are filled with examples of clean, well designed code, and Ruby makes it easier than most other languages to create clean code yourself. The community values and encourages it. Ruby teaches good programming by setting the goal, lowering the barrier, and providing a lot of assistance and encouragement.

I was thrilled last year when Chris Pine’s Learn to Program was published, and now _why has taken up the flag with his brilliant Hackety Hack. We should support efforts that are focused on using Ruby to teach children to program. I think it’s the best way available right now to grow a generation of great programmers.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Full text indexing with Swish-e» not another ruby framework
Swish-e is a command-line full text indexer similar to ht://Dig. Swish-e sports a brilliant hack. When indexing, one can ask Swish-e to index the output of a command:

swish-e -S prog -i ./output_documents.rb
The output_documents.rb dumps out a series of html documents:

#!/usr/bin/ruby



require 'dbi'

require 'pp'



dbh = DBI.connect("dbi:Mysql:test:localhost", "user", "pass")

# get server version string and display it

artbase = dbh.select_all("SELECT * from objects")



artbase.each do |object|

path = '/object/' + object['object_id'].to_s

mtime = object['modified'].to_time.to_i

html = <


#{object['title']}





#{object['body']}





HTML

print "Path-Name: #{path}\r\n"

print "Last-Mtime: #{mtime}\r\n"

print "Content-Length: #{html.length}\r\n"

print "\r\n"

print html

end

Swish-e is FAST , in every way that matters:



* Installation is simple -- it's just a few commands

* Indexing and searching is speedy

* Integration is a breeze, since you are just executing commands.



Discovering Swish-e is like witnessing the birth of Athena, fully grown and ready for battle. I highly recommend it.



There is an important security note for use with websites. I'll post more when I work out the Ruby equivalent of the recommended Perl techniques.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Erring in Hackety Hack 0.4» RedHanded

I’m not sure if there’s any fixing the arcane parse errors of Ruby, but here’s a stab at it. I need to do some examination of other IDEs to see what else is being done to fix this.

Anyway, some screen captures from H-ety H 0.4.

This release has a lot of fixes to the bundled Try Ruby. (Problems with the cursor, browser crashes, tutorial loading time.) But the main feature is the new friendly and condensed error messages.

These same error messages are expanded into HTML in the program editor:

The next release will work on highlighting the line which threw the error and some links in the exception to help pages for any involved classes or error messages.

Here’s another nice feature. The bundled Try Ruby has a progress bar for page fetching. I want this console to be irresistible to you lot!!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 DrbDatasource» not another ruby framework
I've been working out a contradiction in web apps:
  • it's nice for each page to be independent, without having to worry about changes from other enviroments
  • it's nice to have just a few cached database connections
I can use continuations to make repeated ruby requests independent, but the problem is that I want a few objects to persist. Implementing something that will roll back modifications to Kernel while preserving a few database connections seemed daunting. Until I realized ... run the connections in a separate process and communicate using drb.

Update: Ara Howard has released a postgres connection pool
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Double Gets as Heredoc» RedHanded

From John Joyce in [ruby-talk:245343]:

I’m a little surprised at this. In irb, I tried puts gets gets. Why? I don’t know. But basically, gets gets, seems to almost act like a heredoc!

Such a simple and unintended thing: the double-gets. Do you see how it works?


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Chairman Takahashi in Taiwan» RedHanded

It’s so rare to find video of talks in English by our friends from Nihon Ruby-no Kai, but here is a lightning talk by Masayoshi Takahashi at last weekend’s OSDC in Taiwan. In case you haven’t had the pleasure. (Spotted on matz’ blog.)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Bridges and Software» Glenn Vanderburg: Blog
(I sent this to the NFJS speakers’ mailing list last week, and Ben Galbraith suggested I repost it here.)

Every now and then I hear someone compare software development to bridge building. (Bridge building, of course, is just a placeholder here for "real engineering," which in the speaker’s mind is much cleaner and more manageable than the current messy state of software development.) Sometimes it’s "software development isn’t like building bridges," while on other occasions it’s "software development should be more like building bridges." In either case, though, the implication is clear: bridge building is predictable, rote, unexciting, very manageable work, and software development is not. The only difference is whether the speaker likes software development the way it is, or wishes it could be different.

I think both positions are misinformed. And no, I’m not about to pull out my magic prescription for how to solve all the software industry’s problems by making it more like bridge building. In my experience, software developers tend to have an idealized, unrealistic view of what "real engineering" is like. Sure, some kinds of bridges are so well understood by now that there’s very little risk involved; freeway overpasses and the like are churned out regularly and routinely (in much the same way that simple CRUD applications, whether web- or desktop-based, are usually safe bets for even inexperienced development teams). But from what I’ve learned, bridge building in general is a lot more like modern software development than most people realize. And I think the software industry can learn some lessons from the history of bridge building.

Take, for example, the bridges of Swiss engineer Robert Maillart. His best known bridge, Salginatobel, was just featured in a really nice piece about some of the best man-made structures.

Maillart was seeking new designs that would take advantage of the properties of a new material: reinforced concrete. It had been in use for some time, and builders had figured out how to work with it, but Maillart realized that reinforced concrete had unique properties that would permit the use of new forms, resulting in significant savings (due to reduced material costs).

The formal methods used by civil engineers at the time weren’t up to the challenge of analyzing these structures (known today as "hollow box arches" and "deck-stiffened arches"). Maillart verified the designs empirically, by building models, rolling barrels full of concrete over them, etc. etc. The civil engineering establishment of the day vilified him as a charlatan who was endangering lives and cheating his customers by building bridges that would fall down. But he got customers anyway, because his designs were much, much cheaper to build. (The fact that they were strikingly beautiful didn’t hurt.)

Another engineer of the time was Leon Moisseiff, a strong proponent of formal methods and the developer of "deflection theory," at the time the state of the art in mathematical analysis of suspension bridges. Moisseiff designed a bridge intended to be a showpiece for the power of deflection theory. It was the Tacoma Narrows bridge. After its famous collapse, other bridges that had been designed with Moisseiff’s assistance (such as the Golden Gate) were retrofitted with stiffening trusses. It turned out that deflection theory was deeply flawed in a way that nobody had yet realized.

One of Maillart’s bridges did fall down … after being buried under an avalanche. One was demolished because more capacity was required. The rest are still in use, and the forms he pioneered are now standard design taught to civil engineers. The math eventually caught up with Maillart’s methods. As the story I linked to above notes, Maillart is an inspiration to the current superstar of bridge design, Santiago Calatrava.

I think there are some important lessons here for the software profession. The lesson is definitely not that "real engineering" is a mechanistic, purely construction-oriented process, which is the lesson that is usually assumed when software is compared to bridges.

Note: I have at best an interested layman’s knowledge of the history of bridge engineering. Sources include Henry Petroski’s wonderful Engineers of Dreams: Great Bridge Builders and the Spanning of America for information about Moisseiff, and David P. Billington’s article "The Revolutionary Bridges of Robert Maillart" (from the July 2000 edition of Scientific American). For what I believe to be the best description of the true relationship between software development and other engineering disciplines, I encourage you to read "What is Software Design?", Jack Reeves’ brilliant essay.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 Aha, Notice the Expando Which Precludes» RedHanded

Mark Pilgrim: The UNSELECTABLE attribute is implemented as an expando. Setting the expando property of the document object to false precludes the functionality of all expandos.

Kxxxx, oh when the jargon on MSDN hits stride and blossoms into complete psychedelia.

Someone please assemble a Wikipedia page for this rare bird. I want creators’ bios. I want the original legal pads. I want pronunciation mp3s. GO!!


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 A New Hope» not another ruby framework
This site was dedicated to the NARF web libraries. These have been moved to http://www.ruby-web.org. From now on, NARF will be dedicated to an attitude towards projects. That what Ruby needs isn't big ideas, but problem solving code.



In other words, this site will be dedicated to the attitude that generated ruby-web and raainstall. I will celebrate the can do, pragmattic, software engineering mentality that has made projects like Perl and PHP so friendly.



I will continue to post updates on the status of ruby-web, but I will also feature useful projects like the Nullsoft Installer System, Docbook, and whatever else is friendly and productive.



I hope to follow the example of these great projects. Cue the fanfare, courtesy of http://www.frazmtn.com/~punstr/midi/.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 1. NARF 2. ruby-web 3. ???? 4. Profit!!!» not another ruby framework
Chad Fowler just linked to an article describing local maximums and career optimization. I guess Point C is the same as 3. ????.



Each time I sit down and think about Ruby vs other web environments, I see so much room for improvement. I thought the scary stuff was behind me, and then I started thinking about database support.



The next dip will be in sorting out the nitty gritty of database support. I think the main problem with DBI is driver support -- that'll teach me C for sure! Sorting out easy to use binary installers is also a pain.



Btw, Kirk Haines, developer of IOWA, pointed out that IOWA already has developed a Drb connection pool.

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 <data> support for plist.rb» not another ruby framework
I've uploaded support to plist.rb. Special thanks goes to Mat Schaffer, who did the hard work of finding a test case. elements are returned as Tempfiles, and can be replaced with an IO or StringIO:



# reading elements

data = Plist::parse_xml("example.plist");

data['image'].read



# changing elements

bin = File.open("example.jpg"){ |f| f.read }

data['image'] = StringIO.new( bin )

data.save_plist("example_data-v2.plist")




The easiest way to install is to "gem install plist"

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:16 "I don't think this is an act that a healthy company would commit."» Glenn Vanderburg: Blog
Douglas Crockford says, "I don't think this is an act that a healthy company would commit.". He was referring to Media Rights Technologies, but he could just as easily have been referring to Microsoft.

Tim Bray, as he so often does, nails it.


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:15 lucille 開発日記 >> LLVM 2.0 & gcc 4.2» Matzにっき
LLVM 2.0のJIT性能は(少なくともあるベンチマークでは)gcc 4.2よりも 高速であったという話。 LLVMの性能が高いって話は以前から聞いてはいたけど、 ネーティブコンパイラに勝つってのは予想外であった。 もうちょっといろんな局面での性能比もみたいものだ。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:15 Rail Spikes: Rails developers: experts or script kiddies?» Matzにっき
Railsには質の悪い開発者が流れこんでいるんじゃないか、という話。 先日のコードモンキーの話と似てる。 Rails(やRuby)がニッチな間は、コミュニティを構成するのは マイナーな言語やフレームワークに気がつくだけの「アンテナが高い人」が中心で、 一般的に技術レベルが高いことが期待されていたが、 こうあちこちで取り上げられるようになると、いつまでもそれを期待するわけにはいかない。 Rails largely draws its market share from PHP and Java. Rails apps can be written as quickly as PHP, and can be as robust and maintainable..
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:15 Part2 Rubyに学ぶ「Ruby on Railsの正体」:ITpro» Matzにっき
「Rubyの秘密」。 日経ソフトウェアに掲載された時も思ったのだが、 制約と自由の関係について的確な指摘がなされていると思う。 ある種の制約は自由を増やす傾向がある。 ある種の自由は人間の負担を増す傾向がある。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:15 Dr. Dobb's | Python NetWorkSpaces and Parallel Programs | 7 2, 2007» Matzにっき
NetWorkSpacesという仕組みを使ってプロセス間通信をすることで、 異言語間通信 分散処理 を実現しようという話。PythonとRの間で通信ができると言うことは、 当然、Rubyでも利用可能だと思う。 通信コストが十分に低ければマルチコアを活用する目的にも使えるかも。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image19:15 23 Programming Languages compared through their Amazon book sales» Matzにっき
Amazonの売り上げに見る人気言語ランキング。 これは総計ではなく、その言語についてもっともAmazon売り上げが多い書籍各1冊の 順位によるランキング。ちなみに上位三位は JavaScript - JavaScript: The Definitive Guide Java - Head First Java, 2nd Edition Ruby - Programming Ruby: The Pragmatic Programmers' Guide, Second Edition だそうだ。もちろん、この計算方法では、Javaのような書籍がたくさん出ている言語は 売り上げが分散する傾向があるので不利になるだろう。 それでも2位になるJavaはたいしたものか。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image10:39 如何禁止在文本框中输入中文» Ruby Object Oriented
具体步骤: 方法一:用文本框的CSS属性ime-mode实现。 <input onpaste="return false" ondragenter="return false"  style="ime-mode:disabled"> 提示:设置ime-mode为disabled的意思是禁止在输入时禁止用户激活输入中文,韩文,日文等的输入法(IME)状态,因为这个只能检测到键盘的输入,对通过鼠标操作的粘贴和拖放无效。 方法二:在松开按键时用脚本检查文本框的值,只保留Unicode编码在0和255之间的字符。 <script> function check(str){  var temp=""  for(var i=0;i<str.length;i++)       if(str.charCodeAt(i)>0&&str.charCodeAt(i)<255)          temp+=str.charAt(i)  return temp  }  </script> <input onpaste="return false" ondragenter="return false"  onkeyup="this.value=check(this.value)"> 方法三:把所有双字节字符替换为空。 <input onpaste="return false" ondragenter="return false"  onkeyup="this.value=this.value.replace(/[^\x00-\x80]/gi,’’)"> 方法四:把中文字符替换为空。 <input onpaste="return false" ondragenter="return false"  onkeyup="this.value=this.value.replace(/[\u0391-\uFFE5]/gi,’’)"> 特别提示 本例代码运行后,第一种方法是不能切换输入法,所以无法输入中文,其它三种方法是在输入中文后立即被替换为空,同时禁止了粘贴和拖放事件。 特别说明 本例主要是css属性ime-mode和对中文或双字节字符的判断应用。 ime-mode 设置输入方法编辑器(IME)的状态。 charCodeAt返回指定位置上字符的 Unicode 编码值。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image09:28 全责制 vs 分解制» Ruby Object Oriented
全责制:如果能够在一个页面中完成所有责任,为什么要使用多个页面? 分解制:如果能够在多个页面中分担每种责任,为什么要使用一个页面?
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image03:22 Breaking News – Web C...» Projectionist

Breaking News – Web Crash 2007


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image02:53 Rails框架技术讲座:分页技术插件will_paginate中文化» 道喜技术日记

Rails框架技术讲座:分页技术插件will_paginate中文化

  • 前提
    1. 分页技术插件will_paginate
    2. 基于Console使用本地化插件gibberish
    3. 基于网络服务器使用本地化插件gibberish
  • 问题提出
    在该插件中页面主要存在Previous和Next两个单词,这是我们想主要中文化的内容。事情并不是那么简单,因为我们一是从技术上不能简单在插件中把这两个词改成中文;二是要是我们需要多种文字时有该如何办呢;三是即使去修改插件好像也有点麻烦。
  • 实施方案
    使用上面的相关资料,在Rails框架的文件app/helpers/application_helper.rb中增加下面的方法就可以了,当然还要在文件lang/zh.yml文件中增加中文!但是在页面应用时,使用方法xwill_paginate。
      def xwill_paginate entries = @entries
        will_paginate entries,
                      :prev_label => "No TRANSLATION: Previous"[:Previous],
                      :next_label => "No TRANSLATION: Next"[:Next]
      end
  • 实施结果

add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Wed 18 July, 2007

Click here to bookmark this link.Channel Image18:02 Engage in a debate» Ruby Object Oriented
A lively discussion can be invigorating. As long as you avoid letting it digress into an argument, you can have a lot of fun debating the pros and cons of an issue with a friend or colleague. Playing with your brain stimulates blood flow and strengthens the connections (synapses) between nerve cells in the brain. You’ll [...]
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image17:01 浏览器点返回-页面已过期-问题重现» Ruby Object Oriented
1.表单提交是post(get不会有这个问题) 2.点title 3.点浏览器返回 –经典的”页面已过期”的问题就重现啦 <?php session_start();//就是因为这个session的原因啦. if ( $_POST['q'] ) {     echo( '<a href="index.php?id=1">title</a>' );     exit(); } elseif($_GET['id']) {     echo( "title content" );       exit(); }else{   ?> <FORM METHOD=POST ACTION="index.php">     <INPUT TYPE="text" NAME="q">     <INPUT TYPE="submit"> </FORM>   <?}?> 解决办法: 用session_cache_limiter session_cache_limiter('private'); session_start(); //剩下的同上
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image11:28 Matz, Koichi访谈(一): Ruby虚拟机» LetRails
这是一个系列访谈 ,采访者为James Gray,内容涉及Ruby虚拟机,多线程以及国际化等方面,接受采访的Matz为Ruby语言的创造者,Koichi(以下简称ko1)是YARV项目 的主导者,YARV项目的目标是为Ruby...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image00:44 Subject: 3 days of video st...» Projectionist

Tue 17 July, 2007

Click here to bookmark this link.Channel Image23:01 SchützaBlog 2007: Urschützenlied» chris blogs

Das Biberacher Schützenlied ist für mich auch nach längerem Nachdenken das einzige christliche deutsche Lied, das ich inbrünstig singen kann.

Meist werden nur drei Strophen gesungen was eigentlich schade ist, da auch die anderen schön sind.

Du, den die Felder uns entdeckten,
du den der Blumen Flor erhob,
auch die unscheinbaren Insekten,
o Schöpfer, predigen dein Lob.
Hier sammeln wirtschaftliche Bienen,
sie pflücken emsig, uns zu dienen,
die beste Kraft der Blumen ab.
Du lehrst die Seidenwürmer weben:
sie sterben, edler aufzuleben,
und spinnen sich ihr kostbar Grab.

Oder auch:

Die Felsen, die so traurig scheinen,
sind dir, o Mensch, zum Dienst geweiht.
Die Quelle tröpfelt aus den Steinen,
und mit der Quelle Fruchtbarkeit.
Wie? Werd ich auf den heitren Auen,
auf die des Himmels Schätze tauen,
den frommen Lenz nicht selbst gewahr?
Seht, mich umringen laue Weste.
Dort winken mir die schwanken Äste,
der Baum beut seine Frucht mir dar.

—Christian Sturm, 1775

Scheene Schütza

NP: Funny van Dannen—Eurythmieschuhe


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image13:54 It’s a shame this poor litt...» Projectionist
It’s a shame this poor little usage gets such a bum rap.

Jennifer Dailey-O’Cain on the quotative like


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image10:02 前所未有的遭遇死机» Suave's Blog
Ubuntu 上用 ruby 的 REXML 去 parse 二十几万个 xml 文件,内容很简单,文件也很小。遭遇不确定性死机,甚至有一次直接重启了。昨天一边 parse 一边往 mysql 里插,在50万左右的时候再次死机! 死机...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image01:42 SchützaBlog 2007: Bunter Umzug» chris blogs

Die WG-Trommler gingen dieses Jahr beim Bunten Umzug als Hawaiianerinnen, die anderen gingen alle als Bauarbeiter. Zumindest schien es so.

Wagen, die man gerne hätte:

  • Tangowagen, damit nicht alles im Viervierteltakt läuft.
  • Brennereiwagen, als Komplement zum Brauerwagen.
  • RAF-Wagen, als moderner Schwarz Veri.
  • Abiturientenwagen

Sonst fällt mir dazu nichts ein,
Scheene Schütza

NP: Funny van Dannen—Kunden der Zeit


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image00:30 Avoiding left turns saves gas» Projectionist

Tip Avoiding left turns saves gas

Last year, UPS cut 28 million miles from truck routes, saving roughly three million gallons of fuel, in good part by mapping routes that minimize left turns.
(source: http://tinyurl.com/2d6uy6)


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Mon 16 July, 2007

Click here to bookmark this link.Channel Image23:42 JRuby Inside上线» LetRails
与Ruby Inside类似,不过从它的名字我们就能想到,JRuby Inside的内容将主要集中在JRuby方面,当然,Ruby Inside上也还会有关于JRuby的内容,不过如果你是JRuby的粉丝,那么我相信JRuby Inside会使你的脉...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image08:07 django两岁了» 动态感觉 静观其变
django已经两岁了,django官方网站上公布了这个消息,算起来确实够快的。想想刚开始推出时,我也迫不及待的想看看到底如何呢?不过当时我对django的一些写法不是很满意,感觉有些难受,所以一直都没有进入,如今却不知不觉也开始用它了,呵呵,事难料,自己也难料啊。人的思维会因为某个触发点而改变,而我改变的一个很重要的原因,可能就是jquery,通过jquery,我学习javascript,也从这里真正看懂了一些django的philosophies,很奇怪吧(django和jquery扯上关系了)。也许别人会以别的角度进入django的。django总体来说还是偏向于保守,偏执于自己的philosophies,这是不讨人喜欢的一个地方,这也是一些人特别喜欢它的一个原因。最近django的test framework方面有些进展了,增加了一些东西,有时间要看看它。
...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image06:44 Adobe全新电子书籍阅读器新版发行» 天天红玉世界
Click here to bookmark this link.Channel Image04:47 Rails框架插件系列:创建中文pdf文件插件ActiveFPDF» 道喜技术日记

Rails框架插件系列:创建中文pdf文件插件ActiveFPDF


add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Click here to bookmark this link.Channel Image02:34 Thatcher on Drums» Projectionist

Sun 15 July, 2007

Click here to bookmark this link.Channel Image22:38 在Agile Day讲Ruby on JVM» 梦想风暴
去年Agile Day的时候,我还在沈阳,没有近距离感受ThoughtWorks带来的敏捷盛宴。今年的Agile Day,我已经成为了一名ThoughtWorker。我不仅仅有机会到了现场,更是成为了一个演讲者。演讲的题目自然是我现在的工作重点:Ruby on JVM。公司对Ruby的关注从这次Agile Day的日程安排中可见一斑,在技术/工具分会场的四场演讲中,就有两场与Ruby相关:第一场我现在的老板Chad讲企业级Ruby和我的Ruby on JVM。

虽然讲的是自己熟悉的东西,但准备这次演讲的材料还是花了很大的力气。面对的观众不同,讲的内容就应该有所差别。从众多相关的内容选择出让观众有兴趣的内容,而且深浅适度,这是个问题。所以,每次有讲演的机会,我都对仔细考虑讲的内容。好在在ThoughtWorks总是可以找到人一起讨论,一旦确定了演讲的基调,就拥有了骨架,剩下的问题就是血肉丰满起来。在准备这次演讲的内容过程中,yawl和Ola Bini都给了我不少建议。

这次Agile Day的活动,公司允许任何人在中国的ThoughtWorker参加。本来周六的活动,人在西安的ThoughtWorker周五晚上出发。为了更好的准备这次的演讲,我提前一天到北京。对于自己所讲的内容,因为经过了自己的思考,我觉得还好,我最主要的担心就是怕自己会紧张。在北京办公室准备的过程中,我才发现,原来大家都一样,每个演讲者都是怕自己会紧张,所以,为了能在大会时有个良好的表现,大家都在一遍遍回顾着自己的所讲的内容,偶尔还要拉几个观众实战一下。我就给人当了演习观众。当然,我也会拉着别人来当观众。第一次讲的时候,我能清楚的感觉到自己在开始的时候,声音有一些微微的颤抖,语言的表达上有些凌乱,好在这是练习。Mingle产品经理Adam看我的讲稿之后,第一反应就是问我Mingle是否可以运行在XRuby上,这也增强了我对讲稿的信心,不过,我的答案还是令人遗憾的“暂时不行“。

Agile Day当天,ThoughtWorker们都会充当杂役,所以,早早就去现场干活。稍微得到一些清闲的时候,脑子里就一次次回顾着要讲的内容。确实这次大会人来了好多,要在这么多人面前讲东西,无论事先我做了多少准备,我还是会觉得紧张,尽管表面上还和同事们开着玩笑。其实,原本我希望在Agile Day多听几场演讲,但事实上,在别人演讲的时候,我都在休息室准备自己的演讲,根本没有心情去听。Chad结束演讲之后跟我说,我还在演讲中提到你了,我只能很抱歉的说,我没有听到。真正到自己站在台上开始演讲,我发现自己的声音没有了练习时的颤抖,这也给了自己不少信心。随着演讲的进行,我也就自己渐渐进入了状态,也就不太顾忌那些无关的东西了。至于表现得到底如何,我不知道,别人评价去吧!gigix之后就告诉我,我经常出现背向观众的情况。之后,精神一下子松懈下来,感觉好累,在外面的沙发上,躺了好长时间,所以,我后面一场的演讲也没怎么听。对我而言,当我是演讲者时,其实往往意味着失去一次很好的学习机会。

虽然大家都愿意去听各种各样的演讲,但实际上,一个演讲真正能让人记住的只有非常有限的内容,所以,我所希望的只是通过这次演讲,让更多的人知道我们在Ruby on JVM上的努力是有价值的。如果能够吸引更多的人加入到这个过程中来,那就是太完美了。
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl

Sat 14 July, 2007

Click here to bookmark this link.Channel Image22:36 使用ruby-prof获取rails应用的profile» LetRails
ruby-prof最新的0.5版本开始支持Rails,但是文档并没有相应更新,这是来在Charlie Savage的一篇关于如何在Rails中使用ruby-prof的指南,希望对你有所帮助。 假设你发现你的Rails应用对某个请求的处理...
add to del.icio.us add to del.icio.us. look up in del.icio.us.   add to furl.net add to furl
Sources