<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ruohanc (陈若涵)</title>
    <link>https://ruby-china.org/ruohanc</link>
    <description>其实我是SA..正在学写代码...</description>
    <language>en-us</language>
    <item>
      <title>基于 rbenv 的多版本共存 ruby 运行时 rpm 打包实践 (提供下载)</title>
      <description>&lt;p&gt;一年前发了 &lt;a href="https://ruby-china.org/topics/16352" title=""&gt;rbenv system wide install (support for multi-user usecase)&lt;/a&gt; 帖子之后，今天又带来该方案的升级版：rpm 分发&lt;/p&gt;

&lt;p&gt;先看最终成果：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo yum install rbenv-ruby21 rbenv-ruby22 -y
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/39ae0105993cd1de4666eceb774d1127.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;接着就可以直接用 rbenv 了&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/31c29fa220f8dd8484b967d9923b7305.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="RPM 下载"&gt;RPM 下载&lt;/h3&gt;
&lt;p&gt;需要下载的同学移步 &lt;a href="https://build.opensuse.org/project/show/home:crhan:rbenv" rel="nofollow" target="_blank" title=""&gt;OBS&lt;/a&gt; 寻找，RH 系的包我都打好了&lt;/p&gt;
&lt;h2 id="最佳实践"&gt;最佳实践&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;对于 ssh 的用户，通过 &lt;code&gt;export RBENV_VERSION=2.2.0&lt;/code&gt; (或者 &lt;code&gt;rbenv shell 2.2.0&lt;/code&gt;) 来指定当前 shell 使用的 ruby 版本&lt;/li&gt;
&lt;li&gt;对于部署 app 的 case，在 app 的根目录下放置 &lt;code&gt;.ruby_version&lt;/code&gt; 文件来唯一确定使用的版本号&lt;/li&gt;
&lt;li&gt;没事别改 &lt;code&gt;rbenv global&lt;/code&gt; 对于线上生产机器来说，可能存在意想不到的副作用&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sun, 11 Jan 2015 12:14:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/23668</link>
      <guid>https://ruby-china.org/topics/23668</guid>
    </item>
    <item>
      <title>[投票] ruby.taobao.org 是否要 proxy rubygems 的 API 请求</title>
      <description>&lt;p&gt;起源是 &lt;a href="/pynic" class="user-mention" title="@pynic"&gt;&lt;i&gt;@&lt;/i&gt;pynic&lt;/a&gt; 发的帖子 &lt;a href="https://ruby-china.org/topics/19431" title=""&gt;淘宝源问题&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;因为淘宝 gems 镜像只是简单的 mirror 了上游的 gems 包 (使用工具 &lt;a href="https://github.com/alibaba/rubygems-mirror" rel="nofollow" target="_blank" title=""&gt;rubygems-mirror&lt;/a&gt;), 上传到阿里云 oss 之后再用 nginx 做前端做了一个 302 重定向实现的。&lt;/p&gt;

&lt;p&gt;因为本地没有任何应用跑着，所以 api 请求在本地肯定是无法服务了，之前 &lt;a href="/huacnlee" class="user-mention" title="@huacnlee"&gt;&lt;i&gt;@&lt;/i&gt;huacnlee&lt;/a&gt; 的解决方案是给 api 请求加了一个 proxy 到 &lt;a href="https://rubygems.org" rel="nofollow" target="_blank"&gt;https://rubygems.org&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;从我个人的使用感受上来说，加了这个 proxy 后 gems 的安装速度反而变慢了，因为从中国去 rubygems 的线路确实不好，就算在阿里的机房也没有明显优势。&lt;/p&gt;
&lt;h2 id="区别"&gt;区别&lt;/h2&gt;&lt;h3 id="proxy api"&gt;proxy api&lt;/h3&gt;
&lt;p&gt;代理 api 请求之后在 &lt;code&gt;gem install&lt;/code&gt; 的时候就会精确的获得 gems 的依赖关系，通过少量的 &lt;a href="https://ruby-china.org/topics/19431#reply4" title=""&gt;API 请求&lt;/a&gt; 来生成依赖图，然后下载对应的包&lt;/p&gt;
&lt;h3 id="api 404"&gt;api 404&lt;/h3&gt;
&lt;p&gt;api 请求 404 之后就会转而去下载 specs.4.8.gz 文件，拿到完整的 gem specs 列表，然后再去请求每个被安装 gems 的所有版本的 gemspec 文件&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.1.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.1.1-java.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.1-java.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.1.2.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.2.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.1.2-java.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.2-java.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.1.3.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.3.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.1.3-java.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.1.3-java.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.2.0.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.2.0.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.2.0-java.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.2.0-java.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.3.1.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.3.1.gemspec.rz
200 OK
GET https://ruby.taobao.org/quick/Marshal.4.8/thread_safe-0.3.1-java.gemspec.rz
302 Moved Temporarily
GET https://rubygems-china.oss.aliyuncs.com/quick/Marshal.4.8/thread_safe-0.3.1-java.gemspec.rz
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="投票"&gt;投票&lt;/h2&gt;
&lt;p&gt;其实就是征集下反馈：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;最近两个月的 gems.taobao.org 访问速度 (开了 api 的 proxy), 比起之前的访问速度如何，更好了还是更差了？应该继续打开这个 API Proxy 还是任由它 404, 还是说有人有兴趣写一个应用来提供本地的 API 服务？&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;注：现在 API 是 Proxy 的，即每次请求都会在后端请求到 &lt;a href="https://rubygems.org" rel="nofollow" target="_blank"&gt;https://rubygems.org&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <author>ruohanc</author>
      <pubDate>Tue, 05 Aug 2014 16:02:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/20847</link>
      <guid>https://ruby-china.org/topics/20847</guid>
    </item>
    <item>
      <title>分享几个部署时解决 ENV 变量问题的方案</title>
      <description>&lt;p&gt;比如 Rails 4.1 引入的 secrets.yml 中，production 默认的 SECRET_KEY_BASE 是 &lt;code&gt;&amp;lt;%= ENV["SECRET_KEY_BASE"] %&amp;gt;&lt;/code&gt;. 大家在线上部署时候是如何解决这个问题的呢.?&lt;/p&gt;

