<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">

  <title><![CDATA[Ruby 迷]]></title>
  <link href="http://rubyer.me/atom.xml" rel="self"/>
  <link href="http://rubyer.me/"/>
  <updated>2013-12-22T23:45:54+08:00</updated>
  <id>http://rubyer.me/</id>
  <author>
    <name><![CDATA[Cam Song]]></name>
    <email><![CDATA[neosoyn@gmail.com]]></email>
  </author>
  <generator uri="http://octopress.org/">Octopress</generator>

  
  <entry>
    <title type="html"><![CDATA[GitHub Mate: 单文件下载更方便]]></title>
    <link href="http://rubyer.me/blog/2013/12/20/github-mate/"/>
    <updated>2013-12-20T20:31:55+08:00</updated>
    <id>http://rubyer.me/blog/2013/12/20/github-mate</id>
    <content type="html"><![CDATA[<p>GitHub 不是 Dropbox，GitHub 侧重的是代码分享，而不是文件存储，比如曾经有的文档上传功能也被砍掉了 <a href="https://github.com/blog/1302-goodbye-uploads">Goodbye, Uploads</a>。 而且 GitHub 还有意让文件下载复杂化，每次想下载一个文件都要右键Raw，然后目标另存为，请问还能做的再麻烦一点吗。
Git 本身不像 SVN 支持目录或文件克隆，所以对于体积大的项目，又是网速差的环境只能==了。</p>

<p>所以才写了 <a href="https://chrome.google.com/webstore/detail/github-mate/baggcehellihkglakjnmnhpnjmkbmpkf">GitHub Mate</a> 这个 Chrome 插件，完全开源：<a href="https://github.com/camsong/chrome-github-mate">源码</a></p>

<p>目前源码逻辑很简单，有两个功能，一个是点击文件图标下载文件，实现逻辑在<a href="https://github.com/camsong/chrome-github-mate/blob/master/script.js#L3">这里</a>。
主要有3步：</p>

<ol>
<li>在 document 上代理所有文件图标上的 click 事件，这样不用分别绑定事件，而且支持 GitHub 的 Pjax。</li>
<li>根据点击的图标计算出文件的实际下载路径。</li>
<li>添加一个匿名<code>a</code>标签，并使用HTML5的 <code>download</code> 属性来设置下载路径，模拟点击<code>a</code>标签开始下载。</li>
</ol>


<p>另一个功能是显示未读通知（notification）数，通过添加一个定时器去抓取notification页面，方法很原始。其实对于我这种不太活跃的所谓“开源爱好者“没啥用处，基本不会有什么通知，以后会做成可选的，节省资源。</p>

<p>未来考虑支持文件夹下载，初步想法是找类似 Heroku, Nitrous.io 这种免费的服务来做后台自动clone仓库，并打包文件夹，然后回传地址，这样做实现起来不难，关键是对于大项目延迟会比较大，小项目下载文件夹速度提升又不大，还需要在考虑考虑。</p>

<p>不得不说，Chrome 插件体系设计实在太简洁了，而且对插件(extension)和应用(app)都有很好的支持和细分。
<a href="https://developer.chrome.com/extensions/getstarted.html">官方文档</a> 示例都非常赞。有人说Chrome web store未来会替代Google Play和App Store，目前我只能“呵呵”，以后逆袭也不一定。</p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Ruby Simple HTTP Server With Rack]]></title>
    <link href="http://rubyer.me/blog/2012/12/12/ruby-simple-http-server-with-rack/"/>
    <updated>2012-12-12T14:56:00+08:00</updated>
    <id>http://rubyer.me/blog/2012/12/12/ruby-simple-http-server-with-rack</id>
    <content type="html"><![CDATA[<p>最近使用JavaScript比较多，如果是静态页面，Chrome AJAX请求本地文件经常会出现。</p>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>XMLHttpRequest cannot load
</span><span class='line'>file:///*******. 
</span><span class='line'>Origin null is not allowed by Access-Control-Allow-Origin.</span></code></pre></td></tr></table></div></figure>


<p>这里因为Chrome安全机制不允许AJAX加载本地文件，你可以启动Chrome时加参数<code>chrome.exe --allow-file-access-from-files</code>。
但我不喜欢这种方法，偏好启动一个web server。</p>

<p>Python 2.* 的做法是<code>python -m SimpleHTTPServer</code>，Python 3.* 的做法是<code>python -m http.server</code>，Ruby的做法也非常简单。</p>

<p>2步搞定：</p>

<h3>1. 安装rack，并新建rack配置文件config.ru：</h3>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>gem install rack
</span><span class='line'>echo "run Rack::Directory.new('')" &gt; ~/config.ru</span></code></pre></td></tr></table></div></figure>


<h3>2. 切换到任意目录运行</h3>

<figure class='code'><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class=''><span class='line'>rackup ~/config.ru</span></code></pre></td></tr></table></div></figure>


<p>如果觉得命令长就建立alias <code>alias rp='rackup ~/config.ru'</code></p>

<p>默认启动的server端口是9292，<code>-p [port_num]</code>可以修改端口号，打开浏览器即可当前目录的文件列表：
<a href="http://locahost:9292/">http://locahost:9292/</a></p>

<h3>Appendix: rack and rackup</h3>

<h4>Rack:</h4>

<p>Rack provides a minimal, modular and adaptable interface for developing web applications in Ruby. By wrapping HTTP requests and responses in the simplest way possible, it unifies and distills the API for web servers, web frameworks, and software in between (the so-called middleware) into a single method call.</p>

<h4>Rackup:</h4>

<p>Rackup is a useful tool for running Rack applications, which uses the Rack::Builder DSL to configure middleware and build up applications easily.</p>

<h3>Thanks to</h3>

<p><a href="http://blog.samsonis.me/2010/02/rubys-python-simplehttpserver/">http://blog.samsonis.me/2010/02/rubys-python-simplehttpserver/</a></p>

<p><a href="https://github.com/rack/rack">https://github.com/rack/rack</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Advanced Rails Debug]]></title>
    <link href="http://rubyer.me/blog/2012/09/18/advanced-rails-debug/"/>
    <updated>2012-09-18T18:32:00+08:00</updated>
    <id>http://rubyer.me/blog/2012/09/18/advanced-rails-debug</id>
    <content type="html"><![CDATA[<p>这是我在<a href="http://ruby-china.org/topics/5582">Ruby Tuesday</a>上分享的记录，介绍几种调试Rails程序的方法</p>

<h3>1. ruby-debug, ruby-debug19</h3>

<p>没人维护，bug多。Ruby 1.9.3后不推荐使用</p>

<h3>2. debugger</h3>

<p>ruby 1.9.3后的选择，功能强大，缺点是没有语法高亮。</p>

<h4>项目中引用debugger方法</h4>

<p>修改Gemfile</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">group</span> <span class="ss">:development</span><span class="p">,</span> <span class="ss">:test</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">gem</span> <span class="s1">&#39;debugger&#39;</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>在需要设置断点的地方：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">require</span> <span class="s1">&#39;debugger&#39;</span><span class="p">;</span> <span class="n">debugger</span>
</span></code></pre></td></tr></table></div></figure>


<h4>查看源文件方法</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">list</span>       <span class="c1">#往后翻看代码</span>
</span><span class='line'><span class="n">list</span><span class="o">-</span> <span class="o">[</span><span class="n">n</span><span class="o">]</span>  <span class="c1">#往前翻看代码</span>
</span><span class='line'><span class="n">list</span><span class="o">=</span>      <span class="c1">#查看当前运行处代码</span>
</span></code></pre></td></tr></table></div></figure>


<p>list可以缩写为l</p>

<h4>查看方法栈（stack frames）</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">backtrace</span><span class="o">/</span><span class="n">where</span>               <span class="c1"># 查看</span>
</span><span class='line'><span class="n">frame</span> <span class="o">[</span><span class="n">n</span><span class="o">]</span>                     <span class="c1"># 跳到指定stack frames</span>
</span><span class='line'><span class="n">up</span> <span class="o">[</span><span class="n">n</span><span class="o">]</span> <span class="p">(</span><span class="err">缩写</span><span class="n">u</span><span class="p">)</span> <span class="err">和</span> <span class="n">down</span> <span class="o">[</span><span class="n">n</span><span class="o">]</span>     <span class="c1"># 在stack frames层里来回切换</span>
</span></code></pre></td></tr></table></div></figure>


<h4>执行控制</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">next</span>           <span class="c1"># 执行下一行，遇到方法调用不进入。</span>
</span><span class='line'><span class="n">step</span>           <span class="c1"># 执行一步，遇到方法调用进入。</span>
</span><span class='line'><span class="n">continue</span><span class="o">/</span><span class="n">c</span>     <span class="c1"># 执行到下一个断点。</span>
</span><span class='line'><span class="n">finish</span> <span class="o">[</span><span class="n">n</span><span class="o">]</span>     <span class="c1"># 执行到指定的frame才返回。注意编号是从下往上数。</span>
</span></code></pre></td></tr></table></div></figure>


<h4>其它常用命令</h4>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">help</span>
</span><span class='line'><span class="n">info</span>
</span></code></pre></td></tr></table></div></figure>


<h3>3. pry</h3>

<p>替代irb，我最喜欢的是语法高亮。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">help</span>
</span><span class='line'><span class="n">cd</span> <span class="o">.</span><span class="n">.</span>
</span><span class='line'><span class="n">whereami</span>
</span><span class='line'><span class="nb">self</span>
</span><span class='line'><span class="n">ls</span>
</span><span class='line'><span class="n">show</span><span class="o">-</span><span class="n">doc</span>
</span><span class='line'><span class="n">show</span><span class="o">-</span><span class="nb">method</span>
</span><span class='line'><span class="n">edit</span><span class="o">-</span><span class="nb">method</span>
</span></code></pre></td></tr></table></div></figure>


<h4>pry-nav</h4>

<p>pry只是替代erb，并不能调试rails，加上rails后即可pry-nav。
增加3种基本调试指令。</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">step</span>
</span><span class='line'><span class="k">next</span>
</span><span class='line'><span class="n">continue</span>
</span></code></pre></td></tr></table></div></figure>


<h4>pry-stack_explorer</h4>

<p>Pry的插件，用于查看方法栈</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="p">(</span><span class="n">pry</span><span class="p">)</span> <span class="n">main</span><span class="p">:</span> <span class="mi">0</span><span class="o">&gt;</span> <span class="n">show</span><span class="o">-</span><span class="n">stack</span>
</span><span class='line'>
</span><span class='line'><span class="no">Showing</span> <span class="n">all</span> <span class="n">accessible</span> <span class="n">frames</span> <span class="k">in</span> <span class="n">stack</span> <span class="p">(</span><span class="mi">5</span> <span class="k">in</span> <span class="n">total</span><span class="p">):</span>
</span><span class='line'><span class="o">--</span>
</span><span class='line'><span class="o">=&gt;</span> <span class="c1">#0 [method] gamma</span>
</span><span class='line'>   <span class="c1">#1 [method] beta</span>
</span><span class='line'>   <span class="c1">#2 [method] alpha</span>
</span></code></pre></td></tr></table></div></figure>


<h4>使用pry调试rails项目</h4>

<p>修改Gemfile</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">group</span> <span class="ss">:development</span><span class="p">,</span> <span class="ss">:test</span> <span class="k">do</span>
</span><span class='line'>  <span class="n">gem</span> <span class="s1">&#39;pry&#39;</span>
</span><span class='line'>  <span class="n">gem</span> <span class="s1">&#39;pry-nav&#39;</span>
</span><span class='line'>  <span class="n">gem</span> <span class="s1">&#39;pry-stack_explorer&#39;</span> <span class="c1"># 如果不查看方法栈，可以省略</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<p>在需要设置断点的地方：</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="nb">binding</span><span class="o">.</span><span class="n">pry</span>
</span></code></pre></td></tr></table></div></figure>


<h3>4. 参考</h3>

<p><a href="https://github.com/cldwalker/debugger">https://github.com/cldwalker/debugger</a></p>

<p><a href="https://github.com/pry/pry">https://github.com/pry/pry</a></p>

<p><a href="https://github.com/pry/pry-stack_explorer">https://github.com/pry/pry-stack_explorer</a></p>

<p><a href="http://guides.rubyonrails.org/debugging_rails_applications.html">http://guides.rubyonrails.org/debugging_rails_applications.html</a></p>
]]></content>
  </entry>
  
  <entry>
    <title type="html"><![CDATA[Speed Up With Rails Cache]]></title>
    <link href="http://rubyer.me/blog/2012/09/04/speed-up-with-rails-cache/"/>
    <updated>2012-09-04T10:51:00+08:00</updated>
    <id>http://rubyer.me/blog/2012/09/04/speed-up-with-rails-cache</id>
    <content type="html"><![CDATA[<p>这是我在<a href="http://ruby-china.org/topics/5281">Ruby Tuesday</a>上分享的记录，介绍Rails缓存的使用方法</p>

<h4>Two Big Problems</h4>

<blockquote><p>There are only two hard problems in Computer Science: cache
invalidation and naming things. &ndash; Phil Karlton</p></blockquote>

<p>Fortunately, Rails has made it perfect!</p>

<h3>启用缓存</h3>

<p>默认development模式禁用缓存，production环境启用缓存</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">config</span><span class="o">.</span><span class="n">action_controller</span><span class="o">.</span><span class="n">perform_caching</span> <span class="o">=</span> <span class="kp">true</span>
</span></code></pre></td></tr></table></div></figure>


<h3>缓存核心：<code>Rails.cache</code></h3>

<p>3种基本操作</p>

<ul>
<li><p>读
<code>Rails.cache.write 'foo', 'bar'</code></p></li>
<li><p>写
<code>Rails.cache.read 'foo'</code></p></li>
<li><p>不存在则写，存在则读</p></li>
</ul>


<p><code>Rails.cache.fetch 'a_big_data' do { (1..1000000).inject(:+) }</code></p>

<p>缓存默认是以文件形式保存，文件位置
<code>./tmp/cache</code></p>

<h3>缓存原理</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">body_html</span>
</span><span class='line'>  <span class="no">Rails</span><span class="o">.</span><span class="n">cache</span><span class="o">.</span><span class="n">fetch</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">cache_key</span><span class="si">}</span><span class="s2">/body_html&quot;</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">render</span><span class="p">(</span><span class="n">body</span><span class="p">)</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h3>缓存策略</h3>

<ul>
<li><code>Rails.cache</code></li>
<li>Fragment caching</li>
<li>Action caching</li>
<li>Page caching</li>
<li>HTTP caching</li>
</ul>


<h3>Fragment Caching</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
<span class='line-number'>11</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="o">&lt;</span><span class="sx">%= cache @post do %&gt;</span>
</span><span class='line'><span class="sx">  &lt;p&gt;</span>
</span><span class='line'><span class="sx">    &lt;b&gt;Title:&lt;/b&gt;</span>
</span><span class='line'><span class="sx">    &lt;%=</span> <span class="vi">@post</span><span class="o">.</span><span class="n">title</span> <span class="sx">%&gt;</span>
</span><span class='line'><span class="sx">  &lt;/p&gt;</span>
</span><span class='line'>
</span><span class='line'>  <span class="o">&lt;</span><span class="nb">p</span><span class="o">&gt;</span>
</span><span class='line'>    <span class="o">&lt;</span><span class="n">b</span><span class="o">&gt;</span><span class="no">Content</span><span class="p">:</span><span class="o">&lt;</span><span class="sr">/b&gt;</span>
</span><span class='line'><span class="sr">    &lt;%= @post.content %&gt;</span>
</span><span class='line'><span class="sr">  &lt;/</span><span class="nb">p</span><span class="o">&gt;</span>
</span><span class='line'><span class="o">&lt;</span><span class="sx">% end </span><span class="o">%&gt;</span>
</span></code></pre></td></tr></table></div></figure>


<p>手动设置过期</p>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">expire_fragment</span><span class="p">(</span><span class="ss">:controller</span> <span class="o">=&gt;</span> <span class="s1">&#39;products&#39;</span><span class="p">,</span> <span class="ss">:action</span> <span class="o">=&gt;</span> <span class="s1">&#39;recent&#39;</span><span class="p">,</span>
</span><span class='line'><span class="ss">:action_suffix</span> <span class="o">=&gt;</span> <span class="s1">&#39;all_products&#39;</span><span class="p">)</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Fragment Caching 效果</h3>

<p><img src="http://rubyer.me/fragment-caching-result.png" alt="Fragment caching result" /></p>

<h3>Fragment Caching key生成策略</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">cache</span> <span class="s1">&#39;explicit-key&#39;</span>      <span class="c1"># views/explicit-key</span>
</span><span class='line'><span class="n">cache</span> <span class="vi">@post</span>               <span class="c1"># views/posts/2-1283479827349</span>
</span><span class='line'><span class="n">cache</span> <span class="o">[</span><span class="vi">@post</span><span class="p">,</span> <span class="s1">&#39;sidebar&#39;</span><span class="o">]</span>  <span class="c1"># views/posts/2-2348719328478/sidebar</span>
</span><span class='line'><span class="n">cache</span> <span class="o">[</span><span class="vi">@post</span><span class="p">,</span> <span class="vi">@comment</span><span class="o">]</span>   <span class="c1">#</span>
</span><span class='line'><span class="n">views</span><span class="o">/</span><span class="n">posts</span><span class="o">/</span><span class="mi">2</span><span class="o">-</span><span class="mi">2384193284878</span><span class="o">/</span><span class="n">comments</span><span class="o">/</span><span class="mi">1</span><span class="o">-</span><span class="mi">2384971487</span>
</span><span class='line'><span class="n">cache</span> <span class="ss">:hash</span> <span class="o">=&gt;</span> <span class="ss">:of_things</span> <span class="c1"># views/localhost:3000/posts/2?hash_of_things</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Action Caching</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">caches_action</span> <span class="ss">:index</span><span class="p">,</span> <span class="ss">:cache_path</span> <span class="o">=&gt;</span> <span class="nb">proc</span> <span class="p">{</span><span class="o">|</span><span class="n">c</span><span class="o">|</span> <span class="p">{</span> <span class="ss">:tag</span> <span class="o">=&gt;</span>
</span><span class='line'><span class="no">Post</span><span class="o">.</span><span class="n">maximum</span><span class="p">(</span><span class="s1">&#39;updated_at&#39;</span><span class="p">)</span> <span class="p">}</span> <span class="p">}</span>
</span></code></pre></td></tr></table></div></figure>


<h3>Page Caching</h3>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="n">caches_page</span> <span class="ss">:index</span>
</span></code></pre></td></tr></table></div></figure>


<p>特点：
* 很快但无用
* 第一次访问时会在<code>public</code>目录生成静态html结尾文件，此后访问就会跳过所有validation和filter。</p>

<h3>HTTP Caching</h3>

<h5>报文头：</h5>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="no">Cache</span><span class="o">-</span><span class="no">Control</span><span class="p">:</span> <span class="n">max</span><span class="o">-</span><span class="n">age</span><span class="o">=</span><span class="mi">0</span><span class="p">,</span> <span class="kp">private</span><span class="p">,</span> <span class="n">must</span><span class="o">-</span><span class="n">revalidate</span>
</span></code></pre></td></tr></table></div></figure>


<h5>示例：</h5>

<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">show</span>
</span><span class='line'>  <span class="vi">@post</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">find</span> <span class="n">params</span><span class="o">[</span><span class="ss">:id</span><span class="o">]</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="n">stale?</span> <span class="vi">@post</span><span class="p">,</span> <span class="ss">:etag</span> <span class="o">=&gt;</span> <span class="vi">@post</span><span class="o">.</span><span class="n">posted_at</span> <span class="k">do</span>
</span><span class='line'>    <span class="n">respond_with</span> <span class="vi">@post</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>




<figure class='code'><figcaption><span></span></figcaption><div class="highlight"><table><tr><td class="gutter"><pre class="line-numbers"><span class='line-number'>1</span>
<span class='line-number'>2</span>
<span class='line-number'>3</span>
<span class='line-number'>4</span>
<span class='line-number'>5</span>
<span class='line-number'>6</span>
<span class='line-number'>7</span>
<span class='line-number'>8</span>
<span class='line-number'>9</span>
<span class='line-number'>10</span>
</pre></td><td class='code'><pre><code class='ruby'><span class='line'><span class="k">def</span> <span class="nf">index</span>
</span><span class='line'>  <span class="vi">@posts</span> <span class="o">=</span> <span class="no">Post</span><span class="o">.</span><span class="n">all</span>
</span><span class='line'>
</span><span class='line'>  <span class="k">if</span> <span class="n">stale?</span><span class="p">(</span><span class="ss">:last_modified</span> <span class="o">=&gt;</span> <span class="vi">@posts</span><span class="o">.</span><span class="n">last</span><span class="o">.</span><span class="n">updated_at</span><span class="o">.</span><span class="n">utc</span><span class="p">)</span>
</span><span class='line'>    <span class="n">respond_to</span> <span class="k">do</span> <span class="o">|</span><span class="nb">format</span><span class="o">|</span>
</span><span class='line'>      <span class="nb">format</span><span class="o">.</span><span class="n">html</span> <span class="c1"># index.html.erb</span>
</span><span class='line'>      <span class="nb">format</span><span class="o">.</span><span class="n">json</span> <span class="p">{</span> <span class="n">render</span> <span class="n">json</span><span class="p">:</span> <span class="vi">@posts</span> <span class="p">}</span>
</span><span class='line'>    <span class="k">end</span>
</span><span class='line'>  <span class="k">end</span>
</span><span class='line'><span class="k">end</span>
</span></code></pre></td></tr></table></div></figure>


<h5>特点：</h5>

<ul>
<li>如果没有修改，直接返回304，不需要返回网页内容</li>
<li>最有效的缓存方式</li>
<li>工作在协议层，更快</li>
<li>使用HTTP头(Last-Modified, ETag, If-Modified-Since, If-None-Match,
Cache-Control)</li>
</ul>


<h3>Tips</h3>

<ul>
<li>别碰swapper，除非非它不可。</li>
<li>为所有缓存使用自动过期的key。</li>
<li>经常把 <code>belongs to</code> 和 <code>:touch =&gt; true</code> 结合使用</li>
<li>使用 <code>Rails.cache</code> 来缓存查询到的数据</li>
<li>在每次部署应用后不要忘记设置ENV[&lsquo;RAILS_APP_VERSION&rsquo;]</li>
<li>一定要缓存你的assets静态文件。</li>
<li>缓存粒度一定要小，以此提高命中率</li>
</ul>


<h3>Thanks to</h3>

<p><a href="http://www.broadcastingadam.com/2012/07/advanced_caching_revised/">http://www.broadcastingadam.com/2012/07/advanced_caching_revised/</a></p>

<p><a href="http://guides.rubyonrails.org/caching_with_rails.html">http://guides.rubyonrails.org/caching_with_rails.html</a></p>

<p><a href="http://railslab.newrelic.com/scaling-rails">http://railslab.newrelic.com/scaling-rails</a></p>
]]></content>
  </entry>
  
</feed>
