<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
  <channel>
    <title>I am sailing, I am sailing</title>
    <description>Coder</description>
    <link>http://quake.javaeye.com</link>
    <language>UTF-8</language>
    <copyright>Copyright 2003-2008, JavaEye.com</copyright>
    <docs>http://blogs.law.harvard.edu/tech/rss</docs>
    <generator>JavaEye - 做最棒的软件开发交流社区</generator>
      <item>
        <title>Hibernate可以从Rails的ActiveRecord学到什么？</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/208718" style="color:red;">http://quake.javaeye.com/blog/208718</a>&nbsp;
          发表时间: 2008年06月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <span style="font-size: medium">1. 约定大于配置</span><br />Rails的理念就是约定大于配置，这在ActiveRecord模块里面体现的淋漓尽致，没有hibernate繁琐的mapping xml或者annotation，它是直接根据数据库中表的字段信息配合少量关系定义去实现ORM。<br />以一个简单的论坛主题贴为例子：<br /><pre name="code" class="ruby">
class Topic &lt; ActiveRecord::Base
  belongs_to :user
  belongs_to :forum
  has_many :posts
end

class Post &lt; ActiveRecord::Base
  belongs_to :topic
  belongs_to :user
end
</pre><br />只用定义对象之间的关系，其他属性，比如topic的id, title, created_at都是根据数据库中表的字段来自动生成。<br />而在Hibernate里面，就需要在pojo里面定义多个属性，以及getter/setter，然后用mapping xml或者annotation定义这些属性和数据库表/字段的映射以及各个对象之间的关系(one-to-many, many-to-one, etc)。<br /><br /><span style="color: red">Hibernate实现该特性难度：***</span><br />因为Hibernate和ActiveRecord设计出发点正好相反。前者是对象驱动数据库：定义mapping文件，然后自动生成数据库脚本。而后者是数据库驱动对象：设计好数据库，动态生成对象属性。<br /><br /><br /><span style="font-size: medium">2. 数据库迁移工具</span><br />ActiveRecord的数据库migration脚本非常好用，能够让我们在开发/部署时候做方便的数据库结构变更。<br />而Hibernate本身并没有提供这项功能，我之前用hibernate开发的时候，经常为了这个问题而需要写一些迁移SQL，如果做产品，还要考虑到不同的数据库要提供不同的迁移脚本。<br /><br /><span style="color: red">Hibernate实现该特性难度：*</span><br />Hibernate应该提供内置的migration tool，让它作为一项最佳实践来推广。<br /><br /><br /><span style="font-size: medium">3. 动态代码生成</span><br />由于Ruby动态语言的特性，ActiveRecord能够把原先在Hibernate里面麻烦的代码，变得很简洁。<br /><br />还是以前面的论坛主题贴为模型，我们需要对一个主题贴进行回复，在rails里面我们可以这样写：<br /><pre name="code" class="ruby">
topic = Topic.find(10000)
topic.posts.create(:user => current_user, :body => "回复内容")
</pre><br />ActiveRecord利用动态代码生成，在Topic上的has_many posts集合，自动添加了一个create方法，负责处理往这个集合添加新对象以及维护关系。<br />而相应的Hibernate代码，大概是这样：<br /><pre name="code" class="java">
Topic topic = session.find(Topic.class, 10000);
Post post = new Post();
post.setUser(currentUser);
post.setBody("回复内容");
post.setTopic(topic);
topic.getPosts().add(post);
session.update(topic);
</pre><br /><br />再一个例子，为了性能考虑，我们往往会在Topic表上添加一个posts_count的冗余字段，在Rails里面只用添加一个counter_cache<br /><pre name="code" class="ruby">
class Post &lt; ActiveRecord::Base
  belongs_to :topic, :counter_cache => true
end
</pre><br />其他代码都不用动，ActiveRecord就可以利用动态代码生成，帮你在有新回帖的时候给这个栏位自动+1了。<br />而在Hibernate里面，我们就要手写几行代码来做这种事情了。<br /><br />这类型的特性在Rails里面很多，这里就不一一列举了。<br /><br /><span style="color: red">Hibernate实现该特性难度：**</span><br />可以利用Hibernate的inteceptor或者event机制，配合mark性质的interface，来实现部分功能。<br /><br /><br /><span style="font-size: medium">4. named_scope (Has Finder) 功能</span><br />这是Rails2.1的新特性，之前是用Has Finder插件实现的。<br />我们以JavaEye的新闻模型为例子，它有一个status栏位，代表是否被批准，还有一个category栏位，代表是属于什么分类：<br /><pre name="code" class="ruby">
class News &lt; ActiveRecord::Base
  named_scope :approved, :conditions => {:status => 'approved'}
  named_scope :categoried, lambda { |category| { :conditions => ['category = ?', category] } }
  named_score :recent, lambda { |time| { :conditions => ['created_at > ?'], time } }
end
</pre><br />我们在controller里面就可以这样组合使用：<br /><pre name="code" class="ruby">
#被批准的新闻
News.approved
#被批准的Java新闻
News.approved.categoried("java")
#最近2周被批准的Ruby新闻
News.approved.categoried("java").recent(2.weeks.ago)
</pre><br /><br />这个代码看起来非常舒服，犹如阅读英文一般自然。<br /><br /><span style="color: red">Hibernate实现该特性难度：***</span><br />这其实也是动态语言特性所带来的，基于Java的Hibernate几乎是无法实现这个特性。<br /><br /><span style="font-size: medium">5. 高性能的集合操作</span><br />还是以前面的论坛主题贴为模型，显示一个主题贴的回帖数目，在rails里面我们这样写：<br /><pre name="code" class="ruby">
topic.posts.size
</pre><br />它只会生成select count(*)的语句，而不需要把整个posts集合初始化。<br /><br />再比如对回帖做分页显示：<br /><pre name="code" class="ruby">
topic.posts.paginate(:page => 1, :per_page => 10)
</pre><br />它也只会生成相应的分页语句。<br /><br />在Hibernate3，lazy collection proxy可以做到类似的操作，但是代码就复杂多了：<br /><pre name="code" class="java">
( (Integer) session.createFilter( posts, "select count(*)" ).list().get(0) ).intValue()
session.createFilter( posts, "").setFirstResult(0).setMaxResults(10).list();
</pre><br />而且其他的更多集合操作特性也无法实现<br /><br /><br />-------广告分割线-------<br />还有许许多多其他优秀特性等待你去挖掘，Rails中除了ActiveRecord以外，也还有其他优秀的地方，试用一下Rails，会发现用它来写web应用是一件很享受的事情。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/208718#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 27 Jun 2008 15:54:57 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/208718</link>
        <guid>http://quake.javaeye.com/blog/208718</guid>
      </item>
      <item>
        <title>Java程序员应该学习Ruby</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/208478" style="color:red;">http://quake.javaeye.com/blog/208478</a>&nbsp;
          发表时间: 2008年06月27日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Java v.s Ruby，prototype js v.s jquery， Hibernate v.s iBatis v.s EJB ...<br />这种语言之争，框架之争，每隔<a href="http://www.javaeye.com/topic/180517" target="_blank">一段时间</a>总会在论坛<a href="http://www.javaeye.com/topic/206906" target="_blank">出现</a><br /><br />最近我读到一篇博客：<a href="http://jbossdna.blogspot.com/2008/06/java-developers-should-learn-ruby.html" target="_blank">Java程序员应该学习Ruby</a>，非常赞同作者的观点，粗略翻译其中的小部分，希望大家可以减少这种无意义的争论<br /><br />--------翻译开始分割线--------<br />Java程序员应该学习Ruby<br /><br />当然，它不一定是Ruby，你可以挑选其他语言，比如ErLang，甚至JavaScript，只要它和Java有足够的差异就可以了。<br />因为它能够让你成为一个更好的Java程序员：<br /><br /><span style="font-size: medium">1. 学习另外一种语言，它能够让你深入不同的开发者社区</span><br /><br />针对相同的问题，你可以找到不同的思想和不同的做法，或许它们不一定是更好，只是不同而已。其他社区往往有新鲜的视角来看待相同的问题，有时候甚至会让你更感激Java社区（比如Java有大量优秀的library）<br /><br /><span style="font-size: medium">2. 学习另一种语言，可以教你新的idioms</span>（idioms - 我想用行话来翻译idiom更准确一些）<br /><br />你可以在Java使用其中的一些行话，或者由于语言限制，你还不能使用它。<br />以Ruby的blocks为例子，它是Ruby闭包的一种表现，比方说你可以很方便地遍历数组，然后做一些操作(打印)：<br /><pre name="code" class="ruby">
