<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>fbsender (FBSENDER)</title>
    <link>https://ruby-china.org/fbsender</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Linode 1024 - Ubuntu 15.04 从 0 开始架设 WebServer Rails + Passenger + Nginx</title>
      <description>&lt;p&gt;硬件环境：linode 1024 (10$每月 SSD VPS) 
OS: ubuntu 15.04
目前运行站点：&lt;a href="http://www.ddzhusu.com" rel="nofollow" target="_blank" title=""&gt;滴滴住宿&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;rails 站点做迁移，从 linode 2048 ubuntu 12.04 到当前设备，简单配置使网站运行起来，Rails + Passenger + Nginx，数据库使用 Mysql（读取远程 DB）。&lt;/p&gt;

&lt;p&gt;系统初始化后只有 root 账户，先使用 root 账户登录，配置下基本环境。&lt;/p&gt;
&lt;h2 id="Ruby运行环境"&gt;Ruby 运行环境&lt;/h2&gt;&lt;h2 id="安装ruby"&gt;安装 ruby&lt;/h2&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install ruby  
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;linode ubuntu 源版本为 2.1.2，如需其他版本，需要自行下载 ruby 源码编译安装，使用 rvm 也很方便（生产环境不建议使用 rvm）&lt;/p&gt;
&lt;h2 id="安装gem与必要的依赖"&gt;安装 gem 与必要的依赖&lt;/h2&gt;
&lt;p&gt;试着 gem install 一下即将用到的 gem，安装不成功的时候会提示缺少哪些依赖，按照提示 google 一下都可以解决。
下面是一些必须要的开发包，运行 rails 应用时，还有很多依赖需要安装...&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-get install ruby2.1-dev
apt-get install mysql-client #默认版本5.6
apt-get install mysql-server #默认版本5.6
apt-get install libmagickwand-dev
apt-get install libmysqlclient-dev
apt-get install nodejs
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;linode ubuntu apt 源还是比较新的，前几日弄了个阿里云 ubuntu 14.04 apt-get 源相当陈旧，需自行更新。&lt;/p&gt;
&lt;h2 id="Passenger 与 Nginx"&gt;Passenger 与 Nginx&lt;/h2&gt;&lt;h2 id="安装"&gt;安装&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#install_on_debian_ubuntu" rel="nofollow" target="_blank" title=""&gt;Passenger 官方文档&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;下面的指令依然由 root 账户执行。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 561F9B9CAC40B2F7
apt-get install apt-transport-https ca-certificates
echo 'deb https://oss-binaries.phusionpassenger.com/apt/passenger vivid main' &amp;gt; /etc/apt/sources.list.d/passenger.list
chmod 600 /etc/apt/sources.list.d/passenger.list
apt-get update
apt-get install nginx-extras passenger
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="配置"&gt;配置&lt;/h2&gt;
&lt;p&gt;执行 /usr/bin/passenger-config —-root 获取 passenger_root&lt;br&gt;
然后在 nginx.conf http 节点下增加 passenger_root 刚刚得到的结果         &lt;/p&gt;

&lt;p&gt;http 节点下增加&lt;br&gt;
passenger_ruby /usr/bin/ruby;&lt;br&gt;
passenger_max_pool_size 10;            &lt;/p&gt;

&lt;p&gt;在 nginx.conf 头部添加 env PATH; 否则 nodejs —— js runtime 找不到，没有相关的环境变量。&lt;/p&gt;
&lt;h3 id="简单的nginx配置"&gt;简单的 nginx 配置&lt;/h3&gt;
&lt;p&gt;目前使用 nginx 时，工作进程使用 work 账户，进行相应的权限限制。&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;env PATH;  #for nodejs，增加环境变量
user work;  #新建一个work账户，用它来启动nginx工作进程
worker_processes 1;  # 与服务器核心数量匹配
pid /run/nginx.pid; #pidfile位置

events {
        worker_connections 768;
        # multi_accept on;
}