&lt;p&gt;我搜了几个方案分享一下&lt;/p&gt;
&lt;h2 id="通过设置对端 sshd_config 接受本端环境变量实现: http://overmind.ws/blog/2014/04/27/capistrano-3/"&gt;通过设置对端 sshd_config 接受本端环境变量实现：&lt;a href="http://overmind.ws/blog/2014/04/27/capistrano-3/" rel="nofollow" target="_blank"&gt;http://overmind.ws/blog/2014/04/27/capistrano-3/&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;大意是通过设置 sshd_config 的 &lt;code&gt;PermitUserEnvironment yes&lt;/code&gt; 后，再在本端的 ~/.ssh/environment 中手动写环境变量 &lt;code&gt;SECRET_KEY_BASE=66a2caf0d57e376cae89a297656c1224e5951609591374f9ba0a31a77ba36c4fcafd2f&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;这样通过 capistrano ssh 到对端后对端的环境中就带上了这个变量，于是搞定。&lt;/p&gt;

&lt;p&gt;缺点在于如果你要在一个机器上向对端部署多个应用就跪了&lt;/p&gt;
&lt;h2 id="通过 rbenv 插件 rbenv-vars 实现: https://intercityup.com/blog/deploying-app-env-variables-with-rbenv-passenger-and-capistrano/"&gt;通过 rbenv 插件 rbenv-vars 实现：&lt;a href="https://intercityup.com/blog/deploying-app-env-variables-with-rbenv-passenger-and-capistrano/" rel="nofollow" target="_blank"&gt;https://intercityup.com/blog/deploying-app-env-variables-with-rbenv-passenger-and-capistrano/&lt;/a&gt;
&lt;/h2&gt;
&lt;p&gt;rbenv 插件可以读取应用根目录下的 .rbenv-vars 文件，根据文件内容设置环境变量。于是只要在 capistrano 的 deploy.rb 中加上 &lt;code&gt;set :linked_files, %w{config/database.yml .rbenv-vars}&lt;/code&gt; 就可以了&lt;/p&gt;

&lt;p&gt;缺点是必须要安装 rbenv 和 rbenv-vars. 我在生产环境是直接用自编译的 ruby rpm 包，所以没 rbenv....&lt;/p&gt;
&lt;h2 id="通过 dotenv 或者 figaro gem 实现"&gt;通过 &lt;a href="https://github.com/bkeepers/dotenv" rel="nofollow" target="_blank" title=""&gt;dotenv&lt;/a&gt; 或者 &lt;a href="https://github.com/laserlemon/figaro" rel="nofollow" target="_blank" title=""&gt;figaro&lt;/a&gt; gem 实现&lt;/h2&gt;
&lt;p&gt;两个 gem 的功能都类似，都是提供一种机制能帮你预先把对应的变量放进 ENV Hash 中，其中最大的区别是 dotenv 鼓励你把 &lt;code&gt;.env&lt;/code&gt; 文件放入 repo, 方便新开发者直接上手，而 figaro 默认把配置文件加入了 &lt;code&gt;.gitignore&lt;/code&gt;. 见仁见智吧。&lt;/p&gt;

&lt;p&gt;另外 figaro 还有一个特性是 integrated with heroku, 通过 &lt;code&gt;figaro heroku:set -e production&lt;/code&gt; 命令直接搞定。&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Tue, 01 Jul 2014 22:30:42 +0800</pubDate>
      <link>https://ruby-china.org/topics/20264</link>
      <guid>https://ruby-china.org/topics/20264</guid>
    </item>
    <item>
      <title>ruby.taobao.org 启用 SSL (非强制跳转)</title>
      <description>&lt;p&gt;好吧没想到这贴也上精华了，那就说一下目前的情况。之前 ruby.taobao.org 站点是大约 2011 年 &lt;a href="/huacnlee" class="user-mention" title="@huacnlee"&gt;&lt;i&gt;@&lt;/i&gt;huacnlee&lt;/a&gt; 和 &lt;a href="/fsword" class="user-mention" title="@fsword"&gt;&lt;i&gt;@&lt;/i&gt;fsword&lt;/a&gt; 合力搞起来的。由于机器过保 + 网络安全整顿的原因，ruby.taobao.org 必须要搬到一个相对安全的环境内。目前的选择就是上阿里云，服务器使用 ECS 虚拟机，前端负载均衡使用 SLB, 后端对象存储则上 OSS.&lt;/p&gt;