animals = ['lion','tiger', 'bear']
animals.each {|animal| puts animal }
</pre><br /><br />很遗憾，目前Java还没有闭包，在Java 6里面如果要做类似的事情就是通过匿名内部类来解决，需要2个接口：<br /><pre name="code" class="java">
public interface OnEach&lt;T> {
  void run(T obj);
}
public interface List&lt;T> ... {
  void each( OnEach&lt;T> action );
}
</pre><br /><br />然后上面ruby例子就可以这样用：<br /><pre name="code" class="java">
List&lt;String> animals = Arrays.asList( new String[]{"lion", "tiger", "bear"} );
animals.each( new OnEach&lt;String>() {
 public void run( String animal ) {
  System.out.println(animal);
 }
});
</pre><br /><br />不过还是有点麻烦，Java 7将会引进闭包，目前已经有<a href="http://www.javaworld.com/javaworld/jw-06-2008/jw-06-closures.html" target="_blank">多个设计</a><br /><br /><span style="font-size: medium">3. 学习另一种语言，也迫使您使用不同的工具和过程</span><br /><br />以Ruby的<a href="http://rspec.info/" target="_blank">RSpec</a>为例，它是一个<a href="http://behaviour-driven.org/" target="_blank">Behavior Driven Development</a>框架，通过使用它你会发现和Java社区的Test Driven Development区别，并且可以从中学到很多。<br /><br /><br />Java是伟大的，并且还会继续，但是它需要进化。它已经有13年的历史了，我们一些人几乎把所有的时间都花在Java领域。去探索一下其他语言，我打赌你会成为一个更好的Java程序员。<br />--------翻译结束分割线--------<br /><br /><br />我之前一直是一个Java程序员，去年开始接触Ruby，在不到一年的时间里（更准确的说是在学习了Ruby 2个星期后），我觉得已经变成了一个更好的Java程序员，你还在等什么，开始学习Ruby吧。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/208478#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 27 Jun 2008 09:35:07 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/208478</link>
        <guid>http://quake.javaeye.com/blog/208478</guid>
      </item>
      <item>
        <title>Rails2.1 bug serialized 属性不能被dirty check</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/207311" style="color:red;">http://quake.javaeye.com/blog/207311</a>&nbsp;
          发表时间: 2008年06月24日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          把Rails从2.0.2升级到了2.1，跑了一下JavaEye的单元测试代码，发现了一个很奇怪的错误：某个serialized 属性无法被持久化到数据库，经过一番查找，结果发现是Rails 2.1引入的partial update和dirty object check导致的bug：<br /><a href="http://rails.lighthouseapp.com/projects/8994/tickets/360-dirty-tracking-on-serialized-columns-is-broken" target="_blank">http://rails.lighthouseapp.com/projects/8994/tickets/360-dirty-tracking-on-serialized-columns-is-broken</a><br /><br />在Rails团队解决这个bug之前，一个临时的解决方法是手工调用serialized_name_will_change!方法，告知这个属性将会被改变。<br /><br />从milestone上看这个问题是2.1.1版本还未解决的最后一个issue了，大家不妨等2.1.1出来再升级。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/207311#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 24 Jun 2008 08:59:00 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/207311</link>
        <guid>http://quake.javaeye.com/blog/207311</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 中英文混合字符串截取</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/201531" style="color:red;">http://quake.javaeye.com/blog/201531</a>&nbsp;
          发表时间: 2008年06月09日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          这篇Ruby每周一测有点特殊，它不是翻译<a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a>上的文章，而是我自己出的一个quiz <img src="/images/smiles/icon_smile.gif"/>：<br /><br />我们在做页面排版的时候，为了避免过长字符串撑开页面，经常需要调用截取过长字符串的方法，rails已经为我们提供了一个方法：<br /><pre name="code" class="ruby">
ActionView::Helpers::TextHelper#truncate(text, length = 30, truncate_string = "...")
</pre><br /><br />调用很简单：<br /><pre name="code" class="ruby">
truncate("Once upon a time in a world far far away", 14)
# => Once upon a...

truncate("Once upon a time in a world far far away")  
# => Once upon a time in a world f...

truncate("And they found that many people were sleeping better.", 25, "(clipped)")
# => And they found that many (clipped)
</pre><br /><br />但是遇到中文字符串的时候它就不那么完美了：它把一个中文作为和英文相同的长度来截取，使用同样的length参数，会导致截取的英文字符串比中文字符串在<span style="color: red"><strong>视觉上短很多</strong></span><br />为了解决这个问题，JavaEye使用的方法是把一个中文大约视为2个英文的宽度，实现truncate_u方法：<br /><pre name="code" class="ruby">
truncate_u(text, length = 30, truncate_string = "...")
</pre><br /><br />执行结果和rails的truncate略有不同，length是指中文字宽，truncate_string不计算在length里<br /><pre name="code" class="ruby">
truncate_u("english string", 2)
# 截取2个中文字宽，所以是返回4个英文加上"..."
# => engl...

truncate_u("中文字符串", 2)
# => 中文...

truncate_u("中文 and english", 6)
# 截取6个中文字宽，所以是返回2个中文，8个ascii字符，以及truncate_string
# => 中文 and eng ...

truncate_u("中文 and english", 8)
# 完整截取，返回和输入一致的字符串
# => 中文 and english
</pre><br /><br />这次的每周一测就是实现这个方法，或者你有另外更好的中英文混合字符串截取想法，也可以一起来讨论
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/201531#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 09 Jun 2008 17:56:21 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/201531</link>
        <guid>http://quake.javaeye.com/blog/201531</guid>
      </item>
      <item>
        <title>Ruby - 条条道路通罗马</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/200008" style="color:red;">http://quake.javaeye.com/blog/200008</a>&nbsp;
          发表时间: 2008年06月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby语言有TMTOWTDI的味道 (There’s more than one way to do it)，一些人认为这是一种不好的味道，但我觉得这很好玩，颇有条条道路通罗马意味。我翻译过一些<a href="http://www.javaeye.com/search?type=topic&query=Ruby%E6%AF%8F%E5%91%A8%E4%B8%80%E6%B5%8B&sort=created_at" target="_blank">Ruby Quiz</a>的题目，可以看到很多不同的ruby解法，从好玩中学到别人的想法和知识，这很棒。<br /><br />写这篇文章的一个起因是问答频道的一个题目：<a href="http://www.javaeye.com/problems/117" target="_blank">ruby 怎么利用正则表达式在把一个字符串数组中的数字放到一个数组中？</a>，我从其他人的解答中学到了一些string对象以前从来不注意的方法。<br />第2个原因是一篇博客：<a href="http://www.rubyinside.com/21-ruby-tricks-902.html" target="_blank">21个你应该使用的Ruby小技巧</a>，学到了很多非常棒的小技巧，可以让代码更简练。<br />第3个原因还是一篇博客：<a href="http://blog.citrusbyte.com/2008/6/2/ruby-tmtowtdi-episode-1" target="_blank">Ruby TMTOWTDI, Episode 1</a>，作者在他们的开发团队中会经常举办小比赛，出一个题目让大家用ruby来解决，然后会评选出性能最好和最优雅的2个获胜者。这篇博客的问题是：<br /><div class="quote_title">引用</div><div class="quote_div"><br />给定一个类似下面格式的字符串<br /><pre name="code" class="ruby">
