<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>serco (Cxg)</title>
    <link>https://ruby-china.org/serco</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>未登录状态，浏览器点返回不会回退页面</title>
      <description>&lt;p&gt;这算是个 bug 还是 feature？&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Mon, 09 Jun 2025 22:32:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/44194</link>
      <guid>https://ruby-china.org/topics/44194</guid>
    </item>
    <item>
      <title>这字体丑的我想哭</title>
      <description>&lt;p&gt;突然用 windows 上了一下社区，字体不忍直视，丑的令人发指啊。
主题列表页字体居然是&lt;code&gt;sans-serif&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;即使是 CNode 看上去字体也比这个舒服多了。&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Mon, 02 May 2016 23:18:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/29898</link>
      <guid>https://ruby-china.org/topics/29898</guid>
    </item>
    <item>
      <title>[上海] 循绿生态科技 招 前端工程师, Ruby 工程师  [10-25k]</title>
      <description>&lt;p&gt;我们目前安家在徐家汇附近的一幢老洋房里，内装设计都是老板亲自操刀的。 &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;全部采用绿色环保建材，无污染。 &lt;/li&gt;
&lt;li&gt;室内有 N 个公司的空气净化器，从几百的 C grade 到几万的 A grade 的，保证室内 pm2.5 永远处在人体无害的水平（可能一些人意识不到室内空气污染远远严重于室外） &lt;/li&gt;
&lt;li&gt;App 上就能看到办公室 pm2.5，温度湿度等指标 &lt;/li&gt;
&lt;li&gt;厨房间配备符合欧盟标准的直饮水过滤设备 &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;为什么强调这些呢，因为我们是一家从事室内空气监测和认证的科技公司。客户覆盖地产，金融，奢侈品等行业巨头，铁狮门，麦肯锡，GUCCI 等都在使用我们的解决方案。 
最重要的，公司目前处在快速上升期，发展空间巨大，期权兑现指日可待啊。 &lt;/p&gt;

&lt;p&gt;下面就是比较 boring 的部分了&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;公司前端技术栈 ES6 Webpack React Redux, 后端 Ruby on Rails, Java&lt;/p&gt;
&lt;h5 id="前端工程师"&gt;前端工程师&lt;/h5&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;要求  

1. 本科及以上学历， CS 相关专业优先 
2. 前端开发相关经验 1-3 年 
3. 熟练掌握 Javascript ，熟悉 React, React Native 的优先 
4. 了解浏览器渲染的工作原理和 http 协议 

加分项 
1. 有大型前端项目经验 
2. 熟悉或者使用过 Backbone.js 或 Angular 或 Ember.js 或 Vue.js 
3. 熟悉 Webpack 等构建工具 
4. 热衷环境保护 
&lt;/code&gt;&lt;/pre&gt;&lt;h5 id="Ruby 工程师"&gt;Ruby 工程师&lt;/h5&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;要求  

1. 本科及以上学历， CS 相关专业优先 
2. Web开发相关经验 1-3 年 
3. 熟练掌握 Ruby, Rails，熟悉 Ruby 社区web开发相关 gem
4. 熟悉 linux, http 协议 
5. 熟悉MySQL, Postgres, Redis等至少一种数据库

加分项 

1. 有大型项目经验 
2. 有独立发布的 gem 或者 活跃的技术 blog
3. 熟悉 Javascript 及前端工具链
4. 热衷环境保护 
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;待遇 &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;10-25k/m, 13 薪 &lt;/li&gt;
&lt;li&gt;现磨咖啡，水果，Macbook &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;记得联系我哦 cxg#giga.build
PS: 暂时不接受 Remote&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Tue, 19 Apr 2016 10:06:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/29768</link>
      <guid>https://ruby-china.org/topics/29768</guid>
    </item>
    <item>
      <title>源码阅读系列 - connection_pool</title>
      <description>&lt;p&gt;项目地址：&lt;a href="https://github.com/mperham/connection_pool" rel="nofollow" target="_blank" title=""&gt;https://github.com/mperham/connection_pool&lt;/a&gt;，官方介绍如下&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Generic connection pooling for Ruby.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;如果你使用过 sidekiq 或者 dalli（多线程模式，需要自行设置），那你已经使用了这个 Gem。而且你猜的没错，他们的作者都是 Mike Perham（&lt;a href="https://github.com/mperham" rel="nofollow" target="_blank" title=""&gt;Github 地址&lt;/a&gt;）。&lt;/p&gt;

