<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>ashley (Ashley)</title>
    <link>https://ruby-china.org/ashley</link>
    <description>Keep moving on</description>
    <language>en-us</language>
    <item>
      <title>Rails ：ActiveRecord 查询的小贴士</title>
      <description>&lt;p&gt;最近太忙了，一直没抽出时间翻译一些好的文章，趁着年会休息的空档继续写写~~
下面是文章 Rails: Tips for Speeding up ActiveRecord Queries 的翻译，作者 NICK REYNOLDS，原文链接&lt;a href="http://www.webascender.com/Blog/ID/553/Rails-Tips-for-Speeding-up-ActiveRecord-Queries" rel="nofollow" target="_blank"&gt;http://www.webascender.com/Blog/ID/553/Rails-Tips-for-Speeding-up-ActiveRecord-Queries&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;运用 ActiveRecord 是使用 Ruby on Rails 的乐趣之一。它简短且贴心 – 将可能十分冗长的 SQL 语句变成简短且可读性高的 Ruby 语句。但是，如果不小心，轻易写出来的 ActiveRecord 请求会产生表现不佳的 SQL，或让你的 app 内存占用飙升—— 尤其是在你处理大型数据库表的情况下。幸运的是，ActiveRecord 为编写高性能查询提供了一个极好的工具包。这里，我们将重点介绍其中几个工具和一些注意事项。&lt;/p&gt;

