<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Lucia_ca (Lucia)</title>
    <link>https://ruby-china.org/Lucia_ca</link>
    <description></description>
    <language>en-us</language>
    <item>
      <title>Sidekiq 中如何通过 rails console 获取每个注册的 workers 及对应的所属 queue？</title>
      <description>&lt;p&gt;项目中定义了很多 worker，在做整理的时候，想要列出每个注册的队列下都有哪些 worker，注册的队列在配置文件里可以看到，但是每个队列的 worker 如何通过 rails console 获取？
初步的方法是查看官方文档，翻阅 sidekiq/api，里面给到的方法都是针对已经入列的job，通过Sidekiq::Queue.all获取到的并不是注册的队列，Sidekiq::Workers.new 得到的也不是所有注册的 workers，而是当前活动的 workers。
请问有没有方法可以直接列出所有注册的 worker 以及它对应的队列？&lt;/p&gt;</description>
      <author>Lucia_ca</author>
      <pubDate>Fri, 04 Jan 2019 14:29:01 +0800</pubDate>
      <link>https://ruby-china.org/topics/37971</link>
      <guid>https://ruby-china.org/topics/37971</guid>
    </item>
    <item>
      <title>求助：当 undef_method 遇上 method_missing，rails 如何处理属性方法？</title>
      <description>&lt;p&gt;使用 undef_method，遇到的一个问题，想不明白 rails 是如何处理的，不知哪位大神可以给到一个解答。&lt;/p&gt;

&lt;p&gt;场景如下：&lt;/p&gt;

&lt;p&gt;user model 含有字段 name，同时 include 了一个 module UserAddon，使用 undef_method 来禁止调用引入的 name 方法，按照 undef_method 的定义，
此时 User 的对象调用 name 时，应该会报错，但是进入终端后，发现没有，反而返回了正确的结果。&lt;/p&gt;

&lt;p&gt;代码如下：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;## app/models/user.rb&lt;/span&gt;

&lt;span class="c1"&gt;# == Schema Information&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;# Table name: users&lt;/span&gt;
&lt;span class="c1"&gt;#&lt;/span&gt;
&lt;span class="c1"&gt;#  id                          :integer          not null, primary key&lt;/span&gt;
&lt;span class="c1"&gt;#  email                       :string(254)&lt;/span&gt;
&lt;span class="c1"&gt;#  name                        :string(254)&lt;/span&gt;
&lt;span class="c1"&gt;#  password_digest             :string(254)&lt;/span&gt;
&lt;span class="c1"&gt;#  created_at                  :datetime         not null&lt;/span&gt;
&lt;span class="c1"&gt;#  updated_at                  :datetime         not null&lt;/span&gt;

&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="no"&gt;ActiveRecord&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;UserAddon&lt;/span&gt;
  &lt;span class="n"&gt;undef_method&lt;/span&gt; &lt;span class="ss"&gt;:name&lt;/span&gt;
&lt;span class="k"&gt;end&lt;/span&gt;

&lt;span class="c1"&gt;## app/models/user_addon.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;UserAddon&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;name&lt;/span&gt;
    &lt;span class="s2"&gt;"hello"&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;这时，rails c 进入 console：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;User&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;first&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; #&amp;lt;User id: 1, name: "admin", email: "test@gmail.com", created_at:……&amp;gt;&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;include?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; false&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; "admin"&lt;/span&gt;

&lt;span class="err"&gt;$&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt;

&lt;span class="c1"&gt;# =&amp;gt; Couldn't locate a definition for user.name&lt;/span&gt;

&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;respond_to?&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# =&amp;gt; true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 pry 的$ ，找不到 user.name 的定义，但是执行 user.name 却返回了正确的结果，此时一定调用了 method_missing。但是，如何查看 rails 是如何实现的呢？&lt;/p&gt;

&lt;p&gt;ruby 元编程中在有关 rails 的属性方法中曾经提到，当第一次访问一个属性时，这个属性是一个幽灵方法，ActiveRecord::Base # method_missing() 会把它转换成一个真实的方法，同时创建出读，写，查询方法，比如上面的 name，会创建 name, name=, name?，这样下次就可以直接调用。&lt;/p&gt;