&lt;p&gt;作为一个通用的连接池项目，它的代码足够简单易读。&lt;/p&gt;
&lt;h3 id="1-基本用法"&gt;1-基本用法&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="vg"&gt;$redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;size: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="vg"&gt;$redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;smembers&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="2-目录结构"&gt;2-目录结构&lt;/h3&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;|--lib
   |--connection_pool
     |--timed_stack.rb
     |--version.rb
   |--connection_pool.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;整个项目只有 4 个 class&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;ConnectionPool&lt;/span&gt; &lt;span class="c1"&gt;# Pool class&lt;/span&gt;
&lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;TimedStack&lt;/span&gt; &lt;span class="c1"&gt;# Stack，用于生成和保存连接&lt;/span&gt;
&lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PoolShuttingDownError&lt;/span&gt; &lt;span class="c1"&gt;# 继承自 RuntimeError 的 Error&lt;/span&gt;
&lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Wrapper&lt;/span&gt; &lt;span class="c1"&gt;# ConnectionPool 的简单包装，可以忽略&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="3-原理"&gt;3-原理&lt;/h3&gt;
&lt;p&gt;整个项目的运行原理，大致如下：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ConnectionPool 会在实例化（下面称该实例为 pool）时同时创建一个 TimedStack 的实例对象（下面称该实例为 timed_stack）用来保存可用的连接。

&lt;ul&gt;
&lt;li&gt;pool 有一个实例变量 &lt;code&gt;@key = :"current-#{@available.object_id}"&lt;/code&gt; 来标记自己&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;每当 pool 调用 with 方法时，会从 timed_stack pop 出一个可用的连接。

&lt;ul&gt;
&lt;li&gt;timed_stack 中的连接是在使用时动态创建的，最大数为配置参数 size。&lt;/li&gt;
&lt;li&gt;在操作 timed_stack 时，使用了 &lt;code&gt;Mutex&lt;/code&gt; 线程锁来保证线程安全，另外使用了 &lt;code&gt;ConditionVariable&lt;/code&gt; 来保证资源的可用或者 raise Timeout::Error。&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;在步骤 2 中使用 pool 的线程也会生成一个 stack 用来保存正在使用的连接，并且在使用完毕后归还给 timed_stack。

&lt;ul&gt;
&lt;li&gt;可以每次生成一个新的线程来执行，比如 &lt;code&gt;Thread.new { pool.with {|con| con.do_something} }&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;使用 pool 的线程的 stack 可以用 pool 的 &lt;code&gt;@key&lt;/code&gt; 来找到对应的 stack，&lt;code&gt;::Thread.current[@key]&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;代码中 从 timed_stack 到 调用线程的 stack 被称之为 &lt;strong&gt;checkout&lt;/strong&gt;，相应的，从线程的 stack 返回到 timed_stack 被称之为 &lt;strong&gt;checkin&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="4-ConnectionPool 部分代码解释"&gt;4-ConnectionPool 部分代码解释&lt;/h3&gt;&lt;h4 id="步骤1"&gt;步骤 1&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 使用，创建一个连接池&lt;/span&gt;
&lt;span class="vg"&gt;$redis&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;size: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;initialize&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Line #44, lib/connection_pool.rb&lt;/span&gt;
  &lt;span class="c1"&gt;# block 是用于生成连接的代码，比方 Redis.connect&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'Connection pool requires a block'&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;

  &lt;span class="c1"&gt;# 配置部分，默认是 DEFAULTS = {size: 5, timeout: 5}&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;DEFAULTS&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;merge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="vi"&gt;@size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="vi"&gt;@available&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;TimedStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@size&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 实例了一个栈，用于保存连接&lt;/span&gt;
  &lt;span class="vi"&gt;@key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="ss"&gt;:"current-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="vi"&gt;@available.object_id&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="ss"&gt;"&lt;/span&gt; &lt;span class="c1"&gt;# 分配一个 pool 的 key，以后方便找回&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="步骤2&amp;amp;3"&gt;步骤 2&amp;amp;3&lt;/h4&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 使用 pool 来执行操作&lt;/span&gt;
