<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>easyhappy (andy)</title>
    <link>https://ruby-china.org/easyhappy</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>[上海] 美国 Robin8 诚聘中、高 Ruby 工程师 2 名</title>
      <description>&lt;h3 id="先说说我们"&gt;先说说我们&lt;/h3&gt;
&lt;p&gt;Robin8 Inc. 是来自美国纽约的高科技公司，我们的产品帮助进行社交营销公关的用户更高效地使用大数据，优化其媒体选择和效果。该模式已经在美国市场的测试取得成绩，目前我们在成立中国团队并开发更加适应国情的数据平台和产品。&lt;strong&gt;&lt;em&gt;现在进入中国，组建技术团队，所以现在是您加入的最好时机!!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="薪资、福利："&gt;薪资、福利：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;15K－25K／月，五险一金，交通、餐饮补贴&lt;/li&gt;
&lt;li&gt;正常带薪休假及体检福利&lt;/li&gt;
&lt;li&gt;可选的员工股权激励&lt;/li&gt;
&lt;li&gt;开放的办公室和工作氛围&lt;/li&gt;
&lt;li&gt;在有全球化团队流转需要时，我们还可以申请 H1B 签证帮助您在美国工作&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="我们希望您："&gt;我们希望您：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1-3 年 Ruby on Rails 开发经验;&lt;/li&gt;
&lt;li&gt;熟悉 Ruby on Rails，Ruby 生态环境，和各种常用 Gems；&lt;/li&gt;
&lt;li&gt;熟悉 JavaScript 和 CSS，了解常见前端框架/基础类库；熟悉 HTML，了解 HTML5 特性；&lt;/li&gt;
&lt;li&gt;使用过至少一种关系型或者 NoSQL 数据库；&lt;/li&gt;
&lt;li&gt;使用过至少一种版本控制工具；&lt;/li&gt;
&lt;li&gt;了解 Linux，Nginx 等上下游相关环境，能部署和优化 Web 项目；&lt;/li&gt;
&lt;li&gt;对产品可用性和易用性有要求，对新兴技术有好奇；&lt;/li&gt;
&lt;li&gt;有 React 经验的优先;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;当然如果您没有 Rails 经验，只要您愿意学，我们也是乐意带您一起成长。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;您大部分的工作时间会是在 Rails 服务器端编程。与此同时，您会知道市场／公关／社交媒体领域的最新动向，并思考如何将其转化为产品；也可以了解或参与机器学习／自然语言处理和大规模数据处理项目；或是参与到任何感兴趣并能胜任的企业方向。&lt;/p&gt;

&lt;p&gt;请将您的简历发送到：&lt;em&gt;andyhu@robin8.com&lt;/em&gt; ；&lt;/p&gt;

&lt;p&gt;公司地址：上海静安区江宁路 77 号恒顺大楼 7 层；&lt;/p&gt;

&lt;p&gt;公司网址：www.robin8.net。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Tue, 01 Mar 2016 16:20:06 +0800</pubDate>
      <link>https://ruby-china.org/topics/29169</link>
      <guid>https://ruby-china.org/topics/29169</guid>
    </item>
    <item>
      <title>最近网站被恶意攻击了</title>
      <description>&lt;p&gt;Hi, 万能的 ruby 朋友们，最近 我的网站 被攻击了。攻击的方式： &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;只攻击一个 api&lt;br&gt;
&lt;/li&gt;
&lt;li&gt; ip 经常换，但是 也就是那 几百个 ip。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt; user_agent 暂时没变。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt; cookies 暂时没变。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt; request.referer 伪造的是正常的。&lt;br&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;目前我能想到的是 通过 图片验证码，来提高 这个 api 的安全性。&lt;/p&gt;
&lt;h3 id="问题"&gt;问题&lt;/h3&gt;
&lt;p&gt;请问如何能获取到 这个 爬虫的 真实 ip。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Fri, 26 Feb 2016 11:32:32 +0800</pubDate>
      <link>https://ruby-china.org/topics/29115</link>
      <guid>https://ruby-china.org/topics/29115</guid>
    </item>
    <item>
      <title>[上海] 美国 Robin8 诚聘初、中 Ruby 工程师 3 名 [已结束 (感谢大家的关注)]</title>
      <description>&lt;h3 id="先说说我们"&gt;先说说我们&lt;/h3&gt;
&lt;p&gt;Robin8 Inc. 是来自美国纽约的高科技公司，我们的产品帮助进行社交营销公关的用户更高效地使用大数据，优化其媒体选择和效果。该模式已经在美国市场的测试取得成绩，目前我们在成立中国团队并开发更加适应国情的数据平台和产品。&lt;strong&gt;&lt;em&gt;现在进入中国，组建技术团队，所以现在是您加入的最好时机!!&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id="薪资、福利："&gt;薪资、福利：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;10K－20K／月，五险一金，交通、餐饮补贴&lt;/li&gt;
&lt;li&gt;正常带薪休假及体检福利&lt;/li&gt;
&lt;li&gt;可选的员工股权激励&lt;/li&gt;
&lt;li&gt;开放的办公室和工作氛围&lt;/li&gt;
&lt;li&gt;在有全球化团队流转需要时，我们还可以申请 H1B 签证帮助您在美国工作&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="我们希望您："&gt;我们希望您：&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;1-3 年 Ruby on Rails 开发经验;&lt;/li&gt;
&lt;li&gt;熟悉 Ruby on Rails，Ruby 生态环境，和各种常用 Gems；&lt;/li&gt;
&lt;li&gt;熟悉 JavaScript 和 CSS，了解常见前端框架/基础类库；熟悉 HTML，了解 HTML5 特性；&lt;/li&gt;
&lt;li&gt;使用过至少一种关系型或者 NoSQL 数据库；&lt;/li&gt;
&lt;li&gt;使用过至少一种版本控制工具；&lt;/li&gt;
&lt;li&gt;了解 Linux，Nginx 等上下游相关环境，能部署和优化 Web 项目；&lt;/li&gt;
&lt;li&gt;对产品可用性和易用性有要求，对新兴技术有好奇；&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;em&gt;当然如果您没有 Rails 经验，只要您愿意学，我们也是乐意带您一起成长。&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;您大部分的工作时间会是在 Rails 服务器端编程。与此同时，您会知道市场／公关／社交媒体领域的最新动向，并思考如何将其转化为产品；也可以了解或参与机器学习／自然语言处理和大规模数据处理项目；或是参与到任何感兴趣并能胜任的企业方向。&lt;/p&gt;

&lt;p&gt;请将您的简历发送到：&lt;em&gt;hr_china@robin8.com&lt;/em&gt; ；&lt;/p&gt;

&lt;p&gt;公司地址：上海市静安区愚园路 20 号东海广场 3 号楼 15 楼 创客中心；&lt;/p&gt;

&lt;p&gt;公司网址：www.robin8.com。&lt;/p&gt;
&lt;h3 id="补充说明"&gt;补充说明&lt;/h3&gt;
&lt;p&gt;实习生 我们也是需要的，只要你足够聪明，那就来吧。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Mon, 21 Sep 2015 10:13:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/27414</link>
      <guid>https://ruby-china.org/topics/27414</guid>
    </item>
    <item>
      <title>移动 IM 学习笔记</title>
      <description>&lt;p&gt;最近在看移动 IM 相关的资料，然后发现网上有很多的资料，所以在学习过程中，整理了一些笔记，供那些 想了解 移动 IM 的童鞋一些参考。&lt;/p&gt;