&lt;p&gt;但是，这里很显然，user.methods.include?(:name) 返回了 false，这里并没有创建 name 这个方法，那么 rails 是如何让 user.name 返回了"admin"的呢？&lt;/p&gt;

&lt;p&gt;我看了下 rails 的&lt;a href="https://github.com/rails/rails/blob/master/activemodel/lib/active_model/attribute_methods.rb" rel="nofollow" target="_blank" title=""&gt;attribute_methods&lt;/a&gt;中 method_missing 部分的代码，苦于水平有限，没看懂这里到底是如何实现的，不知哪位大神可以给到一个清晰的解答或者指个方向？thx!&lt;/p&gt;</description>
      <author>Lucia_ca</author>
      <pubDate>Tue, 04 Sep 2018 19:21:43 +0800</pubDate>
      <link>https://ruby-china.org/topics/37438</link>
      <guid>https://ruby-china.org/topics/37438</guid>
    </item>
    <item>
      <title>Ruby 中 require,load,autoload,extend,include,prepend 的区别</title>
      <description>&lt;h2 id="Ruby中require,load,autoload,extend,include,prepend的区别"&gt;Ruby 中 require,load,autoload,extend,include,prepend 的区别&lt;/h2&gt;&lt;h4 id="补充："&gt;补充：&lt;/h4&gt;
&lt;p&gt;根据 rubyist 们的留言，做了两点补充：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;使用 extend, require, include 时，module 在祖先链中的差异&lt;/li&gt;
&lt;li&gt;有关 load 中的参数 true&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;详见文末。&lt;/p&gt;

&lt;hr&gt;

&lt;p&gt;作为 ruby 新手，对这 6 位容易拎不清，Google 全网，没有找到完整的对比，决定写一篇，希望能给同样迷惑的小伙伴一个参考。&lt;/p&gt;
&lt;h4 id="写在前面"&gt;写在前面&lt;/h4&gt;
&lt;p&gt;关于这个问题，已经有很多大牛给到过解答，稍完整的比如：&lt;a href="http://web-k.github.io/blog/2012/12/19/ruby-require-load/" rel="nofollow" target="_blank" title=""&gt;About Ruby require / load / autoload / include / extend&lt;/a&gt;，RubyChina 上也有很精彩的解答：&lt;a href="https://ruby-china.org/topics/25706" title=""&gt;基础 Ruby 中 Include, Extend, Load, Require 的使用区别&lt;/a&gt;，决定整理下各位大牛的解答，顺带加点个人的理解，对这 6 位进行下对比。&lt;/p&gt;
&lt;h4 id="正文"&gt;正文&lt;/h4&gt;
&lt;p&gt;先给它们简单分类下：require，load, autoload 均涉及到文件的加载，归为一类，剩下的 include，prepend，extend 归为第二类。先来看第一类。&lt;/p&gt;
&lt;h4 id="require"&gt;require&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;kernel method，可以加载 ruby 文件，也可以加载外部的库。&lt;/li&gt;
&lt;li&gt;相比 load ,针对同一个文件，它只加载一次&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="load"&gt;load&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;与 require 很类似，但是&lt;code&gt;load&lt;/code&gt;会每次都重新加载文件。&lt;/li&gt;
&lt;li&gt;大部分情况下，除非你加载的库变动频繁，需要重新加载以获取最新版本，一般建议用 require 来代替 load.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id="autoload"&gt;autoload&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;用法稍稍不同：&lt;code&gt;autoload(const_name, 'file_path')&lt;/code&gt;, 其中 const_name 通常是模块名，或者类名。&lt;/li&gt;
&lt;li&gt;对于 load 和 require，在 ruby 运行到 require／load 时，会立马加载文件，而 autoload 则只有当你调用 module 或者 class 时才会加载文件。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;看个例子来感受下三者的不同：【#= &amp;gt; 表示输出结果】&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;## module_m.rb&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;M&lt;/span&gt;
  &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'load a module'&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;A&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;hello&lt;/span&gt;
      &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s1"&gt;'hello'&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="c1"&gt;## test.rb&lt;/span&gt;

