<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>LetRails &#187; Ruby</title>
	<atom:link href="http://www.letrails.cn/archives/category/ruby/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.letrails.cn</link>
	<description>为Ruby on Rails在中文社区的枝繁叶茂贡献点滴</description>
	<lastBuildDate>Fri, 10 Sep 2010 13:27:14 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Roxy: Ruby代理库</title>
		<link>http://www.letrails.cn/archives/roxy-a-ruby-proxy-library/</link>
		<comments>http://www.letrails.cn/archives/roxy-a-ruby-proxy-library/#comments</comments>
		<pubDate>Tue, 02 Dec 2008 16:41:01 +0000</pubDate>
		<dc:creator>yuanyi</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/roxy-a-ruby-proxy-library</guid>
		<description><![CDATA[Roxy是Ryan Daigle写的一个Ruby代理库，它可以让你轻松的向关联对象添加方法，就像has_many为关联对象添加的build和create方法那样，比如： require 'roxy' class Person &#160;&#160;include Roxy::Moxie &#160;&#160;attr_accessor :first, :last, :parents &#160;&#160;proxy :parents do &#160;&#160;&#160;&#160;def divorced? &#160;&#160;&#160;&#160;&#160;&#160;proxy_target.size > 1 and proxy_target.collect { &#124;parent&#124; parent.last }.uniq.size > 1 &#160;&#160;&#160;&#160;end &#160;&#160;end end 现在你就可以直接在person.parents上直接调用divorced?方法了， -&#62; person.parents.divorced? => true&#124;false 当然如果只是简单的修改find条件，那么named_scope无疑是个更好的选择，更多信息及安装方法请看这里。]]></description>
			<content:encoded><![CDATA[<p><a href="http://github.com/yfactorial/roxy/tree/master">Roxy</a>是Ryan Daigle写的一个Ruby代理库，它可以让你轻松的向关联对象添加方法，就像has_many为关联对象添加的build和create方法那样，比如：</p>
<p class="code"><code class="ruby">require 'roxy'<br />
class Person<br />
&nbsp;&nbsp;include Roxy::Moxie<br />
&nbsp;&nbsp;attr_accessor :first, :last, :parents<br />
&nbsp;&nbsp;proxy :parents do<br />
&nbsp;&nbsp;&nbsp;&nbsp;def divorced?<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;proxy_target.size > 1 and proxy_target.collect { |parent| parent.last }.uniq.size > 1<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>现在你就可以直接在person.parents上直接调用divorced?方法了，</p>
<p class="code"><code class="ruby"><br />
-&gt; person.parents.divorced? => true|false<br />
</code></p>
<p>当然如果只是简单的修改find条件，那么named_scope无疑是个更好的选择，<a href="http://ryandaigle.com/articles/2008/11/10/implement-ruby-proxy-objects-with-roxy">更多信息及安装方法请看这里</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/roxy-a-ruby-proxy-library/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Writing Efficient Ruby Code Short Cut</title>
		<link>http://www.letrails.cn/archives/writing-efficient-ruby-code-review/</link>
		<comments>http://www.letrails.cn/archives/writing-efficient-ruby-code-review/#comments</comments>
		<pubDate>Wed, 05 Mar 2008 09:44:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/writing-efficient-ruby-code-review</guid>
		<description><![CDATA[这本书目前只完成了第一章，不过出版社已经迫不及待的发售了Shortcut版本（有点类似电影宣传片，但是价格不菲），这本书的作者Stefan Kaes就是Letrails上访问量最高的文章之一《Rails应用优化指南》的作者。书中的内容主要来自作者参与Rails Core开发以及他自己的几个Rails咨询项目中的经验。 至于Shortcut，只有48页，主要讲了一些Ruby编程的最佳实践，有些内容《Rails应用优化指南》也有讲到，对于编写高质量的Ruby代码还是有帮助的，但12刀的价格，尽管RMB持续升值，性价比仍然过低（且大部分内容根据目录标题应该都可以谷歌到），还是期待整书面世。]]></description>
			<content:encoded><![CDATA[<p><img src='http://lilac.greatweb.cn/rails/wp-content/uploads/2008/03/showcover-1aspx.jpeg' alt='showcover-1aspx.jpeg' /></p>
<p>这本书目前只完成了第一章，不过出版社已经迫不及待的发售了<a href="http://www.informit.com/store/product.aspx?isbn=0321540034&amp;rl=1">Shortcut版本</a>（有点类似电影宣传片，但是价格不菲），这本书的作者<a href="http://railsexpress.de/blog/">Stefan Kaes</a>就是Letrails上访问量最高的文章之一《<a href="http://www.letrails.cn/archives/12">Rails应用优化指南</a>》的作者。书中的内容主要来自作者参与Rails Core开发以及他自己的几个Rails咨询项目中的经验。</p>
<p>至于Shortcut，只有48页，主要讲了一些Ruby编程的最佳实践，有些内容《Rails应用优化指南》也有讲到，对于编写高质量的Ruby代码还是有帮助的，但12刀的价格，尽管RMB持续升值，性价比仍然过低（且大部分内容根据目录标题应该都可以谷歌到），还是期待整书面世。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/writing-efficient-ruby-code-review/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Matz在Google Tech Talks上的演讲</title>
		<link>http://www.letrails.cn/archives/google-tech-talks-matz-ruby-1-9/</link>
		<comments>http://www.letrails.cn/archives/google-tech-talks-matz-ruby-1-9/#comments</comments>
		<pubDate>Tue, 26 Feb 2008 07:14:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/google-tech-talks-matz-ruby-1-9</guid>
		<description><![CDATA[主要讲了Ruby1.9的变动，比如： e1 = [1, 2, 3, 4].each e2 = [10, 11, 4].each loop { &#160;&#160;p e1.next + e2.next } #prints 11, 13 and 7 还是蛮不错的，不用担心听不懂，因为Matz的英语实在是。。。]]></description>
			<content:encoded><![CDATA[<p>主要讲了Ruby1.9的变动，比如：</p>
<p class="code"><code class="ruby">e1 = [1, 2, 3, 4].each<br />
e2 = [10, 11, 4].each<br />
loop {<br />
&nbsp;&nbsp;p e1.next + e2.next<br />
}<br />
#prints 11, 13 and 7</code></p>
<p>还是蛮不错的，不用担心听不懂，因为Matz的英语实在是。。。</p>
<p><object width="425" height="355"><param name="movie" value="http://www.youtube.com/v/oEkJvvGEtB4&#038;rel=1"></param><param name="wmode" value="transparent"></param><embed src="http://www.youtube.com/v/oEkJvvGEtB4&#038;rel=1" type="application/x-shockwave-flash" wmode="transparent" width="425" height="355"></embed></object></p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/google-tech-talks-matz-ruby-1-9/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ruby Metaclass详解</title>
		<link>http://www.letrails.cn/archives/ruby-metaclass-tutorials/</link>
		<comments>http://www.letrails.cn/archives/ruby-metaclass-tutorials/#comments</comments>
		<pubDate>Mon, 18 Feb 2008 04:45:23 +0000</pubDate>
		<dc:creator>yuanyi</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/ruby-metaclass-tutorials</guid>
		<description><![CDATA[来自whytheluckystiff.net。 &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; 如果你是Ruby Metaprogramming的新手，那么下面的代码或许会帮你找到一点感觉： class Object &#160;&#160;# The hidden singleton lurks behind everyone &#160;&#160;def metaclass; class > class MailTruck >> &#160;&#160;attr_accessor :driver, :route >> &#160;&#160;def initialize( driver, route ) >> &#160;&#160;&#160;&#160;@driver, @route = driver, route >> &#160;&#160;end >> end >> m = MailTruck.new( "Harold", ['12 Corrigan Way', '23 Antler Ave'] ) => #&#60;MailTruck:0x81cfb94 @route=["12 Corrigan [...]]]></description>
			<content:encoded><![CDATA[<p>来自<a href="http://www.whytheluckystiff.net/articles/seeingMetaclassesClearly.html">whytheluckystiff.net</a>。<br />
&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;</p>
<p>如果你是Ruby Metaprogramming的新手，那么下面的代码或许会帮你找到一点感觉：</p>
<p class="code"><code class="ruby"><br />
class Object<br />
&nbsp;&nbsp;# The hidden singleton lurks behind everyone<br />
&nbsp;&nbsp;def metaclass; class << self; self; end; end<br />
&nbsp;&nbsp;def meta_eval &blk; metaclass.instance_eval &blk; end<br />
&nbsp;&nbsp;# Adds methods to a metaclass<br />
&nbsp;&nbsp;def meta_def name, &#038;blk<br />
&nbsp;&nbsp;&nbsp;&nbsp;meta_eval { define_method name, &#038;blk }<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;# Defines an instance method within a class<br />
&nbsp;&nbsp;def class_def name, &#038;blk<br />
&nbsp;&nbsp;&nbsp;&nbsp;class_eval { define_method name, &#038;blk }<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>摸不着头脑？没关系，先将这个文件保存起来，会用得到的，下面我们正式开始：</p>
<p>在讲解Metaclass之前，让我们先来看看什么是class和object？（注意，小写开头的class和object指代广义的类和对象，而大写开头的Class和Object则指代Ruby中的Class和Object class）</p>
<p class="code"><code class="ruby"><br />
>> class MailTruck<br />
>> &nbsp;&nbsp;attr_accessor :driver, :route<br />
>> &nbsp;&nbsp;def initialize( driver, route )<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;@driver, @route = driver, route<br />
>> &nbsp;&nbsp;end<br />
>> end<br />
>> m = MailTruck.new( "Harold", ['12 Corrigan Way', '23 Antler Ave'] )<br />
=> #&lt;MailTruck:0x81cfb94 @route=["12 Corrigan Way", "23 Antler Ave"],<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@driver="Harold"&gt;<br />
>> m.class<br />
=> MailTruck<br />
</code></p>
<p>我们可以将object看作是变量或者说实例变量的载体，一个MailTruck object一旦初始化完成，就将拥有两个变量：@driver以及 @route。它们可以存储任何其它对象：</p>
<p class="code"><code class="ruby"><br />
>> m.instance_variable_set( "@speed", 45 )<br />
=> 45<br />
>> m.driver<br />
=> "Harold"<br />
</code></p>
<p>让我们来看看这是如何实现的，当Ruby执行到attr_accessor :driver这句话时，它就为MailTruck class定义了一对读写方法：driver以及driver=，也就是说实例变量保存在object中，而实例变量的访问方法（accessor method）保存在class中。</p>
<p>这是一个需要牢记的重要概念：<strong>方法存储在class中，而非object。</strong></p>
<p>但class也是object，这个想必你们都知道，因为在Ruby中，一切皆对象，也就是说，在object上运行的方法，也可以在class上运行：</p>
<p class="code"><code class="ruby"><br />
>> m.object_id<br />
=> 68058570<br />
>> MailTruck.object_id<br />
=> 68069450<br />
</code></p>
<p>但是我们前面又讲过，变量保存在object中，而方法保存在class中，既然class也是object，那class的方法必然保存在另一个class中，这样岂不是无限循环了？</p>
<p>但事实不是这样的，这一切都终止在Object class，实际上，Ruby中的class并不是一个真正的object，我们可以从Ruby源代码中看到如下定义：</p>
<p class="code"><code class="ruby"><br />
struct RObject {<br />
&nbsp;&nbsp;struct RBasic basic;<br />
&nbsp;&nbsp;struct st_table *iv_tbl;<br />
};<br />
struct RClass {<br />
&nbsp;&nbsp;struct RBasic basic;<br />
&nbsp;&nbsp;struct st_table *iv_tbl;<br />
&nbsp;&nbsp;struct st_table *m_tbl;<br />
&nbsp;&nbsp;VALUE super;<br />
};<br />
</code></p>
<p>我们可以看到，class有一个m_tbl存储所有的方法，还有一个super字段存储parent class，但是object没有，不过对于Ruby程序员来说，class又符合作为一个object所必须的条件：可以存储变量，并且可以回溯到Object class，因此，我们可以将它当作object对待：</p>
<p class="code"><code class="ruby"><br />
>> m = MailTruck.new<br />
=> #&lt;MailTruck:0x815c45c&gt;<br />
>> m.class<br />
=> MailTruck<br />
>> MailTruck.class<br />
=> Class<br />
>> MailTruck.superclass<br />
=> Object<br />
>> Class.superclass.superclass<br />
=> Object<br />
>> Class.class<br />
=> Class<br />
>> Object.class<br />
=> Class<br />
>> Object.superclass<br />
=> nil<br />
</code></p>
<p>上面class之间复杂的关系是否让你抓狂，下面这个图或许可以让问题简单点：</p>
<p><a href='http://lilac.greatweb.cn/rails/wp-content/uploads/2008/02/class_tree.png' title='class_tree.png'><img src='http://lilac.greatweb.cn/rails/wp-content/uploads/2008/02/class_tree.png' alt='class_tree.png' /></a></p>
<p>从这张图我们可以看出：</p>
<ul>
<li>Class继承自Object</li>
<li>Object的class是Class</li>
<li>Class的class是它自己</li>
<li>MailTrunk以及其它所有自定义class都是Class的object</li>
<li>MailTrunk以及其它所有自定义class都继承自Object</li>
</ul>
<p>简单的说，就是，在继承层次上，所有class都继承自Object，同时，所有class都是Class的对象，而Class又继承自Object，因此所有class也都是Object的对象，结论：所有class既继承自Object，同时又是Object的对象。</p>
<p>那么什么是metaclass呢？根据wikipedia的解释，metaclass就是定义其它class的class。但这个定义明显不适用于 Ruby，因为在Ruby中对应这个概念的就是Class，让我们看看在Ruby中改如何向Class添加一个方法，然后在定义class是使用它：</p>
<p class="code"><code class="ruby"><br />
>> class Class<br />
>> &nbsp;&nbsp;def attr_abort( *args )<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;abort "Please no more attributes today."<br />
>> &nbsp;&nbsp;end<br />
>> end<br />
>><br />
>> class MyNewClass<br />
>> &nbsp;&nbsp;attr_abort :id, :diagram, :telegram<br />
>> end<br />
</code></p>
<p>是的，上面的代码打印出了”Please no more attributes today.“，现在我们可以在定义class时调用attr_abort了，是的，在Ruby中我们可以随时随地修改class的定义，但这不是 meta，这不过时普普通通的代码而已，那么究竟什么是Ruby metaclass呢？既然wiki的定义不适合，我们就需要自己定义一个，在我看来：”Ruby metaclass就是object用来重新它自己的class“。</p>
<p>现在，我们已经知道：object不能拥有方法。但有些时候你可能想让一个object拥有它自己的方法，那该如何办呢，答案就是metaclass：</p>
<p class="code"><code class="ruby"><br />
>> require 'yaml'<br />
>> class << m<br />
>> &nbsp;&nbsp;def to_yaml_properties<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;[&#8217;@driver&#8217;, &#8216;@route&#8217;]<br />
>> &nbsp;&nbsp;end<br />
>> end<br />
>> YAML::dump m<br />
&#8212; !ruby/object:MailTruck<br />
driver: Harold<br />
route:<br />
&nbsp;&nbsp;- 12 Corrigan Way<br />
&nbsp;&nbsp;- 23 Antler Ave<br />
</code></p>
<p>我们可以看到object m已经有了它自己的to_yaml_properties 方法，那么这个方法存储在哪里呢，它就存储在m的metaclass中，由于metaclass位于class继承层次的最下面，因此它将首先被发现，这也就意味着：定义在metaclass中的方法查找效率是最高的，这也正是metaclass的精髓所在。</p>
<p>或许你已经猜到了class << m 返回的就是object m的metaclass，但一般我们使用下面这种更直接的方式，它们的效果其实是一样的：</p>
<p class="code"><code class="ruby"><br />
def m.to_yaml_properties<br />
&nbsp;&nbsp;['@driver', '@route']<br />
end<br />
</code></p>
<p>现在是时间回头看看我们在文章开头给出的那段Ruby代码了，在IRB中require它，然后我们看看该如何来使用它（如果后面的例子都将依赖开始的代码）。</p>
<p class="code"><code class="ruby"><br />
>> m.metaclass<br />
=> #&lt;Class:#&lt;MailTruck:0x81cfb94&gt;&gt;<br />
>> m.metaclass.class<br />
=> Class<br />
>> m.metaclass.superclass<br />
=> #&lt;Class:MailTruck&gt;<br />
>> m.metaclass.instance_methods<br />
=> [&#8230;, &#8220;to_yaml_properties&#8221;, &#8230;]<br />
>> m.singleton_methods<br />
=> [&#8221;to_yaml_properties&#8221;]<br />
</code></p>
<p>我们可以看到m.metaclass，它返回了一个class，但是这个class是附着在一个特定的object的，也就是说这个class中定义的方法将能被这个特定的object所调用。Ruby称这种特殊的class为virtual class。</p>
<p>接下来的问题就是：metaclass需要metaclass吗？可以试试下面的代码：</p>
<p class="code"><code class="ruby"><br />
>> m.metaclass.metaclass<br />
=> #&lt;Class:#&lt;Class:#&lt;MailTruck:0x81cfb94&gt;&gt;&gt;<br />
>> m.metaclass.metaclass.metaclass<br />
=> #&lt;Class:#&lt;Class:#&lt;Class:#&lt;MailTruck:0x81cfb94&gt;&gt;&gt;&gt;<br />
</code></p>
<p>是的，metaclass自己也有metaclass，因为它们自己也是object，但我们一般不需要使用metaclass的metaclass，因为意义不大，不过还是让我们来看看metaclass的嵌套：</p>
<p class="code"><code class="ruby"><br />
>> m.meta_eval do<br />
>> &nbsp;&nbsp;self.meta_eval do<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;self.meta_eval do<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def ribbit; "*ribbit*"; end<br />
>> &nbsp;&nbsp;&nbsp;&nbsp;end<br />
>> &nbsp;&nbsp;end<br />
>> end<br />
>> m.metaclass.metaclass.metaclass.singleton_methods<br />
=> ["class_def", "metaclass", "constants", "meta_def",<br />
&nbsp;&nbsp;&nbsp;&nbsp;"attr_test", "nesting", "ribbit"]<br />
</code></p>
<p>class的metaclass的意义仅仅在于，你可以为某个class定义只有他自己才能访问的方法，除了这个目的，定义在class（或者metaclass）的metaclass中的方法没有任何意义，因为没人会访问它们。</p>
<p>另外需要注意一点，我们上面讲过，object的metaclass中的方法将优于object的class继承树中的方法被找到，但是metaclass 的metaclass则不会，也就是说m.metaclass.metaclass将只影响m.metaclass方法的查找，而不会影响m。</p>
<p>下面让我们来看看metaprogramming最为重要的一个技巧，这个技巧在Rails以及Ruby/X11等应用metaprogramming的项目中随处可见，如果你阅读了本文的其它部分，而错过了这一节，那就相当于你上了某门课程的所有课，却唯独逃了考试前最后一次划重点的课程一样。</p>
<p>在开始之前，让我们先来回顾下两个重要的概念：</p>
<ol>
<li>class也是object，因此class也可以拥有实例变量</li>
<li>metaclass也可以拥有实例方法，但是对于它们所附着的object而言，这些方法变成了singleton方法，这些方法会优于类的继承树被找到。</li>
</ol>
<p>现在让我们来看看class的实例变量，注意，我是指在class中使用实例变量，而不是class的method中：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;@trucks = []<br />
&nbsp;&nbsp;def MailTruck.add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;@trucks << truck<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>但是为什么不直接使用class 变量呢？</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;@@trucks = []<br />
&nbsp;&nbsp;def MailTruck.add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;@@trucks << truck<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>它们两个看起来没什么区别，对吗？答案是否定的。基于以下两个原因，我们应该尽可能的用class变量来取代class实例变量：</p>
<ol>
<li>我们可以很清楚的区分出class变量，因为它们有两个@符合。</li>
<li>class变量可以被实例方法所引用，如果需要的话</li>
</ol>
<p>例如，下面的代码工作正常：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;@@trucks = []<br />
&nbsp;&nbsp;def MailTruck.add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;@@trucks << truck<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;def say_hi<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts "Hi, I'm one of #{@@trucks.length} trucks!"<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>而这段则不行：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;@trucks = []<br />
&nbsp;&nbsp;def MailTruck.add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;@trucks << truck<br />
&nbsp;&nbsp;end<br />
&nbsp;&nbsp;def say_hi<br />
&nbsp;&nbsp;&nbsp;&nbsp;puts "Hi, I'm one of #{@trucks.length} trucks!"<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>很明显，我们应该尽量避免使用class实例变量，而改为使用class变量。</p>
<p>同样，我们已经知道，所有的class方法都定义在metaclass中，这也是为什么我们可以使用self来定义class方法的原因：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;def self.add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;@@trucks << truck<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>这和下面这段代码是相同的：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;class << self<br />
&nbsp;&nbsp;&nbsp;&nbsp;def add( truck )<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;@@trucks << truck<br />
&nbsp;&nbsp;&nbsp;&nbsp;end<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>大多数情况下，metaclass的instance method和class的instance variable一样，没什么用处。</p>
<p>不过当我们将类继承也考虑进来，那么情形就大为不同了，我们来看看下面这段代码：</p>
<p class="code"><code class="ruby"><br />
class MailTruck<br />
&nbsp;&nbsp;def self.company( name )<br />
&nbsp;&nbsp;&nbsp;&nbsp;meta_def :company do; name; end<br />
&nbsp;&nbsp;end<br />
end</code></p>
<p>现在，我们已经有了一个可以在MailTrunk以及它的child class的类定义中访问的company方法：</p>
<p class="code"><code class="ruby"><br />
class HappyTruck < MailTruck<br />
&nbsp;&nbsp;company "Happy's -- We Bring the Mail, and That's It!"<br />
end</code></p>
<p>在HappyTruck 中调用company方法会发生什么呢？meta_def做了些什么事情，从它的命名我们就可以看出了，它向HappyTruck class的metaclass添加了名为company的方法，这样做的真正意义就在于，company被添加到了HappyTruck class的metaclass中，而不是MailTruck。</p>
<p>这看起来很简单，但却很强大，不是吗？你可以通过定义简单的class method来向它的child class的metaclass添加方法，事实上，这也是Rails metaprogramming的秘密所在。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/ruby-metaclass-tutorials/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>for循环与each的区别</title>
		<link>http://www.letrails.cn/archives/difference-between-for-loop-and-each/</link>
		<comments>http://www.letrails.cn/archives/difference-between-for-loop-and-each/#comments</comments>
		<pubDate>Fri, 15 Feb 2008 14:12:16 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/for%e5%be%aa%e7%8e%af%e4%b8%8eeach%e7%9a%84%e5%8c%ba%e5%88%ab</guid>
		<description><![CDATA[for和each的区别主要在于： for是通过调用each实现，因此for更慢一些 for会在each的scope之外创建一个局部变量，这在某些情况下会引发问题 关于第二点，下面的代码可以很好的说明这个问题： irb&#62; [1, 2, 3].each do &#124;m&#124; puts m end irb&#62; puts m NameError: undefined local variable or method `m' for main:Object irb&#62; for n in [1, 2, 3] do puts n; end irb&#62; puts n =&#62; 3 如果你不了解这一点，那么在某些特殊的情况下，你可能会遇到麻烦，Ruby Forum的某个用户提交的一段代码很好的说明了for可能引发的问题： a = [] for n in [1, 2, 3] do a &#60;&#60; [...]]]></description>
			<content:encoded><![CDATA[<p>for和each的区别主要在于：</p>
<ol>
<li>for是通过调用each实现，因此for更慢一些</li>
<li>for会在each的scope之外创建一个局部变量，这在某些情况下会引发问题</li>
</ol>
<p>关于第二点，下面的代码可以很好的说明这个问题：</p>
<p class="code"><code class="ruby"><br />
irb&gt; [1, 2, 3].each do |m| puts m end<br />
irb&gt; puts m<br />
NameError: undefined local variable or method `m' for main:Object<br />
irb&gt; for n in [1, 2, 3] do  puts n; end<br />
irb&gt; puts n<br />
=&gt; 3<br />
</code></p>
<p>如果你不了解这一点，那么在某些特殊的情况下，你可能会遇到麻烦，<a href="http://www.ruby-forum.com/topic/128646">Ruby Forum的某个用户提交的一段代码</a>很好的说明了for可能引发的问题：</p>
<p class="code"><code class="ruby"><br />
a = []<br />
for n in [1, 2, 3] do<br />
a &lt;&lt; Proc.new {puts "#{n}"}<br />
end<br />
[1,2,3].each do |m|<br />
a &lt;&lt; Proc.new {puts "#{m}"}<br />
end<br />
a.each { |p| p.call }<br />
</code></p>
<p>运行结果：</p>
<p>3<br />
3<br />
3<br />
1<br />
2<br />
3</p>
<p>很显然，for循环的结果不是我们所期待的，因此，结论就是：<strong>应该尽可能的使用each替代for循环。</strong></p>
<p><strong>更新</strong>：感谢<a href="http://shiningray.cn/">ShiningRay</a>，应该使用each代替for的真正原因是，for实际上是通过each实现的，但它在each的scope外面定义了一个同名变量，下面的代码可以说明问题：</p>
<p class="code"><code class="ruby">&gt;&gt; a = “1\n2\n”<br />
&gt;&gt; def a.each<br />
&gt;&gt; yield(1)<br />
&gt;&gt; end<br />
&gt;&gt; for i in a<br />
&gt;&gt; puts i<br />
&gt;&gt; end<br />
1<br />
=&gt; nil</code></p>
<p>也就是说“for i in [1, 2]”就相当于“i = nil；[1,2].each do |i|”，因此前面的结论是不正确的，for应该比each慢（没有进行过测试），这才是for真正的问题所在。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/difference-between-for-loop-and-each/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Ruby技巧3则</title>
		<link>http://www.letrails.cn/archives/3-ruby-tips/</link>
		<comments>http://www.letrails.cn/archives/3-ruby-tips/#comments</comments>
		<pubDate>Fri, 25 Jan 2008 12:00:44 +0000</pubDate>
		<dc:creator>yuanyi</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/ruby%e6%8a%80%e5%b7%a73%e5%88%99</guid>
		<description><![CDATA[1. 构造正则 我们都知道，可以通过一下两种方式来构造正则： irb> /ruby/ => /ruby/ irb> Regexp.new('ruby') => /ruby/ 但实际上还有一种： irb> %r{ruby} => /ruby/ 如同%w, %q一样，%r将一个字符串转换为一个正则，并且你不止可以使用{}作为起始，结束符： irb> %r!ruby! => /ruby/ irb> %r&#124;ruby&#124; => /ruby/ 实际上，你可以使用任何不在正则中出现的字符作为字符串的起始和结束符，比如@＃$%^&#038;等等。 来自这里 2. alias 与 alias_method的区别 来自pragmati.st, 区别有3点： alias是Ruby的一个关键字，而alias_method是Module类的一个方法 alias的参数就是方法本身（method identify），注意，不是字符串，也不是Symbol，alias_method的参数则是字符串或者symbol，并且使用逗号分隔。 alias_method可以重定义，而alias则不能 alias new_method_name old_method_name alias_method :new_method_name, ld_method_name alias_method 'new_method_name', 'old_method_name' 3. ruby 中的printf irb> "my name is %s" [...]]]></description>
			<content:encoded><![CDATA[<p>1. 构造正则</p>
<p>我们都知道，可以通过一下两种方式来构造正则：</p>
<p class="code"><code class="ruby"><br />
irb> /ruby/<br />
=> /ruby/<br />
irb> Regexp.new('ruby')<br />
=> /ruby/<br />
</code></p>
<p>但实际上还有一种：</p>
<p class="code"><code class="ruby"><br />
irb> %r{ruby}<br />
=> /ruby/<br />
</code></p>
<p>如同%w, %q一样，%r将一个字符串转换为一个正则，并且你不止可以使用{}作为起始，结束符：</p>
<p class="code"><code class="ruby"><br />
irb> %r!ruby!<br />
=> /ruby/<br />
irb> %r|ruby|<br />
=> /ruby/<br />
</code></p>
<p>实际上，你可以使用任何不在正则中出现的字符作为字符串的起始和结束符，比如@＃$%^&#038;等等。</p>
<p>来自<a href="http://www.novemberain.com/2008/1/22/perlisms-in-ruby-regular-expression-syntaxes<br />
">这里</a></p>
<p>2. alias 与 alias_method的区别</p>
<p>来自pragmati.st, 区别有3点：</p>
<ol>
<li>alias是Ruby的一个关键字，而alias_method是Module类的一个方法</li>
<li>alias的参数就是方法本身（method identify），注意，不是字符串，也不是Symbol，alias_method的参数则是字符串或者symbol，并且使用逗号分隔。</li>
<li>alias_method可以重定义，而alias则不能</li>
</ol>
<p class="code"><code class="ruby"><br />
alias new_method_name old_method_name<br />
alias_method :new_method_name, <img src='http://www.letrails.cn/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' /> ld_method_name<br />
alias_method 'new_method_name', 'old_method_name'<br />
</code></p>
<p>3. ruby 中的printf</p>
<p class="code"><code class="ruby"><br />
irb> "my name is %s" % ['yzhang']<br />
=> "my name is yzhang"<br />
irb> "your score is %.2f" % [97.2835]<br />
=> "your score is 97.28"<br />
</code></p>
<p>实际上就是String#% 方法。它接受一个数组作为输入。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/3-ruby-tips/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>使用Flog测试你的Ruby代码复杂度</title>
		<link>http://www.letrails.cn/archives/62/</link>
		<comments>http://www.letrails.cn/archives/62/#comments</comments>
		<pubDate>Mon, 10 Sep 2007 12:04:00 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/62</guid>
		<description><![CDATA[简介 Flog是一个计算你的Ruby代码复杂度的工具，来自大牛Ryan Davis的seattle.rb项目。 安装 $ sudo gem install flog 使用 $ find . -name \*.rb &#124; xargs flog 这条命令将会计算你当前目录下的所有.rb文件的复杂度。 Flog根据以下条件判断你的代码复杂度，得分越高，说明你的代码越复杂， eval，6分 分支语句，1.2分 ==，1.2分 puts，1.2分 赋值语句，1.2分 Fixnum，0.4分 因此下面这段代码的得分就是11.2分： 图片来自RubyInside。]]></description>
			<content:encoded><![CDATA[<p><a href="http://seattlerb.rubyforge.org/"><img src="http://ruby.sadi.st/Flog_files/Seattle.rb.small.png" align="right" border="0" height="113" width="182" /></a></p>
<p><strong>简介</strong></p>
<p><a href="http://ruby.sadi.st/Flog.html">Flog</a>是一个计算你的Ruby代码复杂度的工具，来自<a href="http://seattlerb.rubyforge.org/">大牛Ryan Davis的seattle.rb项目</a>。</p>
<p><strong>安装</strong></p>
<p class="code"><code>$ sudo gem install flog</code></p>
<p><strong>使用</strong></p>
<p class="code"><code>$ find . -name \*.rb | xargs flog</code></p>
<p>这条命令将会计算你当前目录下的所有.rb文件的复杂度。</p>
<p>Flog根据以下条件判断你的代码复杂度，得分越高，说明你的代码越复杂，</p>
<ul>
<li>eval，6分</li>
<li>分支语句，1.2分</li>
<li>==，1.2分</li>
<li>puts，1.2分</li>
<li>赋值语句，1.2分</li>
<li>Fixnum，0.4分</li>
</ul>
<p>因此下面这段代码的得分就是11.2分：</p>
<p><img src="http://www.rubyinside.com/wp-content/uploads/2007/08/flog.jpg" border="0" /></p>
<p>图片来自<a href="http://www.rubyinside.com/scoring-your-codes-complexity-with-flog-586.html">RubyInside</a>。</p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/62/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JRuby Inside上线</title>
		<link>http://www.letrails.cn/archives/37/</link>
		<comments>http://www.letrails.cn/archives/37/#comments</comments>
		<pubDate>Mon, 16 Jul 2007 15:42:29 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[新闻]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/37</guid>
		<description><![CDATA[与Ruby Inside类似，不过从它的名字我们就能想到，JRuby Inside的内容将主要集中在JRuby方面，当然，Ruby Inside上也还会有关于JRuby的内容，不过如果你是JRuby的粉丝，那么我相信JRuby Inside会使你的脉搏跳动的更快一些。 JRuby Inside的Feed订阅地址：http://feeds.feedburner.com/JRubyInside]]></description>
			<content:encoded><![CDATA[<p>与<a href="http://www.rubyinside.com/">Ruby Inside</a>类似，不过从它的名字我们就能想到，<a href="http://www.jrubyinside.com/">JRuby Inside</a>的内容将主要集中在<a href="http://jruby.codehaus.org/">JRuby</a>方面，当然，Ruby Inside上也还会有<a href="http://www.rubyinside.com/category/jruby/">关于JRuby的内容</a>，不过如果你是JRuby的粉丝，那么我相信JRuby Inside会使你的脉搏跳动的更快一些。</p>
<p><img src="http://www.rubyinside.com/wp-content/uploads/2007/07/jrubyinside.jpg" /></p>
<p>JRuby Inside的Feed订阅地址：<a href="http://feeds.feedburner.com/JRubyInside">http://feeds.feedburner.com/JRubyInside</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/37/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>JRuby1.0发布</title>
		<link>http://www.letrails.cn/archives/14/</link>
		<comments>http://www.letrails.cn/archives/14/#comments</comments>
		<pubDate>Mon, 11 Jun 2007 17:19:41 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[新闻]]></category>

		<guid isPermaLink="false">http://www.letrails.cn/archives/14</guid>
		<description><![CDATA[JRuby，Ruby语言的Java实现，经过漫长的等待之后，终于发布了1.0版本 ，此版本的特性包括： 完全兼容Ruby1.8.5版本 支持大部分Ruby builtin class 支持从Ruby内部定义及使用Java class Bean Scripting Framework（BSF）支持 多License支持（CPL/GPL/LGPL) JRuby项目始于2001年，最初仅仅是对Ruby 1.6的简单porting，但是随着2006年9月Sun公司的介入，JRuby项目开始进入一个高速发展的阶段，随着1.0版本的发布，JRuby项 目的开发者宣称大部分兼容性Bug都已经得到了解决，现在”它基本可以工作了（It will just works！）！“ 事实上，许多公司（Thoughtworks是最著名的），都期盼着JRuby项目能够释放Rails在企业应用开发上的强大动力，现在，随着 JRuby1.0的发布，让我们有理由相信，Rails进军企业级应用的那一天已经不远了，相信Ruby社区很快就会出现大量的基于JRuby的新应用以 及开发指南。]]></description>
			<content:encoded><![CDATA[<p><a href="http://jruby.codehaus.org/" target="_blank">JRuby</a>，Ruby语言的Java实现，经过漫长的等待之后，终于<a href="http://ola-bini.blogspot.com/2007/06/jruby-10.html" title="发布了1.0版本">发布了1.0版本</a> ，此版本的特性包括：</p>
<ul>
<li>完全兼容Ruby1.8.5版本</li>
<li>支持大部分Ruby builtin class</li>
<li>支持从Ruby内部定义及使用Java class</li>
<li>Bean Scripting Framework（BSF）支持</li>
<li>多License支持（CPL/GPL/LGPL)</li>
</ul>
<p>JRuby项目始于2001年，最初仅仅是对Ruby 1.6的简单porting，但是随着2006年9月Sun公司的介入，JRuby项目开始进入一个高速发展的阶段，随着1.0版本的发布，JRuby项 目的开发者宣称大部分兼容性Bug都已经得到了解决，现在”它基本可以工作了（It will just works！）！“</p>
<p>事实上，许多公司（Thoughtworks是最著名的），都期盼着JRuby项目能够释放Rails在企业应用开发上的强大动力，现在，随着 JRuby1.0的发布，让我们有理由相信，Rails进军企业级应用的那一天已经不远了，相信Ruby社区很快就会出现大量的基于JRuby的新应用以 及开发指南。</p>
<p><img src="http://www.rubyinside.com/wp-content/uploads/2007/06/jrubylogo.png" /></p>
]]></content:encoded>
			<wfw:commentRss>http://www.letrails.cn/archives/14/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