&lt;h3 id="移动IM技术选型要点"&gt;移动 IM 技术选型要点&lt;/h3&gt;
&lt;p&gt;1、协议选型
2、IM 服务器选型
3、协议和 IM 服务器改造
4、移动 IM 常见问题以及一些解决方案 
5、一些第三方服务&lt;/p&gt;
&lt;h3 id="一、常用的IM协议"&gt;一、常用的 IM 协议&lt;/h3&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/b11cd1f45eee8326215e0985a3541081.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="二、IM 服务器的选择"&gt;二、IM 服务器的选择&lt;/h3&gt;
&lt;p&gt;经过这几天在网上的调研，发现目前比较流行的几个 IM 服务器 也就是 Openfire、Tigase, Ejabberd:&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/e2bfd15bc496c428a6755c73a6a15e96.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;备注：
&lt;a href="http://www.csdn.net/article/2012-09-10/2809790-zoosk-the-engineering-behind-real-time" rel="nofollow" target="_blank" title=""&gt;详解 Zoosk 千万用户实时通信背后的开源技术&lt;/a&gt; &lt;/p&gt;
&lt;h3 id="三、XMPP协议的问题及改进"&gt;三、XMPP 协议的问题及改进&lt;/h3&gt;
&lt;p&gt;1、登录握手部分改进&lt;br&gt;
Xmpp QuickStart  &lt;/p&gt;

&lt;p&gt;2、心跳改进&lt;br&gt;
原先 Xmpp 使用的 Ping/Pong 40+ 字节，改进为单向 white space ping, 4 字节。&lt;br&gt;
备注：心跳单向四个字节，在 Xmpp 协议下，估计应该是极限了吧。在私有协议协议下，一来一往两个字节足够。  &lt;/p&gt;

&lt;p&gt;3、文件传输&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Xmpp 的文件传输采用的点对点的传输; 改进为 http 上传到 server&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;语音、视频压缩上传&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;图片默认下载缩略图&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;4、Presense&lt;/p&gt;

&lt;p&gt;移动互联网环境下，不管用户是否在线，都会假设 用户永远在线。&lt;br&gt;
这是因为移动网络环境导致，比如从 wifi 切换到 3G、处于地铁、WIFI 边缘地带等，如果还采用 PC 端 类似 QQ 那种方式，很可能会造成重连风暴。&lt;/p&gt;

&lt;p&gt;5、Muc 聊天室&lt;/p&gt;

&lt;p&gt;Muc 是聊天室协议，在业务层面进行改进，发送消息时 发送给所有用户，不管他在不在线&lt;/p&gt;
&lt;h3 id="四、基于Openfire 服务器的改进"&gt;四、基于 Openfire 服务器的改进&lt;/h3&gt;
&lt;p&gt;1、发送消息回执&lt;/p&gt;

&lt;p&gt;在 server 端维护一个消息队列，当收到 client 发送会的消息回执时，将这个消息删掉&lt;/p&gt;

&lt;p&gt;2、性能改进&lt;/p&gt;

&lt;p&gt;不要使用内置的数据库，对于 Vcard 或者好友列表信息 可以考虑放到 Redis&lt;/p&gt;

&lt;p&gt;3、如果是消息量很大的话，消息存储可以使用 Kafka（和数据库集群之间存定时拉取关系），分布式锁基于 Zookeeper，前端 LVS 做负载均衡。&lt;/p&gt;
&lt;h3 id="五、移动IM的那些坑点"&gt;五、移动 IM 的那些坑点&lt;/h3&gt;
&lt;p&gt;1、长连接&lt;/p&gt;

&lt;p&gt;android 平台 维护 client 到 server 的长连接&lt;/p&gt;

&lt;p&gt;IM 或推送，建立长连接是必须的，可以节省 TCP 来回创建的开销，但断线之后，是否需要即刻重连，尤其是处于地铁、WIFI 边缘地带，可能会造成重连风暴，需要添加稍加延迟连接机制。&lt;/p&gt;

&lt;p&gt;2、心跳包 GGSN&lt;/p&gt;

&lt;p&gt;维护移动网 GGSN&lt;/p&gt;

&lt;p&gt;3、消息回执处理 Ack&lt;/p&gt;

&lt;p&gt;移动网络很容易丢包，发送、接受应加入回执处理&lt;/p&gt;

&lt;p&gt;4、语音、图片的收发优化&lt;/p&gt;

&lt;p&gt;大数据拆分成多个包，一个包大概 10 字节&lt;/p&gt;
&lt;h3 id="六、第三方的IM服务"&gt;六、第三方的 IM 服务&lt;/h3&gt;
&lt;p&gt;1、&lt;a href="http://www.easemob.com/" rel="nofollow" target="_blank" title=""&gt;环信&lt;/a&gt;(个人感觉选他不错), 大概是从 2013 年 4 月创立，到目前为止号称 有 6000 万注册用户，有 1000+ app 使用&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/03d00843dd54e43aeef7116e3441d23a.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;2、&lt;a href="https://leancloud.cn/" rel="nofollow" target="_blank" title=""&gt;leancloud&lt;/a&gt; 2013 年 9 月发布以来，已经吸引了近万移动应用和开发者加入。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/2b50edb84500ecb2c97fceac1b59c58a.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="七、结论"&gt;七、结论&lt;/h3&gt;
&lt;p&gt;如果说自己搭建一套 IM 框架的：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;基本能用需要 3 个月&lt;/li&gt;
&lt;li&gt;做的比较好需要 9 月到 1 年时间&lt;/li&gt;
&lt;li&gt;做的像微信一样，那么需要 2 年时间&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果说基于现有的 IM 服务器搭建的话，个人觉得 从 IMserver 性能以及后期维护和招人成本上来看，应该是 Tigase &amp;gt; Openfire &amp;gt; Ejabberd&lt;/p&gt;
&lt;h3 id="八、写在最后"&gt;八、写在最后&lt;/h3&gt;
&lt;p&gt;如果你也对 IM 感兴趣的话，可以看一看 环信的一个&lt;a href="http://v.csdn.hudong.com/s/article.html?arcid=15819558" rel="nofollow" target="_blank" title=""&gt;讲座&lt;/a&gt;, 对应的&lt;a href="http://vdisk.weibo.com/s/A0GI9rXObFMd" rel="nofollow" target="_blank" title=""&gt;ppt&lt;/a&gt;。&lt;br&gt;
当然了，由于我本人接触 IM 这块也不太久，所以肯定会有一些遗漏，欢迎大家提意见呀...&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Thu, 06 Nov 2014 14:54:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/22530</link>
      <guid>https://ruby-china.org/topics/22530</guid>
    </item>
    <item>
      <title>今天是梅西生涯十周年</title>
      <description>&lt;p&gt;首先 承认 自己是 一个梅西球迷，当然也是巴萨的球迷，今天看到 梅西 出道 10 周年了。