&lt;span class="c1"&gt;## require ：只加载一次&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"first load: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"load again: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;require&lt;/span&gt; &lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load a module&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; first load: true&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load again: false&lt;/span&gt;

&lt;span class="c1"&gt;# load ：多次加载&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"first load: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"load again: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;load&lt;/span&gt; &lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load a module&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; first load: true&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load a module&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load again: true&lt;/span&gt;

&lt;span class="c1"&gt;# autoload ：调用时才加载&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"first load: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;autoload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"load again: &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="nb"&gt;autoload&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="ss"&gt;:M&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="s1"&gt;'./module_m.rb'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="no"&gt;M&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="no"&gt;A&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;hello&lt;/span&gt; 
&lt;span class="c1"&gt;#= &amp;gt; first load:&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; load again:&lt;/span&gt;
&lt;span class="c1"&gt;#= &amp;gt; hello&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;不过现在应该很少有 rubyist 用 autoload 了。&lt;/p&gt;

&lt;p&gt;2011 年，Matz 针对 Autoload will be dead，有如下的声明：&lt;/p&gt;

&lt;p&gt;&lt;img src="https://ws4.sinaimg.cn/large/006tKfTcgy1fpq5qxl950j30dx06iwfp.jpg" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;至于原因，则是 autoload 本身在多线程环境下存在基本的缺陷，这个我并没有尝试过，不是很理解。stack overflow 上&lt;a href="https://stackoverflow.com/questions/804297/when-to-use-require-load-or-autoload-in-ruby?rq=1&amp;amp;utm_medium=organic&amp;amp;utm_source=google_rich_qa&amp;amp;utm_campaign=google_rich_qa" rel="nofollow" target="_blank" title=""&gt;When to use &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;load&lt;/code&gt; or &lt;code&gt;autoload&lt;/code&gt; in Ruby?&lt;/a&gt;有位是这么说的：&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The lazyness of autoload sounds nice in theory, &lt;strong&gt;but many Ruby modules do things like monkey-patching other classes, which means that the behavior of unrelated parts of your program may depend on whether a given class has been used yet or not&lt;/strong&gt;。&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;他提到了猴子补丁的情况。可惜没有例子，不然应该能更容易理解。&lt;/p&gt;

&lt;p&gt;顺带提一句，Rails 的 ActiveRecord 中大量使用的 autoload，跟这里的 autoload 不是一回事，它是 module ActiveSupport::Autoload 中的方法。&lt;/p&gt;
&lt;h4 id="include"&gt;include&lt;/h4&gt;
&lt;p&gt;当一个类或者模块 include 了一个 module M 时，则该类或者模块就拥有了该 module M 的方法。&lt;/p&gt;

&lt;p&gt;当涉及多个类调用同一方法时，这个方法就可以抽离出来，放入 module 中，然后类只需 include 该 module 即可。这样的做法也正体现了 DRY 原则。&lt;/p&gt;

&lt;p&gt;例如：&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;M&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="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello"&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;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;M&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;D&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M&lt;/span&gt;
&lt;span class="k"&gt;end&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;#= &amp;gt; hello &lt;/span&gt;
&lt;span class="no"&gt;D&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;#= &amp;gt; hello &lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;include 的另一种较常见的用法是&lt;strong&gt;搭配 extend&lt;/strong&gt;，实现&lt;strong&gt;包含并扩展&lt;/strong&gt;类的功能，同时可能还会搭配着钩子方法 included。在一些常用 gem 的源代码中，可以看到这类用法的身影。&lt;/p&gt;
&lt;h4 id="extend"&gt;extend&lt;/h4&gt;
&lt;p&gt;当一个类或者对象使用 extend 时，相当于&lt;strong&gt;打开了该类或者该对象的单件类&lt;/strong&gt;，为其添加了单件方法。&lt;/p&gt;