"a10 b20 c25 d40"
</pre><br />写一段代码把它转化成hash<br /><pre name="code" class="ruby">
{'a' => 10, 'b' => 20, 'c' => 25, 'd' => 40 }
</pre><br /></div><br />从解答中可以学到很多好玩的小技巧，有兴趣的可以一看。<br /><br />我觉得这种在团队中推行类似ruby quiz的方法有很多好处，在之前的Java团队我也用过：<br />1. 增加整个团队的互动<br />2. 了解他人的编码风格，以便更好的协作<br />3. 知识共享，把他人的知识/小技巧变成自己的<br />大家有兴趣的话，不妨在自己的团队中也试试看
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/200008#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 04 Jun 2008 10:30:28 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/200008</link>
        <guid>http://quake.javaeye.com/blog/200008</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 方法名缩写调用</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/197895" style="color:red;">http://quake.javaeye.com/blog/197895</a>&nbsp;
          发表时间: 2008年05月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby每周一测 - <a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a> 是Ruby Talk邮件列表上的一个持续了很长时间活动，每周有一个小题目被提出来，然后大家进行解答讨论。Amazon上还有相关的书： <a href="http://www.amazon.com/Best-Ruby-Quiz-Pragmatic-Programmers/dp/0976694077" target="_blank">Best of Ruby Quiz</a>。我尝试挑选其中的一些题目进行翻译，做一个每周一测系列，欢迎大家参与讨论。<br /><br />-----题目分割线-----<br />命令行操作通常都会支持缩写，这周的Ruby Quiz要实现一个支持方法名缩写调用机制，举具体例子来看，假设一个Mine对象有step, next, stop, exit 4个方法，我们用abbrev操作定义这4个方法可以被缩写调用：<br /><pre name="code" class="ruby">
class Mine
  abbrev :step, :next, :stop
  abbrev :exit
end
</pre><br /><br />如下调用将会产生：<br /><pre name="code" class="ruby">
Mine.new.e # 调用exit方法
Mine.new.st # 因为step和stop都符合st这个缩写，应该抛出错误提醒用户
Mine.new.a # 应该抛出NoMethodError错误
</pre><br /><br />一个需要留意的地方，缩写方法不能调用其他缩写：<br /><pre name="code" class="ruby">
class Nine
  abbrev :hash
  abbrev :has
end

Nine.new.ha # => [:hash, :has]
Nine.new.has # => 不能调用hash方法，应该抛出NoMethodError错误

class Nine
def has; 42; end
end
Nine.new.has # => 这个时候应该返回42
</pre><br /><br />针对这些特殊情况的测试，原文提供了一个完整的<a href="http://rubyquiz.com/test-abbrev.rb" target="_blank">单元测试</a>代码。<br /><br /><br />-----解答分割线-----<br />原题和一些解法在这里：<a href="http://rubyquiz.com/quiz110.html" target="_blank">http://rubyquiz.com/quiz110.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/197895#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 28 May 2008 16:14:43 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/197895</link>
        <guid>http://quake.javaeye.com/blog/197895</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 海龟画图</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/192746" style="color:red;">http://quake.javaeye.com/blog/192746</a>&nbsp;
          发表时间: 2008年05月13日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby每周一测 - <a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a> 是Ruby Talk邮件列表上的一个持续了很长时间活动，每周有一个小题目被提出来，然后大家进行解答讨论。Amazon上还有相关的书： <a href="http://www.amazon.com/Best-Ruby-Quiz-Pragmatic-Programmers/dp/0976694077" target="_blank">Best of Ruby Quiz</a>。我尝试挑选其中的一些题目进行翻译，做一个每周一测系列，欢迎大家参与讨论。<br /><br />-----题目分割线-----<br />海龟作图(Logo)是我最早学习的一种编程语言，相信许多我的同龄人都接触过这个语言，正是它让我对编程产生了浓厚兴趣，在rubyquiz上看到<a href="http://rubyquiz.com/quiz104.html" target="_blank">这篇利用ruby实现海龟画图的每周一测后</a>，倍感亲切：<br /><div class="quote_title">引用</div><div class="quote_div"><br />想像你控制了一只小海龟在一片沙滩上行动，你可以控制它前进(FORWARD)，后退(BACK)，左右转弯(LEFT/RIGHT)，然后用它的尾巴抬起，放下来作画(PENUP/PENDOWN)<br /></div><br /><br />举例来说，画一个100*100的正方形，可以这样写：<br /><pre name="code" class="ruby">
pen_down
4.times { forward 100; right 90 }
</pre><br /><br />完成这次的每周一测你需要做一些准备工作：<br />1. 下载一个<a href="http://rubyquiz.com/turtle.zip" target="_blank">turtle.zip</a>，这里包含了基本的框架<br />2. 安装tcl/tk以及相关的ruby库<br /><br />在解压后的zip包里面，有个lib/turtle.rb，完成它里面的方法就实现了海龟画图的功能。<br /><br />通过调用<br />ruby turtle_viewer.rb samples/byzantium.rb <br />可以看到附带的几个例子效果。<br /><br />让我们来重温一下儿时熟悉的小海龟画图吧：<br /><img src="http://www.javaeye.com/upload/attachment/23937/adb6fa8d-7c2e-390c-b849-6134cadd6ac8.png" /><br /><br /><pre name="code" class="ruby">
def byzantium(r, n)
   return if n &lt; 1
   fd r; rt 135
   4.times {
      pd; fd 2 * r * sin(45 * DEG); pu
      byzantium(r / 2, n - 1)
      rt 90
   }
   lt 135; bk r
end
byzantium(100, 4)
</pre><br /><br />-----解答分割线-----<br />原题和一些解法在这里：<a href="http://rubyquiz.com/quiz104.html" target="_blank">http://rubyquiz.com/quiz104.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/192746#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 13 May 2008 22:39:04 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/192746</link>
        <guid>http://quake.javaeye.com/blog/192746</guid>
      </item>
      <item>
        <title>Rails 2.1值得关注的新特性</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/189171" style="color:red;">http://quake.javaeye.com/blog/189171</a>&nbsp;
          发表时间: 2008年05月04日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://www.javaeye.com/news/2118" target="_blank">Rails 2.1快出来了</a>，和2.0相比它又添加了很多新特性，列举一下我认为值得关注的新特性：<br /><br /><span style="font-size: medium">1. Has Finder 功能</span><br /><br />广受欢迎的<a href="http://pivots.pivotallabs.com/users/nick/blog/articles/284-hasfinder-it-s-now-easier-than-ever-to-create-complex-re-usable-sql-queries" target="_blank">Has Finder</a>插件被集成到了2.1的代码中，不过换了种写法，使用named_scope:<br /><pre name="code" class="ruby">
class User &lt; ActiveRecord::Base
  named_scope :active, :conditions => {:active => true}
  named_scope :inactive, :conditions => {:active => false}
  named_scope :recent, lambda { { :conditions => ['created_at > ?', 1.week.ago] } }
end

# 用法
User.active    # same as User.find(:all, :conditions => {:active => true})
User.inactive # same as User.find(:all, :conditions => {:active => false})
User.recent   # same as User.find(:all, :conditions => ['created_at > ?', 1.week.ago])