回想起来我是在 2010 年 开始 看巴萨，开始看梅西，当时的巴萨可以是正值巅峰中的巅峰，基本是遇神杀神了...&lt;/p&gt;

&lt;p&gt;当时就在想，靠，球还可以这么踢...&lt;/p&gt;

&lt;p&gt;慢慢的爱上了 西甲、爱上了巴萨、爱上了梅西... 习惯了每天早上第一件事情 就是打开新浪体育西甲比赛...&lt;/p&gt;

&lt;p&gt;顺便上一个&lt;a href="http://v.youku.com/v_show/id_XODA1MTQwNTg4.html" rel="nofollow" target="_blank" title=""&gt;优酷视频：绚丽到爆！梅西一个足球的王者&lt;/a&gt; &lt;img title=":smile:" alt="😄" src="https://twemoji.ruby-china.com/2/svg/1f604.svg" class="twemoji"&gt; &lt;/p&gt;

&lt;p&gt;顺便 想问下，论坛的小伙伴们，有哪些足球粉，有平时踢球的么....&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Fri, 17 Oct 2014 13:30:34 +0800</pubDate>
      <link>https://ruby-china.org/topics/22087</link>
      <guid>https://ruby-china.org/topics/22087</guid>
    </item>
    <item>
      <title>基于地址位置，查询附近的人 ，解决方案及性能分析 [已更新， 详见下面的结论]</title>
      <description>&lt;h3 id="1、场景介绍"&gt;1、场景介绍&lt;/h3&gt;
&lt;p&gt;对于很多 LBS 应用来说，让用户寻找周围的好友 可能 都是一个必不可少的功能，下面 我们就以这个功能为例：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;显示我附近的人&lt;/li&gt;
&lt;li&gt;由近到远排序&lt;/li&gt;
&lt;li&gt;显示距离&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;对于以上的问题，目前解决方案有很多种，比如：&lt;/p&gt;

&lt;p&gt;a. 基于 MySQL 数据库
b. 采用 GeoHash 索引，基于 MySQL
c. MySQL 空间存储（MySQL Spatial Extensions）
d. 使用 MongoDB 存储地理位置信息
e. 使用 PostgreSQL 存储地理位置信息&lt;/p&gt;

&lt;p&gt;关于 a、b、c,  &lt;a href="http://www.infoq.com/cn/articles/depth-study-of-Symfony2" rel="nofollow" target="_blank" title=""&gt;这篇文章&lt;/a&gt; 已经很好的说明了，这里就不一一赘述，下面我们主要是基于方案 d 深入探讨一些东西。&lt;/p&gt;
&lt;h3 id="2、使用MongoDB存储地理位置信息"&gt;2、使用 MongoDB 存储地理位置信息&lt;/h3&gt;
&lt;p&gt;MongoDB 原生支持地理位置索引，可以直接用于位置距离计算和查询。查询结果默认将会由近到远排序，而且查询结果也包含目标点对象、距离目标点的距离等信息。&lt;/p&gt;

&lt;p&gt;而且 geoNear 是 MongoDB 原生支持的查询函数，所以性能上也做到了高度的优化，完全可以应付生产环境的压力。&lt;/p&gt;
&lt;h3 id="3、MongoDB索引介绍"&gt;3、MongoDB 索引介绍&lt;/h3&gt;
&lt;p&gt;2d index:&lt;/p&gt;

&lt;p&gt;使用 2d index 能够将数据作为 2 维平面上的点存储起来，在 MongoDB 2.2 以前 推荐使用 2d index 索引。
现在 MongodDB 2.6 了，推荐使用 2dspere index&lt;/p&gt;

&lt;p&gt;2dsphere index:&lt;/p&gt;

&lt;p&gt;2dsphere index 支持球体的查询和计算，同时它支持数据存储为&lt;a href="http://docs.mongodb.org/manual/reference/glossary/#term-geojson" rel="nofollow" target="_blank" title=""&gt;GeoJSON&lt;/a&gt; 和传统坐标。&lt;/p&gt;
&lt;h3 id="4、性能测试"&gt;4、性能测试&lt;/h3&gt;
&lt;p&gt;先说说 测试环境：&lt;/p&gt;

&lt;p&gt;Mac Pro(处理器 Intel Core i5、2.4 GHz、2 核、16G 内存) + Mongo 2.6 + Rails4.1.4&lt;/p&gt;

&lt;p&gt;model 代码：&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;User&lt;/span&gt;
   &lt;span class="n"&gt;field&lt;/span&gt; &lt;span class="ss"&gt;:location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="ss"&gt;type: &lt;/span&gt;&lt;span class="no"&gt;Array&lt;/span&gt;
   &lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="s2"&gt;"2d"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;background: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
   &lt;span class="c1"&gt;# 或者 index({ location: "2dsphere"}, { background: true })&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;nearby&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coordinate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;max_distance&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
       &lt;span class="c1"&gt;# 5公里内， 符合条件的记录， 默认取100个。同时会按照距离的远近 进行排序。&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;geo_near&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;coordinate&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;max_distance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;max_distance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fdiv&lt;/span&gt;   &lt;span class="mi"&gt;6371&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;spherical&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;distance_multiplier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;6371000&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;code&gt;命令1&lt;/code&gt;的 查询时间：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.nearby([117.490219, 40.962954]).count
# 5公里内， 符合条件的记录， 默认取100个。同时会按照距离的远近 进行排序。
# 距离 存在 attributes["geo_near_distance"] 中， example：User.nearby([117.490219, 40.962954]).first["geo_near_distance"]

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/c33d7630ce10a201aca627eab3bdb025.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;通过测试发现，使用 2d index 在数据量 变大的过程中，查询时间 会变的 非常慢，而使用 2d sphere index 基本可以控制在 0.5s 左右。&lt;code&gt;这里 留下一个问题: 为什么会是这样的？&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;使用&lt;code&gt;命令2&lt;/code&gt;：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.where(:location =&amp;gt; {"$within" =&amp;gt; {"$centerSphere" =&amp;gt; [[116.490219, 42.962954], (5.fdiv(6371) )]}}).count
# 5公里内， 符合条件的记录、默认会选出所有符合条件的结果。
# 缺点是 需要自己进行排序, 且需要自己计算 geo_near_distance。

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/4b64cc7eb87b18ecbfdbf0d8c2cba9bc.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;命令2&lt;/code&gt; 因为不需要 对 符合条件的结果 进行排序，所以 查询时间 相比 &lt;code&gt;命令1&lt;/code&gt;的 查询时间 大大减少。&lt;/p&gt;

&lt;p&gt;备注:
每 1w 条 数据的插入时间是 8s 左右。&lt;/p&gt;
&lt;h3 id="5、其他的一些 概念的东西"&gt;5、其他的一些 概念的东西&lt;/h3&gt;
&lt;p&gt;MongoDB 查询地理位置默认有 3 种距离单位：
米 (meters)
平面单位 (flat units，可以理解为经纬度的“一度”)
弧度 (radians)&lt;/p&gt;