&lt;span class="vg"&gt;$redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;with&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sadd&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'foo'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;with&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="c1"&gt;# Line #59, lib/connection_pool.rb&lt;/span&gt;
  &lt;span class="c1"&gt;# 延后 interrupt，以免出现 connection leak，比方主线程中断时&lt;/span&gt;
  &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:never&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 从 timed_stack checkout 一个 connection&lt;/span&gt;
    &lt;span class="k"&gt;begin&lt;/span&gt;
      &lt;span class="no"&gt;Thread&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;handle_interrupt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Exception&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:immediate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="c1"&gt;# 执行连接上的操作，比方 conn.sadd('foo', 1)&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;ensure&lt;/span&gt;
      &lt;span class="n"&gt;checkin&lt;/span&gt; &lt;span class="c1"&gt;# 保证 checkin，归还连接给 timed_stack&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;check out&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="c1"&gt;# Line #86, lib/connection_pool.rb&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
    &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="vi"&gt;@timeout&lt;/span&gt;
    &lt;span class="vi"&gt;@available.pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;timeout: &lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 从 timed_stack 取一个连接&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;last&lt;/span&gt; &lt;span class="c1"&gt;# 如果已经有，直接使用线程的 stack 里最后一个连接&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="c1"&gt;# 把连接 push 线程的 stack&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;check in&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;checkin&lt;/span&gt; &lt;span class="c1"&gt;# Line #98, lib/connection_pool.rb&lt;/span&gt;
  &lt;span class="n"&gt;conn&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;pop_connection&lt;/span&gt; &lt;span class="c1"&gt;# 从线程的 stack pop 出连接&lt;/span&gt;
  &lt;span class="vi"&gt;@available.push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;stack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt; &lt;span class="c1"&gt;# 如果线程的 stack 已经清空，那么把连接放回到 timed_stack&lt;/span&gt;

  &lt;span class="kp"&gt;nil&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;shutdown&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 关闭整个连接池&lt;/span&gt;
&lt;span class="vg"&gt;$redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;shutdown&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;conn&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;quit&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Line #105, lib/connection_pool.rb&lt;/span&gt;
  &lt;span class="vi"&gt;@available.shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="5-TimedStack 部分代码解释"&gt;5-TimedStack 部分代码解释&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 使用，创建一个保存连接的 stack&lt;/span&gt;