# 还可以把他们组合起来组合用
User.active.recent
</pre><br /><br />你还可以传递参数：<br /><pre name="code" class="ruby">
class User &lt; ActiveRecord::Base
  named_scope :registered, lambda { |time_ago| { :conditions => ['created_at > ?', time_ago] }
end

User.registered 7.days.ago # same as User.find(:all, :conditions => ['created_at > ?', 7.days.ago])
</pre><br /><br />和对象关联定义类似，你还可以使用扩展：<br /><pre name="code" class="ruby">
class User &lt; ActiveRecord::Base
  named_scope :inactive, :conditions => {:active => false} do
    def activate
      each { |i| i.update_attribute(:active, true) }
    end
  end
end

# Re-activate all inactive users
User.inactive.activate
</pre><br /><br />Rails2.1这个新特性可以极大地简化查询代码组合，达到更好的代码重用率，我们JavaEye的很多查询代码都可以从这个新特性上获益。<br /><br /><br /><span style="font-size: medium">2. Dirty Objects</span><br /><br />Rails2.1添加了类似Hibernate的检查对象是否变更机制，但是在使用上比Hibernate更加简洁，功能更加强大：<br /><pre name="code" class="ruby">
article = Article.find(:first)
article.changed?  #=> false

# 它还可以单独检查某个属性是否变更过
# 使用  attr_name_changed? 方法
article.title  #=> "Title"
article.title = "New Title"
article.title_changed? #=> true

# 使用  attr_name_was 方法获取变更前的值
article.title_was  #=> "Title"

# 使用 attr_name_change 方法同时获取新旧2个值
article.title_change  #=> ["Title", "New Title"]
</pre><br /><br />这个新特性可以用来方便地做变更日志，状态改变监测等等多种用途，和原先需要自己写扩展代码相比要方便多了。<br /><br /><br /><span style="font-size: medium">3. Partial Updates</span><br /><br />在Dirty Objects的基础上，只更新对象变更属性的功能也加入了进来：<br /><pre name="code" class="ruby">
article = Article.find(:first)
article.title  #=> "Title"
article.subject  #=> "Edge Rails"

# 只更新一个属性
article.title = "New Title"

# 只有更新过的属性被执行了update操作
article.save
  #=>  "UPDATE articles SET title = 'New Title' WHERE id = 1"
</pre><br /><br />如果要使用这个特性，需要设置：<br /><pre name="code" class="ruby">
ActiveRecord::Base.partial_updates = true
</pre><br />partial updates会提高更新的性能，我们JavaEye的一些使用update_all操作的代码都可以改成使用partial updates了。<br /><br /><a href="http://ryandaigle.com/" target="_blank">http://ryandaigle.com/</a> 是一个国外的专门发布Rails新特性介绍的博客，除了上面提到的3点以外，还有一些特性值得关注：<br /><ul><li><a href="http://ryandaigle.com/articles/2008/4/1/what-s-new-in-edge-rails-gem-dependencies" target="_blank">Gem Dependencies</a></li><li><a href="http://ryandaigle.com/articles/2008/4/2/what-s-new-in-edge-rails-utc-based-migration-versioning" target="_blank">UTC-based Migration Versioning</a></li><li><a href="http://ryandaigle.com/articles/2008/3/24/what-s-new-in-edge-rails-has-one-through" target="_blank">Has One :through</a></li><li><a href="http://ryandaigle.com/articles/2008/1/25/what-s-new-in-edge-rails-easier-timezones" target="_blank">Easier Timezones</a></li></ul>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/189171#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sun, 04 May 2008 09:32:46 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/189171</link>
        <guid>http://quake.javaeye.com/blog/189171</guid>
      </item>
      <item>
        <title>使用libmemcached提速memcached的操作</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/187489" style="color:red;">http://quake.javaeye.com/blog/187489</a>&nbsp;
          发表时间: 2008年04月28日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://tangent.org/552/libmemcached.html" target="_blank">libmemcached</a>是一个基于C/C++实现的memcached client library，<a href="http://blog.evanweaver.com/files/doc/fauna/memcached/files/README.html" target="_blank">memcached gem</a>给这个library提供了ruby封装，根据原作者的性能评测，它比目前常用的memcache-client gem最多要<a href="http://blog.evanweaver.com/files/doc/fauna/memcached/files/BENCHMARKS.html" target="_blank">快150倍</a>。<br /><br />因为对memcache的操作在rails处理整个http请求中所占时间比例并不多，而且JavaEye网站大部分是做cache读取操作，于是做了2个试验测试一下2者对于提升整个网站的性能到底有多少帮助:<br />1. 测试访问JavaEye网站的首页，在这个请求中只有一个缓存读取操作，使用ab简单地跑单次请求10000次：<br />使用memcache-client，平均完成每个请求是9.247 ms<br />使用memcached，平均完成每个请求是8.982 ms<br /><br /><strong>对于整体性能提升在3%左右</strong><br /><br />2. 测试访问某个论坛版面的页面，整个请求有超过60次的缓存读取操作，使用ab简单跑单次请求1000次：<br />使用memcache-client，平均完成每个请求是95.872 ms<br />使用memcached，平均完成每个请求是91.591 ms<br /><br /><strong>对于整体性能提升在5%左右</strong><br /><br />从试验可以看出，对于整体性能还是有一定提高的。JavaEye用的cache插件是cache_fu，它只支持memcache-client，不过通过简单的修改就可以支持这个新gem，我提交了一个补丁，有兴趣的话可以从这里下载到<a href="https://groups.google.com/group/acts_as_cached/browse_thread/thread/ff2eaea0c3c61611" target="_blank">补丁</a>。<br /><br />--分割线--<br />cache_fu的作者已经将这个补丁添加到代码树，可以从github checkout:  <a href="http://github.com/defunkt/cache_fu/tree/master" target="_blank">http://github.com/defunkt/cache_fu/tree/master</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/187489#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 28 Apr 2008 12:03:18 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/187489</link>
        <guid>http://quake.javaeye.com/blog/187489</guid>
      </item>
      <item>
        <title>爸爸是属什么的？</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/185621" style="color:red;">http://quake.javaeye.com/blog/185621</a>&nbsp;
          发表时间: 2008年04月22日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          幼儿园的老师在教小家伙们学习十二生肖<br /><br />老师：你是属什么的？<br />儿子：属小鸭子的<br /><br />...十二生肖什么时候有了鸭子？老师强忍住笑<br /><br />老师：妈妈是属什么的？<br />儿子：属蛇的<br /><br />不错，有进步<br /><br />老师再问：爸爸是属什么的？<br />儿子：属自行车的<br /><br />...这下再也忍不住了，笑倒一片老师<br /><br /><br /><br /><img src="http://quake.javaeye.com/upload/attachment/21427/8bbc9513-c94d-3b86-b038-150941d9c841.jpg" />
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/185621#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 22 Apr 2008 21:03:34 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/185621</link>
        <guid>http://quake.javaeye.com/blog/185621</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 容易记的电话号码</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/183412" style="color:red;">http://quake.javaeye.com/blog/183412</a>&nbsp;
          发表时间: 2008年04月16日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby每周一测 - <a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a> 是Ruby Talk邮件列表上的一个持续了很长时间活动，每周有一个小题目被提出来，然后大家进行解答讨论。Amazon上还有相关的书： <a href="http://www.amazon.com/Best-Ruby-Quiz-Pragmatic-Programmers/dp/0976694077" target="_blank">Best of Ruby Quiz</a>。我尝试挑选其中的一些题目进行翻译，做一个每周一测系列，欢迎大家参与讨论。<br /><br />-----题目分割线-----<br /><br />以前在国外的影视或者广告中看到出现含字母的电话号码，比如1-800-PICK-UPS (美国UPS快递号码)，心中不免有些疑惑：难道国外的电话是可以拨字母的？后来请教国外朋友，才明白这个疑问有点傻有点天真<img src="/images/smiles/icon_smile.gif"/> 看一下常见的电话键盘：<br /><img src="http://www.javaeye.com/topics/download/8c4abc11-ff4a-33a4-b70a-eda64ebaf69d" /><br />每个数字旁边都有3个或者4个字母对应，那么上面这个电话号码其实就是1-800-7425-877，这样就把一个难记的电话号码通过简单的单词记住了。这周的题目就是完成下面这个方法，通过查找字典把输入的数字变成可能的字母输出，比如输入8737829得到USE-RUBY，为了编程简单，这里假设字典文件已经被读取到一个words的数组里面作为参数传递：<br /><pre name="code" class="ruby">
def build_word_list(number, words = %w{USE RUBY} , mapping = %w{ABC DEF GHI JKL MNO PQRS TUV WXYZ}, delimeter = "-")
  
end
</pre><br /><br />-----解答分割线-----<br />原题和一些解法在这里：<a href="http://rubyquiz.com/quiz20.html" target="_blank">http://rubyquiz.com/quiz20.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/183412#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 16 Apr 2008 15:40:57 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/183412</link>
        <guid>http://quake.javaeye.com/blog/183412</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 液晶屏数字</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/178880" style="color:red;">http://quake.javaeye.com/blog/178880</a>&nbsp;
          发表时间: 2008年04月02日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby每周一测 - <a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a> 是Ruby Talk邮件列表上的一个持续了很长时间活动，每周有一个小题目被提出来，然后大家进行解答讨论。Amazon上还有相关的书： <a href="http://www.amazon.com/Best-Ruby-Quiz-Pragmatic-Programmers/dp/0976694077" target="_blank">Best of Ruby Quiz</a>。我尝试挑选其中的一些题目进行翻译，做一个每周一测系列，欢迎大家参与讨论。<br /><br />-----题目分割线-----<br /><br />我们会在很多地方看到液晶屏样式显示的数字，比方说DVD/微波炉显示时间，常见的实现是利用7个发光二极管来做的：<br /><img src="http://www.javaeye.com/topics/download/634529e7-0055-3f42-bd7c-6a39f61587c8" /><br /><br />这周的题目就是完成下面这个class，调用display方法进行液晶数字显示：<br /><pre name="code" class="ruby">
class LCD
	def initialize(scale=1)
		
	end

	def display(digits)	
	
	end
end
</pre><br /><br />输出举例：<br /><pre name="code" class="ruby">
> lcd = Lcd.new
> puts lcd.display(86)
 -  -
| ||
 -  -
| || |
 -  -
</pre><br /><br />这里采用"-", "|" 和空格进行输出， 并且scale参数能够指定输出样式的大小，在上面的例子中如果指定scale为2，输出结果就会变成：<br /><pre name="code" class="ruby">
> lcd = Lcd.new(2)
> puts lcd.display(86)
 --  --
|  ||
|  ||
 --  -- 
|  ||  |
|  ||  |
 --  -- 
</pre><br /><br /><br />-----解答分割线-----<br />原题和一些解法在这里：<a href="http://rubyquiz.com/quiz14.html" target="_blank">http://rubyquiz.com/quiz14.html</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/178880#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Wed, 02 Apr 2008 16:08:05 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/178880</link>
        <guid>http://quake.javaeye.com/blog/178880</guid>
      </item>
      <item>
        <title>Ruby每周一测 - 找零钱</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/175886" style="color:red;">http://quake.javaeye.com/blog/175886</a>&nbsp;
          发表时间: 2008年03月25日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Ruby每周一测 - <a href="http://rubyquiz.com/" target="_blank">Ruby Quiz</a> 是Ruby Talk邮件列表上的一个持续了很长时间活动，每周有一个小题目被提出来，然后大家进行解答讨论。Amazon上还有相关的书： <a href="http://www.amazon.com/Best-Ruby-Quiz-Pragmatic-Programmers/dp/0976694077" target="_blank">Best of Ruby Quiz</a>。我尝试挑选其中的一些题目进行翻译，做一个每周一测系列，欢迎大家参与讨论。<br /><br />-----题目分割线-----<br /><br />这周的题目是找零钱，假设我们需要找给别人39美分的零钱，那么结果将会是(美元的硬币有25,10,5,1这种)：<br /><pre name="code" class="ruby">
>> make_change(39)
=> [25, 10, 1, 1, 1, 1]
</pre><br /><br />假设我们的硬币种类有10,7,1，那么找14美分的零钱结果将会是：<br /><pre name="code" class="ruby">
>> make_change(14, [10, 7, 1])
=> [7, 7]
</pre><br /><br />这次的每周一测就是完成该方法： <br /><pre name="code" class="ruby">
def make_change(amount, coins = [25, 10, 5, 1])

end
</pre><br /><br />这个方法应该返回最优化的结果，即总的零钱个数最少。<br />另外，为了编程方便，这里假设coins已经是排序完毕的，并且如果无解的话，返回nil： make_change(5, coins = [4,2]) => nil<br /><br /><br />-----解答分割线-----<br />原题和一些解法在这里：<a href="http://rubyquiz.com/quiz154.html" target="_blank">http://rubyquiz.com/quiz154.html</a><br />原文的解答说明简单翻译见：<a href="http://www.javaeye.com/post/501439" target="_blank">http://www.javaeye.com/post/501439</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/175886#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 25 Mar 2008 16:23:32 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/175886</link>
        <guid>http://quake.javaeye.com/blog/175886</guid>
      </item>
      <item>
        <title>一个奇怪的JS导致Firefox Session Restore失效问题</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/173024" style="color:red;">http://quake.javaeye.com/blog/173024</a>&nbsp;
          发表时间: 2008年03月17日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Firefox有一个很有用的Session Restore功能：当浏览器由于异常原因崩溃或者不小心点了刷新按钮时候，能够自动保留之前填写的数据。<br />但是JavaEye的编辑器不知道什么原因导致这个功能失效，经过调试代码发现了能够重现这个问题的一个简单例子：<br /><pre name="code" class="html">
&lt;html>
&lt;body>
&lt;div id="d">&lt;/div>
&lt;textarea style="width: 300px; height: 300px;">&lt;/textarea>
&lt;script>
var new_div = document.createElement('div');
document.getElementById('d').appendChild(new_div);
new_div.innerHTML = "&lt;input type='button' value='a'/>";
&lt;/script>
&lt;/body>
&lt;/html>
</pre><br />用Firefox打开这个html，在textarea里面随便填写一些内容，然后刷新，这些内容就丢失了。<br />但是令人费解的时候，如果innerHTML里面写的不是input，而且其他html，比如：<br /><pre name="code" class="html">
new_div.innerHTML = "&lt;a href='#'>test&lt;/a>";
</pre><br />这样刷新页面，textarea里面的内容就能够正常保持。<br /><br />更令人费解的是，只要调整一下第3行和第4行代码的顺序，这个问题也不会出现。<br />以上情况在Firefox2 @ Ubuntu 7.10或者Windows上都可以重现， 初步怀疑是Firefox的Session Restore bug， 不过在它的bug list上也没有找到，不知道大家有没有遇到过类似问题？
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/173024#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Mon, 17 Mar 2008 15:32:13 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/173024</link>
        <guid>http://quake.javaeye.com/blog/173024</guid>
      </item>
      <item>
        <title>Try() 和 Maybe Monad</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/169001" style="color:red;">http://quake.javaeye.com/blog/169001</a>&nbsp;
          发表时间: 2008年03月07日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在Ruby里用到对象图导航(Object Graph Navigation)的时候，有时候需要判断对象是否为nil，很常见这样的代码：<br /><pre name="code" class="ruby">
#显示某个产品的分类名称
product.category ? product.category.name : nil
</pre><br />ozmm.org的chris最近介绍了一个好方法，他给这个方法起名叫<a href="http://ozmm.org/posts/try.html" target="_blank">try()</a>，给Object添加一个try方法：<br /><pre name="code" class="ruby">
class Object
  def try(method)
    send method if respond_to? method
  end
end
</pre><br />这样上面的代码就可以简化成<br /><pre name="code" class="ruby">
product.category.try(:name)
</pre><br /><br />这个try的实际用途很多，比如:<br /><pre name="code" class="ruby">
#删除某个可能存在的用户
User.find_by_name("JavaEye").try(:destroy)
#找出最后一个未激活用户的名字
User.find_all_by_active(false).last.try(:name)
</pre><br /><br />但是这个简单的try()有很多限制，比如原先这样的代码就不能解决:<br /><pre name="code" class="ruby">
#默认值
product.category ? product.category.name : "N/A"
#多层对象图导航
product.category.owner.name
</pre><br /><br />对此Anders Engström提供了一个<a href="http://www.gnejs.net/2008/03/02/improved-try/" target="_blank">Improved 'try()'</a>，上面的代码可以简化成<br /><pre name="code" class="ruby">
product.category.try(:name, :default => "N/A")
product.category.try(:owner, :name)
</pre><br /><br />但是又有人觉得这样不够直观了，提供了一个类似Groovy做法的: <a href="http://www.urubatan.info/2008/03/a-better-try-for-ruby-why-not-do-the-groovy-way/" target="_blank">A better “try()” for Ruby, why not do the Groovy way?</a><br />Groovy语言本身提供了内置的?.操作: person?.name，而上面这篇文章则通过在方法名后面添加"_"来实现相同的目的<br /><pre name="code" class="ruby">
product.category.owner_.name_
</pre><br /><br />Q1: 和方法2相比，它少了一个默认值的处理，大家觉得添加这样的特性如何？<br /><pre name="code" class="ruby">
product.category.name_(:default => "N/A")
</pre><br /><br />上面这3种try()方法都是通过method missing实现的，这篇文章提到的<a href="http://blog.pretheory.com/arch/2008/02/the_maybe_monad_in_ruby.php" target="_blank">Maybe Monad</a>也可以解决这个问题：<br /><pre name="code" class="ruby">
Maybe.new(product).category.name.value("N/A")
</pre><br /><br />Q2: 这些方法你更喜欢用哪一种呢？或者你有其他更好的方法？欢迎讨论。<br />我比较喜欢方法2，感觉代码侵入比较小，缺点是多层导航的时候不够直观。而方法4Maybe Monad的优缺点正好与之相反，如果能综合这2种方法就好了。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/169001#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Fri, 07 Mar 2008 11:44:51 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/169001</link>
        <guid>http://quake.javaeye.com/blog/169001</guid>
      </item>
      <item>
        <title>Google Chart API简介</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/154774" style="color:red;">http://quake.javaeye.com/blog/154774</a>&nbsp;
          发表时间: 2008年01月10日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://code.google.com/apis/chart" target="_blank">Google Chart API</a>能够让我们利用URL传递参数来产生图表，比如简单的这样一句HTML代码：<br /><pre name="code" class="xml">
&lt;img src="http://chart.apis.google.com/chart?cht=bvs&chs=200x125&chd=s:JavaEye" />
</pre><br />就可以产生柱状图：<br /><img src="http://chart.apis.google.com/chart?cht=bvs&chs=200x125&chd=s:JavaEye" /><br /><br />通过查看上面的URL，共有3个参数：<br /><div class="quote_title">引用</div><div class="quote_div"><br /><strong>cht: </strong> 代表了图表的类型（Chart Type的缩写），在上面的例子中bvs是代表垂直格式的Bar Chart<br /><strong>chs: </strong> 代表了图表的大小（Chart Size的缩写），在上面的例子中就是宽200px，高125px<br /><strong>chd: </strong> 代表了图表的数据 （Chart Data的缩写），在上面的例子中s:JavaEye代表什么意思呢？允许我卖个小关子，后面再介绍<br /></div><br /><br />我们再来看一个稍微复杂点的例子：<br /><pre name="code" class="xml">
&lt;img src="http://chart.apis.google.com/chart?chtt=JavaEye&cht=p3&chs=300x150&chd=s:JavaEye&chl=J|a|v|a|E|y|e" />
</pre><br /><br /><img src="http://chart.apis.google.com/chart?chtt=JavaEye&cht=p3&chs=300x150&chd=s:JavaEye&chl=J|a|v|a|E|y|e" /><br /><br />和第一个例子相比，多了2个参数：<br /><div class="quote_title">引用</div><div class="quote_div"><br /><strong>chtt: </strong> 代表了图表的标题（Chart Title的缩写）<br /><strong>chl: </strong>  代表了图表项标签（Chart Label的缩写），在上面的例子中用竖线(|)分割的JavaEye正好对应到每个数据项<br /></div><br /><br />现在让我来解开前面的小关子：<br /><div class="quote_title">引用</div><div class="quote_div"><br /><strong>chd: </strong> 代表了图表的数据 ，在第一个例子中的s:JavaEye代表用字符串编码，A~Z代表0~25, a~z代表26~51，Google Chart API会根据每个字符所对应的值计算出其比例，然后画出图表。除了这种简单编码外，它还支持多种其他编码，具体文档<a href="http://code.google.com/apis/chart/#chart_data" target="_blank">请看这里</a>。<br /></div><br /><br />Google提供的这个API对于做一些简单图表来说是非常好用的工具，举一个实际的例子，比方说我有某段时间内JavaEye网站的访问次数的IP分布数据：<br /><div class="quote_title">引用</div><div class="quote_div"><br />Beijing		238,471<br />Shanghai	133,918<br />Guangzhou	68,786<br />Shenzhen	59,093<br />Hangzhou	47,626<br />Chengdu		30,700<br />Nanjing		28,799<br />Wuhan		27,535<br />Xian		18,240<br />Changsha	17,013 	<br /></div><br /><br />我们把数据转换成0~100直接的小数，用chd=t:23.8471,13.3918...传递，还可以用chco设置颜色和透明度（0000FF - 蓝色, 50 - 50%的透明度）:<br /><pre name="code" class="xml">
&lt;img src="http://chart.apis.google.com/chart?chtt=JavaEye%20Cities&cht=p3&chs=700x350&chd=t:23.8471,13.3918,6.8786,5.9093,4.7626,3.0700,2.899,2.7535,1.8240,1.7013&chl=Beijing|Shanghai|Guangzhou|Shenzhen|Hangzhou|Chengdu|Nanjing|Wuhan|Xian|Changsha&chco=0000FF50"/>
</pre><br /><br /><img src="http://chart.apis.google.com/chart?chtt=JavaEye%20Cities&cht=p3&chs=700x350&chd=t:23.8471,13.3918,6.8786,5.9093,4.7626,3.0700,2.899,2.7535,1.8240,1.7013&chl=Beijing|Shanghai|Guangzhou|Shenzhen|Hangzhou|Chengdu|Nanjing|Wuhan|Xian|Changsha&chco=0000FF50" /><br /><br />更多图表文档，例子请访问官方网站： <a href="http://code.google.com/apis/chart" target="_blank">http://code.google.com/apis/chart</a><br /><br />参考资料：<br /><a href="http://24ways.org/2007/tracking-christmas-cheer-with-google-charts" target="_blank">Tracking Christmas Cheer with Google Charts</a><br /><a href="http://www.wait-till-i.com/2008/01/08/generating-charts-from-accessible-data-tables-using-the-google-charts-api/" target="_blank">Using Google Charts from accessible data table</a>
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/154774#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 10 Jan 2008 15:52:49 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/154774</link>
        <guid>http://quake.javaeye.com/blog/154774</guid>
      </item>
      <item>
        <title>美化Android - 自动墙纸切换器（二）</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/146942" style="color:red;">http://quake.javaeye.com/blog/146942</a>&nbsp;
          发表时间: 2007年12月08日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在前一篇博客里面，我记录了如何实现一个<a href="http://quake.javaeye.com/blog/142151" target="_blank">简单的文件浏览器</a>，今天记录实现图片选择，预览以及墙纸切换的功能。在代码之前先看一下实现的最终效果：<br />图片查看器：<br /><img src="http://www.javaeye.com/topics/download/f9991752-b9eb-4b0c-a6ac-4493652351f2" /><br />变更了墙纸以后的模拟器：<br /><img src="http://www.javaeye.com/topics/download/1d9f027e-37a5-413a-a919-b3600f29d120" /><br /><br />首先在文件浏览器的onListItemClick方法中加上图片文件的相应事件：<br /><pre name="code" class="java">
  protected void onListItemClick(ListView l, View v, int position, long id) {
    File file = fileList.getItem(position);
    if (file.isDirectory()) {
      fill(file);
    } else {
      File[] images = file.getParentFile().listFiles(IMAGES_FILTER);
      String[] files = new String[images.length];
      for (int i = 0; i &lt; images.length; i++) {
        files[i] = images[i].getAbsolutePath();
      }
      Intent i = new Intent(this, ImageSelector.class);
      i.putExtra(ImageSelector.KEY_FILES, files);
      startSubActivity(i, 0);
    }
</pre><br />这里利用Intent来转递选中的图片文件(files数组)，然后调用startSubActivity方法启动ImageSelector。<br />ImageSelector的代码大部分是参考ApiDemo中的ImageSwitcher，所不同的是，我们要显示的资源是文件系统上的图片，而ApiDemo中是用Resource文件来作的，所以需要改写一下getView方法：<br /><pre name="code" class="java">
    public View getView(int position, View convertView, ViewGroup parent) {
      ImageView i = new ImageView(mContext);
      i.setImageDrawable(ImageSelector.buildDrawable(files[position]));
      i.setAdjustViewBounds(true);
      i.setLayoutParams(new Gallery.LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
      i.setBackground(android.R.drawable.picture_frame);
      return i;
    }
</pre><br /><br />这里我被Android的API困扰了很久，原先认为API中的setImageURI方法应该就可以用文件系统上的图片作为ImageView的内容：<br /><pre name="code" class="java">
i.setImageURI(ContentURI.create(new File(files[position])));
</pre><br />但是怎么都无法生效，后来通过google找到了另外一种做法：<br /><pre name="code" class="java">
  private static Drawable buildDrawable(String filePath) {
    InputStream is = null;
    try {
      URLConnection connection = new URL("file://" + filePath).openConnection();
      is = connection.getInputStream();
      return Drawable.createFromStream(is, filePath);
///...
}
</pre><br />具体原因是什么，只能等Google完全发表android的源代码才能知道了。<br /><br />当用户点击图片的时候，设置为墙纸：<br /><pre name="code" class="java">
  public void onItemClick(AdapterView parent, View v, int position, long id) {
    try {
      URLConnection connection = new URL("file://" + files[position]).openConnection();
      parent.getContext().setWallpaper(connection.getInputStream());
    } catch (IOException e) {
      e.printStackTrace();
    }
    finish();
  }
</pre><br /><br />这样离最终要实现的自动切换墙纸就差2个功能了：<br />1. 用数据库（或则其他方式）记录用户选择的多个墙纸。<br />2. 定时（Service)从这些墙纸中随机选择一个。<br />将会在后续的博客中补上，附件3是目前这些功能的所有代码，你可以下载代码在模拟器中运行，你可能还需要参考一下<a href="http://quake.javaeye.com/blog/142018" target="_blank">如何模拟SDCard这篇文章</a>，把一些图片文件放到SDCard中，让它作为墙纸切换。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/146942#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Sat, 08 Dec 2007 21:37:00 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/146942</link>
        <guid>http://quake.javaeye.com/blog/146942</guid>
      </item>
      <item>
        <title>美化Android - 自动墙纸切换器（一）</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/142151" style="color:red;">http://quake.javaeye.com/blog/142151</a>&nbsp;
          发表时间: 2007年11月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          Android模拟器本身带了一个墙纸切换程序，但是这个功能只能在有限的2张图片中选择，我尝试着实现一个自己的自动墙纸切换程序，它能够从手机的资源中（包括<a href="http://quake.javaeye.com/blog/142018" target="_blank">SD卡</a>)选择多张你想要作为桌面的图片，然后定时切换墙纸。在这里我记录整个开发的过程和大家共享，讨论。<br /><br />首先我们需要实现一个简单的资源管理器，能够浏览手机里面的图片资源：<br /><img src="http://www.javaeye.com/topics/download/ea0914b8-d64b-4b10-8588-422e389edf73" /><br /><br />参考官方文档里面的<a href="http://code.google.com/android/intro/tutorial.html#exercises" target="_blank">3个练习</a>，我在这里采用ListActivity作为显示资源的界面：<br />1. 建立一个Activity，让它extends ListActivity<br /><pre name="code" class="java">
public class WallpaperSwitcher extends ListActivity {
	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.directory_list);
		//默认显示根目录
		fill(new File("/"));
	}
}
</pre><br /><br />2. directory_list.xml内容如下：<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content">

	&lt;ListView id="@id/android:list" android:layout_width="wrap_content"
		android:layout_height="wrap_content" />