&lt;h2 id="Changes"&gt;Changes&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;启用 SSL: &lt;a href="https://ruby.taobao.org" rel="nofollow" target="_blank"&gt;https://ruby.taobao.org&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;使用了 OSS 作为 Gems 存储&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="2014-4-21 更新"&gt;2014-4-21 更新&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;一天才上传了 25W 个 quick marshal 文件，还有 20W 个。&lt;/li&gt;
&lt;li&gt;SSL 搞定了，绑个 hosts &lt;code&gt;223.6.253.37 ruby.taobao.org&lt;/code&gt; 然后访问 &lt;a href="https://ruby.taobao.org" rel="nofollow" target="_blank"&gt;https://ruby.taobao.org&lt;/a&gt; 就能看到啦&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="2014-4-22 更新"&gt;2014-4-22 更新&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;今天就能上传完所有文件，接着就进入正常的更新节奏了&lt;/li&gt;
&lt;li&gt;计划在 2014-4-24 11:00 的时候切域名 ruby.taobao.org&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="2014-04-24 更新"&gt;2014-04-24 更新&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;已上线&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Gemfile&lt;/span&gt;
&lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="s2"&gt;"https://ruby.taobao.org"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sun, 20 Apr 2014 15:54:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/18735</link>
      <guid>https://ruby-china.org/topics/18735</guid>
    </item>
    <item>
      <title>gems 里面也是什么奇葩的名字都有啊</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2014/11efa2ef63a5e0617b0b9226a7fd8dfb.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sun, 20 Apr 2014 12:21:23 +0800</pubDate>
      <link>https://ruby-china.org/topics/18727</link>
      <guid>https://ruby-china.org/topics/18727</guid>
    </item>
    <item>
      <title>Google CodeJam 开始啦~赶快来玩</title>
      <description>&lt;p&gt;我也是第一次接触，给大家一个 quick-start:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;选择题目之后先看题干，写好代码后点下图的 &lt;code&gt;Solve&lt;/code&gt; 按钮
&lt;img src="//l.ruby-china.com/photo/2014/600bf3b8aecda99ab57a2196ea9bae2a.png" title="" alt=""&gt;
&lt;/li&gt;
&lt;li&gt;会自动下载一个 Input file 给你，然后你用这个 input file 计算出 output&lt;/li&gt;
&lt;li&gt;把 output 和 source code 两个文件上传&lt;/li&gt;
&lt;li&gt;继续下一题&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;第一轮还挺简单的~ 我就第三题不会做。&lt;/p&gt;

&lt;p&gt;&lt;a href="http://code.google.com/codejam/" rel="nofollow" target="_blank"&gt;http://code.google.com/codejam/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="第三题"&gt;第三题&lt;/h2&gt;&lt;h2 id="Problem"&gt;Problem&lt;/h2&gt;
&lt;p&gt;Minesweeper is a computer game that became popular in the 1980s, and is still included in some versions of the Microsoft Windows operating system. This problem has a similar idea, but it does not assume you have played Minesweeper.&lt;/p&gt;

&lt;p&gt;In this problem, you are playing a game on a grid of identical cells. The content of each cell is initially hidden. There are M mines hidden in M different cells of the grid. No other cells contain mines. You may click on any cell to reveal it. If the revealed cell contains a mine, then the game is over, and you lose. Otherwise, the revealed cell will contain a digit between 0 and 8, inclusive, which corresponds to the number of neighboring cells that contain mines. Two cells are neighbors if they share a corner or an edge. Additionally, if the revealed cell contains a 0, then all of the neighbors of the revealed cell are automatically revealed as well, recursively. When all the cells that don't contain mines have been revealed, the game ends, and you win.&lt;/p&gt;

&lt;p&gt;For example, an initial configuration of the board may look like this ('*' denotes a mine, and 'c' is the first clicked cell):&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*..*...**.
....*.....
..c..*....
........*.
..........
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There are no mines adjacent to the clicked cell, so when it is revealed, it becomes a 0, and its 8 adjacent cells are revealed as well. This process continues, resulting in the following board:&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;*..*...**.
1112*.....
00012*....
00001111*.
00000001..
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, there are still un-revealed cells that do not contain mines (denoted by '.' characters), so the player has to click again in order to continue the game.&lt;/p&gt;

&lt;p&gt;You want to win the game as quickly as possible. There is nothing quicker than winning in one click. Given the size of the board (R x C) and the number of hidden mines M, is it possible (however unlikely) to win in one click? You may choose where you click. If it is possible, then print any valid mine configuration and the coordinates of your click, following the specifications in the Output section. Otherwise, print "Impossible".&lt;/p&gt;
&lt;h2 id="Input"&gt;Input&lt;/h2&gt;
&lt;p&gt;The first line of the input gives the number of test cases, T. T lines follow. Each line contains three space-separated integers: R, C, and M.&lt;/p&gt;
&lt;h2 id="Output"&gt;Output&lt;/h2&gt;
&lt;p&gt;For each test case, output a line containing "Case #x:", where x is the test case number (starting from 1). On the following R lines, output the board configuration with C characters per line, using '.' to represent an empty cell, '*' to represent a cell that contains a mine, and 'c' to represent the clicked cell.&lt;/p&gt;

&lt;p&gt;If there is no possible configuration, then instead of the grid, output a line with "Impossible" instead. If there are multiple possible configurations, output any one of them.&lt;/p&gt;
&lt;h2 id="Limits"&gt;Limits&lt;/h2&gt;
&lt;p&gt;0 ≤ M &amp;lt; R * C.&lt;/p&gt;
&lt;h3 id="Small dataset"&gt;Small dataset&lt;/h3&gt;
&lt;p&gt;1 ≤ T ≤ 230.&lt;br&gt;
1 ≤ R, C ≤ 5.&lt;/p&gt;
&lt;h3 id="Large dataset"&gt;Large dataset&lt;/h3&gt;
&lt;p&gt;1 ≤ T ≤ 140.&lt;br&gt;
1 ≤ R, C ≤ 50.&lt;/p&gt;
&lt;h2 id="Sample"&gt;Sample&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Input 

5
5 5 23
3 1 1
2 2 1
4 7 3
10 10 82
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Output 

