<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>manageyp (Henry)</title>
    <link>https://ruby-china.org/manageyp</link>
    <description>每个人都有潜在的能量，只是很容易：被习惯掩盖，被时间迷离，被惰性消磨。</description>
    <language>en-us</language>
    <item>
      <title>阿里云 Rails 项目调整 RDS MySQL 编码为 utf8mb4 的详细步骤</title>
      <description>&lt;p&gt;最近，将一个部署在阿里云上的 Rails 项目，连接的 MySQL 数据库的编码，由 utf8 调整为 utf8mb4。
实施过程不是非常顺利，目前，已经部署完成，观察了一段时间，比较稳定。
写了本篇总结，希望可以帮到有需要的朋友。&lt;/p&gt;
&lt;h2 id="环境说明"&gt;环境说明&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; 服务器系统 Centos，版本为 6.5；&lt;/li&gt;
&lt;li&gt; 数据库使用的是阿里云 RDS MySQL，版本为 5.5.18；&lt;/li&gt;
&lt;li&gt; Rails 版本为 4.1.2；&lt;/li&gt;
&lt;li&gt; mysql2 Gem, 版本为 0.3.16。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="为什么要使用 utf8mb4 编码"&gt;为什么要使用 utf8mb4 编码&lt;/h2&gt;
&lt;p&gt;根本的原因在于，采用 utf8 编码的 MySQL 无法保存占位是 4 个字节的 &lt;strong&gt;Emoji 表情&lt;/strong&gt;。
为了使后端的项目，全面支持客户端输入的 Emoji 表情，升级编码为 utf8mb4 是最佳解决方案。
之前一篇博文有讲到，不调整 MySQL 编码，使用 rumoji 替换 Emoji 表情为字母编号。
博客原文链接：Ruby on Rails Use MySQL DB Support iPhone emoji
&lt;a href="http://manageyp.github.com/ruby-on-rails/2014/12/10/ruby-on-rails-use-mysql-db-support-iphone-emoji.html" rel="nofollow" target="_blank"&gt;http://manageyp.github.com/ruby-on-rails/2014/12/10/ruby-on-rails-use-mysql-db-support-iphone-emoji.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;但是，这样处理至少有两个问题：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Emoji 表情会持续的更新，rumoji 库如果没有及时更新，输入新的表情，则会报错。&lt;/li&gt;
&lt;li&gt;使用 rumoji 对用户输入的字符，做正则匹配解析，增加了系统的开销，降低了性能。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;另外，看到很多网友建议，迁移 MySQL 至 PostgreSQL、MongoDB 等，迁移成本不小，暂时不考虑。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;备注：MySQL 5.5.3 版本之后，引入了 utf8mb4 字符集。&lt;/strong&gt;
在 mysql client 端，输入以下命令，确认 mysql server 是否支持 utf8mb4 编码。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql&amp;gt; SHOW CHAR SET WHERE Charset LIKE &lt;span class="s2"&gt;"%utf8%"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
+---------+---------------+--------------------+--------+
| Charset | Description   | Default collation  | Maxlen |
+---------+---------------+--------------------+--------+
| utf8    | UTF-8 Unicode | utf8_general_ci    |      3 |
| utf8mb4 | UTF-8 Unicode | utf8mb4_general_ci |      4 |
+---------+---------------+--------------------+--------+
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;至于排序规则（collation）选择默认的 utf8mb4_general_ci，还是 utf8mb4_unicode_ci。
请参考下面文章的介绍，Character Set &amp;amp; Collation In MySQL：
&lt;a href="http://infopotato.com/blog/index/mysql_character_set_and_collation" rel="nofollow" target="_blank"&gt;http://infopotato.com/blog/index/mysql_character_set_and_collation&lt;/a&gt;
作者从排序的准确性，以及性能方面，告诉我们应该选用 &lt;strong&gt;utf8mb4_unicode_ci&lt;/strong&gt; 。&lt;/p&gt;
&lt;h2 id="实施的步骤"&gt;实施的步骤&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; （1）在阿里云 RDS 控制台，新建一个数据库&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;名称为：production_new
字符集选择：utf8mb4
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （2）修改 database.yml 编码&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# config/database.yml&lt;/span&gt;
&lt;span class="na"&gt;encoding&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;utf8mb4&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （3）Ruby 程序接收和返回 JSON 数据时，强制使用 UTF-8 编码&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;force_encoding&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"UTF-8"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;（4）停止 Ruby 进程，停止队列等服务&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;（5）部署项目报错
正式版部署之前，有在本地和 Staging 做过测试。
信心满满的在正式版部署，执行的过程中，遇到下面的错误：&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Character &lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4'&lt;/span&gt; is not a compiled character &lt;span class="nb"&gt;set &lt;/span&gt;and is not specified &lt;span class="k"&gt;in &lt;/span&gt;the &lt;span class="s1"&gt;'/path/mysql/charsets/Index.xml'&lt;/span&gt; file
rake aborted!
Mysql2::Error: Can&lt;span class="s1"&gt;'t initialize character set utf8mb4 (path: /path/mysql/charsets/)
/path/.rvm/gems/ruby-2.0.0-p598/gems/mysql2-0.3.16/lib/mysql2/client.rb:70:in `connect'&lt;/span&gt;
/path/.rvm/gems/ruby-2.0.0-p598/gems/mysql2-0.3.16/lib/mysql2/client.rb:70:in &lt;span class="sb"&gt;`&lt;/span&gt;initialize&lt;span class="s1"&gt;'
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;经过一番检查后发现，错误是由于当前系统上的 MySQL 客户端版本过低导致。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 列出所有被安装的 mysql 包&lt;/span&gt;
rpm &lt;span class="nt"&gt;-qa&lt;/span&gt; | &lt;span class="nb"&gt;grep &lt;/span&gt;mysql
mysql-devel-5.1.73-3.el6_5.x86_64
mysql-5.1.73-3.el6_5.x86_64
mysql-libs-5.1.73-3.el6_5.x86_64
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （6）移除现有的旧版本，重新安装 5.5 版本的客户端&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 清理现有 mysql&lt;/span&gt;
yum list installed | &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-i&lt;/span&gt; mysql
yum remove mysql mysql-&lt;span class="k"&gt;*&lt;/span&gt;