http {
        sendfile on;
        tcp_nopush on;
        tcp_nodelay on;
        keepalive_timeout 65;
        types_hash_max_size 2048;

        passenger_root /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini;  # passenger 相关配置
        passenger_ruby /usr/bin/ruby;
        passenger_max_pool_size 10;

        include /etc/nginx/mime.types;
        default_type application/octet-stream;

        ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # Dropping SSLv3, ref: POODLE
        ssl_prefer_server_ciphers on;

        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;

        gzip on;
        gzip_disable "msie6";

        server{
                listen 80;
                server_name app_name; # host name，一个端口不通host时很必要
                root /home/work/app/public; # rails 项目目录/public
                rails_env production; # rails env
                passenger_enabled on; # 这个server节点开启 passenger
        }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;修改好配置，执行&lt;/p&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo service nginx restart
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;至此，Rails + Passenger + Nginx 的基本环境就配置完成。&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Wed, 05 Aug 2015 18:59:21 +0800</pubDate>
      <link>https://ruby-china.org/topics/26783</link>
      <guid>https://ruby-china.org/topics/26783</guid>
    </item>
    <item>
      <title>http delete request with entity body</title>
      <description>&lt;h2 id="Http Delete Request"&gt;Http Delete Request&lt;/h2&gt;
&lt;p&gt;最近在对接某 API，自称 RESTful... 遇到了这样的一个 delete 方法，定义如下：&lt;/p&gt;

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

&lt;p&gt;其他的方法（除了 delete 相关）都是采用 POST 方式&lt;/p&gt;

&lt;p&gt;不去吐槽接口的设计了，用起来还是挺方便的。有一个问题，http delete 请求是否可以携带 body？&lt;/p&gt;

&lt;p&gt;查了一些资料，这个帖子讲得比较全面：&lt;a href="http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request" rel="nofollow" target="_blank"&gt;http://stackoverflow.com/questions/299628/is-an-entity-body-allowed-for-an-http-delete-request&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;大体上说，没有明确禁止，即 http delete request 可以携带 body，但是一些 web server 可能会把 delete request 中的 body 给丢弃掉...&lt;/p&gt;

&lt;p&gt;从接口设计角度讲，不该带着。&lt;/p&gt;
&lt;h2 id="Net::HTTP post 与 delete 方法调用示例"&gt;Net::HTTP post 与 delete 方法调用示例&lt;/h2&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#http post&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;post&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http_body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http_header&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;#http delete with body&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;req&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;Delete&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="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http_header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;req&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;body&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http_body&lt;/span&gt;
&lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt; &lt;span class="n"&gt;req&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;#http delete without body&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;Net&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;HTTP&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;port&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;delete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;http_header&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>fbsender</author>
      <pubDate>Thu, 09 Apr 2015 21:02:49 +0800</pubDate>
      <link>https://ruby-china.org/topics/25078</link>
      <guid>https://ruby-china.org/topics/25078</guid>
    </item>
    <item>
      <title>rmmseg-cpp dictionary 中取哈希值相关算法疑问</title>
      <description>&lt;p&gt;gem rmmseg-cpp 使用 c++ 扩展的中文分词 gem    &lt;/p&gt;

&lt;p&gt;分词前，需加载分词所用的词库，为了提升搜索性能，为词库中的每个词依据每个字符与词语长度计算出不同的哈希值，算法如下：&lt;/p&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;hash&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;len&lt;/span&gt;&lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;^=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;key&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;请问这样计算哈希值的目的是什么呢？&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Thu, 09 Oct 2014 16:18:00 +0800</pubDate>
      <link>https://ruby-china.org/topics/21945</link>
      <guid>https://ruby-china.org/topics/21945</guid>
    </item>
    <item>
      <title>ruby include extend prepend 使用方法</title>
      <description>&lt;h2 id="include 与 extend"&gt;include 与 extend&lt;/h2&gt;
&lt;p&gt;先说 include 和 extend，看下面的一段代码：     &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;A&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"method in A"&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;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这样写之后，B 将新增一个实例方法 my_method，C 将新增一个类方法 my_method，同时，B 的祖先链（ancestors）中将增加 A，而 C 的祖先链中没有 A。      &lt;/p&gt;

&lt;p&gt;再谈一下当方法调用时，ruby 是如何在祖先链中找到方法定义的：&lt;br&gt;
1.实例方法，首先在实例中找，然后在实例对象的单件类中找，之后沿祖先链依次向上找&lt;br&gt;
2.类方法，首先在类的单件类中找，然后沿着类的单件类的祖先链依次向上找（类的单件类的祖先链 = 类的祖先链的各个节点的单件类组成的链）    &lt;/p&gt;
&lt;h2 id="ruby prepend"&gt;ruby prepend&lt;/h2&gt;
&lt;p&gt;ruby prepend 与 include 类似，首先都是添加实例方法的，不同的是扩展 module 在祖先链上的放置位置不同，看下面的代码：   &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;A&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"in A"&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;class&lt;/span&gt; &lt;span class="nc"&gt;B&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"in B"&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;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="n"&gt;prepend&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;my_method&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"in C"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="no"&gt;B&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="nf"&gt;my_method&lt;/span&gt;   &lt;span class="c1"&gt;#输出 ‘in B’&lt;/span&gt;
&lt;span class="no"&gt;C&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="nf"&gt;my_method&lt;/span&gt;   &lt;span class="c1"&gt;#输出 ‘in A’&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;B&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt;
&lt;span class="c1"&gt;#输出&lt;/span&gt;
&lt;span class="c1"&gt;#B&lt;/span&gt;
&lt;span class="c1"&gt;#A&lt;/span&gt;
&lt;span class="c1"&gt;#Object&lt;/span&gt;
&lt;span class="c1"&gt;#Kernel&lt;/span&gt;
&lt;span class="c1"&gt;#BasicObject&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;ancestors&lt;/span&gt;
&lt;span class="c1"&gt;#输出&lt;/span&gt;
&lt;span class="c1"&gt;#A&lt;/span&gt;
&lt;span class="c1"&gt;#C&lt;/span&gt;
&lt;span class="c1"&gt;#Object&lt;/span&gt;
&lt;span class="c1"&gt;#Kernel&lt;/span&gt;
&lt;span class="c1"&gt;#BasicObject&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h2 id="ActiveSupport::Concern 代码解析"&gt;ActiveSupport::Concern 代码解析&lt;/h2&gt;
&lt;p&gt;ActiveSupport::Concern 这个 module 代码不多，看到相关使用的时候引出了上面的一系列问题，4.1.5 版本的代码贴在下面，来逐行解析：    &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;ActiveSupport&lt;/span&gt;
  &lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;Concern&lt;/span&gt;
    &lt;span class="c1"&gt;#定义了一种错误类型，在一个extend Concern的类中如果多次使用included方法，会报这个异常&lt;/span&gt;
    &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MultipleIncludedBlocks&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="c1"&gt;#:nodoc:&lt;/span&gt;
      &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;initialize&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt; &lt;span class="s2"&gt;"Cannot define multiple 'included' blocks for a Concern"&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="c1"&gt;#扩展这个module的时候注意使用extend，而不是include&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;extended&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;#:nodoc:&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;instance_variable_set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@_dependencies&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[])&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="c1"&gt;#include一个module的时候，会先调用append_features，在调用included，base为外层发起调用的module或class&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;append_features&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="c1"&gt;#第一眼真心看不出下面的逻辑是做什么的，后面会写代码说明逻辑&lt;/span&gt;
      &lt;span class="k"&gt;if&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;instance_variable_defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@_dependencies&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="nf"&gt;instance_variable_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@_dependencies&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kp"&gt;false&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
        &lt;span class="vi"&gt;@_dependencies.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;dep&lt;/span&gt;&lt;span class="o"&gt;|&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;send&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:include&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dep&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;
        &lt;span class="c1"&gt;#include module时，为base同时扩展类方法&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;extend&lt;/span&gt; &lt;span class="nb"&gt;const_get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ClassMethods&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;const_defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:ClassMethods&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="c1"&gt;#include module时，可以执行included中的方法体&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;class_eval&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="vi"&gt;@_included_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;instance_variable_defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@_included_block&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="c1"&gt;#被引用时执行的方法，这里的参数设计神了...&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;included&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;base&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kp"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="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;base&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;nil?&lt;/span&gt;
        &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="no"&gt;MultipleIncludedBlocks&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;instance_variable_defined?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:@_included_block&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="vi"&gt;@_included_block&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;block&lt;/span&gt;
      &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="k"&gt;super&lt;/span&gt;
      &lt;span class="k"&gt;end&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;写了一段代码来清晰的展示 ActiveSupport::Concern 的执行逻辑：    &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;'active_support'&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;A&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;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&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;"in A"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;#代码执行到这里，A extend ActiveSupport::Concern，于是多了两个类方法，然后又执行了included方法，A的变量@_included_block里面有了待执行的方法&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;B&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;Concern&lt;/span&gt;

  &lt;span class="n"&gt;included&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;"in B"&lt;/span&gt;
  &lt;span class="k"&gt;end&lt;/span&gt;
  &lt;span class="c1"&gt;#代码执行到这里，B extend ActiveSupport::Concern，于是多了两个类方法，然后又执行了included方法，B的变量@_included_block里面有了待执行的方法&lt;/span&gt;

  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;
  &lt;span class="c1"&gt;#include A，要执行的两个方法已经被覆盖了，由Concern中的方法取代，&lt;/span&gt;
  &lt;span class="c1"&gt;#B的@_dependencies的的值为[A]，并且没有执行到super方法，于是B的祖先链中并没有A（推测祖先链的改变是在append_features super里面做的）&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;B&lt;/span&gt;
  &lt;span class="c1"&gt;#先执行B的append_features，由于B中已定义:@_dependencies，来到else分支，此时还没有执行super方法，故C &amp;lt; B 为false，&lt;/span&gt;
  &lt;span class="c1"&gt;#代码继续向下执行，于是执行了动态调用 C include A，再开始执行A的append_features...不再赘述分支逻辑&lt;/span&gt;
  &lt;span class="c1"&gt;#后面还有两句代码，一个是将A与B的module ClassMethod中的方法加到C的类方法中，一个是执行@_included_block中的方法体，&lt;/span&gt;
  &lt;span class="c1"&gt;#由于C include A 被动态调用，A处于C祖先链的更上方，A变量@_included_block中的方法体先被执行&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;#输出&lt;/span&gt;
&lt;span class="c1"&gt;#‘in A’&lt;/span&gt;
&lt;span class="c1"&gt;#‘in B’&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;C 的祖先链，B A ...&lt;br&gt;
B 的祖先链中没有 A      &lt;/p&gt;

&lt;p&gt;存在疑问：include module，变更对象祖先链是在 append_features 方法还是在 included 方法中操作的？或者是别的？&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Fri, 12 Sep 2014 11:26:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/21501</link>
      <guid>https://ruby-china.org/topics/21501</guid>
    </item>
    <item>
      <title>Node.js ORM 包 无法自动匹配表名与列名</title>
      <description>&lt;p&gt;最新在练习使用 coffee script 写后端脚本，需要查询 mysql 数据库，于是寻找 node.js 相关 orm 包。&lt;br&gt;
sequelizejs：&lt;a href="http://sequelizejs.com/" rel="nofollow" target="_blank"&gt;http://sequelizejs.com/&lt;/a&gt;&lt;br&gt;
node-orm2：&lt;a href="https://github.com/dresende/node-orm2" rel="nofollow" target="_blank"&gt;https://github.com/dresende/node-orm2&lt;/a&gt;     &lt;/p&gt;

&lt;p&gt;但是发现这些 orm 包无法像 ActiveRecord 一样自动匹配表名与列名，有下面的两个问题：&lt;/p&gt;

&lt;p&gt;1.nodejs 有木有更易使用的 orm 包？
2.这些功能没有被开发的原因是什么呢？&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Thu, 04 Sep 2014 17:56:04 +0800</pubDate>
      <link>https://ruby-china.org/topics/21389</link>
      <guid>https://ruby-china.org/topics/21389</guid>
    </item>
    <item>
      <title>提问：为何好多人在黑产品经理？</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2013/bc97de725ba84e02c3ed35c29aaafaff.jpg" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Fri, 20 Dec 2013 00:15:15 +0800</pubDate>
      <link>https://ruby-china.org/topics/16323</link>
      <guid>https://ruby-china.org/topics/16323</guid>
    </item>
    <item>
      <title>Rails 项目维护数据库，偏向于使用 ActiveRecord::Migration or 数据库脚本？</title>
      <description>&lt;p&gt;一个关于 ActiveRecord::Migration 的疑问，这东西应用广泛否？&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Tue, 10 Dec 2013 17:17:20 +0800</pubDate>
      <link>https://ruby-china.org/topics/16124</link>
      <guid>https://ruby-china.org/topics/16124</guid>
    </item>
    <item>
      <title>Bootstrap 2 的一个问题，求助~</title>
      <description>&lt;p&gt;&lt;img src="//l.ruby-china.com/photo/2013/b1cd26d022632897b276480101a55818.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;外层 div class='span9'
内部 div class='span2'&lt;/p&gt;

&lt;p&gt;请问如何填充 bootstap 自动留出的空白部分呢？&lt;/p&gt;

&lt;p&gt;网页链接：&lt;a href="http://vxixi.com/category/racket_detail/207?page=1" rel="nofollow" target="_blank"&gt;http://vxixi.com/category/racket_detail/207?page=1&lt;/a&gt;&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Mon, 09 Dec 2013 22:34:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/16101</link>
      <guid>https://ruby-china.org/topics/16101</guid>
    </item>
    <item>
      <title>羽毛球小站 从.net mvc 迁移过来的~</title>
      <description>&lt;p&gt;原本是用.NET MVC 3.0 开发的站点，部署在 Linode 上，mono + apache + mysql&lt;/p&gt;

&lt;p&gt;现在是 rails + bootstrap + passenger + ngnix + mysql&lt;/p&gt;

&lt;p&gt;从开发到部署，相比于.net，rails 方便太多了，ruby 写爬虫也超方便，感慨&lt;/p&gt;

&lt;p&gt;传送门：&lt;a href="http://www.vxixi.com" rel="nofollow" target="_blank"&gt;http://www.vxixi.com&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;网站内容尚在填充中~&lt;/p&gt;</description>
      <author>fbsender</author>
      <pubDate>Thu, 05 Dec 2013 23:25:53 +0800</pubDate>
      <link>https://ruby-china.org/topics/16035</link>
      <guid>https://ruby-china.org/topics/16035</guid>
    </item>
    <item>
      <title>对象的单件方法无法访问所属类的类变量，why？</title>
      <description>&lt;p&gt;标题很拗口，一个关于类变量的问题&lt;/p&gt;

&lt;p&gt;类变量应该是类、子类、类对象、子类对象共享的&lt;/p&gt;

&lt;p&gt;但是类的对象的单件方法却无法访问所属类的类变量...&lt;/p&gt;

&lt;p&gt;代码如下，有木有合理的解释呢？&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&lt;/span&gt;
    &lt;span class="vc"&gt;@@a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"It is @@a"&lt;/span&gt;
    &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;get_a&lt;/span&gt;
        &lt;span class="vc"&gt;@@a&lt;/span&gt;
    &lt;span class="k"&gt;end&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_a&lt;/span&gt;                 &lt;span class="c1"&gt;#=&amp;gt;It is @@a&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test_singleton&lt;/span&gt;
    &lt;span class="s2"&gt;"A test"&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test_singleton&lt;/span&gt;    &lt;span class="c1"&gt;#=&amp;gt;A test&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nc"&gt;obj&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_a_singleton&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="vc"&gt;@@a&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get_a_singleton&lt;/span&gt;        &lt;span class="c1"&gt;#=&amp;gt;in `get_a_singleton': uninitialized class variable @@a in Object (NameError)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;</description>
      <author>fbsender</author>
      <pubDate>Wed, 04 Dec 2013 18:45:57 +0800</pubDate>
      <link>https://ruby-china.org/topics/16006</link>
      <guid>https://ruby-china.org/topics/16006</guid>
    </item>
  </channel>
</rss>