&lt;p&gt;2d 索引能同时支持$center 和$centerSphere，
2dsphere 索引支持$centerSphere。
关于距离单位，$center 默认是度，$centerSphere 默认距离是弧度。&lt;/p&gt;
&lt;h3 id="6、使用PostgreSQL存储地理位置信息"&gt;6、使用 PostgreSQL 存储地理位置信息&lt;/h3&gt;
&lt;p&gt;关于 PostgreSQL 和 Rails 的结合，可以参考 我同事&lt;a href="/windstill" class="user-mention" title="@windstill"&gt;&lt;i&gt;@&lt;/i&gt;windstill&lt;/a&gt;的&lt;a href="http://windstill.me/blog/2014/10/15/rails-with-postgis/" rel="nofollow" target="_blank" title=""&gt;文章&lt;/a&gt;, 这里就不具体描述了&lt;/p&gt;

&lt;p&gt;测试环境介绍：&lt;/p&gt;

&lt;p&gt;Mac Pro(处理器 Intel Core i5、2.4 GHz、2 核、16G 内存) + PostgreSQL 9.3.5 +  &lt;a href="http://postgis.refractions.net/" rel="nofollow" target="_blank" title=""&gt;PostGis2.1.3&lt;/a&gt;(PostgreSQL 的扩展) + Rails4.1.4&lt;/p&gt;

&lt;p&gt;备注：&lt;code&gt;postgis完整实现了opengis 的 Simple Features标准之中的空间对象模型和函数&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;测试命令&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User.select("users.*, st_distance(location, 'point(116.458104 39.966293)') as distance").where("st_dwithin(location, 'point(116.458104 39.966293)', 10000)").order("distance")
# 查找10公里 内结果， 并按照距离进行排序
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;测试结果：&lt;/strong&gt;
&lt;img src="https://l.ruby-china.com/photo/2014/fe9ddd2fc89de863b1166c135ad28844.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="7、结论"&gt;7、结论&lt;/h3&gt;
&lt;p&gt;关于地理位置的计算，其实 Mysql、MongoDB、PostgreSQL 都支持，只不过 MongoDB 和 PostgreSQL 支持的更好一些。
而且通过 测试我们可以发现 MongoDB 在数据量 变大的时候，查询的瓶颈 会变的越来越大。反过来看 PostgreSQL，它的查询时间基本是随着 数据量的增长，而线性增长的。&lt;/p&gt;

&lt;p&gt;所以 如果你的应用 数据量不大 或者说在百万级别的话 可以考虑用 MongoDB。但是如果数据量是千万级别或者更高的话，推荐使用 PostgreSQL。&lt;/p&gt;

&lt;p&gt;当然了 由于我们这个项目业务既 需要 事务，又需要 Geo 计算，所以选择 PostgreSQL 作为我们的主数据库。&lt;/p&gt;
&lt;h3 id="8、留坑"&gt;8、留坑&lt;/h3&gt;
&lt;p&gt;后期 会在使用 PostgreSQL 使用一段 时间后，深入的总结一些关于它的东东...&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Wed, 15 Oct 2014 16:29:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/22059</link>
      <guid>https://ruby-china.org/topics/22059</guid>
    </item>
    <item>
      <title>Sunspot 学习笔记</title>
      <description>&lt;h3 id="Sunspot是什么?"&gt;Sunspot 是什么？&lt;/h3&gt;
&lt;p&gt;Sunspot 用 Ruby 的方式实现了与 Solr 搜索引擎的交互。底层是基于 Rsolr，而且提供了很方便的 DSL 接口实现建立索引和搜索。&lt;/p&gt;
&lt;h3 id="Sunspot使用"&gt;Sunspot 使用&lt;/h3&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sunspot_rails'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'sunspot_solr'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;github: &lt;/span&gt;&lt;span class="s1"&gt;'xhj/sunspot'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;require: &lt;/span&gt;&lt;span class="s1"&gt;'sunspot_solr'&lt;/span&gt;
&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="s1"&gt;'progress_bar'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;备注：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;其中 sunspot_solr 使用&lt;a href="https://ruby-china.org/topics/15897" title=""&gt;sunspot_solr 的衍生版本&lt;/a&gt;(ruby-china 上&lt;a href="/xhj6" class="user-mention" title="@xhj6"&gt;&lt;i&gt;@&lt;/i&gt;xhj6&lt;/a&gt;封装的), 目的是集成 mmseg4j 1.9.1 中文分词插件 (下文会详细介绍)&lt;/li&gt;
&lt;li&gt;添加 gem 的 progress_bar 原因是在执行 task&lt;code&gt;rake sunspot:solr:reindex&lt;/code&gt;时 会在 terminal 上等待较长时间。 &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;安装生成默认的配置信息&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;generate&lt;/span&gt; &lt;span class="n"&gt;sunspot_rails&lt;/span&gt;&lt;span class="ss"&gt;:install&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;运行 Sunspot&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="n"&gt;sunspot&lt;/span&gt;&lt;span class="ss"&gt;:solr:start&lt;/span&gt; &lt;span class="c1"&gt;#后台运行&lt;/span&gt;
&lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="n"&gt;sunspot&lt;/span&gt;&lt;span class="ss"&gt;:solr:run&lt;/span&gt;   &lt;span class="c1"&gt;#在前台运行&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="n"&gt;sunspot&lt;/span&gt;&lt;span class="ss"&gt;:solr:start&lt;/span&gt; &lt;span class="c1"&gt;#后台运行&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;设置 model&lt;/strong&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;User&lt;/span&gt;
  &lt;span class="o"&gt;...&lt;/span&gt;
  &lt;span class="n"&gt;searchable&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;text&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="o"&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;建立索引&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="n"&gt;sunspot&lt;/span&gt;&lt;span class="ss"&gt;:solr:reindex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;在 console&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;fulltext&lt;/span&gt; &lt;span class="s1"&gt;'张小三'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;results&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="中文分词"&gt;中文分词&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;使用 mmseg 之前&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;fulltext&lt;/span&gt; &lt;span class="s1"&gt;'张三'&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;results&lt;/span&gt; &lt;span class="n"&gt;为空&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;修改配置信息 使得在 index 和 query 的时候 都使用 mmseg4j 分词算法&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;文件 wheel-admin/solr/conf/schema.xml 62 行左右，修改为如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;fieldType&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"text"&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.TextField"&lt;/span&gt; &lt;span class="n"&gt;omitNorms&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"false"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;analyzer&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"index"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;tokenizer&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"com.chenlb.mmseg4j.solr.MMSegTokenizerFactory"&lt;/span&gt; &lt;span class="n"&gt;mode&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"max-word"&lt;/span&gt; &lt;span class="n"&gt;dicPath&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"mmseg4j_dict"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.StandardFilterFactory"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.LowerCaseFilterFactory"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/analyzer&amp;gt;
  &amp;lt;analyzer type="query"&amp;gt;
    &amp;lt;tokenizer class="com.chenlb.mmseg4j.solr.MMSegTokenizerFactory" mode="max-word" dicPath="mmseg4j_dict"/&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.StandardFilterFactory"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.LowerCaseFilterFactory"&lt;/span&gt;&lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"solr.PositionFilterFactory"&lt;/span&gt; &lt;span class="o"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/analyzer&amp;gt;
