<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>seaify (seaify)</title>
    <link>https://ruby-china.org/seaify</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>2016年年 度总结</title>
      <description>&lt;p&gt;年度总结这东西，还是以 12 月为基准更好，而不是过年的 2 月。&lt;/p&gt;

&lt;p&gt;过去的一整年，都是在远程，基本在大理，不过，也出过 3 次远门。&lt;/p&gt;

&lt;p&gt;去女朋友家，去参加小郭和赵航的婚礼，参加陈其赵曦的婚礼。正是因为远程的特性，才能参加这些好朋友的婚礼，和好友在异地生活相聚是很难得的，见证这些重要时刻才会让人觉得生活可贵有意思，不用总是妥协。说到这，就又想念麟游的大虾和自己采摘的樱桃了，以及超大份的不知道叫啥的面条了。&lt;/p&gt;

&lt;p&gt;而今年的 ruby-china，给人印象最深的，其实是成都的美食，最后聚餐的那个盘飧市，太给力了。另外和亚飞，woody 他们也碰了面，远程就是这点也不好，之前的同事，借着这次大会，才见过真容。感觉 ruby 社区才更温暖，更有人情味，人们更真性情。哦，对了，也是最喜欢的后端语言，没有之一。&lt;/p&gt;

&lt;p&gt;参加 ruby-china 大会的当晚，和朋友吃的是功夫鱼，很对我的胃口。自从刚毕业那会公司聚餐，在成都某个大排档，吃过串串后，就认定是最好的城市。后来，去参加陈其婚礼，在他们老家吃过的烧烤，准确来说更像是油炸，但是够特别，全国别地还真没见过，好吃。&lt;/p&gt;

&lt;p&gt;在这呢，还是要感谢小郭赵航，陈其赵曦的热情款待，ruby-china 的活动组织，以及亚飞当年在 rails 上的指点，以及 vuejs 的推荐。&lt;/p&gt;

&lt;p&gt;说说工作上的事情，年初依旧是接活，在英选平台，也有 daocloud 的那个公证处项目。后来加入了风泽科技，这是在自己独立接项目，做网站后，第一次加入团队。其实一个人做远程久了，会有比较强烈的沟通需求，因为没啥人陪你说话，在技术领域。在风泽的接近半年时间里，学会了在 rails 里集成 vuejs, 也学会了 vuejs single page application, 还有该死的个推推送这种东西，再次说下，高德地图文档很不错。还是很高兴认识风泽的各位前同事，你们可能不太懂一年技术领域都没啥人和交流的寂寞感，能多认识些朋友，还是很高兴的。&lt;/p&gt;

&lt;p&gt;最近接了个项目，有机会用 react-native 做了个 ios app，基本已完成，终于能进入个全新的领域，也是挺开心的，能多了解下 app 这个领域，以后和 app 的人也更好沟通。&lt;/p&gt;

&lt;p&gt;在今年，vuejs 用的不错，意义也挺重大，因为当初用 jquery 写复杂界面，哦，cocoon 操作那个 dom 节点，太蛋疼了。如果有了 vuejs 这种神器，前端界面的复杂交互上，倒是不怎么害怕了。而后来的 vuejs spa, 也让自己做了回纯前端，以前呢，要么是后端，要么是前后端一起，突然可以告诉后端，我要 xxx api，嗯，感觉也还可以。&lt;/p&gt;

&lt;p&gt;今年在技术上，rails 集成 vuejs, vuejs spa, react-native，这些使得技术指标倒是达到了，也扩宽了技术面。&lt;/p&gt;

&lt;p&gt;今年在大概看了 2 天房的情况下，在成都买了个房子，后面一波三折，交首付前天晚上，突然政府文件，提高到三成，第二天到现场懵逼了，这都能赶上。以后估计就是在成都定居了，其实生活在大城市也好，相比起大理，我可以去参加些活动，结识些朋友，了解更多前沿的资讯。&lt;/p&gt;

&lt;p&gt;生活总是很奇怪，不经意就过了，也总是有着诸多不满，对过往，对现在。今天汽车上无聊，看了 2 年前的一篇文章，才想起，2 年前，也是在旅途的归家途中，看了那篇文章，这种重现，很有意思，也意味深长。&lt;/p&gt;

&lt;p&gt;汽车旅行，不像飞机那样时间短，也不像火车那样嘈杂，看着窗外退后的草木，适合追忆，回首。&lt;/p&gt;

&lt;p&gt;止。&lt;/p&gt;

&lt;p&gt;ps:  过去的一年半呢，我就是在做国内的项目，以及 upwork, 以及做了半年的全职远程，正是&lt;a href="http://yizaoyiwan.com/discussions/79" rel="nofollow" target="_blank"&gt;http://yizaoyiwan.com/discussions/79&lt;/a&gt; 这篇文章中提到的，放弃的。他们选择了在海外的同事，去联系当地的 digital agencies and design teams，这个选择，在我现在看来很有眼光，方向对了。&lt;/p&gt;

&lt;p&gt;ps2: 之前的其它做 upwork 的朋友，会选择在淘宝上，购买一些口语陪读服务，提升口语，这个坚持也很重要。上次有国外的 hr 给我推荐了这个网站，&lt;a href="https://www.italki.com/home" rel="nofollow" target="_blank"&gt;https://www.italki.com/home&lt;/a&gt; 。口语重要性是第一位的，比技术更前，对于好的国外公司。&lt;/p&gt;

&lt;p&gt;仔细想想，这里才是最有归属感的地方。&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Mon, 21 Nov 2016 14:35:16 +0800</pubDate>
      <link>https://ruby-china.org/topics/31647</link>
      <guid>https://ruby-china.org/topics/31647</guid>
    </item>
    <item>
      <title>打码平台 gem 分享 (对接人工识别验证码平台)</title>
      <description>&lt;p&gt;&lt;a href="https://github.com/seaify/confirmation_code" rel="nofollow" target="_blank"&gt;https://github.com/seaify/confirmation_code&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="支持以下打码平台"&gt;支持以下打码平台&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.jsdati.com/" rel="nofollow" target="_blank" title=""&gt;联众&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="http://www.dama2.com/" rel="nofollow" target="_blank" title=""&gt;打码兔&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;还尝试过云打码，uusee, 挣码等，但都有一些问题，所以没有接入。&lt;/p&gt;

&lt;p&gt;云打码：使用样例，验证码类型设置为了 1-6 位，识别出来少了 1 位。&lt;br&gt;
uusee: api 样例代码太复杂&lt;br&gt;
挣码：给的 http 接口样例，域名都失效了    &lt;/p&gt;

&lt;p&gt;尝试过的所有验证码平台，官方网站+api 都给人很不专业的感觉，比云片网差太多了，所以建议不要充值太多，觉得也许容易跑路。&lt;/p&gt;

&lt;p&gt;欢迎使用，fork,  提 issue 等等&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Mon, 18 Apr 2016 22:49:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/29766</link>
      <guid>https://ruby-china.org/topics/29766</guid>
    </item>
    <item>
      <title>ActiveAdmin member_action popup form/modal</title>
      <description>&lt;p&gt;activeadmin 中 batch_action 支持 BatchActionForm, 能够弹出一个类似 modal 的东西，用来收集用户输入。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;batch_action&lt;/span&gt; &lt;span class="ss"&gt;:flag&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;form: &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="ss"&gt;type: &lt;/span&gt;&lt;span class="sx"&gt;%w[Offensive Spam Other]&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;reason: :text&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;notes:  :textarea&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;hide:   :checkbox&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
   &lt;span class="ss"&gt;date:   :datepicker&lt;/span&gt;
&lt;span class="p"&gt;}&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;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="n"&gt;redirect_to&lt;/span&gt; &lt;span class="n"&gt;collection_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;notice: &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ids&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而 member_action, 并没有类似的支持，如果想在点击 member_action 的链接后，也弹出一个类似的框，应该怎样做呢？&lt;/p&gt;

&lt;p&gt;member_action 对应的 view，写一个这样的 modal，modal 中是 form 表单可以办到，但是那样的话，就是直接跳转到一个新的页面，而不是弹框这种形式。&lt;/p&gt;

