<?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>ひげろぐ &#187; activerecord</title>
	<atom:link href="http://brass.to/blog/tag/activerecord/feed" rel="self" type="application/rss+xml" />
	<link>http://brass.to/blog</link>
	<description>技術者として仕事人としての思うところや覚え書きやらです</description>
	<lastBuildDate>Fri, 30 Jul 2010 10:07:43 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.4</generator>
	<language>ja</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>:selectで取得するカラムを絞ったらパフォーマンスが倍に</title>
		<link>http://brass.to/blog/active_record_select_option.html</link>
		<comments>http://brass.to/blog/active_record_select_option.html#comments</comments>
		<pubDate>Wed, 24 Jun 2009 15:24:18 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[パフォーマンスチューニング]]></category>

		<guid isPermaLink="false">http://brass.to/blog/?p=325</guid>
		<description><![CDATA[最近管理しているDBサーバで継続的にスロークエリが出るようになったので、チューニングしてみたら気持ちの良い結果が出た。
結論から言うとカラム数が多いテーブルに対しては:selectで取得するカラムを絞るのがかなり有効かと思う。
現状把握
今回スロークエリの発生していたテーブルの状況を整理したのが以下。

レコード件数は110万件くらい
カラム数は30程度
インデックスは効いている（explainで確認済み）
処理の性質的にキャッシュは使えない

スロークエリになっているのはもっぱら以下のクエリ。
select * from pages order by updated_at limit 100;
Railsのコードで見るとこんなかんじ。
Page.all(:order => 'updated_at', :limit => 100)
こんな単純なクエリが実行に2秒から10秒程度もかかってスロークエリとして記録されているのは切ない。
インデックスは効いているので問題解決には他のアプローチが必要になる。
考えるに対象は30以上カラムがあってレコードサイズもそこそこ大きいテーブル。
そこで取得するカラムを絞って余計なカラムを取得しないようにしてみたらどうかと思った。
というかクエリが単純すぎてまずはそれくらいしか浮かばなかったわけだけど。
ベンチマークとチューニング
計測なくしてチューニングなしということでベンチマークで使ったのはmybench。

mybench &#8211; a simple benchmarking tool for MySQL

ベンチマークとチューニングは手元の開発環境で実行した。
こちらレコード件数は3万件程度。本番環境より大幅に少ないが十分だろう。たぶん。
全カラム取得とカラムを絞った結果の比較が以下。
10クライアントから100回ずつ、計1000回のリクエストを送るというのを試行回数3回ずつ行った結果。
serialは経過時間（秒）です。
まずは全部まるごと取得している現状のクエリ。
select * from pages order by updated_at limit 100;
# Page.all(:order => 'updated_at', :limit => 100)
  serial  : 29.173278
  serial  : 29.433684
  serial  : 30.258237
これを取得カラムを絞ったものにしてみると。
select id, updated_at from pages order [...]]]></description>
			<content:encoded><![CDATA[<p>最近管理しているDBサーバで継続的にスロークエリが出るようになったので、チューニングしてみたら気持ちの良い結果が出た。<br />
結論から言うとカラム数が多いテーブルに対しては:selectで取得するカラムを絞るのがかなり有効かと思う。</p>
<h4>現状把握</h4>
<p>今回スロークエリの発生していたテーブルの状況を整理したのが以下。</p>
<ul>
<li>レコード件数は110万件くらい</li>
<li>カラム数は30程度</li>
<li>インデックスは効いている（explainで確認済み）</li>
<li>処理の性質的にキャッシュは使えない</li>
</ul>
<p>スロークエリになっているのはもっぱら以下のクエリ。</p>
<pre><code>select * from pages order by updated_at limit 100;</code></pre>
<p>Railsのコードで見るとこんなかんじ。</p>
<pre><code>Page.all(:order => 'updated_at', :limit => 100)</code></pre>
<p>こんな単純なクエリが実行に2秒から10秒程度もかかってスロークエリとして記録されているのは切ない。<br />
インデックスは効いているので問題解決には他のアプローチが必要になる。</p>
<p>考えるに対象は30以上カラムがあってレコードサイズもそこそこ大きいテーブル。<br />
そこで取得するカラムを絞って余計なカラムを取得しないようにしてみたらどうかと思った。</p>
<p>というかクエリが単純すぎてまずはそれくらいしか浮かばなかったわけだけど。</p>
<h4>ベンチマークとチューニング</h4>
<p>計測なくしてチューニングなしということでベンチマークで使ったのはmybench。</p>
<ul>
<li><a href="http://jeremy.zawodny.com/mysql/mybench/" target="_blank">mybench &#8211; a simple benchmarking tool for MySQL</a></li>
</ul>
<p>ベンチマークとチューニングは手元の開発環境で実行した。<br />
こちらレコード件数は3万件程度。本番環境より大幅に少ないが十分だろう。たぶん。</p>
<p>全カラム取得とカラムを絞った結果の比較が以下。<br />
10クライアントから100回ずつ、計1000回のリクエストを送るというのを試行回数3回ずつ行った結果。<br />
serialは経過時間（秒）です。</p>
<p>まずは全部まるごと取得している現状のクエリ。</p>
<pre><code>select * from pages order by updated_at limit 100;
# Page.all(:order => 'updated_at', :limit => 100)
  serial  : 29.173278
  serial  : 29.433684
  serial  : 30.258237</code></pre>
<p>これを取得カラムを絞ったものにしてみると。</p>
<pre><code>select id, updated_at from pages order by updated_at limit 100;
# Page.all(:select => 'id, updated_at', :order => 'updated_at', :limit => 100)

  serial  : 16.422306
  serial  : 17.562543
  serial  : 16.070013</code></pre>
<p>倍近く速くなった。<br />
うつくしい。</p>
<p>いやぁ、チューニングって本当に気持ちがいいものですね。<br />
これを本番環境にアップしたらスロークエリもパッタリなくなり幸せになれました。</p>
<h5>以下詳しく見たい人向け</h5>
<pre><code>select * from pages order by updated_at limit 100;
# Page.all(:order => 'updated_at', :limit => 100)

test: 1000 0.001631 0.060372 0.029173278 29.173278 342.779443571614
  clients : 10
  queries : 1000
  fastest : 0.001631
  slowest : 0.060372
  average : 0.029173278
  serial  : 29.173278
  q/sec   : 342.779443571614

test: 1000 0.001535 0.06981 0.029433684 29.433684 339.746801657584
  clients : 10
  queries : 1000
  fastest : 0.001535
  slowest : 0.06981
  average : 0.029433684
  serial  : 29.433684
  q/sec   : 339.746801657584

test: 1000 0.00298 0.065291 0.030258237 30.258237 330.488521191767
  clients : 10
  queries : 1000
  fastest : 0.00298
  slowest : 0.065291
  average : 0.030258237
  serial  : 30.258237
  q/sec   : 330.488521191767

select id, updated_at from pages order by updated_at limit 100;
# Page.all(:select => 'id, updated_at', :order => 'updated_at', :limit => 100)

test: 1000 0.000327 0.037233 0.016422306 16.422306 608.927881382797
  clients : 10
  queries : 1000
  fastest : 0.000327
  slowest : 0.037233
  average : 0.016422306
  serial  : 16.422306
  q/sec   : 608.927881382797

test: 1000 0.001182 0.050836 0.017562543 17.562543 569.393623691057
  clients : 10
  queries : 1000
  fastest : 0.001182
  slowest : 0.050836
  average : 0.017562543
  serial  : 17.562543
  q/sec   : 569.393623691057

test: 1000 0.000301 0.04706 0.016070013 16.070013 622.277032383234
  clients : 10
  queries : 1000
  fastest : 0.000301
  slowest : 0.04706
  average : 0.016070013
  serial  : 16.070013
  q/sec   : 622.277032383234</code></pre>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/active_record_select_option.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Railsのconsoleにて大量のレコードを少ないメモリで処理する</title>
		<link>http://brass.to/blog/rails_console_active_recor.html</link>
		<comments>http://brass.to/blog/rails_console_active_recor.html#comments</comments>
		<pubDate>Tue, 19 May 2009 02:07:09 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://brass.to/blog/?p=290</guid>
		<description><![CDATA[RailsのconsoleでActiveRecordを使って大量のレコードを処理しようとする場合、とりあえずコントローラ内に書くのと同じように以下のように打ってみると思う。
Item.all.each {&#124;item&#124; item.update_price }
ところが経験ある人も多いと思うけれども、これをやるとレコード数が1000程度でも大量のメモリを食う。
自分の経験を言えば、開発マシンのMacbook Proがスワップを大量発生させてコマ送りのようなレスポンスになった。
それぞれのレコードに対応するオブジェクトがループ終了までガベージコレクションによって破棄されないのでこんな風になる模様。
処理が進むにつれだんだんメモリ消費量が増えていく。
メモリリークのようだけどメモリリークではないんですと。
で、この敵に立ち向かうためにしばらくの間は勤勉さを発揮してある方法を採った。
一度に取得するレコード数にlimitを指定して↑キーとエンターを連打するという頭が悪いけど力技で確実な方法。
Item.all(:limit => 100, :order => 'updated_at').each {&#124;item&#124; item.update_price }
しかしながらさすがにこれを数十回繰り返さないとダメとなった段に勤勉さが底をついた。
というわけでいろいろ試して、これを以下のように書いてみたらメモリ消費は少ないということに気がついた。
(Item.count).times { Item.first(:order => 'updated_at').update_price }
これだとループごとにガベージコレクションがちゃんと働いてくれるみたいだ。
]]></description>
			<content:encoded><![CDATA[<p>RailsのconsoleでActiveRecordを使って大量のレコードを処理しようとする場合、とりあえずコントローラ内に書くのと同じように以下のように打ってみると思う。</p>
<pre><code>Item.all.each {|item| item.update_price }</code></pre>
<p>ところが経験ある人も多いと思うけれども、これをやるとレコード数が1000程度でも大量のメモリを食う。<br />
自分の経験を言えば、開発マシンのMacbook Proがスワップを大量発生させてコマ送りのようなレスポンスになった。</p>
<p>それぞれのレコードに対応するオブジェクトがループ終了までガベージコレクションによって破棄されないのでこんな風になる模様。<br />
処理が進むにつれだんだんメモリ消費量が増えていく。<br />
メモリリークのようだけどメモリリークではないんですと。</p>
<p>で、この敵に立ち向かうためにしばらくの間は勤勉さを発揮してある方法を採った。<br />
一度に取得するレコード数にlimitを指定して↑キーとエンターを連打するという頭が悪いけど力技で確実な方法。</p>
<pre><code>Item.all(:limit => 100, :order => 'updated_at').each {|item| item.update_price }</code></pre>
<p>しかしながらさすがにこれを数十回繰り返さないとダメとなった段に勤勉さが底をついた。<br />
というわけでいろいろ試して、これを以下のように書いてみたらメモリ消費は少ないということに気がついた。</p>
<pre><code>(Item.count).times { Item.first(:order => 'updated_at').update_price }</code></pre>
<p>これだとループごとにガベージコレクションがちゃんと働いてくれるみたいだ。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/rails_console_active_recor.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>ActiveRecordで任意のidを持つレコードを追加する</title>
		<link>http://brass.to/blog/ar_specified_new_record_id.html</link>
		<comments>http://brass.to/blog/ar_specified_new_record_id.html#comments</comments>
		<pubDate>Mon, 09 Mar 2009 13:08:38 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://brass.to/blog/?p=264</guid>
		<description><![CDATA[各レコードのidの決まっているマスタを作るときなどに知っていると便利な小技。
普通ActiveRecordのidは自動で採番され、レコード作成時に指定することも後で変更することもできない。
例えば最後のレコードのidが100の時に

maker = Maker.create(:id => 1000)

などとしても

maker.id
#=> 101

といった結果になる。
しかしfind_or_create_by_idを使うとidを指定してレコードを作成できる。

maker = Maker.find_or_create_by_id(1000)

とすると

maker.id
#=> 1000

イレギュラーな挙動かもしれないけれど、今のところはこのように動く。
ちなみに更新はやっぱりできないので後からidを変えたくなった場合はexecute_sqlなどで強引に変えるしかないっぽいです。
]]></description>
			<content:encoded><![CDATA[<p>各レコードのidの決まっているマスタを作るときなどに知っていると便利な小技。<br />
普通ActiveRecordのidは自動で採番され、レコード作成時に指定することも後で変更することもできない。</p>
<p>例えば最後のレコードのidが100の時に</p>
<p><code>
<pre>maker = Maker.create(:id => 1000)</pre>
<p></code></p>
<p>などとしても</p>
<p><code>
<pre>maker.id
#=> 101</pre>
<p></code></p>
<p>といった結果になる。</p>
<p>しかしfind_or_create_by_idを使うとidを指定してレコードを作成できる。</p>
<p><code>
<pre>maker = Maker.find_or_create_by_id(1000)</pre>
<p></code></p>
<p>とすると</p>
<p><code>
<pre>maker.id
#=> 1000</pre>
<p></code></p>
<p>イレギュラーな挙動かもしれないけれど、今のところはこのように動く。</p>
<p>ちなみに更新はやっぱりできないので後からidを変えたくなった場合はexecute_sqlなどで強引に変えるしかないっぽいです。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/ar_specified_new_record_id.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Amazon WebサービスのレスポンスをActiveRecordでキャッシュ</title>
		<link>http://brass.to/blog/amazon_web_service_cache.html</link>
		<comments>http://brass.to/blog/amazon_web_service_cache.html#comments</comments>
		<pubDate>Thu, 20 Mar 2008 13:49:49 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[amazon]]></category>
		<category><![CDATA[Amazon-Webサービス]]></category>

		<guid isPermaLink="false">http://brass.to/blog/amazon_web_service_cache.html</guid>
		<description><![CDATA[前回RailsでAmazonのWebサービスを使ってみたけれども、何かあるたびに毎回リクエストを送るのはいろいろ無駄があって忍びないのでレスポンスをキャッシュしなければならない。
ということで今回はActiveRecordを使ってざっくりキャッシュしてみる。
キャッシュテーブルにたくさんカラムを定義するのは面倒なので検索キーにしたいものだけカラムとして定義して、あとは結果をシリアライズして突っ込む方針で。
キャッシュ用のテーブルとモデルを作る
まずはキャッシュするためのテーブルとモデルを準備。
テーブル
とりあえずマイグレーションでテーブルを作る。
class CreateAmazonCaches &#60; ActiveRecord::Migration
  def self.up
    create_table :amazon_caches do &#124;t&#124;
      t.string :asin
      t.string :title
      t.text :response_dump

      t.timestamps
    end
  end

  def self.down
    drop_table :amazon_caches
 [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://brass.to/blog/rails_with_amazon_web_service.html">前回</a>RailsでAmazonのWebサービスを使ってみたけれども、何かあるたびに毎回リクエストを送るのはいろいろ無駄があって忍びないのでレスポンスをキャッシュしなければならない。</p>
<p>ということで今回はActiveRecordを使ってざっくりキャッシュしてみる。<br />
キャッシュテーブルにたくさんカラムを定義するのは面倒なので検索キーにしたいものだけカラムとして定義して、あとは結果をシリアライズして突っ込む方針で。</p>
<h4>キャッシュ用のテーブルとモデルを作る</h4>
<p>まずはキャッシュするためのテーブルとモデルを準備。</p>
<h5>テーブル</h5>
<p>とりあえずマイグレーションでテーブルを作る。</p>
<pre><code>class CreateAmazonCaches &lt; ActiveRecord::Migration
  def self.up
    create_table :amazon_caches do |t|
      t.string :asin
      t.string :title
      t.text :response_dump

      t.timestamps
    end
  end

  def self.down
    drop_table :amazon_caches
  end
end</code></pre>
<h5>モデル</h5>
<p>キャッシュを参照するためのモデル。<br />
データを参照するときにレスポンスの内容をデシリアライズする。</p>
<pre><code>class AmazonCache &lt; ActiveRecord::Base
  @reponse_hash = nil
  @search_limit = 10

  def get(name)
    @response_hash = Marshal.restore(response_dump) if @response_hash.nil?
    @response_hash[name.to_sym]
  end

  def self.search(title, order = 'id', limit = nil)
    @search_limit = limit if limit
    self.find(:all, :conditions =&gt; ["title like ?", "%#{title}%"], :order =&gt; order, :limit =&gt; @search_limit)
  end
end</code></pre>
<p>ハッシュのデシリアライズのタイミングはafter_findでもいいかもしれないなぁ。</p>
<h4>キャッシュの保存と参照</h4>
<p>テーブルとモデルができたので次はそれを使って実際にキャッシュする。</p>
<h5>レスポンスをキャッシュする</h5>
<p>以下がレスポンスをキャッシュするためのコード。</p>
<p>get_hashで取得したデータのハッシュだけシリアライズして突っ込む。<br />
（itemのままだとなにやらうまいことMarshalでシリアライズできなかった）</p>
<pre><code>res = Amazon::Ecs.item_search("Rails", :response_group =&gt; 'Large')
res.items.each do |item|
  AmazonCache.create(:asin =&gt; item.get('asin'), :title =&gt; item.get('title'), :response_dump =&gt; Marshal.dump(item.get_hash))
end</code></pre>
<h5>キャッシュを参照する</h5>
<p>参照は以下のように。</p>
<pre><code>items = AmazonCache.search("Rails")
items.first.get(:title) # =&gt; Railsの何かの本とかそんなタイトル</code></pre>
<p>smallimageのように子要素を持つ要素はXMLの断片が保存されている。</p>
<pre><code>items.first.get(:smallimage) # =&gt; "&lt;url&gt;http://ecx.images-amazon.com/images/I/hogehogehoge-.jpg&lt;/url&gt;&lt;height units=\"pixels\"&gt;75&lt;/height&gt;&lt;width units=\"pixels\"&gt;58&lt;/width&gt;"</code></pre>
<p>これは正規表現とかで値を取り出すのが楽かね。<br />
モデルにそれ用のメソッドを追加してしまってもいいかもしれない。</p>
<p>まあひとまず今回はこんなところで。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/amazon_web_service_cache.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>テストする時フィクスチャのリロード忘れに注意</title>
		<link>http://brass.to/blog/fixture_reload.html</link>
		<comments>http://brass.to/blog/fixture_reload.html#comments</comments>
		<pubDate>Tue, 18 Mar 2008 12:47:06 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[テスト]]></category>

		<guid isPermaLink="false">http://brass.to/blog/fixture_reload.html</guid>
		<description><![CDATA[Railsのコントローラのテストにおいて、フィクスチャのリロードをしないでテストを進めると期待通りの結果にならず首をかしげることになる。
初心者のハマリがちなところ。
例えば次のようなフィクスチャがあり
first_feed:
  id: 1
  title: hoge
次のような更新のテストを書くと
post :update, :id =&#62; @first_feed.id, :title =&#62; 'hogehoge'

@first_feed.title.should == 'hogehoge'
更新処理（updateアクション）が成功してもこのテストは失敗する。
@first_feed.titleは&#8221;hoge&#8221;のままだからだ。
期待通りの結果にするには次のようにしなくてはならない。
post :update, :id =&#62; @first_feed.id, :title =&#62; 'hogehoge'

@first_feed.reload
@first_feed.title.should == 'hogehoge'
これはなぜかというとデータベースの更新が@first_feedとは別のActiveRecordインスタンスで行われるため。たぶん。
更新処理内で同じレコードを参照する別のActiveRecordのインスタンスが作られてデータベースの更新はそちらで行われる。
他のインスタンスによる変更を既存のインスタンスであるところの@first_feedが知るすべはないので、リロードしてやらなければならないというわけだ。
というわけでフィクスチャの、と言っているが実はフィクスチャ以外でもこの現象は起こる。
でもテスト時は特にフィクスチャでよくやる。
で、初心者のハマリがちなところとか偉そうに行ってる割に自分自身が昨日これで30分くらいはまってたわけだが。
@first_feed.itemsにアクションで変更が発生したときにも@first_feedをリロードしないといけないんだぜ。
あと長時間の連続コーディングもNGなんだぜ。
]]></description>
			<content:encoded><![CDATA[<p>Railsのコントローラのテストにおいて、フィクスチャのリロードをしないでテストを進めると期待通りの結果にならず首をかしげることになる。<br />
初心者のハマリがちなところ。</p>
<p>例えば次のようなフィクスチャがあり</p>
<pre><code>first_feed:
  id: 1
  title: hoge</code></pre>
<p>次のような更新のテストを書くと</p>
<pre><code>post :update, :id =&gt; @first_feed.id, :title =&gt; 'hogehoge'

@first_feed.title.should == 'hogehoge'</code></pre>
<p>更新処理（updateアクション）が成功してもこのテストは失敗する。<br />
@first_feed.titleは&#8221;hoge&#8221;のままだからだ。</p>
<p>期待通りの結果にするには次のようにしなくてはならない。</p>
<pre><code>post :update, :id =&gt; @first_feed.id, :title =&gt; 'hogehoge'

@first_feed.reload
@first_feed.title.should == 'hogehoge'</code></pre>
<p>これはなぜかというとデータベースの更新が@first_feedとは別のActiveRecordインスタンスで行われるため。たぶん。</p>
<p>更新処理内で同じレコードを参照する別のActiveRecordのインスタンスが作られてデータベースの更新はそちらで行われる。<br />
他のインスタンスによる変更を既存のインスタンスであるところの@first_feedが知るすべはないので、リロードしてやらなければならないというわけだ。</p>
<p>というわけでフィクスチャの、と言っているが実はフィクスチャ以外でもこの現象は起こる。<br />
でもテスト時は特にフィクスチャでよくやる。</p>
<p>で、初心者のハマリがちなところとか偉そうに行ってる割に自分自身が昨日これで30分くらいはまってたわけだが。</p>
<p>@first_feed.itemsにアクションで変更が発生したときにも@first_feedをリロードしないといけないんだぜ。<br />
あと長時間の連続コーディングもNGなんだぜ。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/fixture_reload.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveRecord の find(id) と find_by_id(id) の違い</title>
		<link>http://brass.to/blog/active_record_find_by_id.html</link>
		<comments>http://brass.to/blog/active_record_find_by_id.html#comments</comments>
		<pubDate>Thu, 13 Mar 2008 10:54:52 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>

		<guid isPermaLink="false">http://brass.to/blog/active_record_find_by_id.html</guid>
		<description><![CDATA[両方とも id を指定してレコードを探すことに違いはないが、レコードが見つからなかった場合の挙動に差がある。


レコードが見つからなかったとき


find(id)
例外が発生する


find_by_id(id)
nil が返る


find(id) に find_by_id(id) の挙動を期待していたので以下のようなコードを書いてしまっていた。
@item = Item.find(params[:id]) if params[:id]
render(:nothing => true, :status => '404 Not Found') unless @item
これだとレコードが見つからなかったときにサーバーエラー（ステータスコード 500）になってしまう。
そうならないためには以下のコードが正しい。
@item = Item.find_by_id(params[:id]) if params[:id]
render(:nothing => true, :status => '404 Not Found') unless @item
奥が深い。
参考
ActiveRecord のお勉強 &#8211; Rails で行こう！ &#8211; Ruby on Rails を学ぶ
]]></description>
			<content:encoded><![CDATA[<p>両方とも id を指定してレコードを探すことに違いはないが、レコードが見つからなかった場合の挙動に差がある。</p>
<table>
<tr>
<th colspan="2">レコードが見つからなかったとき</th>
</tr>
<tr>
<td>find(id)</td>
<td>例外が発生する</td>
</tr>
<tr>
<td>find_by_id(id)</td>
<td>nil が返る</td>
</tr>
</table>
<p>find(id) に find_by_id(id) の挙動を期待していたので以下のようなコードを書いてしまっていた。</p>
<pre><code>@item = Item.find(params[:id]) if params[:id]
render(:nothing => true, :status => '404 Not Found') unless @item</code></pre>
<p>これだとレコードが見つからなかったときにサーバーエラー（ステータスコード 500）になってしまう。<br />
そうならないためには以下のコードが正しい。</p>
<pre><code>@item = Item.find_by_id(params[:id]) if params[:id]
render(:nothing => true, :status => '404 Not Found') unless @item</code></pre>
<p>奥が深い。</p>
<h4>参考</h4>
<p><a href="http://d.hatena.ne.jp/elm200/20070316/1174044163" target="_blank">ActiveRecord のお勉強 &#8211; Rails で行こう！ &#8211; Ruby on Rails を学ぶ</a></p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/active_record_find_by_id.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>ActiveRecordおさらい その壱 テーブル周りの規約</title>
		<link>http://brass.to/blog/active_record_rules.html</link>
		<comments>http://brass.to/blog/active_record_rules.html#comments</comments>
		<pubDate>Fri, 05 Oct 2007 14:45:26 +0000</pubDate>
		<dc:creator>akahige</dc:creator>
				<category><![CDATA[未分類]]></category>
		<category><![CDATA[activerecord]]></category>
		<category><![CDATA[Rails]]></category>
		<category><![CDATA[お勉強]]></category>

		<guid isPermaLink="false">http://brass.to/blog/active_record_rules.html</guid>
		<description><![CDATA[Railsおさらいシリーズ。
忘れてること多々なので書いて思い出そうという趣旨です。
ActiveRecordの前提
テーブルとモデルクラスが1対1で対応するO/Rマッパー。
テーブルの構造に関しては以下の規約が基本。

主キーがオートナンバー型が必須
主キーのカラム名はidがデフォルト
テーブル名は複数形がデフォルト
テーブル名はモデルクラス名を小文字アンダースコア区切りにしたものがデフォルト

主キーがオートナンバー型必須なのはマスタデータのIDを任意に設定したいときにちょっとやりにくかったりする。
主キーのカラム名とテーブル名に関しては変更可能だが、必要がなければ規約に従ったほうが絶対幸せになれる。
主キーとテーブル名を変更する
どうしても変更したい場合はモデルクラスの中で以下のメソッドを使って変更できる。

set_primary_key(column_name)
set_table_name(table_name)

class HogeModel &#60; ActiveRecord::Base
  set_primary_key :code
  set_table_name  :hoges
end

その昔は私もcode派でした。
テーブル名の複数型をやめたい
全体的にテーブル名の複数形を止めたい場合は、pluralize_table_names属性の値をfalseにするとできる。
個々のモデルでset_table_nameしても実現できるが、テーブルが多すぎてめんどくさい場合になど使うと便利っぽい。
参考



Ruby on Rails入門―優しいRailsの育て方

posted with amazlet on 07.10.06
西 和則
秀和システム (2006/08)
売り上げランキング: 45695

おすすめ度の平均: 
 これは入門書ではありません。
 入門用としては残念。
 Railsスタートのベストチョイス
Amazon.co.jp で詳細を見る
素敵な本だけど、入門用としては濃すぎる気がする。
近況
その日布団にはいるまで一日は終わらないんだ。
日付をこの日にするためにタイムスタンプちょっと戻したけどセーフってことで。ひとつ。
]]></description>
			<content:encoded><![CDATA[<p>Railsおさらいシリーズ。<br />
忘れてること多々なので書いて思い出そうという趣旨です。</p>
<h4>ActiveRecordの前提</h4>
<p>テーブルとモデルクラスが1対1で対応するO/Rマッパー。<br />
テーブルの構造に関しては以下の規約が基本。</p>
<ul>
<li>主キーがオートナンバー型が必須</li>
<li>主キーのカラム名はidがデフォルト</li>
<li>テーブル名は複数形がデフォルト</li>
<li>テーブル名はモデルクラス名を小文字アンダースコア区切りにしたものがデフォルト</li>
</ul>
<p>主キーがオートナンバー型必須なのはマスタデータのIDを任意に設定したいときにちょっとやりにくかったりする。<br />
主キーのカラム名とテーブル名に関しては変更可能だが、必要がなければ規約に従ったほうが絶対幸せになれる。</p>
<h4>主キーとテーブル名を変更する</h4>
<p>どうしても変更したい場合はモデルクラスの中で以下のメソッドを使って変更できる。</p>
<ul>
<li>set_primary_key(column_name)</li>
<li>set_table_name(table_name)</li>
</ul>
<pre><code>class HogeModel &lt; ActiveRecord::Base
  set_primary_key :code
  set_table_name  :hoges
end
</code></pre>
<p>その昔は私もcode派でした。</p>
<h4>テーブル名の複数型をやめたい</h4>
<p>全体的にテーブル名の複数形を止めたい場合は、pluralize_table_names属性の値をfalseにするとできる。<br />
個々のモデルでset_table_nameしても実現できるが、テーブルが多すぎてめんどくさい場合になど使うと便利っぽい。</p>
<h4>参考</h4>
<p class="amazlet-box" style="margin-bottom: 0px">
<p class="amazlet-image" style="float: left"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798013951/outdoorcook-22/ref=nosim/" title="amazletlink" name="amazletlink" target="_blank"><img src="http://ec1.images-amazon.com/images/I/21BQ6TJSDXL.jpg" alt="Ruby on Rails入門―優しいRailsの育て方" style="border: medium none " /></a></p>
<p class="amazlet-info" style="float: left; margin-left: 15px; line-height: 120%">
<p class="amazlet-name" style="margin-bottom: 10px; line-height: 120%"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798013951/outdoorcook-22/ref=nosim/" title="amazletlink" name="amazletlink" target="_blank">Ruby on Rails入門―優しいRailsの育て方</a>
</p>
<p class="amazlet-powered-date" style="font-size: 7pt; margin-top: 5px; font-family: verdana; line-height: 120%">posted with <a href="http://www.amazlet.com/browse/ASIN/4798013951/outdoorcook-22" title="Ruby on Rails入門―優しいRailsの育て方" target="_blank">amazlet</a> on 07.10.06</p>
<p class="amazlet-detail">西 和則<br />
秀和システム (2006/08)<br />
売り上げランキング: 45695</p>
<p class="amazlet-review" style="margin-top: 10px; margin-bottom: 10px">
<p class="amazlet-review-average" style="margin-bottom: 5px">おすすめ度の平均: <img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-4-5.gif" alt="4.5" /></p>
<p><img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> これは入門書ではありません。<br />
<img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-3-0.gif" alt="3" /> 入門用としては残念。<br />
<img src="http://images-jp.amazon.com/images/G/09/x-locale/common/customer-reviews/stars-5-0.gif" alt="5" /> Railsスタートのベストチョイス</p>
<p class="amazlet-link" style="margin-top: 5px"><a href="http://www.amazon.co.jp/exec/obidos/ASIN/4798013951/outdoorcook-22/ref=nosim/" title="amazletlink" name="amazletlink" target="_blank">Amazon.co.jp で詳細を見る</a></p>
<p>素敵な本だけど、入門用としては濃すぎる気がする。</p>
<h5>近況</h5>
<p>その日布団にはいるまで一日は終わらないんだ。<br />
日付をこの日にするためにタイムスタンプちょっと戻したけどセーフってことで。ひとつ。</p>
]]></content:encoded>
			<wfw:commentRss>http://brass.to/blog/active_record_rules.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