&lt;/LinearLayout>
</pre><br /><br />3. 用来显示每行文件名的file_row.xml内容也很简单：<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;TextView id="@+id/text1"
	xmlns:android="http://schemas.android.com/apk/res/android"
	android:layout_width="wrap_content"
	android:layout_height="wrap_content" />
</pre><br /><br />4. 填充ListView的代码如下：<br /><pre name="code" class="java">
	private void fill(File folder) {
		List&lt;File> files = new ArrayList&lt;File>();
		files.add(folder);
		if (folder.getParentFile() != null)
			files.add(folder.getParentFile());

		for (File file : folder.listFiles(IMAGES_FILTER)) {
			files.add(file);
		}

		fileList = new FileListAdapter(this, R.layout.file_row, files);
		setListAdapter(fileList);
	}
</pre><br />这里用到了一个FileFilter来过滤图片和目录：<br /><pre name="code" class="java">
	private static final FileFilter IMAGES_FILTER = new FileFilter() {
		@Override
		public boolean accept(File f) {
			return f.isDirectory() || f.getName().matches("^.*?\\.(jpg|png|bmp|gif)$");
		}
	};
</pre><br />并且我把当前目录放到了List的第一个，上级目录放到了List的第二个，这样就能实现前面界面中的效果了。<br /><br />5. 写一个 FileListAdapter，用于控制界面的显示：<br /><pre name="code" class="java">
  public View getView(int position, View convertView, ViewGroup parent) {
    TextView view = (TextView) super.getView(position, convertView, parent);
    File file = getItem(position);
    if (position == 0)
      view.setText(view.getResources().getString(R.string.current_folder) + file.getAbsolutePath());
    else if (position == 1 && !isRoot())
      view.setText(R.string.to_parent_folder);
    else
      view.setText(file.getName());
    return view;
  }