&lt;p&gt;activeadmin 似乎定制比较难。&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Mon, 04 Apr 2016 10:11:50 +0800</pubDate>
      <link>https://ruby-china.org/topics/29536</link>
      <guid>https://ruby-china.org/topics/29536</guid>
    </item>
    <item>
      <title>Ruby 无头浏览器咨询</title>
      <description>&lt;p&gt;最近使用到了 watir-webdriver,  在 mac 下使用火狐浏览器，去自动填充元素，在 ubuntu 下使用 headless，无界面去自动填充元素。&lt;/p&gt;

&lt;p&gt;但是会碰到一个问题，连接超时&lt;/p&gt;

&lt;p&gt;CarPublisher.browser.iframe(:id =&amp;gt; "ContainerFrame").wait_until_present&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;#&amp;lt;URI::HTTP http://127.0.0.1:7055/hub/session/8f53eba2-13a2-f14e-97ec-36cfa00253ea/element&amp;gt;
"{\"using\":\"id\",\"value\":\"ContainerFrame\"}"
/Users/chuck/.rvm/gems/ruby-2.2.0/gems/watir-webdriver-0.9.1/lib/watir-webdriver/wait.rb:44:in `until': timed out after 90 seconds, waiting for {:id=&amp;gt;"ContainerFrame", :tag_name=&amp;gt;"iframe"} to become present (Watir::Wait::TimeoutError)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而在打开的火狐浏览器里，这个 iframe, 早就出现了，而在等待 90s 后，selenium-webdriver 说它超时。&lt;/p&gt;

&lt;p&gt;通过 selenium-webdriver, 相当于起了一个 server, 而要操作浏览器的元素，都是通过一个个的 command, 然后发送 get, post 请求来获取或变更元素信息&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;command :describeElement,                        :get,     "session/:session_id/element/:id"
command :findChildElement,                       :post,    "session/:session_id/element/:id/element"
command :findChildElements,                      :post,    "session/:session_id/element/:id/elements"
command :clickElement,                           :post,    "session/:session_id/element/:id/click"
command :submitElement,                          :post,    "session/:session_id/element/:id/submit"
command :getElementValue,                        :get,     "session/:session_id/element/:id/value"
command :sendKeysToElement,                      :post,    "session/:session_id/element/:id/value"
command :uploadFile,                             :post,    "session/:session_id/file"
command :getElementTagName,                      :get,     "session/:session_id/element/:id/name"
command :clearElement,                           :post,    "session/:session_id/element/:id/clear"
command :isElementSelected,                      :get,     "session/:session_id/element/:id/selected"
command :isElementEnabled,                       :get,     "session/:session_id/element/:id/enabled"
command :getElementAttribute,                    :get,     "session/:session_id/element/:id/attribute/:name"
command :elementEquals,                          :get,     "session/:session_id/element/:id/equals/:other"
command :isElementDisplayed,                     :get,     "session/:session_id/element/:id/displayed"
command :getElementLocation,                     :get,     "session/:session_id/element/:id/location"
command :getElementLocationOnceScrolledIntoView, :get,     "session/:session_id/element/:id/location_in_view"
command :getElementSize,                         :get,     "session/:session_id/element/:id/size"
command :dragElement,                            :post,    "session/:session_id/element/:id/drag"
command :getElementValueOfCssProperty,           :get,     "session/:session_id/element/:id/css/:property_name"
command :getElementText,                         :get,     "session/:session_id/element/:id/text"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有大神碰到过这种情况吗，或者说 ruby 下，有没更好的无头浏览器方案？&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Mon, 22 Feb 2016 15:01:10 +0800</pubDate>
      <link>https://ruby-china.org/topics/29050</link>
      <guid>https://ruby-china.org/topics/29050</guid>
    </item>
    <item>
      <title>读取 Ｍodel 中的信息后，如何动态的生成某人的亲属关系图呢,？</title>
      <description>&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/76e3c5a1e22f934aafbf9c1975a0dcac.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;如题，读取数据库里的信息，一个个显示图片且可点击，知道该怎么弄，可是图片与图片之间的连线以及关系名，这种应该怎么生成呢？&lt;/p&gt;

&lt;p&gt;或者前端上面有相应的绘图工具吗？&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Fri, 23 Oct 2015 16:25:13 +0800</pubDate>
      <link>https://ruby-china.org/topics/27794</link>
      <guid>https://ruby-china.org/topics/27794</guid>
    </item>
    <item>
      <title>simple_form 多行输入对齐，以及验证消息显示的问题</title>
      <description>&lt;h2 id="问题"&gt;问题&lt;/h2&gt;&lt;h3 id="使用simple_form的input_field"&gt;使用 simple_form 的 input_field&lt;/h3&gt;
&lt;p&gt;在同一个表单中，每行输入的元素个数，有的是 1，有的是 2，或者 3，但要求某些元素的 label 对齐&lt;/p&gt;

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

&lt;p&gt;我的使用方法是&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;div.row
  label.col-xs-2.control-label = Profile.human_attribute_name("realname")
  div.col-xs-2
    = f.input_field :realname, class: "form-control"

  label.col-xs-offset-2.col-xs-1.control-label 照片
  div.col-xs-3
    - if @profile.avatar?
      = image_tag(@profile.avatar_url(:normal))
    - else
      = image_tag "image-placeholder.png"
    = f.file_field :avatar, class: "form-control"
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种类似的写法，需要保证每行的所有元素都是在 div.row 中，然后设置相应的 col-xs-offset，或者 col-xs-2 这种来保证偏移是相同的，也就是对齐。&lt;/p&gt;

&lt;p&gt;但是这样写，就没法用 simple_form 的出错信息显示，我想到的出错显示的方法就是每个 input 后面，读取 f.object.errors 里面是否有该 input 的 name，有就显示出来，类似&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;7     div.form-group.string.optional class=('has-error' if (@player.errors.include?(:work_start_at)))
  8       label.string.optional.control-label for="player[work_start_at]" 工作开始时间
  9       div.input-group.date.timepicker
 10         input type='text' class="form-control" name="player[work_start_at]" value="#{@screen.player.work_start_at}"
 11           span.input-group-addon
 12             span.glyphicon.glyphicon-time
 13       - if @player.errors.include?(:work_start_at)
 14         span class="help-block" #{@player.errors.get(:work_start_at)[0]}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;但是这样子写，实在是太累了，一个 input，竟然要写这么多代码。而把所有的表单 input error 信息全部显示在 form 表单之上，全部打印出来，也是不可接受的，错误信息，还是应该紧跟输入框。&lt;/p&gt;
&lt;h3 id="使用simple_form的input"&gt;使用 simple_form 的 input&lt;/h3&gt;
&lt;p&gt;使用 f.input, 这种写法，simple_form 会帮我们处理好出错信息的显示问题，但是会带来多行输入时的对齐问题&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;= f.input :mobile,  :wrapper =&amp;gt; "input_wrap"
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;config.wrappers :input_wrap, :tag =&amp;gt; 'div', :class =&amp;gt; 'row form-group', :error_class =&amp;gt; 'has-error' do |b|
  b.use :html5
  b.use :placeholder
  b.use :label, :wrap_with =&amp;gt; {:class =&amp;gt; 'col-xs-2 control-label'}
  b.wrapper :tag =&amp;gt; 'div', :class =&amp;gt; 'col-xs-5' do |ba|
    ba.use :input, :class =&amp;gt; 'form-control'
    ba.use :error, :wrap_with =&amp;gt; { :tag =&amp;gt; 'span', :class =&amp;gt; 'help-block' }
    ba.use :hint,  :wrap_with =&amp;gt; { :tag =&amp;gt; 'p', :class =&amp;gt; 'help-block' }
  end
end
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这种写法，也能处理好单行时，label 占据 col-xs-2, input 占据 col-xs-5 的问题。&lt;/p&gt;

&lt;p&gt;但是当一行需要包含多个元素的输入，如 start_day 和 end_day 时，使用 simple_form 的 f.input, 每个都会生成一个 div 的 wrapper, 两个元素的无法作为兄弟节点，同时存在一个 div.row 中，这样就不能好的为每个 Input 设置 offset 和大小，也就没法和其它行进行 label 的对齐。&lt;/p&gt;

&lt;p&gt;这个问题大家应该碰到过吧？&lt;/p&gt;

&lt;p&gt;假设将每行的 input 当作是一个 ember compoent, 不同的 compoent 之间的内部对齐问题应该怎么解决呢，&lt;a href="/nightire" class="user-mention" title="@nightire"&gt;&lt;i&gt;@&lt;/i&gt;nightire&lt;/a&gt;，layout 虽然也可以作为一个 compoent，但解决不了这种问题吧。我想，这个问题，不同的 input 元素，需要进行对齐，本身应该整体作为一个 compoent 才好，然后集中去解决输入错误验证信息吧。&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Sun, 11 Oct 2015 17:43:35 +0800</pubDate>
      <link>https://ruby-china.org/topics/27629</link>
      <guid>https://ruby-china.org/topics/27629</guid>
    </item>
    <item>
      <title>[已解决] slim 中如何使用一行代码根据变量，来自动禁用或启用一个 input 元素的输入</title>
      <description>&lt;p&gt;有时候会碰到这样的情况，不同角色的用户登录后，可操作的权限是不一样的，有的可编辑，有的只可查看。&lt;/p&gt;

&lt;p&gt;对于同一个_form.html.slim, 就希望能根据一个变量，如果变量为 true, 则该行 input 可编辑，否则 disable 掉。并且要求是单行代码，多行代码太冗余了。&lt;/p&gt;

&lt;p&gt;而类似的有，动态的设置一个 div 的 class,  然后根据不同的 class, 更改相应的样式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;div&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'active'&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;is_active?&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可是 disabled 属性却不能这样操作，如 disabled=true, disabled=false, 没有区别，它出现后，就禁用了。&lt;/p&gt;

&lt;p&gt;求助！&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Sun, 27 Sep 2015 16:29:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/27498</link>
      <guid>https://ruby-china.org/topics/27498</guid>
    </item>
    <item>
      <title>如何解决 Grape API 的 url 在少了一个 / 的情况下居然还能工作的问题</title>
      <description>&lt;p&gt;正常状态： /api/v1/xxx  能工作
BUG： /apiv1/xxx 居然也能工作&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;mount&lt;/span&gt; &lt;span class="no"&gt;Api&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Dispatch&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'/api/'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;grape 请求打印出的路由信息&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Started&lt;/span&gt; &lt;span class="no"&gt;GET&lt;/span&gt; &lt;span class="s2"&gt;"/apiv1/screens"&lt;/span&gt; &lt;span class="k"&gt;for&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;at&lt;/span&gt; &lt;span class="mi"&gt;2015&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;09&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="mi"&gt;18&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mo"&gt;01&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;38&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;0800&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="s2"&gt;"route_info"&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="c1"&gt;#&amp;lt;Grape::Route:0x007fd5e241c9a8 @options={:description=&amp;gt;"Retun screens", :prefix=&amp;gt;nil, :version=&amp;gt;"v1", :namespace=&amp;gt;"/", :method=&amp;gt;"GET", :path=&amp;gt;"/:version/screens(.:format)", :params=&amp;gt;{}, :compiled=&amp;gt;/\A\/(?&amp;lt;version&amp;gt;v1)\/screens(?:\.(?&amp;lt;format&amp;gt;[^\/.?]+))?\Z/}&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;有没有办法，让&lt;a href="http://localhost:3001/apiv1/screens.json" rel="nofollow" target="_blank"&gt;http://localhost:3001/apiv1/screens.json&lt;/a&gt;访问失败？&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Thu, 10 Sep 2015 18:15:33 +0800</pubDate>
      <link>https://ruby-china.org/topics/27274</link>
      <guid>https://ruby-china.org/topics/27274</guid>
    </item>
    <item>
      <title>Grape 的 JSON 参数验证，以及 nested params 问题</title>
      <description>&lt;h2 id="两个问题"&gt;两个问题&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;grape，看文档并不支持对 json parameters, 进行 require 等操作？
它的 require 一个参数后，实际上对应生成的 swagger-ui，都是 form 表单，而且通过 postman，也只有以 form 形式提交的请求才正常&lt;/li&gt;
&lt;li&gt;grape,  对于 nested params,  似乎一直报错？&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;requires&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="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;desc: &lt;/span&gt;&lt;span class="s2"&gt;"播放器id"&lt;/span&gt;
  &lt;span class="n"&gt;requires&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;type: &lt;/span&gt;&lt;span class="no"&gt;Hash&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="ss"&gt;:first_name&lt;/span&gt;
    &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="ss"&gt;:last_name&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;img src="https://l.ruby-china.com/photo/2015/01e00044d56d522671a397b8470b2c1e.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;而另一种写法&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
       &lt;span class="n"&gt;requires&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="no"&gt;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;desc: &lt;/span&gt;&lt;span class="s2"&gt;"播放器id"&lt;/span&gt;
       &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="s2"&gt;"name[first]"&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;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;desc: &lt;/span&gt;&lt;span class="s2"&gt;"空闲内存"&lt;/span&gt;
       &lt;span class="n"&gt;requires&lt;/span&gt; &lt;span class="s2"&gt;"name[last]"&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;Integer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;desc: &lt;/span&gt;&lt;span class="s2"&gt;"空闲内存"&lt;/span&gt;
     &lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/18aa6826292cec24cb16808ba36456a9.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Sun, 30 Aug 2015 17:39:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/27122</link>
      <guid>https://ruby-china.org/topics/27122</guid>
    </item>
    <item>
      <title>Rails 源码分析之 callback 篇</title>
      <description>&lt;h2 id="callback是什么？"&gt;callback 是什么？&lt;/h2&gt;
&lt;p&gt;callback，是运行在 object 的生命周期上，某个事件点上的 hook 代码。&lt;/p&gt;
&lt;h2 id="callback在rails中，哪些地方有被使用到?"&gt;callback 在 rails 中，哪些地方有被使用到？&lt;/h2&gt;
&lt;p&gt;可以发现，abstract_controller,  action_dispatch, active_job, active_model, active_record, active_support 都使用到了 callback&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;chuck&lt;/span&gt;&lt;span class="vi"&gt;@chuck&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;MacBook&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Pro&lt;/span&gt;&lt;span class="ss"&gt;:~&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;seaify&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="nf"&gt;-&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt; &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;                                                                                                                                                                          
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;actionpack&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;abstract_controller&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;actionpack&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;action_dispatch&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;middleware&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activejob&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_job&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activemodel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_model&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activemodel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_model&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;validations&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activerecord&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_record&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;/&lt;/span&gt;&lt;span class="n"&gt;activesupport&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_support&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;更具体的是，ActionController::Base 中的 before_action,  ActiveRecord::Base 中的 before_save, ActiveJob::Base 中的 before_enqueue 等
正是 callback 的使用例子，ActiveSupport::Callbacks 提供了 callback 相关的最基本的功能，而 ActionController::Base,  ActiveRecord::Base 等都是在建立在 ActiveSupport::Callbacks 之上。&lt;/p&gt;
&lt;h2 id="ActiveSupport::Callbacks中的3个核心函数"&gt;ActiveSupport::Callbacks 中的 3 个核心函数&lt;/h2&gt;
&lt;p&gt;define_callbacks, 定义事件点。set_callback，为事件点安装 callback。run_callbacks，运行某个事件点上安装的 callback。&lt;/p&gt;
&lt;h3 id="1. define_callbacks"&gt;1. define_callbacks&lt;/h3&gt;
&lt;p&gt;define_callbacks，在 object 的生命周期中定义事件点，而且这些事件点，并不是必须是 update, save 这些，可以自己定义，比如电商系统中，我们可以增加事件点 update_order，去在 update_order 这个事件的 before, around, after 这些点上注册 callback，如用来发送短信，您的订单以及发货啦，售后审核通过啦。&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;Record&lt;/span&gt;
    &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Callbacks&lt;/span&gt;
    &lt;span class="n"&gt;define_callbacks&lt;/span&gt; &lt;span class="ss"&gt;:update_order&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;update_order&lt;/span&gt;
        &lt;span class="n"&gt;run_callbacks&lt;/span&gt; &lt;span class="ss"&gt;:update_order&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
            &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"- update_order"&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;而对于 ActiveModel::Base 来说，create, update, destroy 等等这些事件点已经事先定义好，而且该事件的对应函数也写好了。&lt;/p&gt;

&lt;p&gt;define_callbacks 源码&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;define_callbacks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;names&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;extract_options!&lt;/span&gt;

  &lt;span class="n"&gt;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="nb"&gt;name&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;class_attribute&lt;/span&gt; &lt;span class="s2"&gt;"_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_callbacks"&lt;/span&gt;
    &lt;span class="n"&gt;set_callbacks&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CallbackChain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nb"&gt;module_eval&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;-&lt;/span&gt;&lt;span class="no"&gt;RUBY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__FILE__&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;__LINE__&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="sh"&gt;
      def _run_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;_callbacks(&amp;amp;block)
        __run_callbacks__(_&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sh"&gt;_callbacks, &amp;amp;block)
      end
&lt;/span&gt;&lt;span class="no"&gt;    RUBY&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;可以看到如果有 define_callbacks :initialize, :save, :destroy，则其实际上，会新生成_run_initialize_callbacks, _run_save_callbacks, _run_destroy_callbacks 这 3 个函数，用来在 run_callbacks 中被调用。同时为 initialize, save, destroy 生成了 3 个 callback chain，用来存储单个 event 的所有 callback。比如在某个 controller 中，before_action 是可以多次被定义的，也就是对于 before_action，有多个 callback。&lt;/p&gt;
&lt;h2 id="2. set_callback"&gt;2. set_callback&lt;/h2&gt;
&lt;p&gt;可以看到，根据传递进来的参数，首先构造出了一个名为 mapped 的 callback 数组，然后根据 prepend 属性，来判断这个 callback 数组，是插入在原有的 CallbackChain 的尾部，还是头部。&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;set_callback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;filter_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;normalize_callback_params&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filter_list&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;self_chain&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;get_callbacks&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;
        &lt;span class="n"&gt;mapped&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&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;filter&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="no"&gt;Callback&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;self_chain&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;end&lt;/span&gt;

        &lt;span class="n"&gt;__update_callbacks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)&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;target&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
          &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="ss"&gt;:prepend&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prepend&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;chain&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;mapped&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
          &lt;span class="n"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;set_callbacks&lt;/span&gt; &lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;chain&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;h2 id="3. run_callbacks"&gt;3. run_callbacks&lt;/h2&gt;
&lt;p&gt;run_callbacks，最终会调用&lt;strong&gt;run_callbacks&lt;/strong&gt;，通过 callbacks.compile, 会去生成 CallbackSequence，并且调用它的 call 函数&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;__run_callbacks__&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;empty?&lt;/span&gt;
    &lt;span class="k"&gt;yield&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;block_given?&lt;/span&gt;
  &lt;span class="k"&gt;else&lt;/span&gt;
    &lt;span class="n"&gt;runner&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;callbacks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;compile&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Filters&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;runner&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;value&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;而 CallbackSequence#call&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;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@before.each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@call.call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="vi"&gt;@after.each&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;call&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;arg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;value&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到首先是去执行&lt;code&gt;@before&lt;/code&gt;这个数组中的各个 callback, 接着执行传递进来的代码块，然后去执行&lt;code&gt;@after&lt;/code&gt;这个数组中的各个 callback。&lt;/p&gt;
&lt;h2 id="后续"&gt;后续&lt;/h2&gt;
&lt;p&gt;callback 的 filter，以及顺序，以及 activemodel 等是怎样使用 ActiveSupport::Autoload 的&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Wed, 12 Aug 2015 13:32:51 +0800</pubDate>
      <link>https://ruby-china.org/topics/26889</link>
      <guid>https://ruby-china.org/topics/26889</guid>
    </item>
    <item>
      <title>Rails 源码分析之 eager_load! 篇</title>
      <description>&lt;h2 id="eager_load!"&gt;eager_load!&lt;/h2&gt;
&lt;p&gt;在 rails server 执行时，有的文件会被提前加载进来，所以这些文件中的 class 就已经被定义了，而有的 class，实际上，是在第一次被使用的时候，才会去根据 class 名，在目录中，去定位到文件，然后读取加载进来。&lt;/p&gt;

&lt;p&gt;造成上述差别的，就是 eager_load!, 如果 rails 初始化时，通过 eager_load! 加载的文件过多，显然初始化时间也越长，但是也会运行的更快，因为省去了根据 class 名，去读取文件的过程。&lt;/p&gt;
&lt;h2 id="application, engines, namespace的eager_load!"&gt;application, engines, namespace 的 eager_load!&lt;/h2&gt;
&lt;p&gt;在 rails 中，application, 各 engine, 或者是 namespace，如果需要在初始化时，就去加载和自己相关的文件，也就是执行 eager_load!, 需要将自己的 namespace 注册到 eager_load_namespaces 中，且必须 config.eager_load 是 true。application 在初始化时，会去运行各种 Railtie#initializer，在 railties/lib/application/finisher.rb 中，&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;initializer&lt;/span&gt; &lt;span class="ss"&gt;:eager_load!&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load&lt;/span&gt;
    &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;run_load_hooks&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:before_eager_load&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&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;:eager_load!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;

&lt;p&gt;那么怎么去修改 config.eager_load_namespaces 呢？请看&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;chuck&lt;/span&gt;&lt;span class="vi"&gt;@chuck&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;MacBook&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Pro&lt;/span&gt;&lt;span class="ss"&gt;:~&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;seaify&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&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="err"&gt;✚&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;grep&lt;/span&gt; &lt;span class="n"&gt;eager_load_namespace&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;ri&lt;/span&gt;                                                                                                                                                                
&lt;span class="n"&gt;actionmailer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;action_mailer&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;
&lt;span class="n"&gt;actionpack&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;action_controller&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;
&lt;span class="n"&gt;actionpack&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;action_dispatch&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionDispatch&lt;/span&gt;
&lt;span class="n"&gt;actionview&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;action_view&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActionView&lt;/span&gt;
&lt;span class="n"&gt;activemodel&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_model&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;
&lt;span class="n"&gt;activerecord&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_record&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;
&lt;span class="n"&gt;activesupport&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;active_support&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;    &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;
&lt;span class="n"&gt;guides&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load`&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;eager&lt;/span&gt; &lt;span class="n"&gt;loads&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load_namespaces`&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;This&lt;/span&gt; &lt;span class="n"&gt;includes&lt;/span&gt; &lt;span class="n"&gt;your&lt;/span&gt; &lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;engines&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt; &lt;span class="n"&gt;frameworks&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt; &lt;span class="n"&gt;other&lt;/span&gt; &lt;span class="n"&gt;registered&lt;/span&gt; &lt;span class="n"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;guides&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load_namespaces`&lt;/span&gt; &lt;span class="n"&gt;registers&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;eager&lt;/span&gt; &lt;span class="n"&gt;loaded&lt;/span&gt; &lt;span class="k"&gt;when&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load`&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;All&lt;/span&gt; &lt;span class="n"&gt;namespaces&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;list&lt;/span&gt; &lt;span class="n"&gt;must&lt;/span&gt; &lt;span class="n"&gt;respond&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sb"&gt;`eager_load!`&lt;/span&gt; &lt;span class="nb"&gt;method&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;guides&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;source&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuring&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;md&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="sb"&gt;`eager_load!`&lt;/span&gt; &lt;span class="no"&gt;If&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load`&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;runs&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="sb"&gt;`config.before_eager_load`&lt;/span&gt; &lt;span class="n"&gt;hooks&lt;/span&gt; &lt;span class="ow"&gt;and&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;calls&lt;/span&gt; &lt;span class="sb"&gt;`eager_load!`&lt;/span&gt; &lt;span class="n"&gt;which&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="sb"&gt;`config.eager_load_namespaces`&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="nf"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;finisher&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;each&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;:eager_load!&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;engine&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;          &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Railtie&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="c1"&gt;# Expose the eager_load_namespaces at "module" level for convenience.&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&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;eager_load_namespaces&lt;/span&gt; &lt;span class="c1"&gt;#:nodoc:&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="vc"&gt;@@eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;railtie&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;        &lt;span class="vc"&gt;@@eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;span class="n"&gt;railties&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;configuration_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;      &lt;span class="n"&gt;assert_includes&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;AppTemplate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以注意到 ActiveSupport, ActionDispatch, ActiveModel, ActionController 等这些 module, 都已经将自己的 namespace 追加到了 config.eager_load_namespaces, 而且我们能注意到 eager_load_namespaces 实际上返回的是一个类变量@@eager_load_namespaces，所以实际上只有一份，各个 module，gem 修改的是同一个变量。&lt;/p&gt;

