<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>flowerains (Alex Wang)</title>
    <link>https://ruby-china.org/flowerains</link>
    <description>bilibili前员工，PHP程序员，学习Ruby和Rails中</description>
    <language>en-us</language>
    <item>
      <title>如何在 Rails 中避免这个 N+1 Query 查询</title>
      <description>&lt;p&gt;现在已经有个这样的关联关系&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# 用户&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:group_users&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:groups&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;through: :group_users&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:messages&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# 小组&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Group&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:group_users&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:users&lt;/span&gt; &lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="ss"&gt;through: :group_users&lt;/span&gt;
  &lt;span class="n"&gt;has_many&lt;/span&gt; &lt;span class="ss"&gt;:messages&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# 小组消息&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Message&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:group&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;# 小组和成员的关联表&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;GroupUser&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ApplicationRecord&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:group&lt;/span&gt;
  &lt;span class="n"&gt;belongs_to&lt;/span&gt; &lt;span class="ss"&gt;:user&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;我在 ERB 模板里面写了这样一句，目的是获取当前这条消息所在小组的所有用户的名称，并且使用','连接他们&lt;/p&gt;
&lt;pre class="highlight erb"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="vi"&gt;@messages.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;message&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;strong&amp;gt;&lt;/span&gt;Group Chat: &lt;span class="cp"&gt;&amp;lt;%=&lt;/span&gt;  &lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;group&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;users&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;:name&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;','&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;&lt;span class="nt"&gt;&amp;lt;/strong&amp;gt;&amp;lt;br/&amp;gt;&lt;/span&gt;
&lt;span class="cp"&gt;&amp;lt;%&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt; &lt;span class="cp"&gt;%&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样子会产生大量的 N+1 query 查询&lt;/p&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;  &lt;span class="nv"&gt;"groups"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"groups"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"groups"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;"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="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"user_id"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"group_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;"group_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="k"&gt;SELECT&lt;/span&gt;  &lt;span class="nv"&gt;"groups"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"groups"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"groups"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;"LIMIT"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt; &lt;span class="k"&gt;INNER&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="nv"&gt;"users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"user_id"&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="nv"&gt;"group_users"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nv"&gt;"group_id"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="p"&gt;[[&lt;/span&gt;&lt;span class="nv"&gt;"group_id"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;那么，请问如何避免这种 N+1 query 查询，或者最好的做法是怎样，请指教？&lt;/p&gt;</description>
      <author>flowerains</author>
      <pubDate>Sun, 16 Jul 2017 11:30:43 +0800</pubDate>
      <link>https://ruby-china.org/topics/33514</link>
      <guid>https://ruby-china.org/topics/33514</guid>
    </item>
    <item>
      <title>苦思冥想，还是来论坛试着寻求上海 Ruby 初级开发工程师的机会</title>
      <description>&lt;p&gt;大家好，我是 4 月份&lt;a href="https://ruby-china.org/topics/32936" title=""&gt;大家觉得我这种情况，是否能够应聘一份 Ruby 的开发工作？&lt;/a&gt;这篇帖子的作者。&lt;/p&gt;

&lt;p&gt;4 月份在写了这篇帖子之后，就又回去继续写 PHP 了，期间只能断断续续的看看 Rails 的书，有拿 windy 的 wblog 改改为自己搭建一个技术博客，放到我自己的美团云服务器上（卡在域名备案了&lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; ）。
从 5 月下旬开始，我也有去尝试找 Ruby 和 Rails 的工作，的确是有些担心薪酬的落幅，和应聘初级职位可能直接被拒的问题（事实也确实是如此）。&lt;/p&gt;

&lt;p&gt;就如同&lt;a href="/Rei" class="user-mention" title="@Rei"&gt;&lt;i&gt;@&lt;/i&gt;Rei&lt;/a&gt;在之前那个帖子里面所说，既然要谋求初级职位，想学习如何写出优化的代码，是要付出一些代价的，所以薪酬上我觉得可以接受一个初级开发的待遇，不过之前职位都是拉勾网上看的，对于初级开发能够提供的职位太少了。&lt;/p&gt;

&lt;p&gt;所以决定在 ruby-china 发个帖，为自己求个职，总结一下自己过往的成绩和项目经验，希望有有识之士能够给个机会，薪酬大家可以坐下来谈嘛，别一口回绝了&lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; &lt;/p&gt;
&lt;h2 id="工作经验和个人描述"&gt;工作经验和个人描述&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;PHP 开发 5 年，其中 3 年在上海某弹幕网站。&lt;/li&gt;
&lt;li&gt;OSX 上开发 5 年，正版软件爱好者。&lt;/li&gt;
&lt;li&gt;业余时间断断续续给其他公司做过 PHP 这块的培训，带过公司 PHP 新手和应届毕业生。&lt;/li&gt;
&lt;li&gt;自己有个美团云的 ubuntu16.04 的机器，时常在上面鼓捣东西。&lt;/li&gt;
&lt;li&gt;平时喜欢逛 NGA、BILIBILI、玩玩 PS4 游戏，通过 kindle 看看书，在 github 上&lt;strong&gt;交友&lt;/strong&gt;。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="曾经做过的项目"&gt;曾经做过的项目&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;某画站  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;画站是一款集用户图片上传，分享，回复一体的网站。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;主要用到了 linux 上的 imagemagick 库，和 PHP 的 imagemagick 扩展，做一些图片的处理，并且上传到云存储系统。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;平时做一做维护优化，涉及到 MySQL 慢查询（通过 slow_query_log 查看慢查询语句，查找来源和优化，explain 判断是否有走索引）。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt; 类似代码中有循环查询数据库，等代码中不合理的方式的写法改进（历史遗留问题都是坑啊&lt;img title=":joy:" alt="😂" src="https://twemoji.ruby-china.com/2/svg/1f602.svg" class="twemoji"&gt; ）&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;某萌战 2015 第一届  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;是持续时间超过一个月的人气动漫角色投票活动，投票周期长，参与人数多。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;有做例如代码输出 HTTP 消息头（Expires，Etag），做网页缓存的控制。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;对于投票，采取直接把票以用户 uid 标识存进 redis 中，利用 redis 的原子性，防止用户每天重复投票。&lt;/li&gt;
&lt;li&gt;API 缓存的生成策略，使用了锁的争抢机制，具体是进程抢到了 reids 的中的某个 key 则查询数据库生成数据，其他没有抢到的直接返回失败，避免对 MySQL 的冲击&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;后期有考虑用 nginx 直接访问 memcached，做页面静态化，如果访问不到 memcached 中的缓存页面，则 error_page 指向 php 进程，再靠 PHP 生成模板页。&lt;br&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;某线上售票平台 时间大概在 2014-2015 陆陆续续做了 2 届&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;对 MySQL 的事务处理（如何使用乐观锁，PHP 利用版本号实现乐观锁），生成不重复订单号（php 生成 uuid）有了不少经验。&lt;br&gt;
&lt;/li&gt;
&lt;li&gt;当然也必须承认为了抵御高并发，是靠堆砌服务器来实现的（胆小如我&lt;img title=":kissing:" alt="😗" src="https://twemoji.ruby-china.com/2/svg/1f617.svg" class="twemoji"&gt; ）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;其他内部系统开发之类的，无非是功能的堆砌，业务的增删改查和复杂程度不同，需要的是把业务抽象成 API 的能力，没什么成就感，就不一一列举了。&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="个人缺陷"&gt;个人缺陷&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;基础知识薄弱，有待以后加强。（最近终于买了《代码大全 2》《深入理解计算机系统》《大话数据结构》待看）。&lt;/li&gt;
&lt;li&gt;英语水平较弱，查查文档和 stackoverflow 可以，不懂的单词还是得靠谷歌，未来要加强英语学习。&lt;/li&gt;
&lt;li&gt;技术栈不全，对于搜索引擎，爬虫，甚至前端都有所缺失，为了成为全栈工程师必须查缺补漏。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="渴望加入这样的公司"&gt;渴望加入这样的公司&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;有 Ruby 或者 Rails 的技术专家，能和您一起共事，向您提问是我的荣幸。&lt;/li&gt;
&lt;li&gt;推崇工程师文化，愿意接受一些新鲜的工具和技术。&lt;/li&gt;
&lt;li&gt;可以凭自己的兴趣接触不同的技术栈，比如我想更多接触和学习一下前端开发，底层架构之类的。&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="结语"&gt;结语&lt;/h2&gt;
&lt;p&gt;感谢大家看了我的长篇大论，凭着 PHP 这块的经验，我也已经拿到过东方头条等公司薪水不错的 offer，还是不甘心最终这几个月的学习白白浪费，对 Ruby 的热爱无处施展。
所以才有这篇帖子。&lt;br&gt;
附送上我的邮箱和微信号，希望对我感兴趣的人能联系我一下或者留下联系方式，Ruby 求职也是挺艰难的。&lt;br&gt;
邮箱：flowerain@163.com&lt;br&gt;
微信号：flowerains&lt;br&gt;
github: github.com/flowerains&lt;br&gt;
如果文章有什么不足或是有什么不符合要求的还请告知与见谅！谢谢各位的观看&lt;img title=":grinning:" alt="😀" src="https://twemoji.ruby-china.com/2/svg/1f600.svg" class="twemoji"&gt; &lt;/p&gt;
&lt;h2 id="后续 2017-07-03"&gt;后续 2017-07-03&lt;/h2&gt;
&lt;p&gt;已经找到 Ruby 工作入职了，感谢每一位给我提供过机会的人，我们有缘再合作~&lt;/p&gt;</description>
      <author>flowerains</author>
      <pubDate>Tue, 27 Jun 2017 21:54:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/33334</link>
      <guid>https://ruby-china.org/topics/33334</guid>
    </item>
    <item>
      <title>大家觉得我这种情况，是否能够应聘一份 Ruby 的开发工作？</title>
      <description>&lt;p&gt;我之前是做 PHP 开发的，算时间已经做了 5 年，
其中三年在上海某弹幕公司工作。&lt;/p&gt;

&lt;p&gt;现在所有的知识点都是基于 PHP 开发扩展开的，虽然有些共通的地方
（比如 git，linux 上的简单运维操作，nginx+mysql+redis 的开发配置，API 请求优化，SQL 等）
但是 Ruby 的经验远不能和 PHP 写了几万行相比。
我从对 Ruby 从纯粹的好奇，到自己业余时间可以用 RoR 搭建一个小网站，做点业务模块是没问题了。
主要还是有些心虚。&lt;/p&gt;

&lt;p&gt;刚好这段时间离职了，有在考虑要不要转换一下编程语言，
选择自己更喜欢的同时还能通过比较查缺补漏，
各位对我有什么建议嘛，感激不尽 (～￣▽￣)～。&lt;/p&gt;

&lt;p&gt;PS.之前是纯后端，HTML 看得懂，CSS,JS 大概只停留在套模板这层次吧。&lt;/p&gt;</description>
      <author>flowerains</author>
      <pubDate>Fri, 05 May 2017 15:59:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/32936</link>
      <guid>https://ruby-china.org/topics/32936</guid>
    </item>
  </channel>
</rss>