&lt;p&gt;比如：&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;MyModule&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello"&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;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;MyModule&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="p"&gt;[]&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;extend&lt;/span&gt; &lt;span class="no"&gt;MyModule&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;a_method&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; hello&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;singleton_methods&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; [:a_method]&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;a_method&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; hello&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;singleton_methods&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; [:a_method]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;使用 include 实现同样的效果：&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;MyModule&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;a_method&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello"&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;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;self&lt;/span&gt;
    &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;MyModule&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="p"&gt;[]&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;obj&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;MyModule&lt;/span&gt;
&lt;span class="k"&gt;end&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;a_method&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; hello&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;singleton_methods&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; [:a_method]&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;a_method&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; hello &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;singleton_methods&lt;/span&gt; &lt;span class="c1"&gt;#= &amp;gt; [:a_method]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;h4 id="prepend"&gt;prepend&lt;/h4&gt;
&lt;p&gt;相比 include，extend，prepend「Available since Ruby 2」的知名度和使用率要少很多。&lt;/p&gt;

&lt;p&gt;prepend 和 include 很像，当一个类 prepend 或 include 一个模块时，该模块中的方法会成为该类的实例方法。&lt;/p&gt;

&lt;p&gt;二者的区别在于，模块在祖先链中的位置。使用 include 时，模块在包含它的类之上。如果是 prepend，则是在 prepend 它的类之下。而祖先链中位置的不同，决定了方法调用的顺序。&lt;/p&gt;

&lt;p&gt;比如下面这个例子：&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;M1&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is module M1"&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;module&lt;/span&gt; &lt;span class="nn"&gt;M2&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is module M2"&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;M1&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M2&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is class 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;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;#=&amp;gt; [M1, C, M2, Object, Kernel, BasicObject]&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;hello&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; hello! this is module M1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;这里，祖先链的顺序是 M1 在最前面，所以即使 C 中定义了一个 method hello，也不会被调用，因为 module M1 覆写了这个 method。&lt;/p&gt;

&lt;p&gt;从上面的例子也可以看出，prepend 是很方便的方法包装器，假定我们想要给 class C 的 hello method 添加一些其他的功能实现，则可以这样写：&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;M1&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"add something outside C#hello"&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="o"&gt;......&lt;/span&gt; &lt;span class="c1"&gt;# 省略module M2&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;M1&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M2&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is class 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;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;hello&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; add something outside C#hello&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; hello! this is class C&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在 module M1 中覆写了 hello，同时使用了 super，调用了 C 中原来的 hello method。&lt;/p&gt;
&lt;h4 id="参考："&gt;参考：&lt;/h4&gt;
&lt;p&gt;&lt;a href="https://bugs.ruby-lang.org/issues/5653" rel="nofollow" target="_blank" title=""&gt;I strongly discourage the use of autoload in any standard libraries" (Re: autoload will be dead)&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="http://web-k.github.io/blog/2012/12/19/ruby-require-load/" rel="nofollow" target="_blank" title=""&gt;About Ruby require / load / autoload / include / extend&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ruby-china.org/topics/25706" title=""&gt;基础 Ruby 中 Include, Extend, Load, Require 的使用区别&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://stackoverflow.com/questions/804297/when-to-use-require-load-or-autoload-in-ruby?rq=1&amp;amp;utm_medium=organic&amp;amp;utm_source=google_rich_qa&amp;amp;utm_campaign=google_rich_qa" rel="nofollow" target="_blank" title=""&gt;When to use &lt;code&gt;require&lt;/code&gt;, &lt;code&gt;load&lt;/code&gt; or &lt;code&gt;autoload&lt;/code&gt; in Ruby?&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;第一次在 RubyChina 发帖，小激动～&lt;/p&gt;

&lt;hr&gt;
&lt;h2 id="补充部分："&gt;补充部分：&lt;/h2&gt;&lt;h4 id="extend, require, include中，module在祖先链中的差异"&gt;extend, require, include 中，module 在祖先链中的差异&lt;/h4&gt;
&lt;p&gt;前面已经提到在使用 include 时，模块在包含它的类之上。如果是 prepend，则是在 prepend 它的类之下。那么使用 extend，模块会出现在哪里？&lt;/p&gt;