&lt;p&gt;以我的实际项目 homepage 为例，可以看到 rails 下常用的几个 module 的 namespace 都有注册到 eager_load_namespace, 而那些第三方的 engine，也都有注册&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mf"&gt;2.1&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="mo"&gt;001&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Homepage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActionDispatch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActiveModel&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActionView&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActionController&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ActionMailer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Coffee&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Jquery&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Turbolinks&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Haml&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Bootstrap&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;RailsSettingsUi&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SimpleForm&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;MdEmoji&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Devise&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SocialShareButton&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Owlcarousel&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Sidekiq&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;DisqusRails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Ahoy&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Kaminari&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Wice&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;WiceGridEngine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BootstrapDatepickerRails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Jquery&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Ui&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Highcharts&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;LazyHighCharts&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;FontAwesome&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Spree&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Spree&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Api&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Select2&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Spree&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Backend&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;CanonicalRails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Spree&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Frontend&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SpreeSample&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SpreeGateway&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;KaminariI18n&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;SpreeI18n&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;QuietAssets&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;Homepage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;ExceptionNotification&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Engine&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;第三方的 engine 注册，是通过 railties/lib/engine.rb, 每个 engine 都有将自己的 namespace 写入，注意 Rails::Railtie Rails::Engine Rails::Application, 是定义好的 abstract_railtie，不会写入&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;inherited&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="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;abstract_railtie?&lt;/span&gt;
    &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Railtie&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Configuration&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;综上解释了，eager_load_namespaces 的修改及由来，但每个 namespace 下，还需要有 method，eager_load!&lt;/p&gt;