&lt;span class="c"&gt;# 修改安装源，不修改源，重新安装的仍然是 5.1 的版本&lt;/span&gt;
rpm &lt;span class="nt"&gt;-Uvh&lt;/span&gt; http://repo.webtatic.com/yum/el6/latest.rpm

&lt;span class="c"&gt;# 安装 5.5 版本的 mysql client&lt;/span&gt;
yum &lt;span class="nb"&gt;install &lt;/span&gt;libmysqlclient16 &lt;span class="nt"&gt;--enablerepo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;webtatic
yum &lt;span class="nb"&gt;install &lt;/span&gt;mysql55w mysql55w-libs mysql55w-devel &lt;span class="nt"&gt;--enablerepo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;webtatic

&lt;span class="c"&gt;# 如果你需要安装 mysql server，请执行&lt;/span&gt;
yum &lt;span class="nb"&gt;install  &lt;/span&gt;mysql55w-server &lt;span class="nt"&gt;--enablerepo&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;webtatic
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （7）重新安装 mysql2 Gem&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;MySQL 5.5 客户端安装完毕之后，再次运行项目，同样出现上面的报错信息。
  于是，决定重新安装一遍 mysql2 Gem。安装完成之后，项目运行正常。&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 重新安装 mysql2 Gem&lt;/span&gt;
gem uninstall mysql2
gem &lt;span class="nb"&gt;install &lt;/span&gt;mysql2 &lt;span class="nt"&gt;-v&lt;/span&gt; &lt;span class="s1"&gt;'0.3.16'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （8）备份和还原数据库&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# 备份现有数据库&lt;/span&gt;
mysqldump &lt;span class="nt"&gt;-h&lt;/span&gt; host &lt;span class="nt"&gt;-u&lt;/span&gt; user &lt;span class="nt"&gt;-p&lt;/span&gt; production_old &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; production_old.sql