Case #1:
Impossible
Case #2:
c
.
*
Case #3:
Impossible
Case #4:
......*
.c....*
.......
..*....
Case #5:
**********
**********
**********
****....**
***.....**
***.c...**
***....***
**********
**********
**********
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sat, 12 Apr 2014 20:52:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/18562</link>
      <guid>https://ruby-china.org/topics/18562</guid>
    </item>
    <item>
      <title>大家 osx 的顶栏有多长啦...</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2014/ae5acc10661362880e812783ca237972.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;我的实在是太长了..经常被盖住..&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Fri, 31 Jan 2014 17:17:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/17064</link>
      <guid>https://ruby-china.org/topics/17064</guid>
    </item>
    <item>
      <title>如何在 C 代码中引用一个 ruby 代码里的对象?</title>
      <description>&lt;p&gt;我想在 C extention 中抛一个自定义的 exception 到 ruby 中。但是这个 exception 我想定义在 ruby 代码里。&lt;/p&gt;

&lt;p&gt;到底能不能 Ruby C extension 中引用 ruby 代码的对象啊，资料真不好找啊。&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sun, 26 Jan 2014 19:02:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/17010</link>
      <guid>https://ruby-china.org/topics/17010</guid>
    </item>
    <item>
      <title>如何让一个 AR 用起来像是另一种 Obj？</title>
      <description>&lt;p&gt;具体场景比如我希望做一个自签名的 CA，那么 CA Certificate 我希望可以序列化后保存在数据库里。然后每次取出这个 model 的时候就像拿出了一个 CA (&lt;code&gt;OpenSSL::X509::Certificate.new raw_pem_string&lt;/code&gt;)，并且这个对象也继承了  &lt;code&gt;OpenSSL::X509::Certificate&lt;/code&gt; 的所有方法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CACertificate&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
    &lt;span class="vi"&gt;@obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;OpenSSL&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;X509&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Certificate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;raw&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;subject&lt;/span&gt; &lt;span class="c1"&gt;# method from OpenSSL::X509::Certificate&lt;/span&gt;
    &lt;span class="vi"&gt;@obj.subject&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;save&lt;/span&gt;
    &lt;span class="vi"&gt;@obj.to_pem&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;CACertificate&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&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="nf"&gt;subject&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我其实还有另一种需求，就是把一个 AR 里面的一个属性当作一个对象来处理，当然保存的时候再用序列化的方式保存，下次取出的时候反序列化即可，比如 IP&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ip&lt;/span&gt;
    &lt;span class="vi"&gt;@ip&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;IPAddress&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;read_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;# 类似这样，但我不知道怎么序列化存进数据库&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;hr&gt;
&lt;h2 id="update:"&gt;update:&lt;/h2&gt;
&lt;p&gt;把 AR 的属性当作对象来处理解决了，有两个方案：&lt;/p&gt;
&lt;h3 id="自己序列化和反序列化"&gt;自己序列化和反序列化&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;ip&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;write_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ip&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;tap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="vi"&gt;@ip&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&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;def&lt;/span&gt; &lt;span class="nf"&gt;ip&lt;/span&gt;
    &lt;span class="vi"&gt;@ip&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;IPAddr&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt; &lt;span class="n"&gt;read_attribute&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ip&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;/code&gt;&lt;/pre&gt;&lt;h3 id="用 rails 提供的直接的序列化方案"&gt;用 rails 提供的直接的序列化方案&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Server&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Base&lt;/span&gt;
  &lt;span class="n"&gt;serialize&lt;/span&gt; &lt;span class="ss"&gt;:ip&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;IPAddress&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>ruohanc</author>
      <pubDate>Thu, 02 Jan 2014 22:08:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/16582</link>
      <guid>https://ruby-china.org/topics/16582</guid>
    </item>
    <item>
      <title>关于 Gem，我真的做对了吗</title>
      <description>&lt;p&gt;关于把 rails 的外部依赖抽成 Gem，我真的作对了吗？本该如此，还是说过程中存在可以优化的点呢？&lt;/p&gt;

&lt;p&gt;背景：我在公司里面用 Rails 写了一个底层运维系统，功能很简单：远程开关服务器电源（通过标准 IPMI 协议与服务器独立的 RMC 芯片通信，由 RMC 实现服务器的上下电）。由两个主要部分组成，一个是中心调度和对外 API 提供的 oob-master。另一个则是机房的本地服务节点，负责发出 ipmi 指令实际操作 BMC。&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/crhan/rubyipmi/tree/mydev" rel="nofollow" target="_blank" title=""&gt;rubyipmi&lt;/a&gt; gem 负责发起实际的 IPMI 请求&lt;/li&gt;
&lt;li&gt;oob-ipmi gem，调用 rubyipmi 的 API 操作 BMC，并捕捉所有已知的 BMC 异常统一返回结果&lt;/li&gt;
&lt;li&gt;oob-branch 作为机房本地服务节点，用 rails 写的，BMC 调用部分直接使用 oob-ipmi API 返回结果&lt;/li&gt;
&lt;li&gt;oob-master 从外部客户接受请求后，通过一定的路由规则找到对应的 oob-branch 下发操作等待回应&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;最近发现 oob-master 上有一个问题，需要通过修改 rubyipmi 解决，结果我为了 rubyipmi 的升级，自己也数不清楚发布了几次（包括 staging 和 production）&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;rubyipmi 升级&lt;/li&gt;
&lt;li&gt;oob-ipmi 升级 rubyipmi&lt;/li&gt;
&lt;li&gt;oob-branch 升级 oob-ipmi&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>ruohanc</author>
      <pubDate>Thu, 02 Jan 2014 16:06:26 +0800</pubDate>
      <link>https://ruby-china.org/topics/16573</link>
      <guid>https://ruby-china.org/topics/16573</guid>
    </item>
    <item>
      <title>rbenv system wide install (support for multi-user usecase)</title>
      <description>&lt;h2 id="起因"&gt;起因&lt;/h2&gt;