&lt;h2 id="各namespace下的eager_load!"&gt;各 namespace 下的 eager_load!&lt;/h2&gt;
&lt;p&gt;eager_load!, 实际上分了 2 派，一种是通过 activesupport/lib/active_support/dependencies/autoload.rb 提供的 eager_load!,  也就是去 extend ActiveSupport::Autoload,  如对于 ActionMailer, ActionDispatch 等&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;ActionDispatch&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;ActiveSupport&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Autoload&lt;/span&gt;

  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;IllegalStateError&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;StandardError&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;

  &lt;span class="n"&gt;eager_autoload&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;autoload_under&lt;/span&gt; &lt;span class="s1"&gt;'http'&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
      &lt;span class="nb"&gt;autoload&lt;/span&gt; &lt;span class="ss"&gt;:Request&lt;/span&gt;
      &lt;span class="nb"&gt;autoload&lt;/span&gt; &lt;span class="ss"&gt;:Response&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;而 activesupport/lib/active_support/dependencies/autoload.rb 的实现方法&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;eager_load!&lt;/span&gt;
  &lt;span class="vi"&gt;@_autoloads.each_value&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而&lt;code&gt;@_autoloads&lt;/code&gt;的由来，是因为在 eager_autoload 的代码块中，&lt;code&gt;@_eager_autoload&lt;/code&gt;已经被暂时置为 true, 所以其中的 autoload 函数，能够为&lt;code&gt;@_autoloads&lt;/code&gt;写入路径的映射关系&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;autoload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;const_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="vi"&gt;@_at_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;unless&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
    &lt;span class="n"&gt;full&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="vi"&gt;@_under_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;const_name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;compact&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="s2"&gt;"::"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Inflector&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;underscore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;full&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;if&lt;/span&gt; &lt;span class="vi"&gt;@_eager_autoload&lt;/span&gt;
    &lt;span class="vi"&gt;@_autoloads&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;const_name&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="n"&gt;const_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;path&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;上述这种办法，是针对于非 engine 的其它 namespace.&lt;/p&gt;