&lt;span class="c"&gt;# 还原至新数据库&lt;/span&gt;
mysql &lt;span class="nt"&gt;-h&lt;/span&gt; host &lt;span class="nt"&gt;-u&lt;/span&gt; user &lt;span class="nt"&gt;-p&lt;/span&gt; production_new &amp;lt; production_old.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （9）执行调整单个表 (table) 编码的 SQL 文件&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;mysql &lt;span class="nt"&gt;-h&lt;/span&gt; host &lt;span class="nt"&gt;-u&lt;/span&gt; user &lt;span class="nt"&gt;-p&lt;/span&gt; production_new &amp;lt; db/sql/utf8mb4_charset.sql
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;SQL 文件内容，举例说明如下:
  通常只需要修改 table 的编码，若该 table 内有字段 (column) 是 VARCHAR，或者 TEXT，
  MySQL 将自动调整该字段的编码，与 table 的默认编码保持一致&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ALTER TABLE &lt;span class="sb"&gt;`&lt;/span&gt;versions&lt;span class="sb"&gt;`&lt;/span&gt; CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;MySQL 索引长度的限制错误&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在执行 SQL 文件时，发现有些 table 更改编码时报错，信息如下：&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ERROR 1071 &lt;span class="o"&gt;(&lt;/span&gt;42000&lt;span class="o"&gt;)&lt;/span&gt;: Specified key was too long&lt;span class="p"&gt;;&lt;/span&gt; max key length is 767 bytes
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;报错原因在于：MySQL Innodb 的索引长度限制为 767 字节，UTF8mb4 字符集是 4 个字节，
  &lt;strong&gt;767 字节 / 4 字节每字符 = 191 字符（即默认的索引最大长度）&lt;/strong&gt;
  因此在 varchar(255) 类型字段上，创建索引会失败，提示最大索引长度为 767 字节。&lt;/p&gt;

&lt;p&gt;实践中发现，MySQL 5.5.x 的版本，只有 Unique 的索引，或者联合索引，才会报错。
  普通索引，Rails 的 Migration 会自动对索引 Index 的长度增加一个 191 的限制。
  而 MySQL 5.6.x 的版本，即使普通索引也会报错。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;处理思路&lt;/strong&gt;：先移除索引，然后修改表的编码，修改成功之后。调整索引对应字段的长度为 191，最后再次创建索引。 &lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ALTER TABLE &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; DROP INDEX index_users_on_email&lt;span class="p"&gt;;&lt;/span&gt;