&lt;p&gt;是 &lt;a href="/luikore" class="user-mention" title="@luikore"&gt;&lt;i&gt;@&lt;/i&gt;luikore&lt;/a&gt; 吕大神的帖子 &lt;a href="http://ruby-china.org/topics/16073" title=""&gt;[姨妈] 终于把 rvm 换成 rbenv 了&lt;/a&gt;, 讨论 rbenv 比之 rvm 不足的地方，我列了这么四点&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;rvm 傻瓜的帮你处理一些库依赖 (特别是在 osx 下系统 readline 和 brew 安装的 GNU readline 傻傻分不清楚的时候)&lt;/li&gt;
&lt;li&gt;rvm 良好的处理了多用户服务器环境下的管理&lt;/li&gt;
&lt;li&gt;它官方有提供 offline 安装的方法，对我来说很重要，我有很多机器都不能上外网 (生产环境安全要求严格).&lt;/li&gt;
&lt;li&gt;有一个 binary 功能，可以让我自己打包一个适应本地环境的 ruby, 避免在每个服务器上编译 (未验证)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;今天来尝试用 rbenv 解决上述问题&lt;/p&gt;
&lt;h2 id="整理下需求:"&gt;整理下需求：&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;目标环境：是 linux 下的 production 运行环境，满足多用户共同使用的需求&lt;/li&gt;
&lt;li&gt;库依赖：只专注于解决第一个问题，跨平台的库依赖问题不予解决 (比如不同系统使用不同的包管理，不同的包名等问题)&lt;/li&gt;
&lt;li&gt;离线安装：能够完全只依赖有限的网络条件 offline 安装 (基本解决)&lt;/li&gt;
&lt;li&gt;多用户支持：使用 linux 组权限解决 rbenv 的 none root 用户使用问题 (比如安装新 ruby, 切换默认 ruby, 全局性的安装&amp;amp;删除 gem)&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="最后的结果"&gt;最后的结果&lt;/h2&gt;&lt;h3 id="多用户支持"&gt;多用户支持&lt;/h3&gt;
&lt;p&gt;通过 linux 的组权限解决，不完美，有点小问题。&lt;/p&gt;

&lt;p&gt;问题在 umask 的设置上，系统默认是 &lt;code&gt;umask 022&lt;/code&gt; 即组权限默认抹去 &lt;strong&gt;写权限&lt;/strong&gt;. 在类似的场景下可能会出现 permission deny: 用户 A 在 gem 的默认位置上安装了 gem A, 但是用户 B 想把它删掉&lt;/p&gt;

&lt;p&gt;解决这个问题的根本办法是请在 production 环境里面使用 &lt;code&gt;bundle install --deployment&lt;/code&gt; 谢谢！&lt;/p&gt;
&lt;h3 id="离线安装支持"&gt;离线安装支持&lt;/h3&gt;
&lt;p&gt;这部分没有写在脚本里，按照两步走：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;离线安装 rbenv 和 ruby-install: 简单，打个 tar 包就好了&lt;/li&gt;
&lt;li&gt;离线安装 ruby: 简单，建立一个 $RBENV_PREFIX/cache 文件夹，然后把 ruby 源代码放进去就好了&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;参考资料：&lt;a href="https://github.com/sstephenson/ruby-build#package-download-caching" rel="nofollow" target="_blank" title=""&gt;Package download caching&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3 id="部署运行方式"&gt;部署运行方式&lt;/h3&gt;
&lt;p&gt;linux 的安全性问题就不赘言了，总之你需要用一个独立的帐号来运行你的 rails app, 那么你应该这么做&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;折腾个什么劲啊，用 capistrano-rbenv 呗&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="安装脚本参考"&gt;安装脚本参考&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://gist.github.com/crhan/8064624#file-rbenv-install-system-wide-sh" rel="nofollow" target="_blank" title=""&gt;GIST 在此&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/usr/local"&lt;/span&gt;
&lt;span class="nv"&gt;RBENV_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREFIX&lt;/span&gt;&lt;span class="s2"&gt;/rbenv"&lt;/span&gt;
&lt;span class="nv"&gt;BIN_PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$PREFIX&lt;/span&gt;&lt;span class="s2"&gt;/bin"&lt;/span&gt;
&lt;span class="nv"&gt;RBENV_GROUP&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"rbenv"&lt;/span&gt;

&lt;span class="nb"&gt;umask &lt;/span&gt;002

&lt;span class="c"&gt;## Install rbenv, ruby-build and rbenv-gem-rehash&lt;/span&gt;
git clone git://github.com/sstephenson/rbenv.git &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;

&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;/plugins
git clone git://github.com/sstephenson/ruby-build.git &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;/plugins/ruby-build
git clone git://github.com/sstephenson/rbenv-gem-rehash.git &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;/plugins/rbenv-gem-rehash

&lt;span class="c"&gt;## add rbenv script to PATH&lt;/span&gt;
&lt;span class="nb"&gt;ln&lt;/span&gt; &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;/bin/rbenv &lt;span class="nv"&gt;$BIN_PATH&lt;/span&gt;/rbenv