&lt;p&gt;在下面例子中，我生成了一个大型在线零售商一般都会用到的交易表。这个表包含几百万行的数据，每行都有保存金额、用户 ID 和其他各种关于不同事务的元数据。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;sum(&amp;amp;:amount) vs. sum(:amount)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;两个调用方式中其中一种比另一种快非常多：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction.sum(&amp;amp;:amount)&lt;/strong&gt;
        &lt;strong&gt;Transaction.sum(:amount)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;它们之间的区别是微妙的。但是第一个调用语句中那个额外的”&amp;amp;”  (查看Symbol#to_proc)，使得求和采用Array#sum来计算，而不是SQL。这意味着rails必须选择所有的列，并将每行数据的模型实例化来构建一个潜在的巨大数组。第二个语句直接让数据库求和，有时候这可能比Ruby更好，而且这个方法完全不用选择任何多余的列或者创建任何模型：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SELECT SUM(amount) FROM &lt;code&gt;transactions&lt;/code&gt;;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;好消息是在 Rails 4.0 中 含有 block 的 ActiveRecord::Calculations#sum 已被弃用，所以如果不小心加了‘&amp;amp;’会收到警告。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;pluck vs. map&lt;/strong&gt;
         &lt;strong&gt;Transaction.all.map(&amp;amp;:user_id)&lt;/strong&gt;
         &lt;strong&gt;Transaction.pluck(:user_id)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;map（又名 collect）是另外一个有用的数组方法。遗憾的是，这里会有问题。因为在执行数组时，当我们想要的可能只是一个单独的列，然而在上面的例子中 rails 需要选择对所有的列实例化行成模型，即使我们只是用在 user_id 之后，交易表中所有列会被选中。&lt;/p&gt;

&lt;p&gt;通过 pluck 的方法（rails 3.2.1 以上版本可用）只需要选择表格中的单一列，不用实现模型实例化。如下，上面 SQL 的示例变得简单多了：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SELECT user_id FROM &lt;code&gt;transactions&lt;/code&gt;;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;当然，如果你已经有了一系列相关的计算模型，映射在数组上可能比数据库查询更快。这种情况下最好衡量和比较下两种方法。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;uniq&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;想象一下你想在交易表上建立唯一的用户 id。使用 pluck 方法，我们可以很容易得到这样一个列表。搭配使用 uniq，可以最少有 2 种方法去过滤列表中重复项，并且其中之一肯定比另一个快得多：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction.pluck(:user_id).uniq&lt;/strong&gt;
        &lt;strong&gt;Transaction.uniq.pluck(:user_id)&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;选用的方法无论是实例化模型还是选择任何额外字段。其不同之处在于在什么位置过滤重复项。在第一种情况下，pluck方法为交易表的每一行都返回一个user_ids的数组。然后用Array#uniq过滤重复项。&lt;/p&gt;

&lt;p&gt;在第二种情况是，uniq 方法实际上是 ActiveRecord::QueryMethods#uniq，它增加了 DISTINCTkeyword 生成 SQL。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SELECT DISTINCT user_id FROM &lt;code&gt;transactions&lt;/code&gt;&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果 user_id 列加上索引的话，数据库可能又会再次加速。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;find_each vs. each&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;假设你要为每一个交易执行一些相关处理。对于一小部分的结果，使用 each 会有很好的效果：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction.where(processed: false).each { |t| ... }&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;现在，假设你的结果集含有成千上万条记录。随着 all.each, 整个结果集需加载到内存来对数组进行迭代。在这一点上，app 很可能直接把内存耗尽。&lt;/p&gt;

&lt;p&gt;为了防止这种情况，ActiveRecord 提供 find_each 方法，这种方法是内部查询的结果集设置在 1000 批次，以便整个结果集不被一次性加载到内存中。从表面上看，这是一个与 each 完全相同的接口：&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Transaction.where(processed: false).find_each { |t| ... }&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;如果 1000 不是你的强项，find_each 只是个围绕ActiveRecord::Batches#find_in_batches的包装器，其批量和偏移量是可以进行设置.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;joins vs. includes&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;在 includes 与 joins 之间做出正确的选择会对性能带来影响。
         如果你需要访问一个关联，有一个很好的点子是使用 includes 预载入。因为 joins 只会在 SQL 上增加 JOIN 表达式，如果你试图访问一个关联（例如 user.transactions）,rails 还是要用另外的 SELECT 来加载关联的每一个行。运用 includes，rails 可以在作用域里加载一个 has_many 关联。另一方面，如果添加表格仅用于过滤在 SQL 的结果集，只需继续使用 joins。如果使用 includes 将选择一些不会用到的列和实例化模型。&lt;/p&gt;

&lt;p&gt;留意 SQL&lt;/p&gt;

&lt;p&gt;警惕那些在 ActiveRecord 查询生成的 SQL，可能会产生糟糕的 SQL 查询和 Ruby 计算。首先你要检查 development.log。这里，有些好的 gems 来帮助你分析你的 APP 和提醒你去处理出现的问题：
         Bullet-提醒你应该立即加载 N+1 查询。&lt;/p&gt;

&lt;p&gt;Peek-利用这个便利的工具查看这些请求在哪里经过/耗时。&lt;/p&gt;

&lt;p&gt;RailsPanel- 在 Chrome 的调试窗口中显示请求信息。&lt;/p&gt;</description>
      <author>ashley</author>
      <pubDate>Wed, 27 Jan 2016 16:08:24 +0800</pubDate>
      <link>https://ruby-china.org/topics/28882</link>
      <guid>https://ruby-china.org/topics/28882</guid>
    </item>
    <item>
      <title>[翻译] JavaScript 与 Ruby 的调试技术</title>
      <description>&lt;p&gt;原文链接：&lt;a href="https://eliotsykes.com/debug-js" rel="nofollow" target="_blank"&gt;https://eliotsykes.com/debug-js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;这是一篇简短但是却很实用的指引，为 Ruby 爱好者总结和演译了与常规 Ruby 调试相对应的在 JavaScript 中的调试技术。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;调试断点&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In Ruby&lt;/span&gt;
&lt;span class="nb"&gt;binding&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;pry&lt;/span&gt;
&lt;span class="n"&gt;byebug&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="no"&gt;In&lt;/span&gt; &lt;span class="no"&gt;JavaScript&lt;/span&gt;
&lt;span class="n"&gt;debugger&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;当 JavaScript 遇上关键字 debugger，且你的浏览器调试器选项卡处于开启状态时，执行将会暂停，JavaScript 源将会在 debugger 断点处展示出来。
正如 Pry 和 Byebug 一样，你可以用控制台在暂停行上检查可用变量以及与其互动（按下 Escape 按钮切换到控制台的快速通道）。
如想恢复执行，点击在调试器标签上的播放（三角图标）按钮。
一个替代关键字 debugger 的方法是，在调试器标签上查看 JS 源，点击行沟从而为特定的代码行设置一个断点。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;记录&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In Ruby&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;inspect&lt;/span&gt;
&lt;span class="nb"&gt;p&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="s2"&gt;"The value of x is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;info&lt;/span&gt; &lt;span class="s2"&gt;"The value of x is &lt;/span&gt;&lt;span class="si"&gt;#{&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="no"&gt;In&lt;/span&gt; &lt;span class="no"&gt;JavaScript&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"The value of x is"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;console.log() 的每个参数将会被输出到浏览器控制台。点击输出的参数从而能更深入地检查它们。
console.log() 的一个方便的功能是它能接受多个参数 – 可接受 console.log(x, y, z)，同时输出 x，y，z 的值到控制台。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;优质输出&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In Ruby&lt;/span&gt;
&lt;span class="n"&gt;pp&lt;/span&gt; &lt;span class="n"&gt;some_obj&lt;/span&gt; &lt;span class="c1"&gt;# Ruby Std-lib PP&lt;/span&gt;
&lt;span class="n"&gt;ap&lt;/span&gt; &lt;span class="n"&gt;some_obj&lt;/span&gt; &lt;span class="c1"&gt;# Using awesome_print gem&lt;/span&gt;

&lt;span class="c1"&gt;# In Rails view templates&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sx"&gt;%= debug some_obj %&amp;gt;

// In JavaScript
console.dir(someObj);
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;在你的浏览器控制台试着运行 console.dir(document) 。点击结果从而进一步研究 document 对象。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;输出堆栈跟踪&lt;/strong&gt;&lt;/p&gt;
&lt;pre class="highlight ruby"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In Ruby&lt;/span&gt;
&lt;span class="nb"&gt;puts&lt;/span&gt; &lt;span class="nb"&gt;caller&lt;/span&gt;

&lt;span class="sr"&gt;//&lt;/span&gt; &lt;span class="no"&gt;In&lt;/span&gt; &lt;span class="no"&gt;JavaScript&lt;/span&gt;
&lt;span class="n"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trace&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;堆栈跟踪展示了函数调用的序列，引出正在执行的当前行。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;探索&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;你已经了解了如何借鉴 Ruby 的调试技巧来更有效地调试 JavaScript。
继续尝试和点击浏览器开发工具，特别是调试器标签，去发现更多可用功能。
阅读浏览器厂商 Firefox 和 Chrome 提高的相关文档，了解更先进的调试功能。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;ES · SEPTEMBER 24, 2015&lt;/strong&gt;&lt;/p&gt;</description>
      <author>ashley</author>
      <pubDate>Fri, 13 Nov 2015 12:14:05 +0800</pubDate>
      <link>https://ruby-china.org/topics/28045</link>
      <guid>https://ruby-china.org/topics/28045</guid>
    </item>
    <item>
      <title>Rails 5: ActionController::Parameters 现在返回一个对象而不是一个 Hash 函数</title>
      <description>&lt;p&gt;当我们把现有的应用升级到最新 Rails 版本 5 时，版本的更新将会将会对我们的程序有很多不同的影响。为了保持我们原有的快速开发与版本更新速度，我将分享一系列的文章为你的 Rails 版本更新做准备。&lt;/p&gt;

&lt;p&gt;在此次版本更新中，一个比较大的变化就是 ActionController::Parameters 的运作方式。ActionController::Parameters 是通过 params 来严格控制传进来 Controller 的参数，而在 Rails 5 新版本之前，params 一直是返回 Hash 函数，而现在它将返回对象。&lt;/p&gt;

&lt;p&gt;注意：这并不影响在 params hash 里的键值访问，例如 params[:id]。通过以下链接，我们可以看到新版本代码的变化：&lt;a href="https://github.com/rails/rails/pull/20868" rel="nofollow" target="_blank"&gt;https://github.com/rails/rails/pull/20868&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;我们可以通过在 params 上加上＃to_h 从而实现访问在对象里面的参数，请参考如下代码：
&lt;img src="https://l.ruby-china.com/photo/2015/ead95a71f351847f3827b0b6021300ac.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;如果 params 没有明确允许（permitted），则 params 只会返回一个包含允许的参数的 Hash，如果所有参数都没有明确允许，params 则只会返回一个空的 hash({})。如果你使用了未允许的 params，上述描述情况，这将会发生在运行#symbolize_keys 或者#slice 时。如果你正在访问没被保存到 model 或者 database 的 params，那么你可能没有明确允许那些参数返回。&lt;/p&gt;

&lt;p&gt;我们仔细观察 ActionController::Parameters 的#to_h 函数会发现，在将其转化为 Hash 前，会先检查 parameters 是否被允许。
&lt;img src="https://l.ruby-china.com/photo/2015/379c35ce5eab22c2ab14bdf6c54dc5f0.png" title="" alt=""&gt;
       让我们看一个后面用到的 slicing params 例子。下面是我们过去使用的 slice params 代码：
&lt;img src="https://l.ruby-china.com/photo/2015/86c8c2cadc0450079f2b36f2160a79c0.png" title="" alt=""&gt;
       返回的结果是：
&lt;img src="https://l.ruby-china.com/photo/2015/efb180bad951c3d844e5e4548cbf55c4.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;但是现在会返回一个 ActionController::Parameters 对象，而不是 Hash。&lt;/p&gt;

&lt;p&gt;在这里调用 #to_h 将会返回一个空的 hash，因为 param_1 和 param_2 都是不被允许的。&lt;/p&gt;

&lt;p&gt;从 ActionController::Parameters 中访问 params，你先要允许这些参数，然后在对象中调用#to_h。下面是之前调用 slice 返回的结果：
&lt;img src="https://l.ruby-china.com/photo/2015/ca29eb4437e849d5542918b54600361a.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;另一种避免返回空 hash 的方法是，使用 #to_unsafe_hash 函数，前提是你明确这些参数不是用户提供并且没有安全风险的情况下：
&lt;img src="https://l.ruby-china.com/photo/2015/99358ccae28e8f223437656ce5d18f40.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;在默认情况下，controller 和 action 的参数是允许返回的。如果你需要返回 controller 和 action 以外的参数，你可以设置在 application.rb 的配置，改为总是允许其他参数返回。注意：这将会返回 string keys 的 hash，而不是 symbol keys。&lt;/p&gt;

&lt;p&gt;配置选择：
&lt;img src="https://l.ruby-china.com/photo/2015/018c2e36801a9d579c2a0e4d1631ed4a.png" title="" alt=""&gt;
      调用 slice：
&lt;img src="https://l.ruby-china.com/photo/2015/2ae1647cff02935f835d0d2fa6952af5.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;如果你不确定是否有时间去升级 Rails 5，我会建议你提前为你的 Controller 代码准备好测试代码，尝试访问 params，这样当你升级的时候你就可以通过运行你的测试代码发现那些需要修改的 params。&lt;/p&gt;</description>
      <author>ashley</author>
      <pubDate>Tue, 03 Nov 2015 12:56:03 +0800</pubDate>
      <link>https://ruby-china.org/topics/27931</link>
      <guid>https://ruby-china.org/topics/27931</guid>
    </item>
    <item>
      <title>[翻译] 实例演示如何创建 Ruby Gem</title>
      <description>&lt;p&gt;最近抽空重新修改了前几天发出来的这篇翻译，有不准确的地方继续提出~~
             原文链接：&lt;a href="http://www.victorareba.com/tutorials/create-ruby-gem-by-example" rel="nofollow" target="_blank"&gt;http://www.victorareba.com/tutorials/create-ruby-gem-by-example&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;毫无疑问，包管理器在 rails 应用软件的开发上扮演着至关重要的角色。关于这点，我们只要想一想 Device，ActiveAdmin 和其他的 Ruby Gem 包就可以知道。然而，虽然我们每天都在使用它们，但是很少有开发人员去创建他们自己的 Gems。这可能是因为在某些实际的创建过程中缺乏清晰的文档，但是从某些方面说，一个 RoR 的开发人员可能已经至少有一次修改过或者创建过一个 gem 来完成他的工作任务。今天，我会带你一起创建一个范例 Gem 包。这是一个基于 The TVDB 来封装的 API Gem 包。你可以在这里查看 Gem TheTVDB 的源代码。  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;开始&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;我们会使用 bundler 这个非常流行的管理项目依赖性的工具。安装命令如下：
             $ gem install bundler
             bundler 安装完成后，我们将创建一个 gem，就叫它 thetvdb 吧：
             $ bundle gem thetvdb
             然后进入这个 gem 目录
             $ cd thetvdb
             列出 gem 文件夹中的文件和文件夹，你会见到如下内容：
&lt;img src="https://l.ruby-china.com/photo/2015/9015cc412aa4cc9b824deb96584e41cb.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Gemspec&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;现在让我们来看看有趣的 gemspec 文件，在我的这个例子中的文件名是 thetvdb.gemspec，它定义了 gem 的配置。我将会加入关于 thetvdb gem 的元数据。
&lt;img src="https://l.ruby-china.com/photo/2015/bd1ef02064655bf55e51ec599bfb51f6.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;版本控制&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;gem 的版本信息会保留在 lib 目录里以 gem 名称命名的目录下的 version.rb 脚本里（在我们的例子里是 lib/thetvdb/version.rb）。版本号是由 3 个用点号分隔的数字字符串组成，格式为“X.X.X”&lt;/p&gt;

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

&lt;p&gt;&lt;strong&gt;功能性&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;现在我们介绍到 gem 的功能性。首先，现在我将要继续添加两个从属物，那就是我们将要利用其余的 i.e 客户端和引入 nokogiri 到 Gemfile。
&lt;img src="https://l.ruby-china.com/photo/2015/1771d0d586a6920bec1fd0f8189b4855.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;然后运行 bundler
            $ bundle install
            在 lib/thetvdb.rb 的文件里调用这两个依赖包。注意，我们需要指定 gem 版本。
&lt;img src="https://l.ruby-china.com/photo/2015/e2af9ddfed3dad0e5a4cc0fd263199e0.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;接下来我会在/lib/thetvdb 目录下创建 client.rb 文件。这个文件会包装 API 的查询。最后，如下完成剩余的代码。
&lt;img src="https://l.ruby-china.com/photo/2015/a2766a7bb1eaeaca015040ac03c85d48.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;get_show&lt;/strong&gt;方法返回节目单以及详细介绍&lt;/p&gt;

&lt;p&gt;注意 ruby 常数 API_KEY，我把它作为一个口令牌来解析。在这个时候我们还没有声明这个常数。我们需要用户在安装 gem 的时候生成一个 initizlier 文件，然后添加他们自己的 TVDB api 密钥。完成这个步骤后，我们需要在 lib/目录下创建一个名为 generators 的目录，然后在这个目录里创建 thetvdb_genrator.rb 的文件。添加如下代码。
&lt;img src="https://l.ruby-china.com/photo/2015/df34ccdc32d30279ea04904d54427c42.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;第二行 source_root 指向我们存放的 generator 模板的地方。在 generators 目录下创建 templates 目录，并在这个目录下创建一个 thetvdb.rb 文件，代码如下。
&lt;img src="https://l.ruby-china.com/photo/2015/783eafb0a735d77b66ec0c2905b94aba.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;最后，包含 client.rb 在我们的/lib/theevdb.rb 这个主文件里，并添加如下代码。
&lt;img src="https://l.ruby-china.com/photo/2015/d19c513157947205876726875c8b5613.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;构建&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;我们使用这个命令来构建 gem
               $ gem build thetvdb.gemspec
              完成构建之后我们就可以推到 ruby gems 网站了
&lt;img src="https://l.ruby-china.com/photo/2015/704cbad66f574308850a8a73c81c2a5d.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;或者如果你想现在本地单机测试一下，你可以安装这个 gem
              $ gem install thetvdb-ruby-0.1.0.gem&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;测试&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;测试如果我们的 gem 是正常运作，那就创建一个 rail 应用软件，然后添加这个 gem 到 Gemfile
&lt;img src="https://l.ruby-china.com/photo/2015/479b60ca42989934fc6e5747cd4dd3fe.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;然后运行 bundler
             $ bundle install&lt;/p&gt;

&lt;p&gt;为 TVDb API 创建初始化文件
             $ rails generate thetvdb&lt;/p&gt;

&lt;p&gt;将你的 API 密钥放在初始化的 thetvdb.rb 文件里。如果你还没有 API 密钥，可以使用我这个。
&lt;img src="https://l.ruby-china.com/photo/2015/0aae56d13228ccf13b810e804628e843.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;在某些 controller 的 action 中，我通过调用 Thetvdb 的 get_show 方法搜索我最喜爱的电视节目“极速前进”。
&lt;img src="https://l.ruby-china.com/photo/2015/c4d001218572d7806e3c2bfcf3f408fc.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;在载入本地服务时，我收到了 JSON 格式的节目单和节目介绍。
&lt;img src="https://l.ruby-china.com/photo/2015/b6e4eac0bce192a44184943e9e0890a5.png" title="" alt=""&gt;
&lt;img src="https://l.ruby-china.com/photo/2015/9d913a25dc0fc7053e3d597214c8ca66.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>ashley</author>
      <pubDate>Thu, 22 Oct 2015 12:07:09 +0800</pubDate>
      <link>https://ruby-china.org/topics/27779</link>
      <guid>https://ruby-china.org/topics/27779</guid>
    </item>
    <item>
      <title>[翻译] 在 Ruby 上什么时候用 freeze 和 frozen？</title>
      <description>&lt;p&gt;找到篇好文，闲来无事翻译成中文，分享给大伙。欢迎随时讨论~~
原文链接：&lt;a href="http://blog.honeybadger.io/when-to-use-freeze-and-frozen-in-ruby/" rel="nofollow" target="_blank"&gt;http://blog.honeybadger.io/when-to-use-freeze-and-frozen-in-ruby/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;如今我们经常看到 freeze 应用在 Ruby 代码中。但对于为什么要用 freeze（冻结）往往不完全清楚。在这遍文章中，我们将了解开发人员会采取冻结变量的几种最常见理由。为了清楚的描述各种情况，我从 Rails 代码库和其他主流的开 源 项 目中摘录了代码来举例。&lt;/p&gt;

&lt;p&gt;创建不变的常量&lt;/p&gt;

&lt;p&gt;在 Ruby 语言中，常量是可变的。这有点让人困惑，但从代码中能轻易的理解到这一点。下面，我创建一组字符常量，并且同时添加另一组字符上去。
&lt;img src="https://l.ruby-china.com/photo/2015/79f99082e6775d8a1e1bc4bec3168dd6.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;通过运用 freeze，我可以创建一个真正意义上的常量。这回，当我尝试修改字符，得到的结果是 RuntimeError。&lt;br&gt;
&lt;img src="https://l.ruby-china.com/photo/2015/a0b61f6464dfa8422d22cdb6a125df57.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;这是一个在 ActionDispatch 代码库上真实的例子。Rails 用文本“[FILTERED]”来替换在日志中敏感数据而达到隐藏数据的效果。这个文本正是储存在冻结常量中。
&lt;img src="https://l.ruby-china.com/photo/2015/2a36793eaf3e614379e87e42e2484b15.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;减少对象分配&lt;/p&gt;

&lt;p&gt;给你的 Ruby app 加速的最佳方法之一是减少已创建对象的数量。关于对象分配一个让人头疼的原因来自散落在大多数应用中到处都是的字符串。
每次你调用一函数，例如是 log(“foobar”)，你就要新建一个字符串对象。如果你的代码每秒要调用上千次函数，这就意味着你每秒要创建上千个字符串。这样工作量就很大了。
幸运的是，Ruby 给了我们一种优化的方式。如果我们冻结一个字符串常量，那么 Ruby 的解析器就只会创建一个字符串对象，并且会储存起来备将来使用。这这里，我将 frozen 和 non-frozen 的字符串进行了性能对比，结果显示性能提升了 50%。
&lt;img src="https://l.ruby-china.com/photo/2015/d8c6e8e282e03ac82707820ec9943f3a.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;你可以通过 Rail router 来看到运行过程。Router 用于响应每个网页的要求，必须要运行的很快，这就需要许多 frozen 的字符串常量。
&lt;img src="https://l.ruby-china.com/photo/2015/0e6fef5554b45a7a15fe9cb9210bf6db.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;Ruby2.2 和之后版本的软件内置优化&lt;/p&gt;

&lt;p&gt;Ruby 2.2 及后续版本（MRI）会自动冻结含有散列键的字符串常量。
&lt;img src="https://l.ruby-china.com/photo/2015/09a6483207d2e94aba5868384b4ede28.png" title="" alt=""&gt;&lt;/p&gt;

&lt;p&gt;而且根据 Matz 公布的消息，在 Ruby3 的所有字符串常量将会被自动冻结。&lt;/p&gt;

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

&lt;p&gt;对象的取值和函数式编程&lt;/p&gt;

&lt;p&gt;尽管 Ruby 不是一种函数式编程语言，但是许多使用者都开始注意到里面函数样式的价值。这种样式的一个主要宗旨是，要防止外部修改。对象初始化之后不应发生改变。
通过在构造器里调用 freeze 函数，保证了对象不会更改。任何意外的外部修改都会导致异常值的出现。&lt;/p&gt;

&lt;p&gt;&lt;img src="https://l.ruby-china.com/photo/2015/5af8c469f874a6b54e0d15ee90b2da7b.png" title="" alt=""&gt;&lt;/p&gt;</description>
      <author>ashley</author>
      <pubDate>Tue, 29 Sep 2015 17:36:27 +0800</pubDate>
      <link>https://ruby-china.org/topics/27521</link>
      <guid>https://ruby-china.org/topics/27521</guid>
    </item>
  </channel>
</rss>