&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;fieldType&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;重新建立索引&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;rake&lt;/span&gt; &lt;span class="n"&gt;sunspot&lt;/span&gt;&lt;span class="ss"&gt;:solr:reindex&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;在 wheel-web 的 console&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt; &lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Section&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
   &lt;span class="n"&gt;fulltext&lt;/span&gt; &lt;span class="s1"&gt;'张三'&lt;/span&gt;
 &lt;span class="k"&gt;end&lt;/span&gt;

 &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;results&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;&amp;amp;&lt;/span&gt;&lt;span class="ss"&gt;:title&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
 &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"张小三"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="o"&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;puts s.hits[0].score
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href="https://code.google.com/p/mmseg4j/" rel="nofollow" target="_blank" title=""&gt;mmseg 的原理&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;mmseg 算法有两种分词方法：simple 和 complex，都是基于正向最大匹配。complex 加了四个规则过虑。官方说：词语的正确识别率达到了 98.41%。mmseg4j 已经实现了这两种分词算法。&lt;/p&gt;

&lt;p&gt;1.5 版的分词速度 simple 算法是 1100kb/s左右、complex算法是 700kb/s左右，（测试机：AMD athlon 64 2800+ 1G 内存 xp）。&lt;br&gt;
1.6 版在 complex 基础上实现了最多分词 (max-word)。“很好听” -&amp;gt; "很好 | 好听"; “中华人民共和国” -&amp;gt; "中华 | 华人 | 共和 | 国"; “中国人民银行” -&amp;gt; "中国 | 人民 | 银行"。&lt;br&gt;
1.7-beta 版，目前 complex 1200kb/s左右, simple 1900kb/s左右, 但内存开销了 50M 左右。上几个版都是在 10M 左右。&lt;br&gt;
1.8 后，增加 CutLetterDigitFilter 过虑器，切分“字母和数”混在一起的过虑器。比如：mb991ch 切为 "mb 991 ch"。  &lt;/p&gt;

&lt;p&gt;目前我们使用的时 mmseg 1.9&lt;/p&gt;
&lt;h3 id="Sunspot的配置参数详解"&gt;Sunspot 的配置参数详解&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;auto_commit_after_request? 每次 http 都会 commit, 默认为 true&lt;/li&gt;
&lt;li&gt;data_path &lt;/li&gt;
&lt;li&gt;hostname&lt;/li&gt;
&lt;li&gt;log_file&lt;/li&gt;
&lt;li&gt;log_level&lt;/li&gt;
&lt;li&gt;path&lt;/li&gt;
&lt;li&gt;port&lt;/li&gt;
&lt;li&gt;solr_home(这个参数可能有点问题，因为每次配置之后，rake sunspot:solr:reindex 都会报 500 错误)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="Sunspot的实时性怎么样?"&gt;Sunspot 的实时性怎么样？&lt;/h3&gt;
&lt;p&gt;默认情况 每次 http 都会 commit。所以实时性 还是很不错的。&lt;/p&gt;
&lt;h3 id="部署"&gt;部署&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;修改 config/sunspot.yml&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="ss"&gt;production:
  solr:
    hostname: &lt;/span&gt;&lt;span class="n"&gt;localhost&lt;/span&gt;
    &lt;span class="ss"&gt;port: &lt;/span&gt;&lt;span class="mi"&gt;8983&lt;/span&gt;
    &lt;span class="ss"&gt;log_level: &lt;/span&gt;&lt;span class="no"&gt;WARNING&lt;/span&gt;
    &lt;span class="ss"&gt;path: &lt;/span&gt;&lt;span class="sr"&gt;/solr/&lt;/span&gt;&lt;span class="n"&gt;default&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;** path: /solr/default instead of path: /solr/productionon**&lt;/p&gt;

&lt;p&gt;利用 capistrano 部署 Solr，相关脚本如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;after&lt;/span&gt; &lt;span class="s2"&gt;"deploy:update_code"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;"solr:symlink"&lt;/span&gt;

&lt;span class="n"&gt;namespace&lt;/span&gt; &lt;span class="ss"&gt;:solr&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"start solr"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:start&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:no_release&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&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;run&lt;/span&gt; &lt;span class="s2"&gt;"cd &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; RAILS_ENV=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;rails_env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; bundle exec rake sunspot:solr:start"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"stop solr"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:stop&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:app&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:no_release&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&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;run&lt;/span&gt; &lt;span class="s2"&gt;"cd &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; RAILS_ENV=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;rails_env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; bundle exec rake sunspot:solr:stop"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"reindex the whole database"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:reindex&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:roles&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:app&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;"cd &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;application_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; RAILS_ENV=&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;rails_env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; bundle exec rake sunspot:solr:reindex"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="n"&gt;desc&lt;/span&gt; &lt;span class="s2"&gt;"Symlink in-progress deployment to a shared Solr index"&lt;/span&gt;
  &lt;span class="n"&gt;task&lt;/span&gt; &lt;span class="ss"&gt;:symlink&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:except&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;:no_release&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="c1"&gt;#创建solr所需要的目录&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;"cd &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;deploy_to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; mkdir -p &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/data"&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;"cd &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;deploy_to&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &amp;amp;&amp;amp; mkdir -p &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/pids"&lt;/span&gt;

    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;"ln -s &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/data/ &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;release_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/data"&lt;/span&gt;
    &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="s2"&gt;"ln -s &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;shared_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/pids/ &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;release_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/solr/pids"&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="Solr、Sphinx、ElasticSearch等搜索引擎比较"&gt;Solr、Sphinx、ElasticSearch 等搜索引擎比较&lt;/h3&gt;
&lt;p&gt;Solr 和 ElasticSearch 比较：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solr 和 ElasticSearch 都是是基于 Lucene 做的，都比较容易支持所以实时更新。&lt;/li&gt;
&lt;li&gt;字典 Solr 的不支持中文分词，但是通过添加分词算法 解决问题 (比如：上面提到 mmseg4j, 或者 IKAnalyzer 分词)&lt;/li&gt;
&lt;li&gt;由于 ElasticSearch 是在 Solr 的基础 重新建立的，能够很方便的实现分布式，而且自带分词系统。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Solr 和 Sphinx 比较：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sphinx 的优点是，简历索引，搜索都比较快; 缺点是对实时性支持比较差，语法上相对弱一些&lt;/li&gt;
&lt;li&gt;Solr 默认有 facet 支持。而 Shphinx 中就得做一些额外的工作才行&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example:&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Sunspot&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Post&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;with&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:blog_id&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;facet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:category_ids&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# facet 告诉Solr 返回的结果包括 blog id 为1的category_ids&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;results&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="nf"&gt;category_ids&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>easyhappy</author>
      <pubDate>Thu, 11 Sep 2014 11:39:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/21473</link>
      <guid>https://ruby-china.org/topics/21473</guid>
    </item>
    <item>
      <title>刚刚收到一个邮件 感觉挺有意思的</title>
      <description>&lt;p&gt;今天 刚刚收到一个邮件，然后他们根据我的邮箱 算出 我的技术特长，然后推荐相关的职位。&lt;/p&gt;