&lt;span class="c"&gt;## Add rbenv to the System wide profile:&lt;/span&gt;
&lt;span class="c"&gt;## @note profiles only will be sourced in `login shell`,&lt;/span&gt;
&lt;span class="c"&gt;##       see the difference here(Chinese): https://gist.github.com/yegle/1564928&lt;/span&gt;
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt; &amp;gt; /etc/profile.d/rbenv.sh
# rbenv setup
export RBENV_ROOT=&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;RBENV_PREFIX&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;
eval "&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="sh"&gt;(rbenv init -)"
&lt;/span&gt;&lt;span class="no"&gt;EOF

&lt;/span&gt;&lt;span class="nb"&gt;chmod&lt;/span&gt; +x /etc/profile.d/rbenv.sh
&lt;span class="nb"&gt;source&lt;/span&gt; /etc/profile.d/rbenv.sh

&lt;span class="c"&gt;## set rbenv group property&lt;/span&gt;
groupadd &lt;span class="nv"&gt;$RBENV_GROUP&lt;/span&gt;
&lt;span class="nb"&gt;chown&lt;/span&gt; &lt;span class="nt"&gt;-R&lt;/span&gt; :rbenv &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt;
find &lt;span class="nv"&gt;$RBENV_PREFIX&lt;/span&gt; &lt;span class="nt"&gt;-type&lt;/span&gt; d &lt;span class="nt"&gt;-exec&lt;/span&gt; &lt;span class="nb"&gt;chmod &lt;/span&gt;g+Xs &lt;span class="o"&gt;{}&lt;/span&gt; &lt;span class="se"&gt;\;&lt;/span&gt;

&lt;span class="c"&gt;## Install Ruby&lt;/span&gt;
&lt;span class="c"&gt;#rbenv install 1.9.3-p484&lt;/span&gt;
&lt;span class="c"&gt;#rbenv install 2.0.0-p353&lt;/span&gt;
&lt;span class="c"&gt;#rbenv global 2.0.0-p353&lt;/span&gt;

&lt;span class="c"&gt;## Rehash:&lt;/span&gt;
&lt;span class="c"&gt;#rbenv rehash&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="2013-12-28 Update: chef 线上部署参考方案"&gt;2013-12-28 Update: chef 线上部署参考方案&lt;/h2&gt;
&lt;p&gt;经过线上验证，rbenv + ruby 完全可以通过 tar 包的方式快速部署到每一个服务器上（每个环境打一次包，用上面提供的脚本就行），我这里有一个 chef 的配置给大家参考：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://gist.github.com/crhan/8157604" rel="nofollow" target="_blank" title=""&gt;Gist: 8157604&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sat, 21 Dec 2013 11:56:11 +0800</pubDate>
      <link>https://ruby-china.org/topics/16352</link>
      <guid>https://ruby-china.org/topics/16352</guid>
    </item>
    <item>
      <title>把 `vender/cache` 目录放入 git 仓库然后部署是最佳实践吗?</title>
      <description>&lt;p&gt;我总认为 git 是放代码的地方，不应该 cache GEM 这些东西，但是不这么做我又不知道如何能够在无外网的环境下部署 rails 应用。求指点..&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Thu, 10 Oct 2013 10:52:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/14639</link>
      <guid>https://ruby-china.org/topics/14639</guid>
    </item>
    <item>
      <title>让你的 OSX 拥有完整的 Emacs Binding.</title>
      <description>&lt;p&gt;搜了半天终于找到，找这个的原因是我打算试试看 Sublime Text, 而在这之前我一直用的是 Vim. 在尝试使用 Sublime Text 的时候总觉的不能快速的 page up 和 page down 十分的不爽。&lt;/p&gt;

&lt;p&gt;OSX 拥有一部分 Emacs Binding: c-f, c-h, c-n ,c-b, 但是以 meta 键开头的 binding 不知道为啥变成了 œ∑†¥&lt;img title=":registered_sign:" alt="®" src="https://twemoji.ruby-china.com/2/svg/ae.svg" class="twemoji"&gt;øπåƒ√ 这些奇怪字符。结果就变成了可以用 c-v 下翻一页，但是却不能用 m-f 上翻一页，让我十分纠结。今天下决心找了一下如何在 OSX 下搞定完整的 Binding, 终于找到了 &lt;a href="http://superuser.com/questions/374799/emacs-like-meta-option-alt-key-functionality-in-os-x-lion" rel="nofollow" target="_blank" title=""&gt;superUser&lt;/a&gt; 上的这个答案。&lt;/p&gt;