ALTER TABLE &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci&lt;span class="p"&gt;;&lt;/span&gt;
ALTER TABLE &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; MODIFY &lt;span class="sb"&gt;`&lt;/span&gt;email&lt;span class="sb"&gt;`&lt;/span&gt; VARCHAR&lt;span class="o"&gt;(&lt;/span&gt;191&lt;span class="o"&gt;)&lt;/span&gt; CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci&lt;span class="p"&gt;;&lt;/span&gt;
ALTER TABLE  &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt; ADD UNIQUE index_users_on_email &lt;span class="o"&gt;(&lt;/span&gt;email&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 shell"&gt;&lt;code&gt;SHOW CREATE TABLE &lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;users&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;ul&gt;
&lt;li&gt; （10）再次启动服务&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;使用 Migration 迁移 Table 编码&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果没有索引的问题，可以使用下面的代码，修改表的编码，简洁许多。
  也可以使用下面的代码，打印 SQL 语句到 .sql 文件。
  然后，对引起索引 Index 错误的 Table 单独增加处理的 SQL 语句。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;up&lt;/span&gt;
  &lt;span class="n"&gt;char_set&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4'&lt;/span&gt;
  &lt;span class="n"&gt;collation&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'utf8mb4_unicode_ci'&lt;/span&gt;
  &lt;span class="n"&gt;table_names&lt;/span&gt; &lt;span class="o"&gt;=&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="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;tables&lt;/span&gt;
  &lt;span class="n"&gt;table_names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;execute&lt;/span&gt; &lt;span class="s2"&gt;"ALTER TABLE `&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;table_name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;` CONVERT TO CHARACTER SET &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;char_set&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; COLLATE &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;collation&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;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;原文链接&lt;/strong&gt; Aliyun RDS Change MySQL Charset From utf8 To utf8mb4:
&lt;a href="http://manageyp.github.com/ruby-on-rails/2015/03/05/aliyun-rds-change-mysql-charset-from-utf8-to-utf8mb4.html" rel="nofollow" target="_blank"&gt;http://manageyp.github.com/ruby-on-rails/2015/03/05/aliyun-rds-change-mysql-charset-from-utf8-to-utf8mb4.html&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;参考链接&lt;/strong&gt; （推荐阅读）：
Support Emoji in Rails 3.2.14
&lt;a href="http://mumaren.me/blog/2013/11/27/support-emoji-in-rails-3-dot-2-14/" rel="nofollow" target="_blank"&gt;http://mumaren.me/blog/2013/11/27/support-emoji-in-rails-3-dot-2-14/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;active_record, MySQL, and emoji
&lt;a href="http://tech.taskrabbit.com/blog/2014/04/24/active-record-mysql-and-emoji/" rel="nofollow" target="_blank"&gt;http://tech.taskrabbit.com/blog/2014/04/24/active-record-mysql-and-emoji/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;update MySQL version from 5.1 to 5.5 in CentOS 6.2
&lt;a href="http://stackoverflow.com/questions/9361720/update-mysql-version-from-5-1-to-5-5-in-centos-6-2" rel="nofollow" target="_blank"&gt;http://stackoverflow.com/questions/9361720/update-mysql-version-from-5-1-to-5-5-in-centos-6-2&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Character Set &amp;amp; Collation In MySQL
&lt;a href="http://infopotato.com/blog/index/mysql_character_set_and_collation" rel="nofollow" target="_blank"&gt;http://infopotato.com/blog/index/mysql_character_set_and_collation&lt;/a&gt;&lt;/p&gt;</description>
      <author>manageyp</author>
      <pubDate>Tue, 17 Mar 2015 18:22:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/24693</link>
      <guid>https://ruby-china.org/topics/24693</guid>
    </item>
    <item>
      <title>ElasticSearch 初次使用小结，一起学习进步哈~</title>
      <description>&lt;h2 id="选用原因"&gt;选用原因&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; 主要原因有：实时性能优越；安装配置简单；RESTful API 和 JSON 格式的文档型数据，降低开发调试的难度。
另外，Tire 这个 Gem 可以简单方便的与 ActiveRecord 整合。测试中发现：ES 自带了中文分词，支持中文搜索，但是，可以换用更高效精确的分词插件。&lt;/li&gt;
&lt;li&gt; 业界资讯：GitHub searches 20TB of data using Elasticsearch, including 1.3 billion files and 130 billion lines of code.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="简单介绍"&gt;简单介绍&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; ElasticSearch 是开源搜索平台领域的一个新成员。
ElasticSearch（简称 ES）是一个基于 Lucene 构建的开源，分布式，RESTful 搜索引擎。 
设计用于云计算中，能够达到搜索实时、稳定、可靠和快速，并且安装使用方便。
支持通过 HTTP 请求，使用 JSON 进行数据索引。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="特点优势"&gt;特点优势&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;（1）Open Source（开源）&lt;/li&gt;
&lt;li&gt;（2）Apache Lucene（基于 Lucene）&lt;/li&gt;
&lt;li&gt;（3）Schema Free(模式自由)&lt;/li&gt;
&lt;li&gt;（4）Document Oriented(面向文档型的设计)&lt;/li&gt;
&lt;li&gt;（5）Real Time Data &amp;amp; Analytics（实时索引数据）&lt;/li&gt;
&lt;li&gt;（6）Distributed（分布式）&lt;/li&gt;
&lt;li&gt;（7）High Availability（高可靠性）&lt;/li&gt;
&lt;li&gt;（8）其他特性：RESTful API；JSON format；multi-tenancy；full text search；conflict management；per-operation persistence&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="安装配置"&gt;安装配置&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;在 Mac OS X 上安装配置步骤（linux 上应该也适用），请参考:
&lt;a href="http://manageyp.github.io/elasticsearch/2013/10/09/elasticsearch-installation.html" rel="nofollow" target="_blank"&gt;http://manageyp.github.io/elasticsearch/2013/10/09/elasticsearch-installation.html&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结合 Tire"&gt;结合 Tire&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Tire Github 地址：&lt;a href="https://github.com/karmi/retire" rel="nofollow" target="_blank"&gt;https://github.com/karmi/retire&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Tire 是一个丰富的 Ruby API 工具包，封装了一系列与 ES 进行接口请求，JSON 数据处理的功能。
而且，针对 ActiveRecord 写了很多处理索引，搜索的实现，非常简单方便的与 Model 进行集成。&lt;/li&gt;
&lt;li&gt;英文原话介绍：Tire is a rich Ruby API and DSL for the Elasticsearch search engine.
It exposes easy-to-use domain specific language for fluent communication with Elasticsearch.
It easily blends with your ActiveModel/ActiveRecord classes for convenient usage in Rails applications.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="实例代码"&gt;实例代码&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;贴出一部分代码，实现了基本的搜索，地理位置排序，实时更新索引。命名为学校（School）只是为了用来交流，实际应用在商户模型上。&lt;/li&gt;
&lt;li&gt;接下来，仍然需要研究 ES 的架构和实现原理；
配置测试更高效的中文分词插件：ik，mmseg，smartcn 等；
同样还有部分酷的功能没有使用，如：facet 等。&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;School&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;Tire&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Search&lt;/span&gt;

  &lt;span class="nb"&gt;attr_accessor&lt;/span&gt; &lt;span class="ss"&gt;:location&lt;/span&gt;
  &lt;span class="n"&gt;attr_accessible&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:latitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:longitude&lt;/span&gt;

  &lt;span class="n"&gt;state_machine&lt;/span&gt; &lt;span class="ss"&gt;:status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;initial: :active&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;
    &lt;span class="n"&gt;state&lt;/span&gt; &lt;span class="ss"&gt;:deleted&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ss"&gt;:set_active&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;transition&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:active&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="ss"&gt;:set_deleted&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="n"&gt;transition&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="ss"&gt;:deleted&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;after_save&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="k"&gt;if&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;active?&lt;/span&gt;
      &lt;span class="n"&gt;tire&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;update_index&lt;/span&gt;
    &lt;span class="k"&gt;else&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;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;remove&lt;/span&gt; &lt;span class="nb"&gt;self&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="nc"&gt;self&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;search&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:lng&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;
    &lt;span class="n"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:lat&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:page&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:per_page&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt;
    &lt;span class="n"&gt;tire&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="ss"&gt;page: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:page&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;per_page: &lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:per_page&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;load: &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;query&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
        &lt;span class="n"&gt;boolean&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;string&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:keyword&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;default_operator: &lt;/span&gt;&lt;span class="s2"&gt;"AND"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:keyword&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;present?&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;if&lt;/span&gt; &lt;span class="n"&gt;latitude&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;longitude&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;
        &lt;span class="n"&gt;sort&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
          &lt;span class="n"&gt;by&lt;/span&gt; &lt;span class="ss"&gt;:_geo_distance&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="ss"&gt;order: &lt;/span&gt;&lt;span class="s2"&gt;"asc"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;unit: &lt;/span&gt;&lt;span class="s1"&gt;'km'&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;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;location&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;longitude: &lt;/span&gt;&lt;span class="n"&gt;longitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;latitude: &lt;/span&gt;&lt;span class="n"&gt;latitude&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_f&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;end&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;include_root_in_json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;to_indexed_json&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;name: &lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;address: &lt;/span&gt;&lt;span class="n"&gt;address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="ss"&gt;location: &lt;/span&gt;&lt;span class="n"&gt;location&lt;/span&gt;
    &lt;span class="p"&gt;}.&lt;/span&gt;&lt;span class="nf"&gt;to_json&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;mapping&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="ss"&gt;:id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:type&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'integer'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:index&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'not_analyzed'&lt;/span&gt;
    &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boost&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;  &lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;analyzer: &lt;/span&gt;&lt;span class="s2"&gt;"snowball"&lt;/span&gt;
    &lt;span class="n"&gt;indexes&lt;/span&gt; &lt;span class="ss"&gt;:address&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;:boost&lt;/span&gt;  &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;analyzer: &lt;/span&gt;&lt;span class="s2"&gt;"snowball"&lt;/span&gt;
    &lt;span class="n"&gt;indexes&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'geo_point'&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;ul&gt;