&lt;p&gt;感觉还是挺有意思的。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2014/a15e69e5341d05193fc62c520e43cb7f.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Thu, 21 Aug 2014 09:50:59 +0800</pubDate>
      <link>https://ruby-china.org/topics/21148</link>
      <guid>https://ruby-china.org/topics/21148</guid>
    </item>
    <item>
      <title>【分享】generator 的那些事</title>
      <description>&lt;h2 id="Rails 自带的generators"&gt;Rails 自带的 generators&lt;/h2&gt;
&lt;p&gt;在一个 Rails 项目中，有很多自带的 genertors，比如最常用的 scaffold，通过命令 rails generator 可以列出所有的 generators：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Rails:
  assets
  controller
  generator
  helper
  integration_test
  mailer
  migration
  model
  resource
  scaffold
  scaffold_controller
  task

ActiveRecord:
  active_record:devise
  active_record:migration
  active_record:model

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果你想查看一个具体 generator 的使用说明，比如 scaffold，使用&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails g scaffold --help
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="generators的源码在哪里？"&gt;generators 的源码在哪里？&lt;/h2&gt;
&lt;p&gt;大部分 Rails 自带的 generators 都放到 gem &lt;a href="https://github.com/rails/rails/tree/4-0-stable/railties/lib/rails/generators/rails" rel="nofollow" target="_blank" title=""&gt;raities-4.0.0/rails/generators&lt;/a&gt;中。 
我们就拿&lt;a href="https://github.com/rails/rails/tree/4-0-stable/railties/lib/rails/generators/rails/scaffold" rel="nofollow" target="_blank" title=""&gt;scaffold&lt;/a&gt; 举例子，主要有三部分组成 :&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;templates/ 所有的模板
USAGE 可以理解成readme
scaffold_generator.rb #generator入口
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;下面主要看看 scaffold_generator.rb, 这里就不贴代码，如果感兴趣可以 进入&lt;a href="https://github.com/rails/rails/blob/4-0-stable/railties/lib/rails/generators/rails/scaffold/scaffold_generator.rb" rel="nofollow" target="_blank" title=""&gt;源码位置&lt;/a&gt; 看看，这里这是说明几个关键点：&lt;/p&gt;

&lt;p&gt;1）source_root 定义了 templates 的位置
2）其中有一句 hook_for :scaffold_controller, required: true；hook_for 的作用唤起一个 generator。 
3) 所有的 public 方法都会被调用。&lt;/p&gt;
&lt;h2 id="generators的加载方式"&gt;generators 的加载方式&lt;/h2&gt;
&lt;p&gt;rails/generators/initializer/initializer_generator.rb 
generators/initializer/initializer_generator.rb 
rails/generators/initializer_generator.rb 
generators/initializer_generator.rb 
$LOAD_PATH&lt;/p&gt;
&lt;h2 id="编写自定义generator， 提高工作效率"&gt;编写自定义 generator，提高工作效率&lt;/h2&gt;
&lt;p&gt;在我们日常的工作中，总会有一些 工作是一些重复，且相同的工作，特别像后台管理页面的一些页面。针对这些情况，编写相应的 generator，可以大大提高我们的工作效率。&lt;/p&gt;

&lt;p&gt;[题外话] 个人向大家&lt;a href="https://github.com/easyhappy/showbuilder" rel="nofollow" target="_blank" title=""&gt;showbuilder&lt;/a&gt;（这个&lt;a href="/ery" class="user-mention" title="@ery"&gt;&lt;i&gt;@&lt;/i&gt;ery&lt;/a&gt;编写的）, 个人觉得是后台管理页面的必备 gem，这里 就不对它细说了。 &lt;/p&gt;

&lt;p&gt;今天要的说是 基于它写了一套&lt;a href="https://github.com/easyhappy/showbuilder/tree/master/lib/generators/showbuilder" rel="nofollow" target="_blank" title=""&gt;generators&lt;/a&gt;&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rails generator showbuilder:slim
rails generator showbuilder:scaffold
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;比如运行 rails g showbuilder:scaffold  admin/my_generators&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    invoke  resource_route
     route    namespace :admin do
  resources :my_generators
end
    invoke  slim
    create    app/views/admin/my_generators
    create    app/views/admin/my_generators/index.html.slim
    create    app/views/admin/my_generators/edit.html.slim
    create    app/views/admin/my_generators/show.html.slim
    create    app/views/admin/my_generators/new.html.slim
    create    app/views/admin/my_generators/_form.html.slim
    create  app/controllers/admin/my_generators_controller.rb
 identical  lib/reborn/base_mongo.rb
    create  app/models/admin/my_generator.rb
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然如果你想使用自己的模板，那么在 Rails.root/config/showbuilder/templates 下建立对于的模板文件就可以了。&lt;/p&gt;
&lt;h2 id="写在最后"&gt;写在最后&lt;/h2&gt;
&lt;p&gt;如果你对这个 gem 感兴趣，可以阅读源码 了解相关机制。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Sat, 19 Jul 2014 13:19:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/20590</link>
      <guid>https://ruby-china.org/topics/20590</guid>
    </item>
    <item>
      <title>[北京] 汽车方向移动互联网新锐公司多个技术职位招募 </title>
      <description>&lt;p&gt;关于我们：
北京乐行东方网络技术有限公司，是一家致力于提供车主生活服务的互联网企业。相信我，在国内当下广义的车联网领域里，提供车主生活服务才是真需求，才是能持续盈利的切入点。那些打着车联网的旗号搞 OBD 和搞智能交通的，或者随口说出要搞个中国版 Car Play 的，无论大小全都弱爆了。&lt;/p&gt;

&lt;p&gt;我们的创始团队拥有超过十年的汽车消费、汽车服务领域的从业经验，精准的后市场需求认知和把握，广泛深厚的资源及人脉，业内多家顶尖品牌的合作经历。&lt;/p&gt;

&lt;p&gt;先说待遇：
1）薪资 1.5 万起，上至 5 万，还嫌少？Ok，上不封顶；
2）正规五险一金缴纳，让那些不缴或者少缴的无良公司去死吧；
3）正规企业福利，该有的都有；
4）期权激励，这个各家初创公司都号称有，但我想说：我们更靠谱；
5）敞开办公、自由舒适、人体工学椅、全 Mac 开发、冷饮茶点无限量等等这些还用说吗？都是标配来的；
6）妹子？好像 V2EX 的招聘帖里都流行写这个，啥男女比例啥大胸前台，其实这些都是幻觉好吗？都不如在一个靠谱团队做着靠谱产品，然后按时下班手握高薪去把妹来的实实在在，女同事不是文工团。。。你懂的。&lt;/p&gt;

&lt;p&gt;我们不打算邀你一起改变世界，这句话大多数人讲出来都像是忽悠。但我们的确既有扎实稳定的行业资源，又有多年互联网运营的技术和经验。成型的盈利模式 2B2C 通吃，已有的客户随时买单。我们给你互联网初创企业自由、geek、有爱的范儿，同时你还无需背负同类初创企业面对的早期高风险，怎么样，有点动心了吗？赶紧投递简历吧。&lt;/p&gt;

&lt;p&gt;地点：北京朝阳区三元桥，地铁出来步行 5 分钟
联系：wheelslife@163.com 邮件中请注明申请的职位
QQ：2950907860（非常用，回复会慢，见谅）&lt;/p&gt;