&lt;p&gt;原理上原帖看吧，这里把代码复制一下：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; ~/Library/KeyBindings
&lt;span class="nb"&gt;cat&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; ~/Library/KeyBindings/DefaultKeyBinding.dict &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt;&lt;span class="no"&gt;EOF&lt;/span&gt;&lt;span class="sh"&gt;
{
/* Keybindings for emacs emulation.  Compiled by Jacob Rus.
 *
 * This is a pretty good set, especially considering that many emacs bindings
 * such as C-o, C-a, C-e, C-k, C-y, C-v, C-f, C-b, C-p, C-n, C-t, and
 * perhaps a few more, are already built into the system.
 *
 * BEWARE:
 * This file uses the Option key as a meta key.  This has the side-effect
 * of overriding Mac OS keybindings for the option key, which generally
 * make common symbols and non-english letters.
 */

    /* Ctrl shortcuts */
    "^l"        = "centerSelectionInVisibleArea:";  /* C-l          Recenter */
    "^/"        = "undo:";                          /* C-/          Undo */
    "^_"        = "undo:";                          /* C-_          Undo */
    "^ "        = "setMark:";                       /* C-Spc        Set mark */
    "^&lt;/span&gt;&lt;span class="se"&gt;\@&lt;/span&gt;&lt;span class="sh"&gt;"       = "setMark:";                       /* C-@          Set mark */
    "^w"        = "deleteToMark:";                  /* C-w          Delete to mark */


    /* Incremental search. */
/* Uncomment these lines If Incremental Search IM is installed */
/*  "^s"        = "ISIM_incrementalSearch:";        /* C-s          Incremental search */
/*  "^r"        = "ISIM_reverseIncrementalSearch:"; /* C-r          Reverse incremental search */
/*  "^g"        = "abort:";                         /* C-g          Abort */


    /* Meta shortcuts */
    "~f"        = "moveWordForward:";               /* M-f          Move forward word */
    "~b"        = "moveWordBackward:";              /* M-b          Move backward word */
    "~&amp;lt;"        = "moveToBeginningOfDocument:";     /* M-&amp;lt;          Move to beginning of document */
    "~&amp;gt;"        = "moveToEndOfDocument:";           /* M-&amp;gt;          Move to end of document */
    "~v"        = "pageUp:";                        /* M-v          Page Up */
    "~/"        = "complete:";                      /* M-/          Complete */
    "~c"        = ( "capitalizeWord:",              /* M-c          Capitalize */
                    "moveForward:",
                    "moveForward:");                                
    "~u"        = ( "uppercaseWord:",               /* M-u          Uppercase */
                    "moveForward:",
                    "moveForward:");
    "~l"        = ( "lowercaseWord:",               /* M-l          Lowercase */
                    "moveForward:",
                    "moveForward:");
    "~d"        = "deleteWordForward:";             /* M-d          Delete word forward */
    "^~h"       = "deleteWordBackward:";            /* M-C-h        Delete word backward */
    "~&lt;/span&gt;&lt;span class="se"&gt;\U&lt;/span&gt;&lt;span class="sh"&gt;007F"   = "deleteWordBackward:";            /* M-Bksp       Delete word backward */
    "~t"        = "transposeWords:";                /* M-t          Transpose words */
    "~&lt;/span&gt;&lt;span class="se"&gt;\@&lt;/span&gt;&lt;span class="sh"&gt;"       = ( "setMark:",                     /* M-@          Mark word */
                    "moveWordForward:",
                    "swapWithMark");
    "~h"        = ( "setMark:",                     /* M-h          Mark paragraph */
                    "moveToEndOfParagraph:",
                    "swapWithMark");

    /* C-x shortcuts */
    "^x" = {
        "u"     = "undo:";                          /* C-x u        Undo */
        "k"     = "performClose:";                  /* C-x k        Close */
        "^f"    = "openDocument:";                  /* C-x C-f      Open (find file) */
        "^x"    = "swapWithMark:";                  /* C-x C-x      Swap with mark */
        "^m"    = "selectToMark:";                  /* C-x C-m      Select to mark*/
        "^s"    = "saveDocument:";                  /* C-x C-s      Save */
        "^w"    = "saveDocumentAs:";                /* C-x C-w      Save as */
    };

}
&lt;/span&gt;&lt;span class="no"&gt;EOF
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote&gt;
&lt;p&gt;PS: 修改完配置后要重启应用才能生效，比如你想在 subl 里面生效那就要重启 subl&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sat, 13 Jul 2013 15:08:42 +0800</pubDate>
      <link>https://ruby-china.org/topics/12479</link>
      <guid>https://ruby-china.org/topics/12479</guid>
    </item>
    <item>
      <title>我是否应该使用 mongodb?(即 mongodb 能比 mysql 更好的解决我面临的问题吗?)</title>
      <description>&lt;p&gt;小弟正在尝试写一个类似监控中心的应用。数据量说多不多，说少不少。每天 12W 条数据。数据库大小每天增加 20M.&lt;/p&gt;

&lt;p&gt;有了数据自然要从各个维度去分析。从时间维度，机房维度，机器型号维度等等。如果我一次取出 12W 条数据，不说 mysql 在默认配置下查询费时 &lt;strong&gt;2s&lt;/strong&gt; 以上，而在 ruby 中建立如此大的一个数组也要耗费近 &lt;strong&gt;10s&lt;/strong&gt;. 更别说做后续更多的判断和统计逻辑。不敢想象如果我以后要分析一周，一个月的数据会演变成什么样的情况。&lt;/p&gt;

&lt;p&gt;于是我冒出了一个 &lt;strong&gt;"是不是该试试 mongodb"&lt;/strong&gt; 的想法，这回我正在通往啃 mongodb 文档的路上，顺便向各位前辈们请教，mongodb 是否能较为快速 (指性能) 的满足我的想法。谢谢啦。&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Mon, 10 Jun 2013 22:16:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/11636</link>
      <guid>https://ruby-china.org/topics/11636</guid>
    </item>
    <item>
      <title>大家的写 rails 时候的集成测试倾向于用 rspec 还是 cucumber?</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/03fedc5ad42f97b1ccdda069636bdd3e.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;暂时觉得还很难取舍。用 cucumber 觉得在文字上比较清晰。但有时候转念一想，明明 Rspec 可以干掉的事情干嘛还要 cucumber 来插一腿啊..&lt;/p&gt;