</pre><br /><br />6. 我还希望能够用后退键(ESC)，能够返回上级目录，那么：<br /><pre name="code" class="java">
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		if (keyCode == KeyEvent.KEYCODE_BACK && !fileList.isRoot()) {
			fill(fileList.getItem(1));
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}
</pre><br /><br />这样一个简单的资源浏览器就完成了，附件是已经打包好的代码。<br />今天就先告一段落，明天继续实现图片显示功能...
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/142151#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 20 Nov 2007 20:45:00 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/142151</link>
        <guid>http://quake.javaeye.com/blog/142151</guid>
      </item>
      <item>
        <title>在Google Android模拟器中使用SD卡</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/142018" style="color:red;">http://quake.javaeye.com/blog/142018</a>&nbsp;
          发表时间: 2007年11月20日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          从<a href="http://code.google.com/android/reference/othertools.html#mksdcard" target="_blank">文档</a>上看，Android模拟器能够让我们使用fat32格式的磁盘镜像作为SD卡的模拟，今天尝试了一下，把过程记录下来和大家分享：<br />1. 进入Android SDK目录下的tools子目录，运行<br />mksdcard -l sdcard 512M /your_path_for_img/sdcard.img<br />这样就创建了一个512M的SD卡镜像文件<br /><br />2. 运行模拟器的时候指定路径(注意需要完整路径)：<br />emulator -sdcard /your_path_for_img/sdcard.img<br />这样模拟器中就可以使用"/sdcard"这个路径来指向模拟的SD卡了<br /><br />那么如何拷贝本机文件到SD卡，或者管理SD卡上的内容呢？<br />A. 在linux下面我们可以mount成一个loop设备，先创建一个目录，比如叫android_sdcard，然后执行：<br />mount -o loop sdcard.img android_sdcard<br />这样管理这个目录就是管理sdcard内容了<br /><br />B. 在windows下面我们可以用mtools来做管理，也可以用android SDK带的命令(这个命令在linux下面也可以用)：<br />adb push local_file sdcard/remote_file
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/142018#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Tue, 20 Nov 2007 13:29:02 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/142018</link>
        <guid>http://quake.javaeye.com/blog/142018</guid>
      </item>
      <item>
        <title>Google Android尝鲜 - 计算器小程序</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/141029" style="color:red;">http://quake.javaeye.com/blog/141029</a>&nbsp;
          发表时间: 2007年11月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          在看了Google Android的<a href="http://code.google.com/android/intro/hello-android.html" target="_blank">入门文档Hello World</a>以后，不禁有点手痒，想自己做点小东西试试看。<br /><br />经过1个多小时的尝试和摸索，终于做出自己的第一个作品：<br /><img src="http://www.javaeye.com/topics/download/974eace8-cb41-44fa-8855-14990f433d3e" /><br /><br />主文件很简单：<br /><pre name="code" class="java">
