<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
    <title type="text" xml:lang="en">ViTarn</title>
    <link type="application/atom+xml" href="http://vitarn.com/rss.xml" rel="self"/>
    <link type="text" href="http://vitarn.com" rel="alternate"/>
    <updated>2011-09-09T01:23:49-07:00</updated>
    <id>http://vitarn.com</id>
    <author>
        <name>Colder</name>
    </author>
    <rights>Copyright (c) 2007-2011 ViTarn</rights>
    
    <entry>
        <title>迅雷 for mac 夹带狗狗搜索</title>
        <link href="http://vitarn.com/2011/09/09/thunder-for-mac-with-gougou-search.html"/>
        <updated>2011-09-09T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/09/09/thunder-for-mac-with-gougou-search.html/</id>
        <summary type="html">&lt;p&gt;迅雷, 你真是不禁夸.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/install-thunder-gougou-search.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>Ruby Koans</title>
        <link href="http://vitarn.com/2011/07/18/ruby-koans.html"/>
        <updated>2011-07-18T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/07/18/ruby-koans.html/</id>
        <summary type="html">&lt;p&gt;学习 Ruby 语言的途径有太多太多, 你可以选择一本经典书籍慢慢看, 也可以找在线的资源(类似那种十五分钟入门的), 甚至有很多 Ruby 语言使用者是从 Ruby On Rails 学起的(例如我).&lt;/p&gt;

&lt;p&gt;不知道从什么时候开始, &lt;a href=&quot;http://www.ruby-lang.org/en/documentation/&quot;&gt;Ruby 官网文档&lt;/a&gt;里出现一篇&lt;a href=&quot;http://rubykoans.com/&quot;&gt;Ruby Koans&lt;/a&gt;, 采用单元测试填空题的方式强化基础知识. 网站访问不了可以直接访问&lt;a href=&quot;https://github.com/edgecase/ruby_koans/tree/master/koans&quot;&gt;源代码库&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;说真的, 做完这套题目以后, 我对 Ruby 有了重新的认识, 这样说有点太官方了, 其实是我的自信心受到了粉碎性打击然后重组.&lt;/p&gt;

&lt;p&gt;将代码下载回来, 运行 &lt;code&gt;ruby path_to_enlightenment.rb&lt;/code&gt;, 就会开始单元测试过程, 因为题目的答案还没有填写, 所以测试肯定是通不过的, 碰到问题就会停下来, 然后提醒你哪个文件的第几行出了问题.&lt;/p&gt;

&lt;p&gt;最先出现问题的文件会是 &lt;code&gt;about_asserts.rb&lt;/code&gt;, 这里是练习一下断言的最基本用法, 以及几道 1+1=2 之类的问题. &lt;code&gt;__&lt;/code&gt;处就是要你填空的地方, 如果不填会提醒你 &lt;code&gt;&amp;lt;&quot;FILL ME IN&quot;&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3 id=&quot;aboutnilrb&quot;&gt;about_nil.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby highlight:5

def test_nil_has_a_few_methods_defined_on_it
    # nil对应空字符串, 所以 &quot;#{nil}&quot; 才不会影响输出.
    assert_equal '', nil.to_s
    # 这个就很新鲜, 之前没有注意到啊.
    assert_equal 'nil', nil.inspect
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutobjectsrb&quot;&gt;about_objects.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

def test_some_system_objects_always_have_the_same_id
    # false, true, nil 三者都有固定的 object_id, 为什么会取 0 2 4 这三个值呢? 请看下文.
    assert_equal 0, false.object_id
    assert_equal 2, true.object_id
    assert_equal 4, nil.object_id
end

def test_small_integers_have_fixed_ids
    # 整型的 object_id 等于 2n+1, 所以负数的 object_id 也是负的.
    # 从 0 开始闲置的 object_id 就只有 0 2 4 等等. 所以之前特殊的 object_id 由此得来.
    assert_equal 1, 0.object_id
    assert_equal 3, 1.object_id
    assert_equal 5, 2.object_id
    assert_equal 201, 100.object_id
end

# 其它对象的 object_id 是随机产生并且绝不重复的(包括 Float), object_id 也是判断对象是否为同一个对象的依据.
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutarraysrb&quot;&gt;about_arrays.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby highlight:[8,11]

def test_slicing_arrays
    array = [:peanut, :butter, :and, :jelly]

    # 这种用法对应于 Array#slice(start, length)
    # 当 length 超过数组长度时忽略.
    assert_equal [:and, :jelly], array[2,20]
    # 当 length 为 0 时返回空数组
    assert_equal [], array[4,0]
    assert_equal [], array[4,100]
    # 当 start 超过数组长度时返回 nil.
    assert_equal nil, array[5,0]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;code&gt;array[4,0]&lt;/code&gt; 返回 &lt;code&gt;[]&lt;/code&gt;, 而 &lt;code&gt;array[5,0]&lt;/code&gt; 却返回 nil. 为什么? &lt;a href=&quot;http://www.ruby-doc.org/core/classes/Array.html#M000218&quot;&gt;Array 文档&lt;/a&gt;把这个称为 special cases. 从源代码里顺着 &lt;code&gt;rb_ary_aref&lt;/code&gt; 方法继续下去就是 &lt;code&gt;rb_ary_subseq&lt;/code&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!c highlight:[6,14]