&lt;p&gt;根据之前的例子，改编了下：&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;M1&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is module M1::hello"&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;module&lt;/span&gt; &lt;span class="nn"&gt;M2&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is module M2"&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;## 添加 M3&lt;/span&gt;
&lt;span class="k"&gt;module&lt;/span&gt; &lt;span class="nn"&gt;M3&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is module M3"&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;M1&lt;/span&gt;
  &lt;span class="kp"&gt;include&lt;/span&gt; &lt;span class="no"&gt;M2&lt;/span&gt;
  &lt;span class="kp"&gt;extend&lt;/span&gt; &lt;span class="no"&gt;M3&lt;/span&gt;
  &lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! this is C#hello"&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;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;#=&amp;gt; [M1, C, M2, Object, Kernel, BasicObject]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;此时，C 的祖先链中并没有出现 M3，那么 M3 在哪里？&lt;/p&gt;

&lt;p&gt;当类 extend 某个 module 时，其实是扩展了该类的类方法，所以，可以在该类的单件类的祖先链里面找找。&lt;/p&gt;

&lt;p&gt;承接上面的例子，查看 C 单件类的祖先链：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;singleton_class&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;#=&amp;gt; [#&amp;lt;Class:C&amp;gt;, M3, #&amp;lt;Class:Object&amp;gt;,#&amp;lt;Class:BasicObject&amp;gt;,Class, Module, Object, Kernel,BasicObject]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;可以看到，M3 在该类的单件类的上方。此时调用 C.hello, 会得到&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; hello! this is module M3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当然，如果你在 C 中定义了类方法 hello，则会调用 C 自定义的这个类方法，比如：&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;......&lt;/span&gt; &lt;span class="c1"&gt;# 省略module M1 M2 M3&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="o"&gt;......&lt;/span&gt; &lt;span class="c1"&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;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! This is C.hello"&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;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt; &lt;span class="c1"&gt;#=&amp;gt; hello! This is C.hello&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;如果想要调用 M3 中的 hello，在 C 的 hello 中加上 super 即可。&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="o"&gt;......&lt;/span&gt; &lt;span class="c1"&gt;# 省略module M1 M2 M3&lt;/span&gt;
&lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;C&lt;/span&gt;
  &lt;span class="o"&gt;......&lt;/span&gt; &lt;span class="c1"&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;hello&lt;/span&gt;
    &lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"hello! This is C.hello"&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="no"&gt;C&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt; 
&lt;span class="c1"&gt;#=&amp;gt; hello! This is C.hello&lt;/span&gt;
&lt;span class="c1"&gt;#=&amp;gt; hello! this is module M3&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;具体有关单件类及祖先链部分，可以查阅&lt;a href="https://book.douban.com/subject/26575429/" rel="nofollow" target="_blank" title=""&gt;《Ruby 元编程》(第 2 版)&lt;/a&gt;第五章，书中有非常详细的图解。&lt;/p&gt;
&lt;h4 id="有关load中的参数true"&gt;有关 load 中的参数 true&lt;/h4&gt;
&lt;p&gt;这个我就直接用书中的解说吧，参考来自&lt;a href="https://book.douban.com/subject/26575429/" rel="nofollow" target="_blank" title=""&gt;《Ruby 元编程》(第 2 版)&lt;/a&gt;第二章。&lt;/p&gt;

&lt;p&gt;用 true 是为了避免 load 带来的一个副作用。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;load('file.rb')&lt;/code&gt;加载进来的文件 file 中，如果含有常量，这些常量并不会像变量一样在加载完成后，落在当前作用域之外，所以这些常量就有可能会污染当前程序的命名空间，而使用&lt;code&gt;load('file.rb', true)&lt;/code&gt;,Ruby 会创建一个匿名空间，用它作为命名空间来容纳 file 中的所有常量，从而避免污染当前程序的命名空间。&lt;/p&gt;</description>
      <author>Lucia_ca</author>
      <pubDate>Wed, 28 Mar 2018 19:41:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/35350</link>
      <guid>https://ruby-china.org/topics/35350</guid>
    </item>
  </channel>
</rss>