&lt;p&gt;大家怎么看呢..&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Fri, 09 Nov 2012 20:27:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/6650</link>
      <guid>https://ruby-china.org/topics/6650</guid>
    </item>
    <item>
      <title>分享一段用 Ruby 模拟网页登录并拿到页面的代码</title>
      <description>&lt;p&gt;要点在于 &lt;code&gt;Net::HTTP.new("example.com").get(url, headers)&lt;/code&gt; 的时候 &lt;code&gt;headers&lt;/code&gt; 中调用 cookie 方法，在没有 &lt;code&gt;@cookie&lt;/code&gt; 变量的时候就登录，然后后期如果得到的返回是 302, (如果 302 代表需要登录). 那就清除 &lt;code&gt;@cookie&lt;/code&gt; 变量再 &lt;code&gt;retry&lt;/code&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s2"&gt;"net/http"&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;PubPage&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;HTTP&lt;/span&gt;

    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="vc"&gt;@@instance&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;
        &lt;span class="vc"&gt;@@instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&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;def&lt;/span&gt; &lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;uri&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;URI&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;?&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
      &lt;span class="n"&gt;resp&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;NeedLoginException&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;resp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;"302"&lt;/span&gt;
      &lt;span class="n"&gt;resp&lt;/span&gt;
      &lt;span class="k"&gt;rescue&lt;/span&gt; &lt;span class="no"&gt;NeedLoginException&lt;/span&gt;
      &lt;span class="vi"&gt;@cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;
      &lt;span class="k"&gt;retry&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="kp"&gt;private&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;http&lt;/span&gt;
      &lt;span class="vi"&gt;@http&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&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="s2"&gt;"example.com"&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;def&lt;/span&gt; &lt;span class="nf"&gt;headers&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s2"&gt;"Cookie"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;cookie&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;def&lt;/span&gt; &lt;span class="nf"&gt;login_data&lt;/span&gt;
      &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;YAML&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;load_file&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;root&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"config/pub_page.yml"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
      &lt;span class="n"&gt;account&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"account"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="n"&gt;password&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"password"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="s2"&gt;"action=login&amp;amp;loginName=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;account&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;amp;pwd=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;password&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;login&lt;/span&gt;
      &lt;span class="vi"&gt;@cookie&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"/login.json"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;login_data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_fields&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'set-cookie'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;match&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/SESSION_ID/&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
        &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/; /&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
      &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;

    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;cookie&lt;/span&gt;
      &lt;span class="n"&gt;login&lt;/span&gt; &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="vi"&gt;@cookie&lt;/span&gt;
      &lt;span class="vi"&gt;@cookie&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;</description>
      <author>ruohanc</author>
      <pubDate>Mon, 29 Oct 2012 23:18:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/6395</link>
      <guid>https://ruby-china.org/topics/6395</guid>
    </item>
    <item>
      <title>Rails console 下, model 中 inspect 出的数据乱码</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/84848d4e3d4323874ff286a797eac19b.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;图片应该可以说明所有问题了。我想知道是就我这样呢。还是都这样。&lt;/p&gt;

&lt;p&gt;如果就我这是这样，有没有什么解决思路呢&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Sat, 20 Oct 2012 22:10:42 +0800</pubDate>
      <link>https://ruby-china.org/topics/6204</link>
      <guid>https://ruby-china.org/topics/6204</guid>
    </item>
    <item>
      <title>想使用 rails 做一个常在线的 gtalk 机器人, 如何让这个机器人 run 起来?</title>
      <description>&lt;p&gt;说的就是我以前做好的贴吧追小说机器人，项目&lt;a href="https://github.com/crhan/tieba_xiaoshuo_bot" rel="nofollow" target="_blank" title=""&gt;在 github 上&lt;/a&gt; .&lt;/p&gt;

&lt;p&gt;我现在想把他在 rails 下重新实现一遍 (其实暂时并没有打算做页面，只是为了借用 rails 完整的工具来部署). 然后我就不知道如何才能让这个机器人一直 run 在线了。&lt;/p&gt;

&lt;p&gt;原本的做法是写一个 sidekiq.rb, 然后在这个文件里面 require 需要的库，然后用全局变量 $bot hold 住一个 xmpp 连接。之后的发送消息什么的操作都通过这个全局变量来做。&lt;/p&gt;

&lt;p&gt;我现在觉得使用全局变量并不是一个合适的方法，但是除此之外我还真不知道怎么样才能正确的 hold 住这个连接了。请教各位。&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Fri, 19 Oct 2012 00:29:12 +0800</pubDate>
      <link>https://ruby-china.org/topics/6170</link>
      <guid>https://ruby-china.org/topics/6170</guid>
    </item>
    <item>
      <title>匹配中文的正则表达片段</title>
      <description>&lt;p&gt;今天在 twitter 上瞅见的：&lt;/p&gt;

&lt;p&gt;"这段正则 /[一 - 龠]+/ 能匹配简体和繁体，至少 Objective-C、JavaScript 和 Ruby 都验证过了，就是不知道字数范围有多少……"   -- ‏&lt;a href="/chrisyipw" class="user-mention" title="@chrisyipw"&gt;&lt;i&gt;@&lt;/i&gt;chrisyipw&lt;/a&gt; &lt;a href="https://twitter.com/ruohanc/status/249108475257425920" rel="nofollow" target="_blank" title=""&gt;推文&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/0c71b207a2b0d0d02694fa0f0db1c9e9.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;ruby-1.9.3-p194&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Fri, 21 Sep 2012 20:19:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/5680</link>
      <guid>https://ruby-china.org/topics/5680</guid>
    </item>
    <item>
      <title>帖子内的图标体验不统一.</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/7a19a8aa8d31cae627eb1ac2199a5f7f.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;如图所示，红色箭头指向的图标会自动弹出提示，黄色箭头指向的那些图标只有悬停之后才有提示，体验不统一啊..&lt;/p&gt;</description>
      <author>ruohanc</author>
      <pubDate>Wed, 08 Aug 2012 16:00:52 +0800</pubDate>
      <link>https://ruby-china.org/topics/4811</link>
      <guid>https://ruby-china.org/topics/4811</guid>
    </item>
  </channel>
</rss>
