「RailsによるアジャイルWebアプリケーション開発」17章まで読了
Active Record その1
Railsのキモって感じな機能ですね。
Rails外で動くActive Record
sqlite3でこんな感じ。depot/exam/ar1.rbに置いているので、相対パスで../になってます。
require 'rubygems' require 'activerecord' ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3") class Order < ActiveRecord::Base end order = Order.find(1) order.name = "Dave Thomas" order.save
列一覧と列の詳細情報の取得
本書中ではscript/console使ってますが、ここでは上のプログラムをコピーして作ってみます。
require 'rubygems' require 'activerecord' ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3") class Order < ActiveRecord::Base end p Order.column_names p Order.columns_hash["payment_type_id"]
結果はこう。
>ruby ar2.rb ruby ar2.rb ["id", "name", "address", "email", "created_at", "updated_at", "payment_type_id"] #<ActiveRecord::ConnectionAdapters::SQLiteColumn:0x301f038 @precision=nil, @primary=false, @name="payment_type_id", @default=nil, @limit=nil, @null=true, @scale=nil, @sql_type="integer", @type=:integer> >
自由課題やったせいで若干違うのですが、目的は達成できたようです。
この手のメタ情報を扱うことが、フレームワークとしては重要なんですよね。
_before_type_cast
列の値を読み込むとき、Railsは適切なRubyの型にキャストするそうです。
で、それを抑制するのが、_before_type_cast。
これを読み込む属性の名前の後ろに付けると良いようです。
サンプルはこれ。
require 'rubygems' require 'activerecord' ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3") class Order < ActiveRecord::Base end o = Order.find(1) casted_updated_at = o.updated_at raw_updated_at = o.updated_at_before_type_cast print casted_updated_at.class.to_s, " / ", casted_updated_at, "\n" print raw_updated_at.class.to_s, " / ", raw_updated_at, "\n"
結果はこう。
>ruby ar3.rb ruby ar3.rb Time / Wed Jun 11 23:50:28 +0900 2008 String / 2008-06-11 23:50:28 >
_before_type_cast指定なしの(キャストされる)方は、Time型になったのに対し、
指定ありの(キャストされない)方は、String型となっています。
どうでもいいが、Time型ってミリ秒以下は扱えないのね。。
ISBNは一意じゃない
なんといってもISBNは一意な値です。
とか書いてありますが、違います。ISBNは一意じゃないんです。
しつこいようだが、悔しかったので繰り返し書いてみる。
http://d.hatena.ne.jp/taka_2/20080611#p1
newとcreateの違い
create = new(オブジェクトのインスタンス化) + save(データベースへの永続化)
って感じです。
動的ファインダ
メソッドがなくても、自動的に作ってくれる(?)なんだかすごい機能。
最初の1件だけ返すバージョンと、条件に合致する行全てを返すバージョンの二通りあります。
find_by_[カラム名] = find(:first, :conditions => ...)
find_all_by_[カラム名] = find(:all, :conditions => ...)
データの再読み込み
ユニットテスト以外の場所で使うことはめったにありません。
だそうですが、コードを書いて検証してみる。
require 'rubygems' require 'activerecord' ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "../db/development.sqlite3") class Order < ActiveRecord::Base end # ID1のnameは'Dave Thomas' o = Order.find(1) p o.name # ID1のnameを'taka_2'に書き換える o2 = Order.find(1) p o2.name o2.name = 'taka_2' o2.save # 書き換え後のnameをそれぞれ表示 p o.name p o2.name # oのnameが古いままなので、再読み込み o.reload # どっちも新しくなった p o.name p o2.name
結果はこう。
"Dave Thomas" "Dave Thomas" "Dave Thomas" "taka_2" "taka_2" "taka_2"
まあ、そのまんまですが。
更新ボタンとかある画面で使えそう。でも、showアクションをもう一度呼べば同じか。。
saveとsave!, createとcreate!の違い
save, create: 失敗時例外が発生しない
save!, create!: 失敗時例外が発生する
!が付いているものの、特に破壊的というわけではなさそうですね。