&lt;p&gt;下面介绍基于 engine 的 eager_load! 的实现&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="mf"&gt;2.1&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="mo"&gt;005&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Homepage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Homepage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;
&lt;span class="mf"&gt;2.1&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="mo"&gt;006&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="no"&gt;Homepage&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_namespaces&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:eager_load!&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;source_location&lt;/span&gt;
 &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"/Users/chuck/.rvm/gems/ruby-2.1.5/gems/railties-4.2.2/lib/rails/engine.rb"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;346&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Eager load the application by loading all ruby&lt;/span&gt;
&lt;span class="c1"&gt;# files inside eager_load paths.&lt;/span&gt;
&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;eager_load!&lt;/span&gt;
  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load_paths&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;load_path&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;matcher&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sr"&gt;/\A&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Regexp&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;escape&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;load_path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;to_s&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="sr"&gt;\/(.*)\.rb\Z/&lt;/span&gt;
    &lt;span class="no"&gt;Dir&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;glob&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;load_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/**/*.rb"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;sort&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;file&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
      &lt;span class="n"&gt;require_dependency&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sub&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;matcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s1"&gt;'\1'&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;所以注意到，在 engine 中，是需要去设置变量 eager_load_paths,  而 railties/lib/rails/engine/configuration.rb 中&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;eager_load_paths&lt;/span&gt;
  &lt;span class="vi"&gt;@eager_load_paths&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;eager_load&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而 paths.eager_load, 是已经被设置好的，也就是 app/assets, app/helpers, app/xxx/concerns,  也就是每个 engine 的下列 eager_load 是 true 的路径都会被加载，&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;paths&lt;/span&gt;
  &lt;span class="vi"&gt;@paths&lt;/span&gt; &lt;span class="o"&gt;||=&lt;/span&gt; &lt;span class="k"&gt;begin&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Paths&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Root&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@root&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"{*,*/concerns}"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/assets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/controllers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;     &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/helpers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/models"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/mailers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;         &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"app/views"&lt;/span&gt;

    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"lib"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;                 &lt;span class="ss"&gt;load_path: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"lib/assets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;          &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"lib/tasks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;           &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"**/*.rake"&lt;/span&gt;

    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"config"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"config/environments"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="no"&gt;Rails&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;env&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.rb"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"config/initializers"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"**/*.rb"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"config/locales"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;      &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"*.{rb,yml}"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"config/routes.rb"&lt;/span&gt;

    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"db"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"db/migrate"&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"db/seeds.rb"&lt;/span&gt;

    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"vendor"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;              &lt;span class="ss"&gt;load_path: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
    &lt;span class="n"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"vendor/assets"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;       &lt;span class="ss"&gt;glob: &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;

    &lt;span class="n"&gt;paths&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;从这些内部代码中，也可得出，若想将我们的代码，也在启动时，自动启动，则在 config/application.rb 中加入&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;paths&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;add&lt;/span&gt; &lt;span class="s2"&gt;"extras"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;eager_load: &lt;/span&gt;&lt;span class="kp"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>seaify</author>
      <pubDate>Mon, 10 Aug 2015 22:16:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/26866</link>
      <guid>https://ruby-china.org/topics/26866</guid>
    </item>
    <item>
      <title>[已解决] 访客统计数据展示问题</title>
      <description>&lt;p&gt;在使用&lt;a href="https://github.com/ankane/ahoyrefer" rel="nofollow" target="_blank"&gt;https://github.com/ankane/ahoyrefer&lt;/a&gt;后，拿到了访客记录，如，ip, 以及这个 ip 所属的国家，城市等信息。&lt;/p&gt;

&lt;p&gt;需要实现这样的效果，如可配置某些字段，如 ip, 国家，分别对其中的每个字段做一次 group,  按次数由大到小排序，每个字段生成一个 chart。在一个页面中，会有多个 chart，每个&lt;/p&gt;

&lt;p&gt;字段生成了一个统计图。&lt;/p&gt;

&lt;p&gt;有现成支持这样功能的 gem 吗，免得重复造轮子，那个 dashing 看样子也不适合。&lt;/p&gt;

&lt;p&gt;之所以没用 google analytic , 用了美国的代理，还是访问超慢，不能接受啊。&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Sat, 01 Aug 2015 13:24:50 +0800</pubDate>
      <link>https://ruby-china.org/topics/26729</link>
      <guid>https://ruby-china.org/topics/26729</guid>
    </item>
    <item>
      <title>[已解决] wice_grid 使用问题</title>
      <description>&lt;p&gt;在使用 wice_grid 中碰到这样的问题，多输出了很多信息，应该是多输出了一个 object, 但我的代码里并没有这样写，找不到是哪儿生成了那个 object 的输出，只有是在使用 wice_grid 才出现，
,
&lt;img src="https://l.ruby-china.com/photo/2015/a5f6b5d5ebd8d32025049399f26c3cb2.png" title="" alt=""&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;show&lt;/span&gt;
  &lt;span class="vi"&gt;@visits_grid&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;initialize_grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Visit&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="ss"&gt;per_page: &lt;/span&gt;&lt;span class="mi"&gt;40&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;grid&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@visits_grid&lt;/span&gt;&lt;span class="p"&gt;)&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;g&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
  &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;column&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;task&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;
    &lt;span class="n"&gt;task&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;title&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;另外是否有这样的 gem，能清晰的定位到页面中的某一个元素是由哪一个模板文件产生的？&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Fri, 31 Jul 2015 18:03:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/26726</link>
      <guid>https://ruby-china.org/topics/26726</guid>
    </item>
    <item>
      <title>求 Ruby 远程兼职项目</title>
      <description>&lt;p&gt;已删除&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Thu, 30 Jul 2015 18:00:43 +0800</pubDate>
      <link>https://ruby-china.org/topics/26708</link>
      <guid>https://ruby-china.org/topics/26708</guid>
    </item>
    <item>
      <title>rspec 实战篇</title>
      <description>&lt;h2 id="本篇介绍rspec的使用"&gt;本篇介绍 rspec 的使用&lt;/h2&gt;
&lt;p&gt;在未接触 rspec 之前，大量使用过 c, python, nodejs, php，但测试方面基本都是空白。现在想来，很多时候不是开发者不想写测试，而是并没有好的测试工具，不够灵活。写测试的难度很多时候都快等于开发了，甚至高过开发。&lt;/p&gt;
&lt;h2 id="tdd好处"&gt;tdd 好处&lt;/h2&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;/ol&gt;
&lt;h2 id="rspec篇"&gt;rspec 篇&lt;/h2&gt;&lt;h3 id="rspec时间相关测试篇"&gt;rspec 时间相关测试篇&lt;/h3&gt;
&lt;p&gt;不少情况下，代码的运行逻辑和时间相关，如到了提前设定的时间范围内，执行 xxx 函数。这种情况下的测试，一般会将时间判断，单独抽离出来成为一个函数，对它进行测试，这时候，我们就需要 faker 时间了，不可能真等到设定的时间范围内。
使用&lt;a href="https://github.com/travisjeffery/timecop" rel="nofollow" target="_blank" title=""&gt;timecop&lt;/a&gt;来 faker 时间，如下面例子，将当前的时间 Tim.now, 设定到 end_time 前 5s，以保证在时间范围内。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt; &lt;span class="s2"&gt;"pass test now_is_in_order_flow_on_peroid?"&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="no"&gt;Timecop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;freeze&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vi"&gt;@end_time&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="k"&gt;do&lt;/span&gt;
    &lt;span class="n"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;Spree&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Order&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;now_is_in_order_flow_on_peroid?&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;to&lt;/span&gt; &lt;span class="n"&gt;eq&lt;/span&gt; &lt;span class="kp"&gt;true&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="rspec 定时任务测试篇，如whenever"&gt;rspec 定时任务测试篇，如 whenever&lt;/h3&gt;
&lt;p&gt;代码中很可能使用 whenever 这样的 gem, 执行些定时任务，怎么测试呢？
whenever 类似的 gem, 达到的效果是帮你生成相应的 crontab 任务，它做的事情其实是和我们的代码逻辑无关的。
我的理解是，如果是定时每隔 5 分钟，要执行下 model.xxx 函数，那实际上我们直接在 rspec 中调用 model.xxx 函数对其进行测试即可。
而如果要测试 whenever 的 crontab 语句生成是否正确，请参考&lt;a href="https://github.com/javan/whenever/blob/master/test/unit/cron_test.rb" rel="nofollow" target="_blank"&gt;https://github.com/javan/whenever/blob/master/test/unit/cron_test.rb&lt;/a&gt; , 大部分情况下，是没有必要对其进行测试的，如果是简单的每隔 xx 分钟/小时。&lt;/p&gt;
&lt;h3 id="rspec helper篇"&gt;rspec helper 篇&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;在 web 的测试中，基本都会去检验是否登录，以及部分代码是登录后才能去执行，那在 model, controller 中，会有大量的测试，需要进行提前登录，这时候就需要使用 helper，在 support 中建立 login_helpers.rb，加入 login_user, login_admin, login_staff 这些函数，在需要做登录的测试中，引入 login_user 即可。&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;login_user&lt;/span&gt;
&lt;span class="n"&gt;before&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:each&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;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:login_as&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;因 rspec 测试并不会去读取 db/seeds 中的数据，但 model，controller 中的许多逻辑测试，可能依赖于某部分数据的提前建立，这时候可以在 support 中建立 data_helpers.rb, 加入 set_init_data 类似的函数，供所有测试去公用这段初始化数据的代码&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="rspec 数据伪造篇"&gt;rspec 数据伪造篇&lt;/h3&gt;
&lt;p&gt;许多情况下，需要伪造 email, name 这些类似的信息，可以使用 faker，随机出字符串和名字等等信息&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;FactoryGirl&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;define&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt;
  &lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:random_string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Lorem&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sentence&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:random_name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="no"&gt;Faker&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;而如果要求是 uniq, 因为要确保 uniq, 变量的一部分就需要每次都不一样，这可以是 timestamp, 也可以是 n(0,1,2..)，每次都不一样&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;sequence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:sku&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="s2"&gt;"SKU-&lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="时间比较匆忙，后面待续"&gt;时间比较匆忙，后面待续&lt;/h3&gt;</description>
      <author>seaify</author>
      <pubDate>Sat, 11 Jul 2015 09:47:19 +0800</pubDate>
      <link>https://ruby-china.org/topics/26442</link>
      <guid>https://ruby-china.org/topics/26442</guid>
    </item>
    <item>
      <title>rails 开发中必备的 gem 推荐</title>
      <description>&lt;h2 id="推荐一些工作中用到过的好用的gem"&gt;推荐一些工作中用到过的好用的 gem&lt;/h2&gt;&lt;h3 id="hirb"&gt;&lt;a href="https://github.com/cldwalker/hirb" rel="nofollow" target="_blank" title=""&gt;hirb&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将 rails console 下 model 的输出变得更标准好看，类似于 mysql，看下图感受下带来的变化
&lt;img src="https://l.ruby-china.com/photo/2015/6fbee69f45ad2d17672e6847018eae35.png" title="" alt=""&gt;
当然，不想每次进 rails console, 都敲遍 Hirb.enable，那在~/.irbrc 中加入&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'rubygems'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'hirb'&lt;/span&gt;
&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'active_record'&lt;/span&gt;
&lt;span class="no"&gt;Hirb&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;enable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="rails_panel"&gt;&lt;a href="https://github.com/dejan/rails_panel" rel="nofollow" target="_blank" title=""&gt;rails_panel&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;chrome 下的插件，能方便的看 status，controller#action, params, log, activerecord 查询语句，不用去看终端日志，因为日志一股脑的全输出，很难看清晰的。react 在 chrome 下也有类似的插件。
&lt;img src="https://l.ruby-china.com/photo/2015/8a530c20b2f42b530f0698a18f412a9c.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="better_errors"&gt;&lt;a href="https://github.com/charliesome/better_errors" rel="nofollow" target="_blank" title=""&gt;better_errors&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;替换掉 rails 默认的出错页面，支持在错误页面里直接输入变量值进行查看，注意图片左侧除输入了&lt;a href="/company" class="user-mention" title="@company"&gt;&lt;i&gt;@&lt;/i&gt;company&lt;/a&gt;，有显示值
&lt;img src="https://l.ruby-china.com/photo/2015/cd3491cd8c2a0c00203ec83bb045bd7f.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="exception_notification"&gt;&lt;a href="https://github.com/smartinez87/exception_notification" rel="nofollow" target="_blank" title=""&gt;exception_notification&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;搭配&lt;a href="https://github.com/stevenosloan/slack-notifier" rel="nofollow" target="_blank" title=""&gt;slack-notifier&lt;/a&gt;使用，exception 发生时，将错误信息发生到 slack 上的某个 channel，&lt;a href="https://ruby-china.org/flowerwrong" title=""&gt;flowerwrong&lt;/a&gt;推荐
&lt;img src="https://l.ruby-china.com/photo/2015/d7204bcd398f19ce88a7aecf2e4bec18.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="simplecov"&gt;&lt;a href="https://github.com/colszowka/simplecov" rel="nofollow" target="_blank" title=""&gt;simplecov&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;配置好后，每次 rspec 运行完测试，会在本地生成覆盖率测试的页面，&lt;a href="https://ruby-china.org/flowerwrong" title=""&gt;flowerwrong&lt;/a&gt;推荐
&lt;img src="https://l.ruby-china.com/photo/2015/1c1b4ea34917db1f29367735c127612a.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="awesome_print"&gt;&lt;a href="https://github.com/michaeldv/awesome_print" rel="nofollow" target="_blank" title=""&gt;awesome_print&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;将 object 输出的更好看， &lt;a href="https://ruby-china.org/qhwa" title=""&gt;qhwa&lt;/a&gt;推荐
&lt;img src="https://l.ruby-china.com/photo/2015/91d8410a7d5a51975f9a94d716027b0c.png" title="" alt=""&gt;&lt;/p&gt;
&lt;h3 id="i18n-js"&gt;&lt;a href="https://github.com/fnando/i18n-js" rel="nofollow" target="_blank" title=""&gt;i18n-js&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;应用场景，前端需要对表单进行验证，验证失败后的信息，是要使用 i18n 的，但其在 rails 里。在没使用 i18n-js 前，传递值是这样的，controller 里将需要传递的 i18n 值，传到页面，写入到某个节点的属性值里，然后在 js 里读取该属性值。想想都知道，这 TM 多蛋疼。
i18n-js 配置正确后，是这样的，直接可以在 js 里，使用 I18n.t，和 rails 的使用完全一致。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'#form-submit-tips'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;text&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;I18n&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"validate.error.real_name"&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;removeClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bg-success'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addClass&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'bg-warning'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;它的原理，实质上，是读取了 config/locales/*.yml，生成了一个 translation.js，也就是 translation.js 是 rails i18n 的一份 js 版，然后再暴露接口 I18n.t 去读取 translation.js 中的数据&lt;/p&gt;
&lt;h3 id="gon"&gt;&lt;a href="https://github.com/gazay/gon" rel="nofollow" target="_blank" title=""&gt;gon&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;更方便的将 rails 的变量传递到 js 里，和 i18n-js 的效果有些类似。
应用创建，页面需要前端验证，验证的规则，需要从后台传递过来
配置正确后，在 rails controller,&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile_regex_format&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Setting&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mobile_regex_format&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 js 里&lt;/p&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;real_name_regex&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;RegExp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gon&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;real_name_regex_format&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h3 id="guard系列"&gt;guard 系列&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/guard/guard-bundler" rel="nofollow" target="_blank" title=""&gt;guard-bundler&lt;/a&gt;, gemfile 变更后，自动执行 bundle&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/glanotte/guard-migrate" rel="nofollow" target="_blank" title=""&gt;guard-migrate&lt;/a&gt;, 新产生 migration 文件，变更后，自动执行 rake db:migrate&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/cpjolicoeur/guard-annotate" rel="nofollow" target="_blank" title=""&gt;guard-annotate&lt;/a&gt;, db schema 文件变更后，自动 annotate, 与 guard-migrate 搭配非常好&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/guard/guard-shell" rel="nofollow" target="_blank" title=""&gt;guard-shell&lt;/a&gt;, 文件变更后，执行相应 shell 命令，场景：使用 i18n-js 时，config/locale/*.yml 变更了的话，需要更新 translation.js 文件，要执行相应的 rake i18n:js:export&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="参考链接"&gt;参考链接&lt;/h3&gt;
&lt;p&gt;&lt;a href="http://blog.eddie.com.tw/2010/04/09/hirb-the-convenient-gem-for-console-and-irb/" rel="nofollow" target="_blank" title=""&gt;Rails Console  irb 裡的方便工具-Hirb&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;ps: 求助啊。链接在 h3 里为啥显示有问题啊，在 github 里是正常的。&lt;/p&gt;</description>
      <author>seaify</author>
      <pubDate>Thu, 09 Jul 2015 10:16:41 +0800</pubDate>
      <link>https://ruby-china.org/topics/26402</link>
      <guid>https://ruby-china.org/topics/26402</guid>
    </item>
    <item>
      <title>weapon，为已有项目，配置 mina 部署，i18n 定制，rails_settings_ui</title>
      <description>&lt;h2 id="简介"&gt;简介&lt;/h2&gt;
&lt;p&gt;原帖是写了一个&lt;a href="https://github.com/seaify/weapon/blob/master/readme.bak.md" rel="nofollow" target="_blank" title=""&gt;rails application template&lt;/a&gt;，但后来发现，rails new myapp -m xx.rb 这种形式，并不方便使用，以及不方便已有项目使用，于是将其改造成了&lt;a href="https://github.com/seaify/weapon" rel="nofollow" target="_blank" title=""&gt;weapon&lt;/a&gt;，一个 gem 包，可以自由去选择为已有项目添加什么样的功能。&lt;/p&gt;
&lt;h2 id="安装和使用"&gt;安装和使用&lt;/h2&gt;
&lt;p&gt;安装方法：gem install 或者添加到 gemfile&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="n"&gt;install&lt;/span&gt; &lt;span class="n"&gt;weapon&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;chuck&lt;/span&gt;&lt;span class="vi"&gt;@chuck&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;MacBook&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;Pro&lt;/span&gt;&lt;span class="ss"&gt;:~&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;seaify&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;weapon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;✔&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;weapon&lt;/span&gt;                                                                                        
&lt;span class="no"&gt;Commands&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;create_gem&lt;/span&gt;          &lt;span class="c1"&gt;# create basic gem information&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;custom_i18n&lt;/span&gt;         &lt;span class="c1"&gt;# custom i18n and use slim as template engine, use simple_form, currently write to zh-CN.yml&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;for_seaify&lt;/span&gt;          &lt;span class="c1"&gt;# only for seaify personal use, combine of other commands act as rails application template&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;help&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;COMMAND&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;      &lt;span class="c1"&gt;# Describe available commands or one specific command&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;install_must_gems&lt;/span&gt;   &lt;span class="c1"&gt;# install must need gems like guard, guard-livereload, guard-rspec...&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;push_to_github&lt;/span&gt;      &lt;span class="c1"&gt;# push to github&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;setup_mina_unicorn&lt;/span&gt;  &lt;span class="c1"&gt;# setup mina deploy and unicorn server&lt;/span&gt;
  &lt;span class="n"&gt;weapon&lt;/span&gt; &lt;span class="n"&gt;setup_settings_ui&lt;/span&gt;   &lt;span class="c1"&gt;# setup settings ui&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="weapon setup_mina_unicorn"&gt;weapon setup_mina_unicorn&lt;/h2&gt;
&lt;p&gt;根据提示输入用户名，主机，路径等信息后，会生成 unicorn 需要使用到的 nginx 文件，并且上传到服务器的/etc/nginx/sites-enable 目录中
执行完，mina ssh, mina deploy, mina console，mina logs, mina unicorn_logs, mina unicorn:restart 这些就都能正常工作了&lt;/p&gt;
&lt;h2 id="weapon create_gem"&gt;weapon create_gem&lt;/h2&gt;
&lt;p&gt;执行 weapon create_gem xxyy,  将会在本地生成一个目录 xxyy,  其中包含 gem 的基本信息，并且会推送到 github 上，而且会自动发布到 rubygems 上。目前 magicfile 这个 gem 的 0.0.1，就是这样生成的。&lt;/p&gt;
&lt;h2 id="weapon install_must_gems"&gt;weapon install_must_gems&lt;/h2&gt;
&lt;p&gt;执行上述命令后，会将我认为必须的一些列 gem 安装到当前的 rails 环境中。&lt;/p&gt;
&lt;h2 id="weapon custom_i18n"&gt;weapon custom_i18n&lt;/h2&gt;
&lt;p&gt;执行 weapon custom_i18n 后，会有个错误，需要再手动执行下 rails g simple_form:install --bootstrap，这个神奇的问题，顺便在此寻求各位大神帮助！！！&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;Use&lt;/span&gt; &lt;span class="sb"&gt;`bundle show [gemname]`&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;see&lt;/span&gt; &lt;span class="n"&gt;where&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;bundled&lt;/span&gt; &lt;span class="n"&gt;gem&lt;/span&gt; &lt;span class="n"&gt;is&lt;/span&gt; &lt;span class="n"&gt;installed&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
         &lt;span class="nf"&gt;run&lt;/span&gt;  &lt;span class="n"&gt;rm&lt;/span&gt; &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stylesheets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;css&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt;
         &lt;span class="n"&gt;run&lt;/span&gt;  &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;simple_form&lt;/span&gt;&lt;span class="ss"&gt;:install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bootstrap&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt;
&lt;span class="no"&gt;Could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="s1"&gt;'simple_form:install'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;meant&lt;/span&gt; &lt;span class="s1"&gt;'integration_test'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'active_record:model'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'resource_route'&lt;/span&gt;
&lt;span class="no"&gt;Run&lt;/span&gt; &lt;span class="sb"&gt;`rails generate --help`&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
      &lt;span class="nf"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffold&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffold&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffold&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffold&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;slim&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffold&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;templates&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;i18n_scaffold_controller&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;  &lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;generators&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;rails&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;i18n_scaffold_controller&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;i18n_scaffold_controller_generator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;insert&lt;/span&gt;  &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;application&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
         &lt;span class="n"&gt;run&lt;/span&gt;  &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;simple_form&lt;/span&gt;&lt;span class="ss"&gt;:install&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="n"&gt;bootstrap&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt; &lt;span class="s2"&gt;"."&lt;/span&gt;
&lt;span class="no"&gt;Could&lt;/span&gt; &lt;span class="ow"&gt;not&lt;/span&gt; &lt;span class="n"&gt;find&lt;/span&gt; &lt;span class="n"&gt;generator&lt;/span&gt; &lt;span class="s1"&gt;'simple_form:install'&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; &lt;span class="no"&gt;Maybe&lt;/span&gt; &lt;span class="n"&gt;you&lt;/span&gt; &lt;span class="n"&gt;meant&lt;/span&gt; &lt;span class="s1"&gt;'integration_test'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'active_record:model'&lt;/span&gt; &lt;span class="ow"&gt;or&lt;/span&gt; &lt;span class="s1"&gt;'resource_route'&lt;/span&gt;
&lt;span class="no"&gt;Run&lt;/span&gt; &lt;span class="sb"&gt;`rails generate --help`&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;more&lt;/span&gt; &lt;span class="n"&gt;options&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;安装后，执行 rails g scaffold post title:string, 会自动的向 config/locales/zh-CN.yml 中写入，会把 model 中的 attribute，自动写入，按 activerecord:attribute:model:field 这种格式&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;chuck&lt;/span&gt;&lt;span class="vi"&gt;@website&lt;/span&gt;&lt;span class="ss"&gt;:~&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;rails&lt;/span&gt; &lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="n"&gt;scaffold&lt;/span&gt; &lt;span class="n"&gt;post&lt;/span&gt; &lt;span class="n"&gt;title&lt;/span&gt;&lt;span class="ss"&gt;:string&lt;/span&gt;                                                                                 
      &lt;span class="n"&gt;invoke&lt;/span&gt;  &lt;span class="n"&gt;active_record&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;    &lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="mi"&gt;20150717051311&lt;/span&gt;&lt;span class="n"&gt;_create_posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;test_unit&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;models&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;post_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;fixtures&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yml&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;  &lt;span class="n"&gt;resource_route&lt;/span&gt;
       &lt;span class="n"&gt;route&lt;/span&gt;    &lt;span class="n"&gt;resources&lt;/span&gt; &lt;span class="ss"&gt;:posts&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;  &lt;span class="n"&gt;i18n_scaffold_controller&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts_controller&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;edit&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;show&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;views&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;_form&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;html&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;slim&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;test_unit&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="nb"&gt;test&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;controllers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts_controller_test&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;helper&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;helpers&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts_helper&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rb&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;      &lt;span class="n"&gt;test_unit&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;  &lt;span class="n"&gt;assets&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;coffee&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;javascripts&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;coffee&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;    &lt;span class="n"&gt;scss&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;      &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stylesheets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;posts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scss&lt;/span&gt;
      &lt;span class="n"&gt;invoke&lt;/span&gt;  &lt;span class="n"&gt;scss&lt;/span&gt;
      &lt;span class="n"&gt;create&lt;/span&gt;    &lt;span class="n"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;assets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;stylesheets&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;scaffolds&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;scss&lt;/span&gt;
&lt;span class="n"&gt;chuck&lt;/span&gt;&lt;span class="vi"&gt;@website&lt;/span&gt;&lt;span class="ss"&gt;:~&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;tmp&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;what&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;master&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;cat&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;locales&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;zh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;CN&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;yml&lt;/span&gt;                                                                                 
&lt;span class="o"&gt;---&lt;/span&gt;
&lt;span class="n"&gt;zh&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="no"&gt;CN&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
  &lt;span class="ss"&gt;action:
    back: &lt;/span&gt;&lt;span class="s2"&gt;"返回"&lt;/span&gt;
    &lt;span class="ss"&gt;new: &lt;/span&gt;&lt;span class="s2"&gt;"创建"&lt;/span&gt;
    &lt;span class="ss"&gt;show: &lt;/span&gt;&lt;span class="s2"&gt;"查看"&lt;/span&gt;
    &lt;span class="ss"&gt;edit: &lt;/span&gt;&lt;span class="s2"&gt;"编辑"&lt;/span&gt;
    &lt;span class="ss"&gt;delete: &lt;/span&gt;&lt;span class="s2"&gt;"删除"&lt;/span&gt;
    &lt;span class="ss"&gt;confirm_delete: &lt;/span&gt;&lt;span class="s2"&gt;"确认删除"&lt;/span&gt;
    &lt;span class="ss"&gt;created:
      successfully: &lt;/span&gt;&lt;span class="s2"&gt;"创建成功"&lt;/span&gt;
    &lt;span class="ss"&gt;updated:
      successfully: &lt;/span&gt;&lt;span class="s2"&gt;"更新成功"&lt;/span&gt;
    &lt;span class="ss"&gt;destroyed:
      successfully: &lt;/span&gt;&lt;span class="s2"&gt;"删除成功"&lt;/span&gt;
  &lt;span class="ss"&gt;activerecord:
    models:
      post: &lt;/span&gt;&lt;span class="n"&gt;post&lt;/span&gt;
    &lt;span class="ss"&gt;attributes:
      post:
        title: &lt;/span&gt;&lt;span class="n"&gt;title&lt;/span&gt;
        &lt;span class="ss"&gt;id: &lt;/span&gt;&lt;span class="no"&gt;ID&lt;/span&gt;
        &lt;span class="ss"&gt;created_at: &lt;/span&gt;&lt;span class="s2"&gt;"创建时间"&lt;/span&gt;
        &lt;span class="ss"&gt;updated_at: &lt;/span&gt;&lt;span class="s2"&gt;"更新时间"&lt;/span&gt;
  &lt;span class="ss"&gt;helpers:
    submit:
      post:
        create: &lt;/span&gt;&lt;span class="s2"&gt;"创建"&lt;/span&gt;
        &lt;span class="ss"&gt;update: &lt;/span&gt;&lt;span class="s2"&gt;"更新"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;同时创建的.html.slim 页面都已经使用了 i18n, 包括 new, edit 这些 action，在 controller 里，返回的 notice 也进行了 i18n.&lt;/p&gt;
&lt;h2 id="其它"&gt;其它&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;weapon setup_settings_ui,  执行完后，访问&lt;a href="http://localhost:3000/settings" rel="nofollow" target="_blank"&gt;http://localhost:3000/settings&lt;/a&gt;，就能去设置更新变量了&lt;/li&gt;
&lt;li&gt;weapon push_to_github,  执行完后，将当下的代码 push 到 github 上去。不用跑到 github 手动创建 repo&lt;/li&gt;
&lt;/ol&gt;</description>
      <author>seaify</author>
      <pubDate>Sat, 04 Jul 2015 23:27:29 +0800</pubDate>
      <link>https://ruby-china.org/topics/26327</link>
      <guid>https://ruby-china.org/topics/26327</guid>
    </item>
  </channel>
</rss>