&lt;span class="no"&gt;TimedStack&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Redis&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connect&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Line #35, lib/connection_pool/timed_stack.rb&lt;/span&gt;
  &lt;span class="vi"&gt;@create_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt; &lt;span class="c1"&gt;# 用来创建连接的代码块&lt;/span&gt;
  &lt;span class="vi"&gt;@created&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="c1"&gt;# 已经创建的连接数量&lt;/span&gt;
  &lt;span class="vi"&gt;@que&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="c1"&gt;# 真正用来保存连接的 stack，用 Ruby 的数组实现&lt;/span&gt;
  &lt;span class="vi"&gt;@max&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;size&lt;/span&gt; &lt;span class="c1"&gt;# 最大连接数&lt;/span&gt;
  &lt;span class="vi"&gt;@mutex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Mutex&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="c1"&gt;# 线程锁&lt;/span&gt;
  &lt;span class="vi"&gt;@resource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;ConditionVariable&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="c1"&gt;# Mutex使用时资源的控制变量&lt;/span&gt;
  &lt;span class="vi"&gt;@shutdown_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt; &lt;span class="c1"&gt;# 用来关闭连接的代码块&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;pop&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="c1"&gt;# Line #71, lib/connection_pool/timed_stack.rb&lt;/span&gt;
  &lt;span class="c1"&gt;# 允许传递 {timeout: 0.7} 这样的参数&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="no"&gt;Hash&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
  &lt;span class="n"&gt;timeout&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fetch&lt;/span&gt; &lt;span class="ss"&gt;:timeout&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;

  &lt;span class="n"&gt;deadline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;timeout&lt;/span&gt;
  &lt;span class="c1"&gt;# 加上线程锁开始操作&lt;/span&gt;
  &lt;span class="vi"&gt;@mutex.synchronize&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="kp"&gt;loop&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="c1"&gt;# 如果已经开始关闭连接了，那么就不该再 pop 出去连接了&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ConnectionPool&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;PoolShuttingDownError&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@shutdown_block&lt;/span&gt;
      &lt;span class="c1"&gt;# 如果 @que 中有可用的连接，取一个出来，返回&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fetch_connection&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;connection_stored?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c1"&gt;# 如果 @que 中没有可用的连接&lt;/span&gt;
      &lt;span class="c1"&gt;# 试着创建一个，成功的话就返回&lt;/span&gt;
      &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;try_create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;

      &lt;span class="c1"&gt;# 创建失败的话，比方已经达到最大连接数后不允许继续创建，那么继续往下走&lt;/span&gt;

      &lt;span class="c1"&gt;# 如果已经超时，抛错&lt;/span&gt;
      &lt;span class="n"&gt;to_wait&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;deadline&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="no"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;Timeout&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"Waited &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;timeout&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; sec"&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;to_wait&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;

      &lt;span class="c1"&gt;# 释放 @mutex 锁，等待有可用连接。等到再次唤醒后再来重新执行这个 loop&lt;/span&gt;
      &lt;span class="vi"&gt;@resource.wait&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@mutex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;to_wait&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;push&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="c1"&gt;# Line #49, lib/connection_pool/timed_stack.rb&lt;/span&gt;
  &lt;span class="c1"&gt;# 加锁开始操作&lt;/span&gt;
  &lt;span class="vi"&gt;@mutex.synchronize&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# 如果已经收到了关闭的代码块，那么关闭这个 push 回来的连接&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="vi"&gt;@shutdown_block&lt;/span&gt;
      &lt;span class="vi"&gt;@shutdown_block.call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="c1"&gt;# 不然就存起来&lt;/span&gt;
      &lt;span class="n"&gt;store_connection&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="c1"&gt;# 释放锁，唤醒等待的操作（比方pop） &lt;/span&gt;
    &lt;span class="vi"&gt;@resource.broadcast&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="kp"&gt;alias_method&lt;/span&gt; &lt;span class="ss"&gt;:&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:push&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;em&gt;shutdown&lt;/em&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;shutdown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# Line #95, lib/connection_pool/timed_stack.rb&lt;/span&gt;
  &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;ArgumentError&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"shutdown must receive a block"&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="nb"&gt;block_given?&lt;/span&gt;

  &lt;span class="c1"&gt;# 加锁开始执行&lt;/span&gt;
  &lt;span class="vi"&gt;@mutex.synchronize&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;# 保存关闭连接的代码块&lt;/span&gt;
    &lt;span class="vi"&gt;@shutdown_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;
    &lt;span class="c1"&gt;# 释放锁，唤醒其他所有等待这个锁的操作（比方pop）&lt;/span&gt;
    &lt;span class="c1"&gt;# 这个时候如果还在执行 pop 里的 loop 就会 raise PoolShuttingDownError&lt;/span&gt;
    &lt;span class="c1"&gt;# 后续使用这些连接的操作都会收到这个 error&lt;/span&gt;
    &lt;span class="vi"&gt;@resource.broadcast&lt;/span&gt;

    &lt;span class="c1"&gt;# 关闭所有的连接&lt;/span&gt;
    &lt;span class="n"&gt;shutdown_connections&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>serco</author>
      <pubDate>Thu, 20 Aug 2015 17:29:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/27002</link>
      <guid>https://ruby-china.org/topics/27002</guid>
    </item>
    <item>
      <title>RubyMotion 的 一个深坑</title>
      <description>&lt;p&gt;项目中刚好用到 objective-c 的一个开源项目 Masonry
示例代码如下&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[view1 mas_makeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(superview).with.insets(padding);
}];
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;用 RubyMotion 和 motion-cocoapods 安装&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Motion&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;App&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setup&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pods&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;pod&lt;/span&gt; &lt;span class="s1"&gt;'Masonry'&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;调用&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mas_makeConstraints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="c1"&gt;# Line 24&lt;/span&gt;
      &lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;center&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equalTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;superview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;一切看上去都很美好，直到现实给了我一耳光&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*** Terminating app due to uncaught exception 'ArgumentError', reason: 'guess_view_controller.rb:24:in `block in viewDidLoad': wrong number of arguments (1 for 0) (ArgumentError)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那就检查下到底哪里出了问题&lt;/p&gt;

&lt;p&gt;&lt;code&gt;p make.center.method('equalTo').arity # return 0&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;妹啊，为啥跟文档说的不一样的。。。
看完源码才知道。。。
 &lt;code&gt;equalTo&lt;/code&gt;返回的是个 block，而 objective-c 的 block 就是 TM 的直接调用的。。。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- (MASConstraint * (^)(id))equalTo {
    return ^id(id attribute) {
        return self.equalToWithRelation(attribute, NSLayoutRelationEqual);
    };
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;好吧，改过来就好了&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mas_makeConstraints&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;lambda&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="c1"&gt;# Line 24&lt;/span&gt;
      &lt;span class="n"&gt;make&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;center&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;equalTo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;superview&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;})&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;本来这只是个小事情，可是难道以后 Objective-C 的库，类似的情况我都要去翻下源码才能确定是不是这个问题嘛。。。