&lt;li&gt;博客上有进一步的讲解：
&lt;a href="http://manageyp.github.io/elasticsearch/ruby-on-rails/2013/10/10/rails-integration-with-elasticsearch-using-tire.html" rel="nofollow" target="_blank"&gt;http://manageyp.github.io/elasticsearch/ruby-on-rails/2013/10/10/rails-integration-with-elasticsearch-using-tire.html&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Github 源代码
&lt;a href="https://github.com/manageyp/grape_demo/blob/master/app/models/school.rb" rel="nofollow" target="_blank"&gt;https://github.com/manageyp/grape_demo/blob/master/app/models/school.rb&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="推荐阅读"&gt;推荐阅读&lt;/h2&gt;
&lt;p&gt;Fog Creek Software 如何使用 Elasticsearch 使 Kiln 的搜索速度提升了 1000 倍（非常值得借鉴）：
&lt;a href="http://www.infoq.com/cn/articles/kiln-elasticsearch/" rel="nofollow" target="_blank"&gt;http://www.infoq.com/cn/articles/kiln-elasticsearch/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Realtime Search: Solr vs Elasticsearch（图形并茂，很有说服力）：
&lt;a href="http://blog.socialcast.com/realtime-search-solr-vs-elasticsearch/" rel="nofollow" target="_blank"&gt;http://blog.socialcast.com/realtime-search-solr-vs-elasticsearch/&lt;/a&gt;&lt;/p&gt;</description>
      <author>manageyp</author>
      <pubDate>Wed, 06 Nov 2013 12:07:02 +0800</pubDate>
      <link>https://ruby-china.org/topics/15337</link>
      <guid>https://ruby-china.org/topics/15337</guid>
    </item>
    <item>
      <title>[上海][浦东][扩招] 一名 Ruby 工程师 (附靓照)[已结束]</title>
      <description>&lt;h2 id="原帖标题：诚招 Ruby 工程师 和 Web 前端工程师"&gt;原帖标题：诚招 Ruby 工程师 和 Web 前端工程师&lt;/h2&gt;&lt;h2 id="公司：银联智惠信息服务（上海）有限公司"&gt;公司：银联智惠信息服务（上海）有限公司&lt;/h2&gt;&lt;h2 id="公司介绍"&gt;公司介绍&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; 银联智惠信息服务（上海）有限公司（UnionPay Smart）组建于 2012 年，是中国银联旗下子公司，旨在建立全新的营销模式和广告营销服务平台，为千万商户开拓 27 亿张银联卡的消费用户市场，服务对象包括海量银联卡持有人及数以千万计商户。公司主营优惠券营销运营业务，致力于打通线上线下（O2O）交易闭环。我们通过对海量用户消费数据的挖掘分析，实现精准实时优惠推送，从而打造一站式广告营销平台，为千万商户开拓数亿张银行卡的消费用户市场。&lt;/li&gt;