rb_ary_subseq(VALUE ary, long beg, long len)
{
    VALUE klass;
    
    // 如果长度大于数组长度, 返回 nil.
    if (beg &amp;gt; RARRAY_LEN(ary)) return Qnil;
    if (beg &amp;lt; 0 || len &amp;lt; 0) return Qnil;

    if (RARRAY_LEN(ary) &amp;lt; len || RARRAY_LEN(ary) &amp;lt; beg + len) {
	len = RARRAY_LEN(ary) - beg;
    }
    klass = rb_obj_class(ary);
    // 如果长度等于 0, 返回空数组.
    if (len == 0) return ary_new(klass, 0);

    return ary_make_partial(ary, klass, beg, len);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;不知道 Matz 当年是不是晃神了, 还是有意为之, 进而造成了下标 4 和 5 的不一致性, 反正这已经是即定事实了.&lt;/p&gt;

&lt;h3 id=&quot;aboutstringsrb&quot;&gt;about_strings.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

def test_flexible_quotes_can_handle_multiple_lines
    long_string = %{# \n
It was the best of times,# \n
It was the worst of times.# \n
}
    assert_equal 54, long_string.size
end

def test_here_documents_can_also_handle_multiple_lines
    long_string = &amp;lt;&amp;lt;EOS
It was the best of times,# \n
It was the worst of times.# \n
EOS
    assert_equal 53, long_string.size
end

# += 操作不会改变原始字符串.
def test_plus_equals_also_will_leave_the_original_string_unmodified
    original_string = &quot;Hello, &quot;
    hi = original_string
    there = &quot;World&quot;
    hi += there
    assert_equal &quot;Hello, &quot;, original_string
end

# &amp;lt;&amp;lt; 操作会修改源始字符串的.
def test_the_shovel_operator_modifies_the_original_string
    original_string = &quot;Hello, &quot;
    hi = original_string
    there = &quot;World&quot;
    hi &amp;lt;&amp;lt; there
    assert_equal &quot;Hello, World&quot;, original_string
end

# 单引号字符串里也会发生转义.
def test_single_quotes_sometimes_interpret_escape_characters
    string = '\\\''
    assert_equal 2, string.size
    assert_equal %{\\'}, string
end

def test_you_can_get_a_substring_from_a_string
    string = &quot;Bacon, lettuce and tomato&quot;
    # 可以像数组那样截取字符串分片
    assert_equal 'let', string[7,3]
    assert_equal 'let', string[7..9]
    # 但是如果只取一个字符的话, 返回的是字符的 ASCII 码.
    assert_equal 97, string[1]
end

def test_strings_can_be_split
    string = &quot;Sausage Egg Cheese&quot;
    words = string.split
    # 字符串分割的默认参数是 $;
    assert_equal [&quot;Sausage&quot;, &quot;Egg&quot;, &quot;Cheese&quot;], words
end

def test_strings_are_not_unique_objects
    a = &quot;a string&quot;
    b = &quot;a string&quot;
    # 值相等.
    assert_equal true, a           == b
    # 但却不是同一个对象.
    assert_equal false, a.object_id == b.object_id
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;这里比较有意思的是 &lt;code&gt;String#split&lt;/code&gt; 的默认值 $; . 它是一个全局变量, 它的唯一用途就是作为 split 方法的默认值出现, 它的初始值是 nil. 你可以通过修改这个全局变量来改变 split 方法的行为.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
&amp;gt;&amp;gt; $; = 'b'
&amp;gt;&amp;gt; &quot;abaabbbccdcbba&quot;.split
=&amp;gt; [&quot;a&quot;, &quot;aa&quot;, &quot;&quot;, &quot;&quot;, &quot;ccdc&quot;, &quot;&quot;, &quot;a&quot;]
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutsymbolsrb&quot;&gt;about_symbols.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

def test_identical_symbols_are_a_single_internal_object
    symbol1 = :a_symbol
    symbol2 = :a_symbol
    # 符号是独一无二的.
    assert_equal true, symbol1           == symbol2
    assert_equal true, symbol1.object_id == symbol2.object_id
end

# all_symbols 方法可以返回所有符号, 这基中就包括方法名.
def test_method_names_become_symbols
    symbols_as_strings = Symbol.all_symbols.map { |x| x.to_s }
    assert_equal true, symbols_as_strings.include?(&quot;test_method_names_become_symbols&quot;)
end

# 在 MRI 版本里, 常量也是符号.
in_ruby_version(&quot;mri&quot;) do
    RubyConstant = &quot;What is the sound of one hand clapping?&quot;
    def test_constants_become_symbols
        all_symbols = Symbol.all_symbols
        
        assert_equal true, all_symbols.include?(:RubyConstant)
    end
end

# 符号可以长的不太一样.
def test_symbols_with_spaces_can_be_built
    symbol = :&quot;cats and dogs&quot;

    assert_equal symbol, symbol.to_sym
end

# 符号也可以在内部插入值.
def test_symbols_with_interpolation_can_be_built
    value = &quot;and&quot;
    symbol = :&quot;cats #{value} dogs&quot;

    assert_equal symbol, &quot;cats and dogs&quot;.to_sym
end

# 符号不是&quot;不可变的&quot;字符串, 它没有字符串的方法.
def test_symbols_do_not_have_string_methods
    symbol = :not_a_string
    assert_equal false, symbol.respond_to?(:each_char)
    assert_equal false, symbol.respond_to?(:reverse)
end

# 连最基本的连接操作都不允许.
def test_symbols_cannot_be_concatenated
    assert_raise(NoMethodError) { :cats + :dogs }
end

# 符号可以动态创建, 但是不推荐这样做.
def test_symbols_can_be_dynamically_created
    assert_equal :catsdogs, (&quot;cats&quot; + &quot;dogs&quot;).to_sym
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutregularexpressionsrb&quot;&gt;about_regular_expressions.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby highlight:13

# 字符串可以像这样查找内容.
def test_a_regexp_can_search_a_string_for_matching_content
    assert_equal &quot;match&quot;, &quot;some matching content&quot;[/match/]
end

# 找不到会返回 nil, 这种方式更像是条件判断.
def test_a_failed_match_returns_nil
    assert_equal nil, &quot;some matching content&quot;[/missing/]
end

# 带星号的正则表达的十分贪婪.
def test_asterisk_means_zero_or_more
    assert_equal &quot;&quot;, &quot;abbcccddddeeeee&quot;[/z*/]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;为什么会发生的情形? 看一下 Ruby 源代码里都做了什么.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!c
# 当 String#slice 的第一个参数类型为 Regexp 时, 调用下面这个函数.
rb_str_subpat(VALUE str, VALUE re, VALUE backref)
{
    if (rb_reg_search(re, str, 0, 0) &amp;gt;= 0) {
        VALUE match = rb_backref_get();
        int nth = rb_reg_backref_number(match, backref);
	    return rb_reg_nth_match(nth, match);
    }
    return Qnil;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;事实上, 是 &lt;code&gt;&quot;abbcccddddeeeee&quot;.match(/z*/)[0]&lt;/code&gt; 返回了空字符串. 如果换成 &lt;code&gt;&quot;abbcccddddeeeee&quot;.match(/missing/)&lt;/code&gt; 就返回 nil 了.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

# 这会儿又表现的十分容易满足, 这简直就是陷阱.
def test_the_left_most_match_wins
    assert_equal &quot;a&quot;, &quot;abbccc az&quot;[/az*/]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;此处的表现十分怪异, 事实上 Ruby 正则也是遵从正常的贪婪原则的.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash

&amp;gt;&amp;gt; &quot;abb&quot;.match /ab*/
=&amp;gt; #&amp;lt;MatchData &quot;abb&quot;&amp;gt;
&amp;gt;&amp;gt; &quot;abb&quot;.match /ab*?/
=&amp;gt; #&amp;lt;MatchData &quot;a&quot;&amp;gt;
&amp;gt;&amp;gt; &quot;abb&quot;.match /ab+?/
=&amp;gt; #&amp;lt;MatchData &quot;ab&quot;&amp;gt;
&amp;gt;&amp;gt; &quot;abb&quot;.match /ab{0,9}/
=&amp;gt; #&amp;lt;MatchData &quot;abb&quot;&amp;gt;

# 只是当出现在字符串末尾时就犯糊涂
&amp;gt;&amp;gt; &quot;aabb&quot;.match /ab*/
=&amp;gt; #&amp;lt;MatchData &quot;a&quot;&amp;gt;
&amp;gt;&amp;gt; &quot;aabb&quot;.match /ab{0,9}/
=&amp;gt; #&amp;lt;MatchData &quot;a&quot;&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看来以后星号正则要慎重使用了.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

# \w 里的连字符是下划线, 不包括减号.
def test_slash_w_is_a_shortcut_for_a_word_character_class
    assert_equal &quot;variable_1&quot;, &quot;variable_1 = 42&quot;[/[a-zA-Z0-9_]+/]
    assert_equal &quot;variable_1&quot;, &quot;variable_1 = 42&quot;[/\w+/]
end

# 不但能匹配, 还能选择返回第几个匹配结果.
def test_parentheses_also_capture_matched_content_by_number
    assert_equal &quot;Gray&quot;, &quot;Gray, James&quot;[/(\w+), (\w+)/, 1]
    assert_equal &quot;James&quot;, &quot;Gray, James&quot;[/(\w+), (\w+)/, 2]
end

# 每次匹配, 结果都会被记入全局变量中.
def test_variables_can_also_be_used_to_access_captures
    assert_equal &quot;Gray, James&quot;, &quot;Name:  Gray, James&quot;[/(\w+), (\w+)/]
    assert_equal &quot;Gray&quot;, $1
    assert_equal &quot;James&quot;, $2
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutconstantsrb&quot;&gt;about_constants.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

class Animal
    LEGS = 4
end

class MyAnimals
    LEGS = 2

    class Bird &amp;lt; Animal
        def legs_in_bird
            LEGS
        end
    end
end

# 嵌套常量赢过继承常量.
def test_who_wins_with_both_nested_and_inherited_constants
    assert_equal 2, MyAnimals::Bird.new.legs_in_bird
end

class MyAnimals::Oyster &amp;lt; Animal
    def legs_in_oyster
      LEGS
    end
end

# 如果定义成这样, 继承变量就赢了.
def test_who_wins_with_explicit_scoping_on_class_definition
    assert_equal 4, MyAnimals::Oyster.new.legs_in_oyster
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutexceptionsrb&quot;&gt;about_exceptions.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

class MySpecialError &amp;lt; RuntimeError
end

# 自定义异常完整的继承树.
def test_exceptions_inherit_from_Exception
    assert_equal RuntimeError, MySpecialError.ancestors[1]
    assert_equal StandardError, MySpecialError.ancestors[2]
    assert_equal Exception, MySpecialError.ancestors[3]
    assert_equal Object, MySpecialError.ancestors[4]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutblocksrb&quot;&gt;about_blocks.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

# 块中的代码甚至会给局部变量带来副作用.
def test_block_can_affect_variables_in_the_code_where_they_are_created
    value = :initial_value
    method_with_block { value = :modified_in_a_block }
    assert_equal :modified_in_a_block, value
end

def test_blocks_can_be_assigned_to_variables_and_called_explicitly
    add_one = lambda { |n| n + 1 }
    # 有两种方法调用 lambda 表达式.
    assert_equal 11, add_one.call(10)
    assert_equal 11, add_one[10]
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutscoperb&quot;&gt;about_scope.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

class AboutScope
    class String
    end
    
    # 当前范围中的类名拥有更高的优先级.
    def test_bare_bones_class_names_assume_the_current_scope
        assert_equal true, AboutScope::String == String
    end
    
    # 当前范围中的类名如果与 Ruby 库中的类名重复, 会造成很多不必要的麻烦.
    def test_nested_string_is_not_the_same_as_the_system_string
        assert_equal false, String == &quot;HI&quot;.class
    end
    
    def test_use_the_prefix_scope_operator_to_force_the_global_scope
        assert_equal true, ::String == &quot;HI&quot;.class
    end
    
    MyString = ::String
    
    # 类名其实只是常量而已.
    def test_class_names_are_just_constants
        assert_equal true, MyString == ::String
        assert_equal true, MyString == &quot;HI&quot;.class
    end
    
    def test_constants_can_be_looked_up_explicitly
        assert_equal true, MyString == AboutScope.const_get(&quot;MyString&quot;)
    end
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;aboutclassmethodsrb&quot;&gt;about_class_methods.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

class Dog
end

# 实例也可以定义方法
def test_you_can_define_methods_on_individual_objects
    fido = Dog.new
    def fido.wag
        :fidos_wag
    end
    assert_equal :fidos_wag, fido.wag
end

# 这个方法只属于这个实例, 不影响类的其它实例.
def test_other_objects_are_not_affected_by_these_singleton_methods
    fido = Dog.new
    rover = Dog.new
    def fido.wag
        :fidos_wag
    end

    assert_raise(NoMethodError) do
        rover.wag
    end
end

LastExpressionInClassStatement = class Dog; 21; end

# 你总能拿到最后一个表达式的结果.
def test_class_statements_return_the_value_of_their_last_expression
    assert_equal 21, LastExpressionInClassStatement
end

SelfInsideOfClassStatement = class Dog; self; end

# 甚至是 self.
def test_self_while_inside_class_is_class_object_not_instance
    assert_equal true, Dog == SelfInsideOfClassStatement
end
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&quot;abouttostrrb&quot;&gt;about_to_str.rb&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;#!ruby

class CanBeTreatedAsString
    def to_s
        &quot;string-like&quot;
    end

    def to_str
        to_s
    end
end

# to_str 有更进一步的作用.
def test_to_str_allows_objects_to_be_treated_as_strings
    assert_equal false, File.exist?(CanBeTreatedAsString.new)
end
&lt;/code&gt;&lt;/pre&gt;

</summary>
    </entry>
    
    <entry>
        <title>抑制 Ruby 警告</title>
        <link href="http://vitarn.com/2011/07/13/ruby-suppress-warning.html"/>
        <updated>2011-07-13T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/07/13/ruby-suppress-warning.html/</id>
        <summary type="html">&lt;p&gt;在 irb 命令行里输入&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
&amp;gt;&amp;gt; X = 1
=&amp;gt; 1
&amp;gt;&amp;gt; X = 2
(irb):28: warning: already initialized constant X
=&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;你会看到上面那行警告, &lt;code&gt;已经初始化过常量 X&lt;/code&gt;, ruby 是在提醒你常量是不应该被改变的, 不过 ruby 只是在抱怨一句罢了, 实际上 X 的值已经由 1 变成 2 了.&lt;/p&gt;

&lt;p&gt;警告是对的, 常量的再次赋值有违原则. 但是人总会碰到情非得已的时候.&lt;/p&gt;

&lt;p&gt;ruby 论坛上有篇&lt;a href=&quot;http://www.ruby-forum.com/topic/127608&quot;&gt;贴子&lt;/a&gt;也提到了这一问题, 沙发搞笑的说忽略事情最简单的方式就是闭上眼睛. 不过五楼是正经人, 给出了解决问题的思路. 顺着思路就想到了这个方法.&lt;/p&gt;

&lt;p&gt;ruby 接受 -W 作为参数.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
ruby -h
-W[level] set warning level; 0=silence, 1=medium, 2=verbose (default)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;运行时对应的是全局变量 $-v&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;nil   -W0&lt;/li&gt;
  &lt;li&gt;false -W1&lt;/li&gt;
  &lt;li&gt;true  -W2&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;这样事情就变得简单了.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!ruby
def suppress_warning &amp;amp;block
    old_v = $-v
    $-v = nil
    yield
ensure
    $-v = old_v
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;试试效果&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
&amp;gt;&amp;gt; X = 1
=&amp;gt; 1
&amp;gt;&amp;gt; suppress_warning { X = 2 }
=&amp;gt; 2
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;嗯, 感觉不错, 你也是不清理不舒服斯基吗?&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>迅雷苹果内部预览版 1.0.1.42</title>
        <link href="http://vitarn.com/2011/07/12/thunder-for-mac-preview-1-0-1-42.html"/>
        <updated>2011-07-12T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/07/12/thunder-for-mac-preview-1-0-1-42.html/</id>
        <summary type="html">&lt;h2 id=&quot;down&quot;&gt;&lt;a href=&quot;http://files.droplr.com/files/12299932/J0At.Thunder1.0.1.42.pkg?AWSAccessKeyId=AKIAJSVQN3Z4K7MT5U2A&amp;amp;Expires=1310451368&amp;amp;Signature=FeSyvgjQjfYox8sxuQ2vJD10R30%3D&quot;&gt;下载地址&lt;/a&gt;&lt;/h2&gt;

&lt;p&gt;支持 Chrome 和 Firefox 扩展, 不支持 Safari.&lt;br /&gt;
&lt;img src=&quot;/images/Thunder-for-mac-preview-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;就算是支持 Chrome 你不能直接去点迅雷专用链接.&lt;br /&gt;
&lt;img src=&quot;/images/Thunder-for-mac-preview-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;右键菜单里有个&amp;rdquo;使用迅雷下载&amp;rdquo;.&lt;br /&gt;
&lt;img src=&quot;/images/Thunder-for-mac-preview-3.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&amp;ldquo;新建下载任务&amp;rdquo;对话框.&lt;br /&gt;
&lt;img src=&quot;/images/Thunder-for-mac-preview-4.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;主界面. 下载速度有点慢.&lt;br /&gt;
&lt;img src=&quot;/images/Thunder-for-mac-preview-5.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>一张有趣的组织结构图</title>
        <link href="http://vitarn.com/2011/06/30/organization-chart-of-large-huge-it-enterprise.html"/>
        <updated>2011-06-30T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/06/30/organization-chart-of-large-huge-it-enterprise.html/</id>
        <summary type="html">&lt;p&gt;摘自 &lt;a href=&quot;http://www.36kr.com/organization-chart&quot;&gt;36氪&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://www.36kr.com/wp-content/uploads/2011/06/73fa01aftw1dinkcskk2nj.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>Google+ 一个干净的 Facebook</title>
        <link href="http://vitarn.com/2011/06/30/google-plus-a-cleaning-facebook.html"/>
        <updated>2011-06-30T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/06/30/google-plus-a-cleaning-facebook.html/</id>
        <summary type="html">&lt;p&gt;&lt;a href=&quot;https://plus.google.com&quot;&gt;Google+&lt;/a&gt; 就这样蹦出来了, 让我这个对 Facebook 又爱又恨的人不免心动.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/google-plus-1.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/google-plus-2.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>Hello Jekyll!</title>
        <link href="http://vitarn.com/2011/06/21/hello-jekyll.html"/>
        <updated>2011-06-21T00:00:00-07:00</updated>
        <id>http://vitarn.com/2011/06/21/hello-jekyll.html/</id>
        <summary type="html">&lt;p&gt;原来 Github 还有这功能.&lt;/p&gt;

&lt;p&gt;比 toto 还简单的 Jekyll.&lt;/p&gt;

&lt;p&gt;由 Github 帮你生成静态化的站点.&lt;/p&gt;

&lt;p&gt;目前感觉相当良好, 只是模板和插件还有点玩不转.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/mojombo/jekyll&quot;&gt;Jekyll on Github&lt;/a&gt;&lt;/p&gt;
</summary>
    </entry>
    
    <entry>
        <title>Mac OS X Server Samba crash</title>
        <link href="http://vitarn.com/2010/08/08/mac-os-x-server-samba-crash.html"/>
        <updated>2010-08-08T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/08/08/mac-os-x-server-samba-crash.html/</id>
        <summary type="html">&lt;p&gt;My Mac pro shutdown because power cut last night.&lt;/p&gt;

&lt;p&gt;Today. Windows user can ping me by computer name. But they can&amp;rsquo;t visit my share folder. There are some error in log:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Samba: ERROR: failed to setup guest info.
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;When I open /etc/smb.conf. I found it&amp;rsquo;s blank file. OK! So. To fix this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
sudo cp -p /etc/smb.conf.template /etc/smb.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Then it works.&lt;/p&gt;
</summary>
    </entry>
    
    <entry>
        <title>Objective-C 笔记</title>
        <link href="http://vitarn.com/2010/07/24/the-notes-of-learning-objective-c.html"/>
        <updated>2010-07-24T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/07/24/the-notes-of-learning-objective-c.html/</id>
        <summary type="html">&lt;p&gt;声明一个类需要两个文件, 接口(.h)和实现(.m).&lt;/p&gt;

&lt;p&gt;接口(interface)更像是&amp;rdquo;声明&amp;rdquo;, 协议(protocol)才是起到&amp;rdquo;接口&amp;rdquo;的作用.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;类方法用加号(+), 实例方法用减号(-).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
+ alloc;
- init;
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;引用类型带星号(*).&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
(NSString *) name
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;方法名包括参数名.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
// 方法名: setWidth:andHeight:   参数: width, height
- (void)setWidth:(float)width andHeight:(float)height;
// 调用写法
[receiver setWidth:1.0 andHeight:2.0];
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;super是关键字; self是变量名, 可以被覆盖.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;&amp;ldquo;类采纳了某协议&amp;rdquo;, 翻译过来就是:&amp;rdquo;类实现了某接口&amp;rdquo;. &amp;ldquo;协议采纳另个协议&amp;rdquo;, 翻译过来就是:&amp;rdquo;接口继承&amp;rdquo;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
// Formatter采纳了Formatting和Prettifying两个协议 
@interface Formatter : NSObject &amp;lt; Formatting, Prettifying &amp;gt;
@end

// 协议采纳协议
@protocol Paging &amp;lt; Formatting &amp;gt;

// 使用协议类型表示实例变量
id &amp;lt;Formatting&amp;gt; anObject;
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;属性声明的格式.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
@property(这里是一些特性, 例如readonly/retain/copy) 类型 名称;

// IBOutlet的意思是把属性暴露给Interface Builder设计器
@property (nonatomic, retain) IBOutlet NSButton *myButton;
&lt;/code&gt;&lt;/pre&gt;

&lt;hr /&gt;
&lt;p&gt;如何在XCode中使用Interface Builder设计器里的对象.&lt;/p&gt;

&lt;p&gt;在设计器里选中对象, 切换到Connections标签, 从Referencing Outlets里扯一条线连接到Controller上, 然后选择实例变量名.&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;数据源委托到控制器.&lt;/p&gt;

&lt;p&gt;对于需要集合数据类型作为数据源的界面元素, 会把dataSource连接到控制器上, 然后由控制器采纳数据源协议并实现方法. 这与以往所见的大不相同, 如果有两个数据源该怎么办?&lt;/p&gt;

&lt;hr /&gt;
&lt;p&gt;关于#pragma. 是用于XCode识别代码的标记, 被编译器忽略.&lt;/p&gt;

&lt;p&gt;方法分类:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
#pragma mark 采纳UIPickerDataSource协议
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;白空格:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
#pragma mark -
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;压制未使用变量警告:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!objc
#pragma unused(unusedVar)
&lt;/code&gt;&lt;/pre&gt;
</summary>
    </entry>
    
    <entry>
        <title>只有井底之蛙才会觉得 Web inspector 复制了 Firebug</title>
        <link href="http://vitarn.com/2010/07/23/frog-under-well-think-web-inspector-copy-firebug.html"/>
        <updated>2010-07-23T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/07/23/frog-under-well-think-web-inspector-copy-firebug.html/</id>
        <summary type="html">&lt;p&gt;一个部落格饶有兴致的介绍Chrome6.0dev中的开发人员工具, 也就是Web Inspector. 博主谦虚的口吻是清晰可见的, 然而急躁的国人仍然在回复中丝毫不客气, 含蓄的骂着&amp;rdquo;兰州烧饼&amp;rdquo;, 还说&amp;rdquo;对Firebug的复制品无爱&amp;rdquo;.&lt;/p&gt;

&lt;p&gt;谁让咱是个爱钻牛角尖的人咧! 我偏要挖一挖历史:&lt;/p&gt;

&lt;p&gt;有据可查的Firebug历史:
&lt;a href=&quot;https://addons.mozilla.org/en-US/firefox/addon/1843/versions/?page=2#version-0.2&quot;&gt;https://addons.mozilla.org/en-US/firefox/addon/1843/versions/?page=2#version-0.2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;有据可查的Web Inspector历史:
&lt;a href=&quot;http://webkit.org/blog/41/introducing-the-web-inspector/&quot;&gt;http://webkit.org/blog/41/introducing-the-web-inspector/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;看看吧, 相隔4天, 哪里谈得上谁复制谁.&lt;/p&gt;

&lt;p&gt;如果偏要说复制品, 倒是可以看看这篇文章:
&lt;a href=&quot;http://antennasoft.net/robcee/2010/05/14/inspector-landing/&quot;&gt;http://antennasoft.net/robcee/2010/05/14/inspector-landing/&lt;/a&gt;&lt;/p&gt;
</summary>
    </entry>
    
    <entry>
        <title>Wash cloth or wash brain</title>
        <link href="http://vitarn.com/2010/07/02/wash-cloth-or-wash-brain.html"/>
        <updated>2010-07-02T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/07/02/wash-cloth-or-wash-brain.html/</id>
        <summary type="html">&lt;h2 id=&quot;look-at-a-good-sample&quot;&gt;Look at a good sample:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/TEBYM7_wjnI/AAAAAAAABdI/0ABj3V6f5zo/s400/siemens.JPG&quot; alt=&quot;Siemens&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;and-another-stupids&quot;&gt;And another stupids:&lt;/h2&gt;

&lt;p&gt;&lt;img src=&quot;http://lh6.ggpht.com/_M94xOMOWd6s/TEBYNKeVCTI/AAAAAAAABdM/iqqwUknH7c4/1.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/TEBYNA0YxLI/AAAAAAAABdQ/lf9-FUFT9HY/2.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/TEBYNFGDOVI/AAAAAAAABdU/w3M-2hkLTPY/3.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh6.ggpht.com/_M94xOMOWd6s/TEBYNulvr2I/AAAAAAAABdY/KD_vNrwnzO8/4.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh6.ggpht.com/_M94xOMOWd6s/TEBYZt73VgI/AAAAAAAABdc/j2eHsKzHGHU/5.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh3.ggpht.com/_M94xOMOWd6s/TEBYZsYowzI/AAAAAAAABdg/tAb2wdGoIyo/6.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/TEBYZjYZKpI/AAAAAAAABdk/yQEssjItfjY/7.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/TEBYZ6sUmUI/AAAAAAAABdo/PyBkqtrXCes/8.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/TEBYZ88ozZI/AAAAAAAABds/MCmRCM8yCrA/9.jpg&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>A lazy usage for factory girl</title>
        <link href="http://vitarn.com/2010/07/02/a-lazy-usage-for-factory-girl.html"/>
        <updated>2010-07-02T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/07/02/a-lazy-usage-for-factory-girl.html/</id>
        <summary type="html">&lt;p&gt;&lt;a href=&quot;http://github.com/thoughtbot/factory_girl&quot;&gt;Factory girl&lt;/a&gt; let us product model instance feel luck. But for me(a lazy boy). I wanna write shorter that standard way.&lt;/p&gt;

&lt;p&gt;So a&amp;hellip; Look code below. I&amp;rsquo;m lazy to explain.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!ruby
# spec/factories.rb

class F
	class &amp;lt;&amp;lt; self
		{:a =&amp;gt; :attributes_for, :b =&amp;gt; :build, :c =&amp;gt; :create, :d =&amp;gt; :define, :s =&amp;gt; :stub, :* =&amp;gt; :sequence, :+ =&amp;gt; :next}.each do |k,v|
			delegate v, :to =&amp;gt; Factory
			alias_method k, v
		end
	end
end

F.d :user do |u|
	u.name &quot;foo&quot;
	u.full_name &quot;福娃&quot;
	u.password &quot;0&quot;
end

F.* :foos do |n|
	&quot;foo_#{n}&quot;
end

# spec/models/user_spec.rb

require &quot;spec_helper&quot;

describe User do
	after do
		User.delete_all
	end

	it &quot;should valid&quot; do
		F.b(:user).should be_valid
	end

	it &quot;should save success&quot; do
		F.c(:user).should_not be_new_record
		User.all.should be_one
	end

	it &quot;should product some foos&quot; do
		F.+(:foos).should eql &quot;foo_1&quot;
		(F + :foos).should eql &quot;foo_2&quot;
	end
end
&lt;/code&gt;&lt;/pre&gt;

</summary>
    </entry>
    
    <entry>
        <title>A joke about mate and pirate</title>
        <link href="http://vitarn.com/2010/06/27/a-joke-about-mate-and-pirate.html"/>
        <updated>2010-06-27T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/06/27/a-joke-about-mate-and-pirate.html/</id>
        <summary type="html">&lt;p&gt;&lt;a href=&quot;http://macromates.com&quot;&gt;Textmate&lt;/a&gt; has a shell version named &amp;ldquo;mate&amp;rdquo;. It&amp;rsquo;s a simple way to open a project directory.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
mate ~/Documents/myproj
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;I use Chinese Wubi input method. And I always forgot switch it. So when I input:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;mate&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The output word is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;贼船&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Translate into English:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pirate ship&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;lol&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>When rails ujs met chrome frame</title>
        <link href="http://vitarn.com/2010/06/11/when-rails-ujs-met-chrome-frame.html"/>
        <updated>2010-06-11T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/06/11/when-rails-ujs-met-chrome-frame.html/</id>
        <summary type="html">&lt;p&gt;Rails ujs let us use other javascript frameworks (like jQuery) in our project. That&amp;rsquo;s cool.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://jquery.org/wp-content/uploads/2010/01/JQuery_logo_color_onwhite-300x74.png&quot; alt=&quot;jQuery&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Here is an article about &lt;a href=&quot;http://www.tripwiremagazine.com/2009/11/top-10-javascript-frameworks-by-google.html&quot;&gt;top 10 javascript frameworks by google&lt;/a&gt;. He use a way (an easy way) to sort these frameworks. Search &amp;ldquo;javascript frameworks&amp;rdquo; in Google. You can see that the default rails javascript frameworks &lt;a href=&quot;http://www.prototypejs.org&quot;&gt;prototype&lt;/a&gt; is not the most popular one now.&lt;/p&gt;

&lt;p&gt;I&amp;rsquo;m working on a small project for my company by rails and jQuery. The newest rails3 use many html5 features. So I decide let user use a modern browser to use my web page. Otherwise IE6 will kill me. How to switch smoothly? I found chrome frame has beta yesterday!&lt;/p&gt;

&lt;p&gt;Someone said that they hate the web page of xxx-browser only. But wait! I use this in my company only! Didn&amp;rsquo;t you saw those enterprise-level soft let you install their plugin?&lt;/p&gt;

&lt;p&gt;Make an IE-only page is easy. Make an IE-except page is easier. lol&lt;/p&gt;

&lt;hr /&gt;

&lt;p&gt;Chrome frame show my html5 page (maybe). It&amp;rsquo;s beautiful than IE. But it cannot works when I send ajax request.&lt;/p&gt;

&lt;p&gt;For example I write a link like this:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!html
&amp;lt;!-- Rails html5 templete --&amp;gt;
&amp;lt;%= link_to &quot;Add user&quot;, new_user_path, :remote =&amp;gt; true %&amp;gt;

&amp;lt;!-- Will product --&amp;gt;
&amp;lt;a href=&quot;/users/new&quot; data-remote=&quot;true&quot;&amp;gt;Add user&amp;lt;/a&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Rails handle these link with data-remote by rails.js, It cancel click event, make a ajax request, then trigger ajax:success event back.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!javascript
// Live is new method in jQuery 1.4+.
$('a[data-confirm]').live('click', function () { ... });

// When user click the link. jQuery will handle it and send a ajax request.
$.ajax({
	url: &quot;/users/new&quot;,
	dataType: &quot;script&quot;,
	...
});
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;But chrome frame look like send a incorrect request to rails. Check the log of rails, I found this line:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;Processing by UsersController#new as */*
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;The right process method is JS because the data type is script. I have test IE FF Chrome and Safari on win and mac. Only chrome frame has this issus.&lt;/p&gt;

&lt;p&gt;I think I should fix this at client side. When I try to get navigator.userAgent by javascript. I found it has the same value as chrome stand-alone.&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/533.4 (KHTML, like Gecko) &lt;strong&gt;Chrome/5.0.375.62&lt;/strong&gt; Safari/533.4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;But rails could detect the right user agent:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727) &lt;strong&gt;chromeframe/5.0.375.62&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Oh! Javascript don&amp;rsquo;t know it&amp;rsquo;s running in chrome frame, so it can do anything. Rails know it&amp;rsquo;s processing the request from chrome frame, but it don&amp;rsquo;t know that&amp;rsquo;s a ajax request.&lt;/p&gt;

&lt;p&gt;After a minute. I decide let rails tell javascript: &amp;ldquo;u r working for chrome frame.&amp;rdquo;&lt;/p&gt;

&lt;p&gt;application.html.erb&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!html
&amp;lt;!-- Hold it in application.html.erb or ur own default layout. for this example put in navigator. --&amp;gt;
&amp;lt;% if @win_ie_with_chromeframe %&amp;gt;
&amp;lt;script&amp;gt;
navigator.chromeframe = true;
&amp;lt;/script&amp;gt;
&amp;lt;% end -%&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;application_controller.rb&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!ruby
# Detect chrome frame in application_controller.rb
before_filter :chromeframe_detect

protected
def chromeframe_detect
  ua = request.user_agent
  @win_ie_with_chromeframe = ua =~ /Windows NT/ and ua =~ /MSIE (\d+)/ and $1.to_i &amp;lt; 9 and ua =~ /chromeframe/
end
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;And then hack $.ajax. In fact I have three things need fix.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Chrome frame cannot send PUT DELETE verb.&lt;/li&gt;
  &lt;li&gt;Append .js to url tell rails I&amp;rsquo;m a JS request.&lt;/li&gt;
  &lt;li&gt;jQuery will try parse the result as JSON when dataType is script. If it got html. You will see an error: &amp;ldquo;Uncaught SyntaxError: Unexpected token &amp;lt;&amp;rdquo;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;application.js&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!javascript
//BUGFIX: Chromeframe miss some features.
(function($) {
	$.oldAjax = $.ajax;

	$.ajax = function(o) {
		// I can't detect it by navigator.userAgent. So I set it on server side.
		if (navigator.chromeframe) {
			// Chromeframe can't send DELETE and PUT verb.
			if (o.type == &quot;DELETE&quot;) {
				o.type = &quot;POST&quot;;
				o.data = &quot;_method=delete&quot;;
			} else if (o.type == &quot;PUT&quot;) {
				o.type = &quot;POST&quot;;
				o.data += &quot;&amp;amp;_method=put&quot;;
			}
		}

		// Chromeframe send incorrect ajax type make rails process the request by */*. The right way is JS. I try many way to avoid this. But I can do this with append .js to url only.
		if (o.dataType == &quot;script&quot; &amp;amp;&amp;amp; !/\.js$/.test(o.url)) {
			o.url += &quot;.js&quot;;
			// Webkit try parse result to json then raise a syntax error when receive html. It appear in inspector only and user can't see that except u r a developer. The url(end of .js) has told rails how to process my request. So I set dataType as text because I need respondText only. I can parse json myself.
			o.dataType = &quot;text&quot;;
		}

		$.oldAjax(o);
	};
});
&lt;/code&gt;&lt;/pre&gt;

</summary>
    </entry>
    
    <entry>
        <title>貌似 AutoCAD 又回到 Mac 了</title>
        <link href="http://vitarn.com/2010/05/23/maybe-autocad-will-back-to-mac.html"/>
        <updated>2010-05-23T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/05/23/maybe-autocad-will-back-to-mac.html/</id>
        <summary type="html">&lt;p&gt;&lt;img src=&quot;http://lh3.ggpht.com/_M94xOMOWd6s/S_h8ULsCF3I/AAAAAAAABaQ/CO9eOXFFmFQ/s400/AutoCAD%20for%20Mac%201.png&quot; alt=&quot;AutoCAD for Mac 1&quot; /&gt;
&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/S_h8Ua_rq3I/AAAAAAAABaU/mgaNR_W4dWg/s400/AutoCAD%20for%20Mac%202.jpg&quot; alt=&quot;AutoCAD for Mac 2&quot; /&gt;
&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/S_h8UWOfQXI/AAAAAAAABaY/B0T33SgFMBA/s400/AutoCAD%20for%20Mac%203.jpg&quot; alt=&quot;AutoCAD for Mac 3&quot; /&gt;
&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/S_h8Uij9-_I/AAAAAAAABac/oX7z3rstSKY/s400/AutoCAD%20for%20Mac%204.png&quot; alt=&quot;AutoCAD for Mac 4&quot; /&gt;
&lt;img src=&quot;http://lh6.ggpht.com/_M94xOMOWd6s/S_h8UsurYKI/AAAAAAAABag/ZijKl2bBDk4/s400/AutoCAD%20for%20Mac%205.png&quot; alt=&quot;AutoCAD for Mac 5&quot; /&gt;
&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/S_h8c0A9MII/AAAAAAAABao/SX2QHBGfe7Q/s400/AutoCAD%20for%20Mac%206.png&quot; alt=&quot;AutoCAD for Mac 6&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>Adobe Air2rc1 drag List item to Trash or RecycleBin has different behavior</title>
        <link href="http://vitarn.com/2010/05/15/adobe-air2rc1-drag-list-item-to-trash-or-recyclebin-has-different-behavior.html"/>
        <updated>2010-05-15T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/05/15/adobe-air2rc1-drag-list-item-to-trash-or-recyclebin-has-different-behavior.html/</id>
        <summary type="html">&lt;pre&gt;&lt;code&gt;#!xml
&amp;lt;s:List dragEnabled=&quot;true&quot; dragMoveEnabled=&quot;true&quot;&amp;gt;
	&amp;lt;s:dataProvider&amp;gt;
		&amp;lt;s:ArrayCollection&amp;gt;
			&amp;lt;fx:Object label=&quot;Item one&quot;/&amp;gt;
			&amp;lt;fx:Object label=&quot;Item two&quot;/&amp;gt;
			&amp;lt;fx:Object label=&quot;Item three&quot;/&amp;gt;
		&amp;lt;/s:ArrayCollection&amp;gt;
	&amp;lt;/s:dataProvider&amp;gt;
&amp;lt;/s:List&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/S-5p6tVP18I/AAAAAAAABZU/YCJ5VIlLX2Q/s800/adobe_air2rc1_drop_list_item_to_trash_on_mac_10_6_3.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;http://lh6.ggpht.com/_M94xOMOWd6s/S-5p6jMd5_I/AAAAAAAABZY/XkaSKjafBxI/s800/adobe_air2rc1_drop_list_item_to_trash_on_mac_10_6_3_after.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh3.ggpht.com/_M94xOMOWd6s/S-5p6-Wtm0I/AAAAAAAABZc/MSUtJhlH5MY/s800/adobe_air2rc1_drop_list_item_to_trash_on_winxp.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/S-5p6xJT8bI/AAAAAAAABZg/vaZZLZp_2tE/s800/adobe_air2rc1_drop_list_item_to_trash_on_winxp_after.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;http://lh4.ggpht.com/_M94xOMOWd6s/S-5qFph_hMI/AAAAAAAABZk/CUiRYTTPBpA/s800/adobe_air2rc1_drop_list_item_to_trash_on_win7.png&quot; alt=&quot;&quot; /&gt;
&lt;img src=&quot;http://lh3.ggpht.com/_M94xOMOWd6s/S-5qFmdy8lI/AAAAAAAABZo/p9PZvfWZjSs/s800/adobe_air2rc1_drop_list_item_to_trash_on_win7_after.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;

&lt;p&gt;I think this is a bug. But I have no solution.&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>Mac 服务器 servermgrd 崩溃</title>
        <link href="http://vitarn.com/2010/05/12/mac-server-servermgrd-crash.html"/>
        <updated>2010-05-12T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/05/12/mac-server-servermgrd-crash.html/</id>
        <summary type="html">&lt;p&gt;首先说一下背景:&lt;/p&gt;

&lt;p&gt;我们平常用Server Admin来管理MacOSX Server时, 是通过图形界面与一个叫servermgrd的后台进程沟通交换数据的, 它由LaunchCtl启动&lt;code&gt;/System/Library/LaunchDaemon/com.apple.servermgrd.plist&lt;/code&gt;实现开机自动运行, 侦听端口311.&lt;/p&gt;

&lt;p&gt;事实上servermgrd是一个Web服务器, 我们的Server Admin是通过HTTP的方式实现远程管理的(即便你在本机使用). 你可以在本机上打开&lt;a href=&quot;https://localhost:311&quot;&gt;https://localhost:311&lt;/a&gt;印证这一点.&lt;/p&gt;

&lt;p&gt;不得不说servermgrd的启动依赖太多东西, 修复的过程让我意识到许多服务的配置都会间接的导致servermgrd崩溃. 我认为这会导致许多不便, 问题的根源是servermgrd不能尝试去修复你的配置, 但至少应该兼容这些未包括在图形界面上或不正确的配置, 例如当配置Apache的时候用户自己打开配置文件加入的参数Server Admin是不会碰的. 总之, 不应该崩溃, 因为它一旦崩溃, Server Admin就无法修改, 这真的很尴尬.&lt;/p&gt;

&lt;p&gt;我的Mac Pro运行着Mac OS X Server 10.6.3. 在一次运行Gateway Setup Assistant失败后, 遭遇了servermgrd不能启动的尴尬局面. Console里显示servermgrd不能启动的原因是&amp;rdquo;Segmentation fault&amp;rdquo;.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!plain
May 12 14:20:39 mes servermgrd[7658]: servermgr_ipfilter:ipfw config:Notice:Flushed IPv4 rules
May 12 14:20:39 mes servermgrd[7658]: servermgr_ipfilter:ipfw config:Notice:Flushed IPv6 rules
May 12 14:20:39 mes com.apple.launchd[1] (com.apple.servermgrd[7658]): Job appears to have crashed: Segmentation fault
May 12 14:20:39 mes com.apple.launchd[1] (com.apple.servermgrd): Throttling respawn: Will start in 9 seconds
May 12 14:20:39 mes com.apple.ReportCrash.Root[7607]: 2010-05-12 14:20:39.824 ReportCrash[7607:440b] Saved crash report for servermgrd[7658] version ??? (???) to /Library/Logs/DiagnosticReports/servermgrd_2010-05-12-142039_localhost.crash
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;我尝试着google各种可能的关键词, 发现servermgrd不能启动的原因真的太多了. 许多问题都没有答案, 解决办法往往是重装系统.&lt;/p&gt;

&lt;p&gt;没有了Server Admin这个图形化的工具, 其实我们还有serveradmin这个shell工具, 它不需要与后端通讯, 只是用起来有点不方便.&lt;/p&gt;

&lt;p&gt;我是在运行向导时出现的问题, 因此我将目标锁定在NAT服务. (说起来容易, 其实到此为止我已经浪费了大半天的时间了.)&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
# 查看NAT服务配置
sudo serveradmin settings nat
nat:reverse = no
nat:unregistered_only = yes
nat:same_ports = yes
nat:natportmap_interface = &quot;en0&quot;
nat:log = yes
nat:clamp_mss = yes
nat:dynamic = yes
nat:log_denied = no
nat:use_sockets = yes
nat:proxy_only = no
nat:enable_natportmap = yes
nat:interface = &quot;&quot;
nat:deny_incoming = no
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;看到了没? NAT的接口竟然指向了空字符串.&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;nat:interface = &quot;&quot;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;修复方法:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;#!bash
# 试着改回正常值
sudo serveradmin settings nat:natportmap_interface = &quot;en1&quot;
nat:natportmap_interface = &quot;en1&quot;
sudo serveradmin settings nat:interface = &quot;en0&quot;
nat:interface = &quot;en0&quot;

# 等10秒看看servermgrd起来没
ps aux | grep servermgrd | grep -v grep
root      7687   0.0  0.2  2577788  38484   ??  Ss    2:20PM   0:03.57 servermgrd -x
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;顺便跟着乔老爷子起哄, BS一下Adobe.&lt;/p&gt;

&lt;p&gt;起死回生的Server Admin再一次尝试连接时, 会出奇的慢, 似乎在重置着自己的配置. 等了N久后显示 &lt;code&gt;Server Admin wants to use the PrivateEncryptedDatak keychain&lt;/code&gt;, 并且提示我输入密码, 可是怎么输也不对.&lt;/p&gt;

&lt;p&gt;你有没有觉得 &lt;code&gt;PrivateEncryptedDatak&lt;/code&gt; 很眼生, 它是谁呀? Google后发现它是Adobe Air的一个示例程序生成的Keychain. Adobe suck!&lt;/p&gt;

&lt;p&gt;删了它, 没事的, 反正就一Demo.&lt;/p&gt;

&lt;p&gt;位置: &lt;code&gt;~/Library/Application Support/Adobe/AIR/ELS/com.adobe.demo.RememberMe/&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;如果你有洁癖, 就继续打开Keychain - Edit - Keychain List. 把那里面的也删除了.&lt;/p&gt;
</summary>
    </entry>
    
    <entry>
        <title>Google 真是越来越可爱了</title>
        <link href="http://vitarn.com/2010/04/26/google-lovely-more.html"/>
        <updated>2010-04-26T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/04/26/google-lovely-more.html/</id>
        <summary type="html">&lt;h3 id=&quot;google--&quot;&gt;Google 真是越来越可爱了, 看图.&lt;/h3&gt;

&lt;p&gt;&lt;img src=&quot;http://lh5.ggpht.com/_M94xOMOWd6s/S9VgjSaGrtI/AAAAAAAABYw/QBR_QRBX5wQ/s800/Google%20lovely%20more.png&quot; alt=&quot;Google lovely more&quot; /&gt;&lt;/p&gt;

</summary>
    </entry>
    
    <entry>
        <title>循环输入用于 Google 日历的 .ics 格式文件</title>
        <link href="http://vitarn.com/2010/04/16/product-an-loop-ics-format-for-google-calendar.html"/>
        <updated>2010-04-16T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/04/16/product-an-loop-ics-format-for-google-calendar.html/</id>
        <summary type="html">&lt;pre&gt;&lt;code&gt;#!ruby
require 'date';

start, days, summary = DateTime.new(2010,1,1), 76, 'åˆ°';

puts %{
    BEGIN:VCALENDAR
    PRODID:-//Google Inc//Google Calendar 70.9054//EN
    VERSION:2.0
    CALSCALE:GREGORIAN
    METHOD:PUBLISH
    X-WR-TIMEZONE:UTC
    X-WR-CALDESC:
};

days.times {
    puts %{
        BEGIN:VEVENT
        DTSTART;VALUE=DATE:#{start.strftime('%Y%m%d')}
        DTEND;VALUE=DATE:#{start = start.next; start.strftime('%Y%m%d')}
        SUMMARY:#{summary}
        END:VEVENT
    }
};

puts %{END:VCALENDAR}
&lt;/code&gt;&lt;/pre&gt;
</summary>
    </entry>
    
    <entry>
        <title>Hello Toto!</title>
        <link href="http://vitarn.com/2010/04/08/hello-toto.html"/>
        <updated>2010-04-08T00:00:00-07:00</updated>
        <id>http://vitarn.com/2010/04/08/hello-toto.html/</id>
        <summary type="html">&lt;h3 id=&quot;about&quot;&gt;About:&lt;/h3&gt;

&lt;p&gt;Write artile by markdown and publish by git.&lt;/p&gt;

&lt;h3 id=&quot;why&quot;&gt;Why?&lt;/h3&gt;

&lt;p&gt;Why not?&lt;/p&gt;

&lt;p&gt;Do u like do a simple thing (write) with a complex way?&lt;/p&gt;

&lt;p&gt;I like toto. Because it so simple and cool. What&amp;rsquo;s blog title? What&amp;rsquo;s category or tags? What&amp;rsquo;s pingback and comment? What&amp;rsquo;s admin control panel? Whatever???&lt;/p&gt;

&lt;h3 id=&quot;support&quot;&gt;Support&lt;/h3&gt;

&lt;p&gt;中文&lt;/p&gt;

&lt;h1 id=&quot;section&quot;&gt;1号字&lt;/h1&gt;

&lt;h2 id=&quot;section-1&quot;&gt;2号字&lt;/h2&gt;

&lt;h3 id=&quot;section-2&quot;&gt;3号字&lt;/h3&gt;

&lt;h4 id=&quot;section-3&quot;&gt;4号字&lt;/h4&gt;

&lt;h5 id=&quot;section-4&quot;&gt;5号字&lt;/h5&gt;

&lt;h6 id=&quot;section-5&quot;&gt;6号字&lt;/h6&gt;

&lt;ul&gt;
  &lt;li&gt;列表
    &lt;ul&gt;
      &lt;li&gt;子项
        &lt;ul&gt;
          &lt;li&gt;子子项&lt;/li&gt;
        &lt;/ul&gt;
      &lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;粗体&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;斜体&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/cloudhead/toto&quot;&gt;链接&lt;/a&gt;&lt;/p&gt;
</summary>
    </entry>
    
</feed>