&lt;p&gt;再给出招聘职位：
一．产品设计师，就是他们常说的产品经理 PM
职位描述
1）参与或者负责乐行东方的产品规划、设计、改进和迭代
2）主导或配合完成产品原型、产品文档、UI 和 UE 设计
3）协调设计、开发等各个环节，确保产品发布节奏
任职资格
1）三年以上移动互联网产品工作经验，曾主导过完整的产品设计
2）熟悉当下主流手机应用及平台特性，熟悉各种原型设计工具
3）对用户需求判断、引导及控制有较强的把握
4）善于合作协调沟通，思维敏捷，具有非常好的书面和口头表达能力
加分项
1）日常生活中经常开车
2）有开发经验，能评估产品的工程难度和工作量
3）有创业经验&lt;/p&gt;

&lt;p&gt;二．iOS 开发工程师
职位描述
1）乐行东方 iOS 应用的设计、开发及测试
2）乐行东方 iOS 代码质量控制
任职资格
1）熟悉 Objective-C、Cocoa 及其 MVC 开发模式
2）熟悉 iOS 应用开发流程
3）至少使用过一种 Objective-C 测试框架
4）至少有一个完整的 iOS 网络应用开发经历
5）熟练使用各种第三方库解决实际问题
6）良好的编码风格，沟通能力和团队合作精神，有责任感
加分项
1）在 App Store 上发布过优秀的 App 作品
2）拥有阅读、学习英文材料的能力，对开源技术有强烈的兴趣和爱好，参与或贡献过代码
3）如有作品链接，Github 帐号，个人技术 blog，还请附上
4）日常生活中经常开车&lt;/p&gt;

&lt;p&gt;三．Android 开发工程师
职位描述
1）乐行东方 Android 应用的设计、开发及测试
2）乐行东方 Android 代码质量控制
任职资格
1）熟悉网络编程，了解常用网络协议
2）熟悉掌握 Android 界面和交互开发
3）至少有一个完整的 Android 应用开发经历
4）熟练使用各种第三方库解决实际问题
5）良好的编码风格，沟通能力和团队合作精神，有责任感
加分项
1）在 Google Play 发布过优秀的 App 作品
2）拥有阅读、学习英文材料的能力，对开源技术有强烈的兴趣和爱好，参与或贡献过代码
3）如有作品链接，Github 帐号，个人技术 blog，还请附上
4）日常生活中经常开车&lt;/p&gt;

&lt;p&gt;四．前端开发工程师
职位描述
1）负责乐行东方 Web 前端交互开发工作
2）不断优化前端程序代码，不断提升网页性能
任职资格
1）精通 JavaScript/CSS/HTML
2）至少熟悉一种面向对象的前端框架
3）能够写出高性能、可复用的前端组件
4）熟悉服务器端开发技术
加分项
1）熟练使用 JavaScript 测试框架
2）了解前端安全机制
3）有前端性能优化经验
4）日常生活中经常开车&lt;/p&gt;

&lt;p&gt;五．移动应用服务器端开发工程师
职位描述
1）设计和开发乐行东方移动应用服务器后端
任职资格
1）熟练掌握 Web 开发相关知识
2）熟悉 Python 语言或者 Ruby 语言
3）熟悉 Python 或者 Ruby 主流框架
4）熟练使用 MySQL，掌握常用数据库应用场景下相关操作
5）两年以上移动应用后端开发经验，实现过科学且高效的 API
加分项
1）熟悉 Unix shell 的使用
2）熟悉 Redis 的使用
3）拥有阅读、学习英文材料的能力，对开源技术有强烈的兴趣和爱好，参与或贡献过代码
5）日常生活中经常开车&lt;/p&gt;

&lt;p&gt;如果你碰巧有朋友、有同学、有同事、有男友符合我们的条件，赶紧让他投递简历吧。凡推荐靠谱候选人成功加入的一律请吃五星酒店海鲜自助大餐（暂定帝都霄云路海航万豪每周五的海鲜盛宴，异地的小伙伴兑现方案待定）。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Wed, 09 Jul 2014 10:15:08 +0800</pubDate>
      <link>https://ruby-china.org/topics/20389</link>
      <guid>https://ruby-china.org/topics/20389</guid>
    </item>
    <item>
      <title>Rails 4 升级 加载多个路由的配置问题</title>
      <description>&lt;h2 id="前序"&gt;前序&lt;/h2&gt;
&lt;p&gt;最近在升级 Rails4，由于项目中用了很多个路由文件，暂列为以下几个：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config/routes.rb
config/routes/admin.rb
config/routes/books.rb
....
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 Rails3，只需配置如下：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config.paths['config/routes'] += %w{admin books}.map{|path| Rails.root.join("config/routes/#{path}.rb")}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然而在升级之后，启动 rails server, 发现报错了：&lt;/p&gt;

&lt;p&gt;这个哥们 config.paths['config/routes'] 为 nil，不能使用 '+='了&lt;/p&gt;

&lt;p&gt;开始还以为升级 Rails4 之后，配置方法发生了变化，但是 查看官方的升级文档，没有提及;&lt;/p&gt;
&lt;h2 id="于是在查看了Rails4 engine的源码:"&gt;于是在查看了&lt;a href="https://github.com/rails/rails/blob/master/railties/lib/rails/engine.rb#l593" rel="nofollow" target="_blank" title=""&gt;Rails4&lt;/a&gt; engine 的源码：&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;initializer :add_routing_paths do |app|
  paths = self.paths["config/routes.rb"].existent

  if routes? || paths.any?
    app.routes_reloader.paths.unshift(*paths)
    app.routes_reloader.route_sets &amp;lt;&amp;lt; routes
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;确实从 Rails3 中 的  paths = self.paths["config/routes"].existent 变成了      paths = self.paths["config/routes.rb"].existent&lt;/p&gt;
&lt;h2 id="Why"&gt;Why&lt;/h2&gt;
&lt;p&gt;为什么 会如有如此改变，还是它就是一个 bug？&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Mon, 10 Mar 2014 15:32:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/17783</link>
      <guid>https://ruby-china.org/topics/17783</guid>
    </item>
    <item>
      <title>Mongoid 升级之后 Mongoid::QueryCache::Middleware 问题</title>
      <description>&lt;h3 id="前言"&gt;前言&lt;/h3&gt;
&lt;p&gt;由于最近在将项目升级到 Rails，顺便将 Mongoid 从也从 3.1.4 升到 3.1.6，至于为什么，可以&lt;a href="http://www.ml-china.org/blog/42" rel="nofollow" target="_blank" title=""&gt;点击这里&lt;/a&gt;
  升级 Mongoid 的一些配置 被除掉了， &lt;a href="http://www.ml-china.org/blog/43" rel="nofollow" target="_blank" title=""&gt;IndentityMap 就是之一&lt;/a&gt;,  然后官方给出的替代方式是使用 Query::Cache Middleware.&lt;/p&gt;

