<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Proxima Fermata</title>
	<atom:link href="http://blog.larus.jp/?feed=rss2" rel="self" type="application/rss+xml" />
	<link>http://blog.larus.jp</link>
	<description>日々是停留</description>
	<lastBuildDate>Wed, 18 Apr 2012 17:54:56 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>JOINは遅い？</title>
		<link>http://blog.larus.jp/?p=560</link>
		<comments>http://blog.larus.jp/?p=560#comments</comments>
		<pubDate>Wed, 18 Apr 2012 07:36:05 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=560</guid>
		<description><![CDATA[MySQLのJOINが遅いというのはよく言われるが、複数回SQLを発行するのとJOINするのがどちらがましなのか疑問だったので、実際どのくらい遅いのか試してみた。 Rails3.2のプロジェクトを作成し、適当なモデルを作ってconsoleでSQLの実行時間を見る。 サンプルコードはgithubに置いた。 モデルはUser -&#60; Item -&#60; Extraで、Userは100、Itemは10ずつで1000、Extraは10ずつで合計10000のレコードを作成することにする。 seed_fuのフィクスチャを使い、rake db:seed_fuで一気にレコードが作成されるようにした。 この状態（commit:830f6dae26189d4ea83b8753471a166712d50568）で全てのエントリを取得させてみた。 User全件(100件) > User.all.count # SELECT `users`.* FROM `users` => 1.0ms Item全件(100*10件) 1.JOINした場合 > User.joins(:items).all.count # SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id` => 3.2ms 2.JOINせず複数回SQLした場合 > Item.where(:user_id =&#62; User.where(:id =&#62; {:not =&#62; nil}).pluck(:id)).all.count # SELECT id FROM `users` WHERE (`users`.`id` [...]]]></description>
			<content:encoded><![CDATA[<p>MySQLのJOINが遅いというのはよく言われるが、複数回SQLを発行するのとJOINするのがどちらがましなのか疑問だったので、実際どのくらい遅いのか試してみた。</p>
<p>Rails3.2のプロジェクトを作成し、適当なモデルを作ってconsoleでSQLの実行時間を見る。<br />
サンプルコードは<a href="https://github.com/nysalor/rails_join" target="_blank">githubに置いた</a>。<br />
モデルはUser -&lt; Item -&lt; Extraで、Userは100、Itemは10ずつで1000、Extraは10ずつで合計10000のレコードを作成することにする。<br />
seed_fuのフィクスチャを使い、rake db:seed_fuで一気にレコードが作成されるようにした。</p>
<p>この状態（<a href="https://github.com/nysalor/rails_join/commit/830f6dae26189d4ea83b8753471a166712d50568" target="_blank">commit:830f6dae26189d4ea83b8753471a166712d50568</a>）で全てのエントリを取得させてみた。</p>
<p><strong>User全件(100件)</strong></p>
<pre>
> User.all.count
# SELECT `users`.* FROM `users`
=> 1.0ms
</pre>
<p><strong>Item全件(100*10件)</strong><br />
<em>1.JOINした場合</em></p>
<pre>
> User.joins(:items).all.count
# SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id`
=> 3.2ms
</pre>
<p><em>2.JOINせず複数回SQLした場合</em></p>
<pre>
> Item.where(:user_id =&gt; User.where(:id =&gt; {:not =&gt; nil}).pluck(:id)).all.count
# SELECT id FROM `users` WHERE (`users`.`id` IS NOT NULL)
# SELECT `items`.* FROM `items` WHERE `items`.`user_id` IN (1..100)
=> 0.6ms + 4.5ms = 5.1ms
</pre>
<p><strong>Extra全件(100*10*10件)</strong><br />
<em>1.JOINした場合</em></p>
<pre>
> User.joins(:items =&gt; :extras).all.count
# SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id` INNER JOIN `extras` ON `extras`.`item_id` = `items`.`id`
=> 35.4ms
</pre>
<p><em>2.JOINせず複数回SQLした場合</em></p>
<pre>
> Extra.where(:item_id =&gt; (Item.where(:user_id =&gt; User.where(:id =&gt; {:not =&gt; nil}).pluck(:id)).pluck(:id))).all.count
# SELECT id FROM `users` WHERE (`users`.`id` IS NOT NULL)
# SELECT id FROM `items` WHERE `items`.`user_id` IN (1..100)
# SELECT `extras`.* FROM `extras` WHERE `extras`.`item_id` IN (1..1000)
=> 0.6ms + 1.8ms + 30.9ms = 33.3ms
</pre>
<p>このケースだとあまり差が出ないので、Extraの件数を10倍にしてみた。（<a href="https://github.com/nysalor/rails_join/commit/96ee43e9319a363666033ac725950283bb80fab8" target="_blank">commit:96ee43e9319a363666033ac725950283bb80fab8</a>）</p>
<p><strong>Extra全件(100*10*100件)</strong><br />
<em>1.JOINした場合</em></p>
<pre>
> User.joins(:items =&gt; :extras).all.count
# SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id` INNER JOIN `extras` ON `extras`.`item_id` = `items`.`id`
=> 358.9ms
</pre>
<p><em>2.JOINせず複数回SQLした場合</em></p>
<pre>
> Extra.where(:item_id =&gt; (Item.where(:user_id =&gt; User.where(:id =&gt; {:not =&gt; nil}).pluck(:id)).pluck(:id))).all.count
# SELECT id FROM `users` WHERE (`users`.`id` IS NOT NULL)
# SELECT id FROM `items` WHERE `items`.`user_id` IN (1..100)
# SELECT `extras`.* FROM `extras` WHERE `extras`.`item_id` IN (1..1000)
=> 0.7ms + 1.9ms + 303.0ms = 305.6ms
</pre>
<p>件数が増えるほど差が広がっている。件数が多い時はJOINしない方が良さそうではある。<br />
まぁ、300msもかかるようだと他の高速化手段を取るべきだろうけど。</p>
<p>ついでにindexを追加してみた。（<a href="https://github.com/nysalor/rails_join/commit/bac53fb2569b5a681a6bacad3e8c13535e4aa141" target="_blank">commit:bac53fb2569b5a681a6bacad3e8c13535e4aa141</a>）</p>
<p><strong>Item全件(100*10件)</strong><br />
<em>1.JOINした場合</em></p>
<pre>
> User.joins(:items).all.count
# SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id`
=> 4.0ms
</pre>
<p><em>2.JOINせず複数回SQLした場合</em></p>
<pre>
> Item.where(:user_id =&gt; User.where(:id =&gt; {:not =&gt; nil}).pluck(:id)).all.count
# SELECT id FROM `users` WHERE (`users`.`id` IS NOT NULL)
# SELECT `items`.* FROM `items` WHERE `items`.`user_id` IN (1..100)
=> 0.7ms + 4.7ms = 5.4ms
</pre>
<p><strong>Extra全件(100*10*100件)</strong><br />
<em>1.JOINした場合</em></p>
<pre>
> User.joins(:items =&gt; :extras).all.count
# SELECT `users`.* FROM `users` INNER JOIN `items` ON `items`.`user_id` = `users`.`id` INNER JOIN `extras` ON `extras`.`item_id` = `items`.`id`
=> 212.1ms
</pre>
<p><em>2.JOINせず複数回SQLした場合</em></p>
<pre>
> Extra.where(:item_id =&gt; (Item.where(:user_id =&gt; User.where(:id =&gt; {:not =&gt; nil}).pluck(:id)).pluck(:id))).all.count
# SELECT id FROM `users` WHERE (`users`.`id` IS NOT NULL)
# SELECT id FROM `items` WHERE `items`.`user_id` IN (1..100)
# SELECT `extras`.* FROM `extras` WHERE `extras`.`item_id` IN (1..1000)
=> 0.6ms + 3.3ms + 556.9ms = 560.8ms
</pre>
<p>む、逆転した。</p>
<p>以上はローカル環境で適当にやっただけなので、そのうちAWSのインスタンスでも立ててちゃんと調べよう。</p>
<p>追記：分かりやすいようにSQL入れました。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=560</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>続々assets:precompile問題</title>
		<link>http://blog.larus.jp/?p=555</link>
		<comments>http://blog.larus.jp/?p=555#comments</comments>
		<pubDate>Wed, 04 Apr 2012 08:51:15 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=555</guid>
		<description><![CDATA[先日のエントリの最後に書いたprecompileが失敗する問題の続き。 Rails3.2.3でも解決していなかったので本腰入れて調べてみた。 具体的には、rake assets:precompileを実行すると以下のようなエラーで中断する。 rake aborted! undefined method `[]' for nil:NilClass (in /path/to/rails_app/app/assets/stylesheets/application.css) /path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-rails-3.2.5/lib/sass/rails/helpers.rb:32:in `resolver' /path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-rails-3.2.5/lib/sass/rails/helpers.rb:22:in `image_path' /path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-3.1.15/lib/sass/script/funcall.rb:88:in `_perform' 以下略 railsをstableにすると発生しなくなったり3.2.3で復活したり長らく原因不明だったが、githubのこのissueを追っかけてようやく原因が分かった。 cssのurlをassetsに対応させるため、erbを埋め込んで以下のようにしていた。 これはprecompileしない環境（development）だとうまく行くが、assets:precompileを実行すると上記のエラーになる。 どうやらasset_pathヘルパが[:custom]オプションを要求するのに対し、sassエンジンが[:custom]オプションなしで初期化されるのが原因らしい。 erbのasset_pathを諦め、styles.css.scssにリネームした上で、以下のように書き換えて解決。 asset_pathがsassではasset-pathになるのが分からなくてハマった。RailsGuideに書いてはあるんだけど例が分かりづらい。 sprocketのドキュメントの方が分かりやすいかも。 なお、asset-pathだとimageオプションが必要だが、文字列を生で書くのが気持ち悪い場合、image-pathにするとオプションが不要になる。 胸のつかえが取れたー。]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.larus.jp/?p=508">先日のエントリ</a>の最後に書いたprecompileが失敗する問題の続き。<br />
Rails3.2.3でも解決していなかったので本腰入れて調べてみた。</p>
<p><span id="more-555"></span><br />
具体的には、rake assets:precompileを実行すると以下のようなエラーで中断する。</p>
<pre>
rake aborted!
undefined method `[]' for nil:NilClass
  (in /path/to/rails_app/app/assets/stylesheets/application.css)
/path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-rails-3.2.5/lib/sass/rails/helpers.rb:32:in `resolver'
/path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-rails-3.2.5/lib/sass/rails/helpers.rb:22:in `image_path'
/path/to/.rvm/gems/ruby-1.9.3-p125/gems/sass-3.1.15/lib/sass/script/funcall.rb:88:in `_perform'
以下略
</pre>
<p>railsをstableにすると発生しなくなったり3.2.3で復活したり長らく原因不明だったが、<a href="https://github.com/rails/sass-rails/issues/81" target="_blank">githubのこのissue</a>を追っかけてようやく原因が分かった。</p>
<p>cssのurlをassetsに対応させるため、erbを埋め込んで以下のようにしていた。</p>
<div id="gist-2299796" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>.bgimage {</div><div class='line' id='LC2'>background: #fffff url(&quot;<span class="cp">&lt;%=</span> <span class="n">asset_path</span> <span class="s1">&#39;css/background.png&#39;</span> <span class="cp">%&gt;</span>&quot;) repeat-x;</div><div class='line' id='LC3'>}</div><div class='line' id='LC4'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2299796/db34989e8279991629e5f33c36aac5ba4e7e2890/styles.css.erb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2299796#file_styles.css.erb" style="float:right;margin-right:10px;color:#666">styles.css.erb</a>
            <a href="https://gist.github.com/2299796">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>これはprecompileしない環境（development）だとうまく行くが、assets:precompileを実行すると上記のエラーになる。<br />
どうやらasset_pathヘルパが[:custom]オプションを要求するのに対し、sassエンジンが[:custom]オプションなしで初期化されるのが原因らしい。<br />
erbのasset_pathを諦め、styles.css.scssにリネームした上で、以下のように書き換えて解決。</p>
<div id="gist-2299802" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nc">.bgimage</span> <span class="p">{</span></div><div class='line' id='LC2'><span class="na">background</span><span class="o">:</span> <span class="mh">#fffff</span> <span class="sx">url(asset-path(&#39;css/background.png&#39;, image)</span><span class="p">)</span> <span class="no">repeat-x</span><span class="p">;</span></div><div class='line' id='LC3'><span class="p">}</span></div><div class='line' id='LC4'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2299802/c9a1f2e2a80524e937838bab7a5043c8a64be02d/styles.css.scss" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2299802#file_styles.css.scss" style="float:right;margin-right:10px;color:#666">styles.css.scss</a>
            <a href="https://gist.github.com/2299802">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>asset_pathがsassではasset-pathになるのが分からなくてハマった。<a href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">RailsGuide</a>に書いてはあるんだけど例が分かりづらい。<br />
<a href="http://rubydoc.info/github/petebrowne/sprockets-sass/master/Sprockets/Sass/Functions#asset_path-instance_method" target="_blank">sprocketのドキュメント</a>の方が分かりやすいかも。<br />
なお、asset-pathだとimageオプションが必要だが、文字列を生で書くのが気持ち悪い場合、image-pathにするとオプションが不要になる。</p>
<div id="gist-2299813" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="nc">.bgimage</span> <span class="p">{</span></div><div class='line' id='LC2'><span class="na">background</span><span class="o">:</span> <span class="mh">#fffff</span> <span class="sx">url(image-path(&#39;css/background.png&#39;)</span><span class="p">)</span> <span class="no">repeat-x</span><span class="p">;</span></div><div class='line' id='LC3'><span class="p">}</span></div><div class='line' id='LC4'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2299813/f27bc499c03639b050f10373141c0f11dc64a915/styles.css.scss" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2299813#file_styles.css.scss" style="float:right;margin-right:10px;color:#666">styles.css.scss</a>
            <a href="https://gist.github.com/2299813">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>胸のつかえが取れたー。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=555</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Emacs23.4</title>
		<link>http://blog.larus.jp/?p=543</link>
		<comments>http://blog.larus.jp/?p=543#comments</comments>
		<pubDate>Wed, 21 Mar 2012 08:29:43 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Emacs]]></category>
		<category><![CDATA[MacOSX]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=543</guid>
		<description><![CDATA[久々にEmacsをビルドした。もちろんCocoa Emacs。 手順はほぼこの通りでOK。 久しぶりにinline patchを当ててみたが、やはりauto-saveとぶつかった時に落ちる。 （auto-save-buffersは使っていないんだけど） これを回避するパッチがmacemacs-jpで流れていたので当てる。 一応、patch -p0で当てられるパッチを作ったので置いておく。 一通りパッチを揃えたら以下の手順でビルド。 patch -p1 < ../emacs-23-lion-fullscreen-test.patch patch -p0 < ../inline_patch-svn/emacs-inline.patch patch -p1 < ../fix-shiftmodifier-patch-for-emacs-inline-patch.diff patch -p0 < ../fix-auto-save-crash.patch ./configure --with-ns --without-x make bootstrap make install Mac Mini(Core2Duo 2.4GHz/8G/SSD)でビルド所要時間13分くらい。 思ったよりも速くなってないけど、まぁCore2Duoだしこんなもんか。i7のMiniかiMac出たら欲しいな。]]></description>
			<content:encoded><![CDATA[<p>久々にEmacsをビルドした。もちろんCocoa Emacs。<br />
手順はほぼ<a href="http://henry.animeo.jp/wp/?p=1624" target="_blank">この通り</a>でOK。</p>
<p>久しぶりにinline patchを当ててみたが、やはりauto-saveとぶつかった時に落ちる。<br />
（auto-save-buffersは使っていないんだけど）<br />
これを回避するパッチが<a href="http://sourceforge.jp/projects/macemacsjp/lists/archive/users/2011-August/001699.html" target="_blank">macemacs-jpで流れていた</a>ので当てる。</p>
<p>一応、patch -p0で当てられるパッチを作ったので置いておく。<br />
<div id="gist-2154269" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="gd">--- a/src/nsterm.m	2012-03-20 12:48:57.000000000 +0900</span></div><div class='line' id='LC2'><span class="gi">+++ b/src/nsterm.m	2012-03-20 13:22:16.000000000 +0900</span></div><div class='line' id='LC3'><span class="gu">@@ -4708,9 +4708,7 @@</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;if (NS_KEYLOG)</div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;NSLog (@&quot;firstRectForCharRange request&quot;);</div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC7'><span class="gd">-  if (NILP (Feval (Fcons (intern (&quot;ns-in-echo-area&quot;), Qnil))))</span></div><div class='line' id='LC8'><span class="gd">-    win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));</span></div><div class='line' id='LC9'><span class="gd">-  else if (WINDOWP (echo_area_window))</span></div><div class='line' id='LC10'><span class="gi">+  if (WINDOWP (echo_area_window))</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;win = XWINDOW (echo_area_window);</div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;else</div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));</div><div class='line' id='LC14'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/2154269/4c6500069ef4164a279475e6dc4d27d3f2f5a17d/fix-auto-save-crash.patch" style="float:right;">view raw</a>
            <a href="https://gist.github.com/2154269#file_fix_auto_save_crash.patch" style="float:right;margin-right:10px;color:#666">fix-auto-save-crash.patch</a>
            <a href="https://gist.github.com/2154269">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>一通りパッチを揃えたら以下の手順でビルド。</p>
<pre>
patch -p1 < ../emacs-23-lion-fullscreen-test.patch
patch -p0 < ../inline_patch-svn/emacs-inline.patch
patch -p1 < ../fix-shiftmodifier-patch-for-emacs-inline-patch.diff
patch -p0 < ../fix-auto-save-crash.patch
./configure --with-ns --without-x
make bootstrap
make install
</pre>
<p>Mac Mini(Core2Duo 2.4GHz/8G/SSD)でビルド所要時間13分くらい。<br />
思ったよりも速くなってないけど、まぁCore2Duoだしこんなもんか。i7のMiniかiMac出たら欲しいな。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=543</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>varnish&amp;nginx</title>
		<link>http://blog.larus.jp/?p=531</link>
		<comments>http://blog.larus.jp/?p=531#comments</comments>
		<pubDate>Wed, 21 Mar 2012 06:57:37 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=531</guid>
		<description><![CDATA[varnishとnginxを使っているサーバをマイグレーションすることになり、今まで外部のLBを通していたのを直接処理することになった。 そこで問題になるのはSSLの扱い。varnishはSSLを扱えないため（作者はopensslのコードはクソだ、と一刀両断している）、httpsのフロントエンドとしては使えない。 そこで順序を入れ替え、nginxをフロントエンドに、varnishを挟んでunicornに投げるようにした。 具体的には以下の通り。 旧構成:LB→varnish→nginx→unicorn 新構成:nginx→varnish→unicorn varnishはUNIX socketに対応していないので（予定はあるようだが）、unicornを適当なポートで待ち受けさせてやらなければならない。 静的ファイルはフロントエンドのnginxで直接捌くためvarnishにキャッシュさせることはできなくなるが、nginx単体で充分なパフォーマンスが出るので考えなくていいだろう。 nginxを80で待ち受けさせて、静的ファイル以外をバックエンドのvarnishに投げ、varnishがさらにバックエンドのunicornに投げる。 これで問題なく動作しているかに見えたが、実は大きな罠があった。 varnishはGETリクエストしかキャッシュしないため、POSTについてはそのままバックエンドに丸投げになるはずが、間にnginxが挟まったことで全てのリクエストがGETになってしまう現象が発生した。 恐らくvclの記述がまずいのだと思うが、とりあえずnginxの方でGETリクエストのみをvarnishに投げ、それ以外は直接unicornに投げるように変更して解決した。 以下はその設定。 /etc/nginx/sites-available/default upstream varnish { server localhost:8080; } upstream unicorn-rails { server localhost:3000; } server { listen 80; server_name rails-app-sample.larus.jp; root /var/www/rails-app/current/public; error_log /var/www/rails-app/current/log/nginx-error.log; location ~ ^/assets&#124;system/ { expires 1y; add_header Cache-Control public; add_header Last-Modified ""; add_header ETag ""; } location = [...]]]></description>
			<content:encoded><![CDATA[<p>varnishとnginxを使っているサーバをマイグレーションすることになり、今まで外部のLBを通していたのを直接処理することになった。<br />
そこで問題になるのはSSLの扱い。varnishはSSLを扱えないため（作者はopensslのコードはクソだ、と<a href="https://www.varnish-cache.org/docs/trunk/phk/ssl.html" target="_blank">一刀両断</a>している）、httpsのフロントエンドとしては使えない。<br />
そこで順序を入れ替え、nginxをフロントエンドに、varnishを挟んでunicornに投げるようにした。</p>
<p><span id="more-531"></span><br />
具体的には以下の通り。</p>
<p>旧構成:<strong>LB→varnish→nginx→unicorn</strong></p>
<p>新構成:<strong>nginx→varnish→unicorn</strong></p>
<p>varnishはUNIX socketに対応していないので（<a href="https://www.varnish-cache.org/trac/ticket/1020" target="_blank">予定はあるようだが</a>）、unicornを適当なポートで待ち受けさせてやらなければならない。<br />
静的ファイルはフロントエンドのnginxで直接捌くためvarnishにキャッシュさせることはできなくなるが、nginx単体で充分なパフォーマンスが出るので考えなくていいだろう。</p>
<p>nginxを80で待ち受けさせて、静的ファイル以外をバックエンドのvarnishに投げ、varnishがさらにバックエンドのunicornに投げる。<br />
これで問題なく動作しているかに見えたが、実は大きな罠があった。<br />
varnishはGETリクエストしかキャッシュしないため、POSTについてはそのままバックエンドに丸投げになるはずが、間にnginxが挟まったことで全てのリクエストがGETになってしまう現象が発生した。<br />
恐らくvclの記述がまずいのだと思うが、とりあえずnginxの方でGETリクエストのみをvarnishに投げ、それ以外は直接unicornに投げるように変更して解決した。<br />
以下はその設定。</p>
<p><strong>/etc/nginx/sites-available/default</strong></p>
<pre>
upstream varnish {
        server localhost:8080;
}

upstream unicorn-rails {
        server localhost:3000;
}

server {
        listen 80;
        server_name rails-app-sample.larus.jp;
        root /var/www/rails-app/current/public;
        error_log /var/www/rails-app/current/log/nginx-error.log;

        location ~ ^/assets|system/ {
                expires 1y;
                add_header Cache-Control public;
                add_header Last-Modified "";
                add_header ETag "";
        }

        location = /favicon.ico {
            root   /var/www/rails-app/current/public/assets;
        }

        location / {
                proxy_set_header X-Real-IP  $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_set_header Host $http_host;

                if ($request_method = GET) {
                        proxy_pass http ://varnish;
                        # httpの後のスペースは本来は省く
                }

                proxy_pass http ://unicorn-rails;
                # httpの後のスペースは本来は省く
        }

}
</pre>
<p><strong>/etc/varnish/default.vcl</strong></p>
<pre>
backend rails_app {
  .host = "127.0.0.1";
  .port = "3000";
  .connect_timeout = 30s;
}

sub vcl_recv {
  if (req.http.host == "rails-app-sample.larus.jp") {
    set req.backend = rails_app;
    return (lookup);
  }
}
</pre>
<p>なお、以後スケールする場合はnginxをロードバランサにしてvarnish+unicornの組を増やせば良い。</p>
<p>しかしvarnishの作者はDJBの同類っぽくてやや不安・・・</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=531</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>真空断熱マグ</title>
		<link>http://blog.larus.jp/?p=524</link>
		<comments>http://blog.larus.jp/?p=524#comments</comments>
		<pubDate>Sat, 10 Mar 2012 11:53:46 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[その他]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=524</guid>
		<description><![CDATA[真空断熱マグがへこんだので買い換えた。 何となく毎回別々のメーカーのを買っているので、ここらでちょっとレビューしてみる。 保温性能とか重量とかはだいたい一緒なので、その他を中心に。 サーモス「ケータイマグ」 少し太めで持ちにくいが、その分高さは低い。 塗装がはげやすく、すぐボロボロになる。リペイントとか楽しめる人にはいいかも。 蓋のロックはあけやすく、ゆっくり開くのも良い。 飲み口のパーツが掃除しにくく汚れる。 TIGER「サハラマグ」 蓋のロックが固くて開けにくい。勢いよく開く上に、角度が足りず鼻にぶつかる。（サイズや人によるかもしれない） 飲み口は一体化されていて掃除しやすい。 ボディがコーティングされているので塗装がはげない。 象印「ステンレスマグ」 容量が少しだけ少ないが、その分細身で持ちやすい。 底面がわずかに膨らんでいて安定する。 蓋のロックが独特で、開けにくい人もいるかも知れない。勢いよく開くが角度がつけられていて飲みやすい。 飲み口は一体化されていて掃除しやすく、簡易な空気弁がついている。 ボディはコーティングされているようだ。塗装は今のところはげてないが、時間が経ってないのでまだ不明。 なお、たまたまかも知れないけど買ったばかりは妙な匂いがあってなかなか取れなかった。]]></description>
			<content:encoded><![CDATA[<p>真空断熱マグがへこんだので買い換えた。<br />
何となく毎回別々のメーカーのを買っているので、ここらでちょっとレビューしてみる。<br />
保温性能とか重量とかはだいたい一緒なので、その他を中心に。</p>
<p><strong>サーモス「ケータイマグ」</strong><br />
</p>
<p>少し太めで持ちにくいが、その分高さは低い。<br />
塗装がはげやすく、すぐボロボロになる。リペイントとか楽しめる人にはいいかも。<br />
蓋のロックはあけやすく、ゆっくり開くのも良い。<br />
飲み口のパーツが掃除しにくく汚れる。</p>
<p><strong>TIGER「サハラマグ」</strong><br />
</p>
<p>蓋のロックが固くて開けにくい。勢いよく開く上に、角度が足りず鼻にぶつかる。（サイズや人によるかもしれない）<br />
飲み口は一体化されていて掃除しやすい。<br />
ボディがコーティングされているので塗装がはげない。</p>
<p><strong>象印「ステンレスマグ」</strong><br />
</p>
<p>容量が少しだけ少ないが、その分細身で持ちやすい。<br />
底面がわずかに膨らんでいて安定する。<br />
蓋のロックが独特で、開けにくい人もいるかも知れない。勢いよく開くが角度がつけられていて飲みやすい。<br />
飲み口は一体化されていて掃除しやすく、簡易な空気弁がついている。<br />
ボディはコーティングされているようだ。塗装は今のところはげてないが、時間が経ってないのでまだ不明。<br />
なお、たまたまかも知れないけど買ったばかりは妙な匂いがあってなかなか取れなかった。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=524</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>capistrano/multistageとdeploy_to</title>
		<link>http://blog.larus.jp/?p=518</link>
		<comments>http://blog.larus.jp/?p=518#comments</comments>
		<pubDate>Wed, 07 Mar 2012 19:50:19 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=518</guid>
		<description><![CDATA[前回のエントリでnamespaceに起因すると勘違いした不具合。 capistranoのmultistageでdeploy_toにstageごとに異なるパスを指定すると変になるという話。 multistageを使っている時に、config/deploy/staging.rbに以下のように書いたとする。 が、これは期待した動作をしない。deploy:symlinkの時にオーバーライドしたはずのdeploy_toが復活する。もしdeploy.rbでdeploy_toを指定していなければ、デフォルトの/u/apps/#{application}が使われる。 これを回避するには、staging.rbに以下を追加する必要がある。 これならdeploy_toが呼び出された時点で評価される。 しかし、全てのrails_envについて（staging.rb,production.rbなど）同じ内容を書かないといけないのでよろしくない。 ぱっと見だと難しそうなので、ゆっくりソースを追って考えてみます。]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.larus.jp/?p=512">前回のエントリ</a>でnamespaceに起因すると勘違いした不具合。<br />
capistranoのmultistageでdeploy_toにstageごとに異なるパスを指定すると変になるという話。</p>
<p>multistageを使っている時に、config/deploy/staging.rbに以下のように書いたとする。</p>
<div id="gist-1999940" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">set</span> <span class="ss">:rails_env</span><span class="p">,</span> <span class="s1">&#39;staging&#39;</span></div><div class='line' id='LC2'><span class="n">set</span> <span class="ss">:branch</span><span class="p">,</span> <span class="s1">&#39;trunk&#39;</span></div><div class='line' id='LC3'><span class="n">set</span> <span class="ss">:deploy_to</span><span class="p">,</span> <span class="s2">&quot;/var/www/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">-</span><span class="si">#{</span><span class="n">rails_env</span><span class="si">}</span><span class="s2">&quot;</span></div><div class='line' id='LC4'><span class="n">role</span> <span class="ss">:web</span><span class="p">,</span> <span class="s2">&quot;staging-server&quot;</span></div><div class='line' id='LC5'><span class="n">role</span> <span class="ss">:app</span><span class="p">,</span> <span class="s2">&quot;staging-server&quot;</span></div><div class='line' id='LC6'><span class="n">role</span> <span class="ss">:db</span><span class="p">,</span> <span class="s2">&quot;staging-server&quot;</span><span class="p">,</span> <span class="ss">:primary</span> <span class="o">=&gt;</span> <span class="kp">true</span></div><div class='line' id='LC7'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1999940/5cdf5cae2fffdaec240d9bce08f6067732c17fa7/staging.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1999940#file_staging.rb" style="float:right;margin-right:10px;color:#666">staging.rb</a>
            <a href="https://gist.github.com/1999940">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>が、これは期待した動作をしない。deploy:symlinkの時にオーバーライドしたはずのdeploy_toが復活する。もしdeploy.rbでdeploy_toを指定していなければ、デフォルトの/u/apps/#{application}が使われる。</p>
<p>これを回避するには、staging.rbに以下を追加する必要がある。</p>
<div id="gist-1999947" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="n">set</span><span class="p">(</span><span class="ss">:deploy_to</span><span class="p">)</span> <span class="p">{</span> <span class="s2">&quot;/var/www/</span><span class="si">#{</span><span class="n">application</span><span class="si">}</span><span class="s2">-</span><span class="si">#{</span><span class="n">rails_env</span><span class="si">}</span><span class="s2">&quot;</span> <span class="p">}</span></div><div class='line' id='LC2'><span class="n">set</span><span class="p">(</span><span class="ss">:releases_path</span><span class="p">)</span> <span class="p">{</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">deploy_to</span><span class="p">,</span> <span class="n">version_dir</span><span class="p">)</span> <span class="p">}</span></div><div class='line' id='LC3'><span class="n">set</span><span class="p">(</span><span class="ss">:shared_path</span><span class="p">)</span> <span class="p">{</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">deploy_to</span><span class="p">,</span> <span class="n">shared_dir</span><span class="p">)</span> <span class="p">}</span></div><div class='line' id='LC4'><span class="n">set</span><span class="p">(</span><span class="ss">:current_path</span><span class="p">)</span> <span class="p">{</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">deploy_to</span><span class="p">,</span> <span class="n">current_dir</span><span class="p">)</span> <span class="p">}</span></div><div class='line' id='LC5'><span class="n">set</span><span class="p">(</span><span class="ss">:release_path</span><span class="p">)</span> <span class="p">{</span> <span class="no">File</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">releases_path</span><span class="p">,</span> <span class="n">release_name</span><span class="p">)</span> <span class="p">}</span></div><div class='line' id='LC6'><br/></div><div class='line' id='LC7'><span class="c1"># unicornを使っているなら以下も</span></div><div class='line' id='LC8'><span class="n">set</span><span class="p">(</span><span class="ss">:unicorn_config</span><span class="p">)</span> <span class="p">{</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">current_path</span><span class="si">}</span><span class="s2">/config/unicorn.rb&quot;</span> <span class="p">}</span></div><div class='line' id='LC9'><span class="n">set</span><span class="p">(</span><span class="ss">:unicorn_pid</span><span class="p">)</span> <span class="p">{</span> <span class="s2">&quot;</span><span class="si">#{</span><span class="n">current_path</span><span class="si">}</span><span class="s2">/tmp/pids/unicorn.pid&quot;</span> <span class="p">}</span></div><div class='line' id='LC10'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1999947/d4f7c85f9f714d33e9260efff29fdacfcad790ca/staging.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1999947#file_staging.rb" style="float:right;margin-right:10px;color:#666">staging.rb</a>
            <a href="https://gist.github.com/1999947">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>これならdeploy_toが呼び出された時点で評価される。</p>
<p>しかし、全てのrails_envについて（staging.rb,production.rbなど）同じ内容を書かないといけないのでよろしくない。<br />
ぱっと見だと難しそうなので、ゆっくりソースを追って考えてみます。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=518</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>続assets:precompile問題</title>
		<link>http://blog.larus.jp/?p=512</link>
		<comments>http://blog.larus.jp/?p=512#comments</comments>
		<pubDate>Wed, 07 Mar 2012 06:07:17 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=512</guid>
		<description><![CDATA[先日のエントリは色々間違ってました。 まず、Rails3.2でDBに接続しに行く問題はapplication.rbにconfig.assets.initialize_on_precompile = falseを追加することで回避できるみたい。RailsGuidesくらいちゃんと読めって話ですよね。このへんは先日の勉強会で教えて貰いました。 あとdeploy.rbでnamespaceを定義して更新時だけprecompileするコードだけど、multistageを使っているとパスがデフォルトになってしまったりでうまく動作しない。（multistageしてない時には正常動作するはず） こちらはちょっと考え直す必要がありそう。うまく行ったらまた紹介します。 上記、別の問題とごっちゃになってました。そのままのコードで問題なしです。]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.larus.jp/?p=508">先日のエントリ</a>は色々間違ってました。</p>
<p>まず、Rails3.2でDBに接続しに行く問題はapplication.rbに<strong>config.assets.initialize_on_precompile = false</strong>を追加することで回避できるみたい。<a href="http://guides.rubyonrails.org/asset_pipeline.html" target="_blank">RailsGuidesくらいちゃんと読め</a>って話ですよね。このへんは<a href="https://twitter.com/search?q=%23shibuyarails" target="_blank">先日の勉強会</a>で教えて貰いました。</p>
<p><del datetime="2012-03-07T08:41:47+00:00"><br />
あとdeploy.rbでnamespaceを定義して更新時だけprecompileするコードだけど、multistageを使っているとパスがデフォルトになってしまったりでうまく動作しない。（multistageしてない時には正常動作するはず）<br />
こちらはちょっと考え直す必要がありそう。うまく行ったらまた紹介します。<br />
</del><br />
上記、別の問題とごっちゃになってました。そのままのコードで問題なしです。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=512</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>assets:precompile問題</title>
		<link>http://blog.larus.jp/?p=508</link>
		<comments>http://blog.larus.jp/?p=508#comments</comments>
		<pubDate>Mon, 05 Mar 2012 05:49:20 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=508</guid>
		<description><![CDATA[Rails3.1+capistranoの続き的なもの。 しばらくローカルでassets:precompileする運用をやっていたが、色々問題があった。具体的には以下のような感じ。 デザインの細かな修正ごとにprecompileするので、コミットがassets:precompileだらけになる。 precompileした状態でdevelopment環境をロードすると、coffeescriptで書いた関数が2回実行されたりおかしなことになる。 Rails3.2だとprecompile時にデフォルトでproductionデータベースに接続しようとするので、そのままのdatabase.ymlのままローカルで実行するとエラーになる。（これは一応RAILS_ENV=development rake assets:precompileで解決可能） と言うわけで改善を試みた。 参考にしたのはstackoverflowのこのスレ。 まず、Capfileにload &#8216;deploy/assets&#8217;を追加する。この時、必ずload &#8216;config/deploy&#8217;よりも先にすること。そうしないと後述のnamespaceが有効にならない。 次にdeploy.rbに以下のnamespaceを定義。 これでassetsのnamespaceが上書きされ、app/assets以下に変更があった時のみリモートでassets:precompileが行われるようになる。 万事解決良かった良かった。 のはずが、環境によってはprecompileが失敗することがある（この問題？）。ソースを追っかけたけどよく分からなかった。3.2.2で解決したかなぁ。]]></description>
			<content:encoded><![CDATA[<p><a href="http://blog.larus.jp/?p=440">Rails3.1+capistrano</a>の続き的なもの。<br />
しばらくローカルでassets:precompileする運用をやっていたが、色々問題があった。具体的には以下のような感じ。</p>
<ul>
<li>デザインの細かな修正ごとにprecompileするので、コミットがassets:precompileだらけになる。</li>
<li>precompileした状態でdevelopment環境をロードすると、coffeescriptで書いた関数が2回実行されたりおかしなことになる。</li>
<li>Rails3.2だとprecompile時にデフォルトでproductionデータベースに接続しようとするので、そのままのdatabase.ymlのままローカルで実行するとエラーになる。（これは一応<strong>RAILS_ENV=development rake assets:precompile</strong>で解決可能）</li>
</ul>
<p><span id="more-508"></span><br />
と言うわけで改善を試みた。<br />
参考にしたのは<a href="http://stackoverflow.com/questions/9016002/speed-up-assetsprecompile-with-rails-3-1-3-2-capistrano-deployment" target="_blank">stackoverflowのこのスレ</a>。</p>
<p>まず、Capfileに<strong>load &#8216;deploy/assets&#8217;</strong>を追加する。この時、必ずload &#8216;config/deploy&#8217;よりも先にすること。そうしないと後述のnamespaceが有効にならない。<br />
次にdeploy.rbに以下のnamespaceを定義。</p>
<div id="gist-1976903" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'>&nbsp;&nbsp;<span class="n">namespace</span> <span class="ss">:assets</span> <span class="k">do</span></div><div class='line' id='LC2'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">task</span> <span class="ss">:precompile</span><span class="p">,</span> <span class="ss">:roles</span> <span class="o">=&gt;</span> <span class="ss">:web</span><span class="p">,</span> <span class="ss">:except</span> <span class="o">=&gt;</span> <span class="p">{</span> <span class="ss">:no_release</span> <span class="o">=&gt;</span> <span class="kp">true</span> <span class="p">}</span> <span class="k">do</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">from</span> <span class="o">=</span> <span class="n">source</span><span class="o">.</span><span class="n">next_revision</span><span class="p">(</span><span class="n">current_revision</span><span class="p">)</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">capture</span><span class="p">(</span><span class="s2">&quot;cd </span><span class="si">#{</span><span class="n">latest_release</span><span class="si">}</span><span class="s2"> &amp;&amp; </span><span class="si">#{</span><span class="n">source</span><span class="o">.</span><span class="n">local</span><span class="o">.</span><span class="n">log</span><span class="p">(</span><span class="n">from</span><span class="p">)</span><span class="si">}</span><span class="s2"> vendor/assets/ app/assets/ | wc -l&quot;</span><span class="p">)</span><span class="o">.</span><span class="n">to_i</span> <span class="o">&gt;</span> <span class="mi">0</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">run</span> <span class="sx">%Q{cd </span><span class="si">#{</span><span class="n">latest_release</span><span class="si">}</span><span class="sx"> &amp;&amp; </span><span class="si">#{</span><span class="n">rake</span><span class="si">}</span><span class="sx"> RAILS_ENV=</span><span class="si">#{</span><span class="n">rails_env</span><span class="si">}</span><span class="sx"> </span><span class="si">#{</span><span class="n">asset_env</span><span class="si">}</span><span class="sx"> assets:precompile}</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">else</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">logger</span><span class="o">.</span><span class="n">info</span> <span class="s2">&quot;Skipping asset pre-compilation because there were no asset changes&quot;</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC10'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC11'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1976903/96dec51568972d176091429c46f88f5543c388af/deploy_assets.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1976903#file_deploy_assets.rb" style="float:right;margin-right:10px;color:#666">deploy_assets.rb</a>
            <a href="https://gist.github.com/1976903">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>

<p>これでassetsのnamespaceが上書きされ、app/assets以下に変更があった時のみリモートでassets:precompileが行われるようになる。<br />
万事解決良かった良かった。</p>
<p>のはずが、環境によってはprecompileが失敗することがある（<a href="https://github.com/rails/sass-rails/issues/81" target="_blank">この問題？</a>）。ソースを追っかけたけどよく分からなかった。3.2.2で解決したかなぁ。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=508</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ドラッグ＆ドロップでアップロード</title>
		<link>http://blog.larus.jp/?p=500</link>
		<comments>http://blog.larus.jp/?p=500#comments</comments>
		<pubDate>Mon, 05 Mar 2012 04:04:44 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=500</guid>
		<description><![CDATA[Rails3.2でドラッグ＆ドロップするとファイルをアップロードできるようにしてみた。 大体のところは http://kray.jp/blog/rails3-fileupload/ を参考にさせて頂きました。以下、いくつかハマった所だけ。 Webrickやmongrelなら問題ないが、unicornで走らせようとするとrequest.body.lengthがNoMethodErrorを返すので、request.body.sizeに変更する。 さらにtemp_fileの保存時にEncoding::UndefinedConversionErrorが発生するのでforce_encoding(&#8216;utf-8&#8242;)を付ける。 以上を修正した_store_uploadメソッドはこんな感じ。 あと、元記事ではわざと単純にしてあるのだと思うけど、アップロード完了時のコールバックをlocation.reload();にすると複数ファイルをアップロードした時に中断してしまうので、ajaxで何かしら書く。こんな感じにした。 complete_actionにajaxで書き換えるアクションを指定しておいてevalするだけ。 Paperclip初めて使ったけど便利。DBへのblob保存に対応してないけど、確かにS3（+Cloudfront？）使う方が賢い気がするのでいいか。]]></description>
			<content:encoded><![CDATA[<p>Rails3.2でドラッグ＆ドロップするとファイルをアップロードできるようにしてみた。</p>
<p>大体のところは</p>
<p>http://kray.jp/blog/rails3-fileupload/</p>
<p>を参考にさせて頂きました。以下、いくつかハマった所だけ。</p>
<p><span id="more-500"></span><br />
Webrickやmongrelなら問題ないが、unicornで走らせようとするとrequest.body.lengthがNoMethodErrorを返すので、request.body.sizeに変更する。<br />
さらにtemp_fileの保存時にEncoding::UndefinedConversionErrorが発生するのでforce_encoding(&#8216;utf-8&#8242;)を付ける。<br />
以上を修正した_store_uploadメソッドはこんな感じ。<br />
<div id="gist-1976650" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1"># forked from http://kray.jp/blog/rails3-fileupload/</span></div><div class='line' id='LC2'>&nbsp;&nbsp;<span class="k">def</span> <span class="nf">_store_upload</span><span class="p">(</span><span class="n">file</span><span class="p">)</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">xhr?</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">request</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">size</span> <span class="o">==</span> <span class="n">request</span><span class="o">.</span><span class="n">headers</span><span class="o">[</span><span class="s1">&#39;CONTENT_LENGTH&#39;</span><span class="o">].</span><span class="n">to_i</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">file_data</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">body</span><span class="o">.</span><span class="n">read</span> </div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">file_name</span> <span class="o">=</span> <span class="n">file</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">else</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">if</span> <span class="n">file</span><span class="o">.</span><span class="n">instance_of?</span><span class="p">(</span><span class="no">File</span><span class="p">)</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">file_data</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">read</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">file_name</span> <span class="o">=</span> <span class="n">file</span><span class="o">.</span><span class="n">original_filename</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC14'>&nbsp;&nbsp;&nbsp;&nbsp;</div><div class='line' id='LC15'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="k">raise</span> <span class="s2">&quot;upload failure&quot;</span> <span class="k">unless</span> <span class="n">file_data</span></div><div class='line' id='LC16'><br/></div><div class='line' id='LC17'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">temp_file</span> <span class="o">=</span> <span class="no">Tempfile</span><span class="o">.</span><span class="n">new</span><span class="p">(</span><span class="n">file_name</span><span class="p">)</span></div><div class='line' id='LC18'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">temp_file</span> <span class="o">&lt;&lt;</span> <span class="n">file_data</span><span class="o">.</span><span class="n">force_encoding</span><span class="p">(</span><span class="s1">&#39;utf-8&#39;</span><span class="p">)</span></div><div class='line' id='LC19'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span> <span class="o">=</span> <span class="no">Picture</span><span class="o">.</span><span class="n">new</span></div><div class='line' id='LC20'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">image</span> <span class="o">=</span> <span class="n">temp_file</span></div><div class='line' id='LC21'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">image_file_name</span> <span class="o">=</span> <span class="n">file_name</span></div><div class='line' id='LC22'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">user</span> <span class="o">=</span> <span class="n">current_user</span> <span class="k">if</span> <span class="n">current_user</span></div><div class='line' id='LC23'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">tags</span> <span class="o">&lt;&lt;</span> <span class="n">current_tag</span> <span class="k">if</span> <span class="n">current_tag</span></div><div class='line' id='LC24'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">stories</span> <span class="o">&lt;&lt;</span> <span class="n">current_story</span> <span class="k">if</span> <span class="n">current_story</span></div><div class='line' id='LC25'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span><span class="o">.</span><span class="n">save</span></div><div class='line' id='LC26'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="n">temp_file</span><span class="o">.</span><span class="n">close!</span></div><div class='line' id='LC27'>&nbsp;&nbsp;&nbsp;&nbsp;<span class="vi">@picture</span></div><div class='line' id='LC28'>&nbsp;&nbsp;<span class="k">end</span></div><div class='line' id='LC29'><br/></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1976650/dea3eaf485a6df16c9cf09b4fe763929ebf07f0a/_store_upload.rb" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1976650#file__store_upload.rb" style="float:right;margin-right:10px;color:#666">_store_upload.rb</a>
            <a href="https://gist.github.com/1976650">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
</p>
<p>あと、元記事ではわざと単純にしてあるのだと思うけど、アップロード完了時のコールバックをlocation.reload();にすると複数ファイルをアップロードした時に中断してしまうので、ajaxで何かしら書く。こんな感じにした。<br />
<div id="gist-1976652" class="gist">

        <div class="gist-file">
          <div class="gist-data gist-syntax">
              <div class="highlight"><pre><div class='line' id='LC1'><span class="c1"># initializer for fileuploader.js(http://github.com/valums/file-uploader)</span></div><div class='line' id='LC2'><span class="vi">@create_uploader = </span><span class="p">(</span><span class="nx">upload_action</span><span class="p">,</span> <span class="nx">complete_action</span><span class="p">,</span> <span class="nx">token</span><span class="p">)</span> <span class="o">=&gt;</span></div><div class='line' id='LC3'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">uploader = </span><span class="k">new</span> <span class="nx">qq</span><span class="p">.</span><span class="nx">FileUploader</span> <span class="p">{</span></div><div class='line' id='LC4'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">element: </span><span class="nb">document</span><span class="p">.</span><span class="nx">getElementById</span><span class="p">(</span><span class="s">&#39;upload&#39;</span><span class="p">),</span></div><div class='line' id='LC5'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">action: </span><span class="nx">upload_action</span><span class="p">,</span></div><div class='line' id='LC6'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">debug: </span><span class="kc">false</span><span class="p">,</span></div><div class='line' id='LC7'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">params: </span><span class="p">{</span></div><div class='line' id='LC8'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">authenticity_token: </span><span class="nx">token</span></div><div class='line' id='LC9'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">},</span></div><div class='line' id='LC10'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nv">onComplete: </span><span class="p">()</span> <span class="o">=&gt;</span></div><div class='line' id='LC11'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nx">$</span><span class="p">.</span><span class="nx">get</span> <span class="nx">complete_action</span><span class="p">,</span> <span class="nf">(data) -&gt;</span></div><div class='line' id='LC12'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="nb">eval</span> <span class="nx">data</span></div><div class='line' id='LC13'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span class="p">}</span></div></pre></div>
          </div>

          <div class="gist-meta">
            <a href="https://gist.github.com/raw/1976652/d1a60dfbf98fac7ffc7cf5f16b6138522e771ba4/create_uploader.js.coffee" style="float:right;">view raw</a>
            <a href="https://gist.github.com/1976652#file_create_uploader.js.coffee" style="float:right;margin-right:10px;color:#666">create_uploader.js.coffee</a>
            <a href="https://gist.github.com/1976652">This Gist</a> brought to you by <a href="http://github.com">GitHub</a>.
          </div>
        </div>
</div>
<br />
complete_actionにajaxで書き換えるアクションを指定しておいてevalするだけ。</p>
<p>Paperclip初めて使ったけど便利。DBへのblob保存に対応してないけど、確かにS3（+Cloudfront？）使う方が賢い気がするのでいいか。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=500</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>AASMでInvalidTransitionが出る件</title>
		<link>http://blog.larus.jp/?p=487</link>
		<comments>http://blog.larus.jp/?p=487#comments</comments>
		<pubDate>Sat, 14 Jan 2012 14:46:43 +0000</pubDate>
		<dc:creator>webmaster</dc:creator>
				<category><![CDATA[Ruby]]></category>
		<category><![CDATA[Ruby on Rails]]></category>

		<guid isPermaLink="false">http://blog.larus.jp/?p=487</guid>
		<description><![CDATA[AASMをアップデートしたら、テストで例外が出るようになった。 正しくない状態遷移を行うと例外を返すようになったらしい。 AASMの初期化オプションに:whiny_transitions =&#62; falseを与えてやればいい。 以下は例。 aasm :column =&#62; :aasm_status, :whiny_transitions =&#62; false do state :prepared, :initial =&#62; true state :queued 　state :accepted ... event :accept do transitions :to =&#62; :accepted, :from =&#62; [:queued] end ... end この例だと、whiny_transitionsがtrueならpreparedから直接accept!とかすると例外を投げる。 以前は単に遷移せずpreparedのままだった。 まぁ、例外を投げるのが正しい動作だとは思う。作者もそう言ってるみたい。 あくまで既存のコードをいじりたくない場合ってことで。]]></description>
			<content:encoded><![CDATA[<p><a href="https://github.com/rubyist/aasm">AASM</a>をアップデートしたら、テストで例外が出るようになった。<br />
正しくない状態遷移を行うと例外を返すようになったらしい。<br />
AASMの初期化オプションに:whiny_transitions =&gt; falseを与えてやればいい。<br />
以下は例。</p>
<pre>
aasm :column =&gt; :aasm_status, :whiny_transitions =&gt; false do
  state :prepared, :initial =&gt; true
  state :queued
　state :accepted
...
  event :accept do
    transitions :to =&gt; :accepted, :from =&gt; [:queued]
  end
...
end
</pre>
<p>この例だと、whiny_transitionsがtrueならpreparedから直接accept!とかすると例外を投げる。<br />
以前は単に遷移せずpreparedのままだった。</p>
<p>まぁ、例外を投げるのが正しい動作だとは思う。<a href="https://github.com/rubyist/aasm/issues/40">作者もそう言ってるみたい</a>。<br />
あくまで既存のコードをいじりたくない場合ってことで。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.larus.jp/?feed=rss2&#038;p=487</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