累觉。。还是爱&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Thu, 21 May 2015 13:52:22 +0800</pubDate>
      <link>https://ruby-china.org/topics/25683</link>
      <guid>https://ruby-china.org/topics/25683</guid>
    </item>
    <item>
      <title>写了一个 Ping++ Ruby SDK</title>
      <description>&lt;p&gt;花了周末一些时间写了一个 Ping++ 的 SDK，欢迎试玩
Github &lt;a href="https://github.com/serco-chen/easy_ping" rel="nofollow" target="_blank" title=""&gt;https://github.com/serco-chen/easy_ping&lt;/a&gt;&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Wed, 03 Dec 2014 10:58:56 +0800</pubDate>
      <link>https://ruby-china.org/topics/22994</link>
      <guid>https://ruby-china.org/topics/22994</guid>
    </item>
    <item>
      <title>JS &amp; Firebase 这样的组合适合于什么样的场景呢？</title>
      <description>&lt;p&gt;仅仅只是多人游戏，聊天室等等吗？
目前有没有已经上线的有趣些的其他例子？&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Sun, 08 Dec 2013 22:37:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/16076</link>
      <guid>https://ruby-china.org/topics/16076</guid>
    </item>
    <item>
      <title>有人遇到过 RSpec + Capybara 下，有 testcase 随机挂掉的情况吗？</title>
      <description>&lt;p&gt;实在无解了。。找了很久没有找到问题。
已经按照 capybara 的方式等待元素加载完成，甚至在会随机挂掉的 testcase 中加入 wait n seconds 的方式，还是不行。。。&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Mon, 04 Nov 2013 00:00:29 +0800</pubDate>
      <link>https://ruby-china.org/topics/15271</link>
      <guid>https://ruby-china.org/topics/15271</guid>
    </item>
    <item>
      <title>Mina 部署怎么 rollback</title>
      <description>&lt;p&gt;如题，有没有类似 capistrano 的 rollback 功能？&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Sun, 11 Aug 2013 00:30:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/13238</link>
      <guid>https://ruby-china.org/topics/13238</guid>
    </item>
    <item>
      <title>工作之后发现圈子因职业而固定，怎么破？</title>
      <description>&lt;p&gt;比方我是建筑设计行业的，身边的同事自然都在这个圈子里。
就连朋友（除开同学）也大部分在这个圈子里，跟其他圈子的交集太少。&lt;/p&gt;

&lt;p&gt;说主动参加其他圈子的活动吧，有时候会有些格格不入，不知大家有没有这种感觉？&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Sun, 14 Apr 2013 12:50:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/10183</link>
      <guid>https://ruby-china.org/topics/10183</guid>
    </item>
    <item>
      <title>我咋当初就没选计算机呢。。。</title>
      <description>&lt;p&gt;高中同学今年收到 facebook 的 offer，即将携女友赴美工作，羡慕嫉妒恨啊。。。我咋当初就没选计算机专业呢。。。&lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Tue, 11 Dec 2012 13:48:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/7465</link>
      <guid>https://ruby-china.org/topics/7465</guid>
    </item>
    <item>
      <title>Objective-C 真是活跃啊，改进不断啊</title>
      <description>&lt;p&gt;Xcode 4.5 新出现的事物，希望什么时候 Objective-C 能和 Ruby 一样让人省心啊。&lt;/p&gt;

&lt;p&gt;传送门：&lt;a href="http://www.cocoachina.com/bbs/read.php?tid=107251" rel="nofollow" target="_blank"&gt;http://www.cocoachina.com/bbs/read.php?tid=107251&lt;/a&gt;  &lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Sat, 14 Jul 2012 00:18:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/4300</link>
      <guid>https://ruby-china.org/topics/4300</guid>
    </item>
    <item>
      <title>这个文件是用什么算法加密的</title>
      <description>&lt;p&gt;文件链接 &lt;a href="http://115.com/file/bems8qq2#mh.jws" rel="nofollow" target="_blank"&gt;http://115.com/file/bems8qq2#mh.jws&lt;/a&gt;
内容应该是纯英文和数字。求解  &lt;/p&gt;</description>
      <author>serco</author>
      <pubDate>Mon, 07 May 2012 15:02:14 +0800</pubDate>
      <link>https://ruby-china.org/topics/3131</link>
      <guid>https://ruby-china.org/topics/3131</guid>
    </item>
  </channel>
</rss>