&lt;p&gt;在配置文件添加 config.middleware.use(Mongoid::QueryCache::Middleware); &lt;/p&gt;
&lt;h3 id="问题来了"&gt;问题来了&lt;/h3&gt;
&lt;p&gt;假如 我执行下面的操作：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def index
  @users = UserMongo.all
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后其他的地方&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if @users.present?       #----&amp;gt; 标记A
   ...其他操作
   @users.each do |p|    #-----&amp;gt; 标记B
       ....
   end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;执行的'标记 B'的时候，会抛出异常&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;QUERY CACHE  database=tianji collection=users selector={}
TypeError: no implicit conversion of String into Integer
from /home/andy/Documents/mongoid/lib/mongoid/factory.rb:40:in `[]'
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="问题追踪"&gt;问题追踪&lt;/h3&gt;
&lt;p&gt;通过 pry 追踪源码&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module Mongoid
  module QueryCache
    module Cacheable
      def with_cache
        return yield unless QueryCache.enabled?
        return yield if system_collection?
        key = cache_key
        if QueryCache.cache_table.has_key?(key)
          instrument(key) { QueryCache.cache_table[key] }
        else
          value = yield
          QueryCache.cache_table[key] = value
        end
      end
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;发现 在执行'标记 A' &lt;a href="/users.present" class="user-mention" title="@users.present"&gt;&lt;i&gt;@&lt;/i&gt;users.present&lt;/a&gt;?, QueryCache.cache_table[key] 的值已经被设置上了&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;puts QueryCache.cache_table --&amp;gt;
{["tianji", "users", {}]=&amp;gt;{"_id"=&amp;gt;158}}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;然后在 执行'标记 B’的时候 其实 是对  'A'的结果 进行遍历，所以 就会报错。&lt;/p&gt;
&lt;h3 id="我的观点:"&gt;我的观点：&lt;/h3&gt;
&lt;p&gt;我认为 这是 QueryCache 的一个 bug，没有很好区分好  QueryCache.cache_table 的 key。&lt;/p&gt;

&lt;p&gt;补充一下 key 的选取是这样子的：&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def cache_key
    [ operation.database, operation.collection, operation.selector ]
end
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="SOS"&gt;SOS&lt;/h3&gt;
&lt;p&gt;大家在升级 Mongoid 的过程中，有没有遇到同样的问题;  实在不行，我可能会先覆盖部分 Mongoid 源码。&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Tue, 04 Mar 2014 16:18:28 +0800</pubDate>
      <link>https://ruby-china.org/topics/17654</link>
      <guid>https://ruby-china.org/topics/17654</guid>
    </item>
    <item>
      <title>请教如何根据屏幕大小  只显示部分内容</title>
      <description>&lt;p&gt;所用的技术 Jquery Mobile + Backbone + Phonegap 构建 android 的本地应用 A，Rails 作为后台 Web service; &lt;/p&gt;

&lt;p&gt;已知知识：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;设备的 height 和 width&lt;/li&gt;
&lt;li&gt;字体大小，间距等。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A 收到 Rails 传来的数据 Content,   那么：如何 根据屏幕大小 实现是 Content 的 一部分 内容？&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Fri, 14 Feb 2014 14:23:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/17257</link>
      <guid>https://ruby-china.org/topics/17257</guid>
    </item>
    <item>
      <title>ruby 获取 model 名字</title>
      <description>&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&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="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;C&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;#问题 怎么 在这里 获取到 B&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;我的问题是 怎么在 C 的 self.include 中 获取到 B 的名字， 
请知道的告诉一下，谢谢！！&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Sat, 13 Jul 2013 09:52:37 +0800</pubDate>
      <link>https://ruby-china.org/topics/12475</link>
      <guid>https://ruby-china.org/topics/12475</guid>
    </item>
    <item>
      <title>关于中文字符问题</title>
      <description>&lt;p&gt;ruby 文件 包含中文时，运行会报错。 &lt;/p&gt;

&lt;p&gt;上网 google 一下：&lt;/p&gt;

&lt;p&gt;答案是 添加 RUBYOPT= -Ku, 即可&lt;/p&gt;

&lt;p&gt;我的问题是：Ku 是什么含义？&lt;/p&gt;

&lt;p&gt;知道的人，给个 解释，谢谢！！！&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Wed, 10 Jul 2013 11:09:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/12390</link>
      <guid>https://ruby-china.org/topics/12390</guid>
    </item>
    <item>
      <title>ubuntu 下 chrome 出现异常</title>
      <description>&lt;h2 id="环境 ubuntu 12.04"&gt;环境 ubuntu 12.04&lt;/h2&gt;
&lt;blockquote&gt;
&lt;p&gt;在命令行输入 google-chrome  报 以下错误：&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;[9358:9381:1110/103956:ERROR:object_proxy.cc(608)] Failed to get name owner. Got org.freedesktop.DBus.Error.Nam eHasNoOwner: Could not get owner of name 'org.chromium.Mtpd': no such name
    [9358:9381:1110/103956:ERROR:object_proxy.cc(608)] Failed to get name owner. Got org.freedesktop.DBus.Error.NameHasNoOwner: Could not get owner of name 'org.chromium.Mtpd': no such name
    [9406:9406:1110/103956:ERROR:sandbox_init_linux.cc(32)] InitializeSandbox() called with multiple threads in process gpu-process
    [9358:9358:1110/103957:ERROR:object_proxy.cc(513)] Failed to call method: org.chromium.Mtpd.EnumerateStorage: object_path= /org/chromium/Mtpd: org.freedesktop.DBus.Error.ServiceUnknown: The name org.chromium.Mtpd was not provided by any .service files&lt;/p&gt;

&lt;p&gt;ps：上网 google 很久 没有找到解决方法...
    有人 知道 怎么解决这个问题，请跟我说声？先谢了!!!&lt;/p&gt;</description>
      <author>easyhappy</author>
      <pubDate>Sun, 07 Jul 2013 17:27:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/12316</link>
      <guid>https://ruby-china.org/topics/12316</guid>
    </item>
    <item>
      <title>ruby unbind 方法的使用场景</title>
      <description>&lt;p&gt;class Test
      def initialize(value)
        &lt;a href="/x" class="user-mention" title="@x"&gt;&lt;i&gt;@&lt;/i&gt;x&lt;/a&gt; = value
      end&lt;/p&gt;

&lt;p&gt;def my_method
        &lt;a href="/x" class="user-mention" title="@x"&gt;&lt;i&gt;@&lt;/i&gt;x&lt;/a&gt;
      end
    end
    test = Test.new(1)
    m = test.method :my_method
    puts "test.my_method is #{m.call}"&lt;/p&gt;

&lt;p&gt;unbind = m.unbind
    test_2 = Test.new(2)
    m = unbind.bind(test_2)
    puts "-"*30
    puts "test_2.my_method is #{m.call}"&lt;/p&gt;

&lt;p&gt;** 这里我有一个疑问 ** &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;bind 和 unbind 使用场景是什么？&lt;/p&gt;
&lt;/blockquote&gt;</description>
      <author>easyhappy</author>
      <pubDate>Tue, 25 Jun 2013 13:44:25 +0800</pubDate>
      <link>https://ruby-china.org/topics/11975</link>
      <guid>https://ruby-china.org/topics/11975</guid>
    </item>
  </channel>
</rss>