public class Calculator extends Activity {
	private static EditText et;
	private static Interpreter i = new Interpreter();
	
    @Override
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main);        
        et = (EditText)findViewById(R.id.edittext);
        et.append("\n");
        et.setSelection(et.length());//调整光标到最后一行
    }
    
    @Override
    public boolean onKeyUp(int keyCode, KeyEvent event) {
    	if (keyCode == KeyEvent.KEYCODE_NEWLINE) {
    		String input = et.getText().toString();
    		//这里用偷懒的方式取用户最后一行输入                
    		String lastLine = input.substring(input.lastIndexOf("\n", input.length() - 2));
    		et.append("\t\t" + eval(lastLine) + "\n");
        	et.setSelection(et.length());    		
    	}
    	return true;
    }
    
    //用beanshell偷懒来做算式计算
    private Object eval(String input) {
    	try {
			return i.eval(input);
		} catch (EvalError e) {
			return e.getMessage();
		}
    }
}
</pre><br /><br />layout文件也很简单 （EditText的digits属性可以让我们指定允许输入哪些值，如果支持正则表达式就更好了）：<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
&lt;EditText id="@+id/edittext"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:digits="1234567890.+-*/%\n()"
    android:text="@string/help_text"
    />
&lt;/LinearLayout>
</pre><br /><br />Android的SDK确实做得不错，像我这样从来没有做过手机开发的人，通过阅读文档和例子也能很快入门，感觉未来Java在移动平台上的开发也会随着Android发展得越来越快。<br /><br />附件2是这个小程序的打包源代码，在Eclipse引入就可以看到实际运行效果了，欢迎大家沟通交流。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/141029#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 Nov 2007 23:31:00 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/141029</link>
        <guid>http://quake.javaeye.com/blog/141029</guid>
      </item>
      <item>
        <title>Android初体验</title>
        <author>Quake Wang</author>
        <description>
          <![CDATA[
          <br/>
          作者: <a href="http://quake.javaeye.com">Quake Wang</a>&nbsp;
          链接：<a href="http://quake.javaeye.com/blog/140989" style="color:red;">http://quake.javaeye.com/blog/140989</a>&nbsp;
          发表时间: 2007年11月15日
          <br/><br/>
          声明：本文系JavaEye网站发布的原创博客文章，未经作者书面许可，严禁任何网站转载本文，否则必将追究法律责任！
          <br/><br/>
          <a href="http://code.google.com/android/" target="_blank">Android</a>是Google主导的开放式手机平台，它的应用是基于Java语言开发的，今天下载了它的SDK，体验了一把：<br /><br />首先按照官方网站上的<a href="http://code.google.com/android/intro/installing.html" target="_blank">安装SDK文档</a>下载了Android SDK和Eclipse插件.<br /><br />然后按照官方网站上的入门文档<a href="http://code.google.com/android/intro/hello-android.html" target="_blank">Hello, Android!</a>，开始写第一个Android应用<br /><br />比较有意思的是，Android的界面布局除了Java API以外，还提供了基于XML的定义，在res/layout/main.xml文件里面写上这样的内容：<br /><pre name="code" class="xml">
&lt;?xml version="1.0" encoding="utf-8"?>
&lt;LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
&lt;TextView  
    android:layout_width="fill_parent" 
    android:layout_height="wrap_content" 
    android:text="Hello, Android"
    />
&lt;/LinearLayout>
</pre><br /><br />然后在Java代码里面这样调用：<br /><pre name="code" class="java">
    public void onCreate(Bundle icicle) {
        super.onCreate(icicle);
        setContentView(R.layout.main); //插件自动生成常量定义
    }
</pre><br />就可以显示出这样的界面：<br /><img src="http://code.google.com/android/images/hello_world_5.png" /><br /><br />上面的界面是SDK带的模拟器界面，它有很多启动参数和设置，比如模拟不同的分辨率、网络速度，具体的内容可以参考<a href="http://code.google.com/android/reference/emulator.html" target="_blank">官方文档</a><br /><br />Android的SDK还带了很多例子，也是非常好的学习资料，值得一看。
          <br/>
          <span style="color:red;">
            <a href="http://quake.javaeye.com/blog/140989#comments" style="color:red;">本文的讨论也很精彩，浏览讨论>></a>
          </span>
          <br/><br/><br/>
          <span style="color:#E28822;">JavaEye推荐</span>
          <br/>
          <ul class='adverts'><li><a href='/adverts/41' target='_blank'><span style="color:red;font-weight:bold;">北京: 千橡集团暨校内网诚聘软件研发工程师</span></a></li><li><a href='/adverts/42' target='_blank'><span style="color:red;font-weight:bold;">搜狐网站诚聘Java、PHP和C++工程师</span></a></li><li><a href='/adverts/92' target='_blank'><span style="color:red;font-weight:bold;">快来参加7月17日在成都举行的SOA中国技术论坛</span></a></li><li><a href='/adverts/97' target='_blank'><span style="color:blue;font-weight:bold;">Oracle专区上线，有Oracle最新文章，重要下载及知识库等精彩内容，欢迎访问。</span></a></li><li><a href='/adverts/106' target='_blank'><span style="color:blue;font-weight:bold;">JavaEye问答大赛开始了！ 从6月23日 至 7月6日，奖品丰厚 ！</span></a></li></ul>
          <br/><br/><br/>
          ]]>
        </description>
        <pubDate>Thu, 15 Nov 2007 18:45:09 +0800</pubDate>
        <link>http://quake.javaeye.com/blog/140989</link>
        <guid>http://quake.javaeye.com/blog/140989</guid>
      </item>
  </channel>
</rss>