&lt;li&gt; 公司核心管理团队由来自美国硅谷的精英团队组成，成员包括从 Oracle（甲骨文），Morgan Stanley（摩根斯坦利银行），eBay，BEA，LinkedIn 等国内外公司的资深员工，亦拥有多项技术专利。一句话概括：一群硅谷回来的精英组建的团队。&lt;/li&gt;
&lt;li&gt; 公司目前规模：50~100 人&lt;/li&gt;
&lt;li&gt; 公司地址：上海市浦东新区龙东大道 3000 号 8 号楼&lt;/li&gt;
&lt;li&gt; 官方网站：&lt;a href="http://www.unionpaysmart.com/" rel="nofollow" target="_blank"&gt;http://www.unionpaysmart.com/&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="产品介绍"&gt;产品介绍&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; 公司目前主营以下两个产品。&lt;/li&gt;
&lt;li&gt; （1）银联微点是一款全新的 APP 返利应用，涵盖全国上千家著名连锁品牌与本地生活服务类商户，目前已开通上海，未来会开通 20 个城市，银行卡即是您的会员卡，只要在银联微点上绑定您的银行卡，并使用绑定的银行卡到商户消费我们就会将您消费金额的一部分返到您的银联微点账户中。只要您动动手指，我们就送你大大惊喜，在您享受淘优惠的乐趣时我们还给您独享的返利，有了银联微点您的生活会更精彩！&lt;/li&gt;
&lt;li&gt; 银联微点后端服务基于 Rails 打造。&lt;/li&gt;
&lt;li&gt;&lt;p&gt;想了解该产品的更多信息，可以关注微信：upvdian. 扫描二维码
&lt;img src="//l.ruby-china.com/photo/f13c1e501fe76f262976a05bff50e28c.png" title="" alt="扫描二维码"&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;（2）商户营销管理平台，是一个将老会员管理、优惠券推送、新客户营销、大数据分析整合于一体的商户管理平台。它可以帮助您及时掌握新老顾客消费动态，完美评估优惠券精准营销推送效果，自动生成月报周报统计数据，为每一个商户打造独一无二的创新营销整合方案，抓住商机，赢得客户。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;商户营销管理平台系统同样是基于 Rails 打造。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="团队介绍"&gt;团队介绍&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;我们团队主要推进银联微点 APP 的开发和维护。纯技术氛围，不存在你争我夺的竞争，而是相互分享，互相帮助团队。热衷于技术分享，每天 Code Review，每一位同事都成长飞快。&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;如果你是技术怪才；
如果你和我们一样有激情、有梦想； 
如果你对新兴行业有着近乎偏执的热情；
我们会以自由宽松的工作环境、快速成长的业务和未来的无限前景作为交换。
期待你的加入，一起努力，迎接挑战，共同成长！&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;BTW：产品团队美女如云（参见下图），不轻易改需求，每次改良都认真讨论。重视技术的建议，尊重工程师的劳动成果。与工程师同心协力，用心做产品，把“做不到”变成“能做到”！&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="附靓照，所有图片均未PS（^_^）"&gt;附靓照，所有图片均未 PS（^_^）&lt;/h2&gt;&lt;h6 id="办公环境"&gt;办公环境&lt;/h6&gt;
&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/ded54e13ebcf8cc117599743b011902c.jpg" title="" alt=""&gt;&lt;/p&gt;
&lt;h6 id="园区食堂"&gt;园区食堂&lt;/h6&gt;
&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/3b9f36d4fd6031032f26b2cba4beb3c2.jpg" title="" alt="园区食堂"&gt;&lt;/p&gt;
&lt;h6 id="园区环境"&gt;园区环境&lt;/h6&gt;
&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/96328b41488e00a9c44fb6f1c4c832e0.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h6 id="公共交通"&gt;公共交通&lt;/h6&gt;
&lt;p&gt;近地铁 2 号线广兰路，地铁口有园区班车接送。&lt;/p&gt;
&lt;h2 id="招聘职位"&gt;招聘职位&lt;/h2&gt;&lt;h6 id="Ruby 工程师（扩招一人）"&gt;Ruby 工程师（扩招一人）&lt;/h6&gt;
&lt;p&gt;职位要求&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; 学历不限；&lt;/li&gt;
&lt;li&gt; 熟练掌握 Ruby，Rails；&lt;/li&gt;
&lt;li&gt; 熟悉数据库，如 MySQL，Redis，MongoDB；&lt;/li&gt;
&lt;li&gt; 熟悉 Rspec 等测试工具；&lt;/li&gt;
&lt;li&gt; 熟悉代码管理工具，如 Git；&lt;/li&gt;
&lt;li&gt; 熟悉 Web API 设计。&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;加分项&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; 追求简洁的代码，清晰的架构设计；&lt;/li&gt;
&lt;li&gt; 重视测试，有良好的测试习惯；&lt;/li&gt;
&lt;li&gt; 关注并实践最新的技术；&lt;/li&gt;
&lt;li&gt; 参与大型 Web 项目开发；&lt;/li&gt;
&lt;li&gt; 社区活跃分子（褒义词）；&lt;/li&gt;
&lt;li&gt; 开源项目 Contributor&lt;/li&gt;
&lt;/ol&gt;
&lt;h6 id="Web前端（五人）（已结束）"&gt;Web 前端（五人）（已结束）&lt;/h6&gt;
&lt;p&gt;岗位职责：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Web 端功能设计、开发和实现&lt;/li&gt;
&lt;li&gt; 负责各产品线易用性改进和 Web 界面技术优化&lt;/li&gt;
&lt;li&gt; 参与 Web 前沿技术研究和新技术调研&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;任职要求：&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; 3 年以上工作经验&lt;/li&gt;
&lt;li&gt; 精通 Web 前端前沿技术，包括 HTML5/CSS3/Javascript/ActionScript 等&lt;/li&gt;
&lt;li&gt; 深刻理解 Web 标准，对可用性、易用性等相关知识有深入了解和实践经验&lt;/li&gt;
&lt;li&gt; 至少精通一门服务器端语言（包括但不限于 Java/PHP/Python 等），并有项目经验&lt;/li&gt;
&lt;li&gt; 有参与设计复杂平台架构的经验，能承担前端新的技术，标准的积累&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="福利待遇"&gt;福利待遇&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; 待遇丰厚，超业界水平，比照国企。参照个人能力，上不封顶。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="联系方式"&gt;联系方式&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt; HR 邮箱：hr@unionpaysmart.com&lt;/li&gt;
&lt;li&gt; HR 电话：61639031&lt;/li&gt;
&lt;/ul&gt;</description>
      <author>manageyp</author>
      <pubDate>Wed, 10 Jul 2013 11:50:40 +0800</pubDate>
      <link>https://ruby-china.org/topics/12391</link>
      <guid>https://ruby-china.org/topics/12391</guid>
    </item>
  </channel>
</rss>
