Rails-1.1.6 に find_or_initialize_by_* を追加するプラグイン
書いた人: noriaki 2007,06月27日(水) 01:27
RailsのActiveRecordにはfinderというデータベースのデータを検索するメソッドがあります.その中で最もなじみの深いのがfindです.
Article.find(:first, :conditions => ["title = ?", params[:q]])Railsを使ったことのある人なら,上のようなコードを1度は見たことがあると思います.
しかし,Railsでは以下のようにメソッド名をカラムの名前を使って動的に呼び出せる方法が存在します.以下のコードは上記のfindメソッドを利用したのと同じ結果になります.
Article.find_by_title(params[:q])また,findでデータを探して,あればそのオブジェクトを返し,無ければ新しくオブジェクトを作って返したいということがわりとよくあると思うのですが,そんなときに重宝するのがfind_or_create_by_*というメソッドです.(*のところのにはfind_by_titleのようにカラム名が入ります)
article = Article.find_or_create_by_title("Ruby on Rails")
article.new_record? # => false上記コードは,articlesテーブルに"Ruby on Rails"というタイトルのデータがあれば,それをselectしてきて返し,なければ新しくオブジェクトを作成してデータベースに保存します.
さらに,Railsはバージョン1.2.3が公開されて久しいですが,Rails-1.2.3にはfind_or_initialize_by_*というメソッドが使えるようになっています. これは,find_or_create_by_*が文字通りテーブル内にデータが無かったときにはオブジェクトをcreateしているのに対し,find_or_initialize_by_*はオブジェクトをnewして返します.
article = Article.find_or_initialize_by_title("Ruby on Rails")
article.new_record? # => trueつまり,新しく作られたオブジェクトはまだデータベースに保存されておらず,後にarticle.saveを実行したときに初めてデータベースにデータが保存されることになります.
私は,このfind_or_initialize_by_*メソッドをRails-1.1.6の環境で使いたかったのですが,Rials-1.1.6にはこのメソッドがなく,むりやりfind_or_new_by_*などといったメソッドをActiveRecordに追加したりしていました. 今回,他のプラグインの関係でActiveRecord内の動的なfinderの実装を見る機会があったので,ついでにこちらのfind_or_initialize_by_*メソッドをRails-1.1.6の環境で使えるようにプラグインにしました.
acts_as_find_or_initialize_by
acts_as_find_or_initialize_byはActiveRecord::Baseにクラスメソッドとしてfind_or_initialize_by_*メソッドを追加するプラグインです.このプラグインを利用することによって,Rails-1.1.6の環境でもfind_or_initialize_by_*メソッドを使用することができるようになります.
Install
rubyforgeのSVNリポジトリからダウンロードしてRailsプラグインディレクトリに配置するだけです.
$ cd #{RAILS_ROOT}
$ ./script/plugin install svn://rubyforge.org/var/svn/findorinitExample
db/migrate/001_create_articles.rb
class CreateArticles < ActiveRecord::Migration
def self.up
create_table :articles do |t|
t.column :title, :string
t.column :url, :string
t.column :body, :text
t.column :created_on, :datetime
t.column :updated_on, :datetime
end
add_index :articles, :title
end
def self.down
drop_table :articles
end
end./script/console
>> Article.count
=> 0
>> article = Article.find_or_initialize_by_title("Ruby on Rails")
=> #<Article:0xb71400c0 @attributes={"created_on"=>nil, "body"=>nil,
"title"=>"Ruby on Rails", "updated_on"=>nil, "url"=>nil}, new_recordtrue
>> article.body = "Rails is a full-stack, open-source web framework."
=> "Rails is a full-stack, open-source web framework."
>> article.url = "http://www.rubyonrails.org/"
=> "http://www.rubyonrails.org/"
>> article.new_record?
=> true
>> Article.count
=> 0
>> article.save
=> true
>> Article.count
=> 1
>> article = Article.find_or_initialize_by_title("Ruby on Rails")
=> #<Article:0xb7122228 @attributes={"created_on"=>"2007-06-27 02:05:06",
"body"=>"Rails is a full-stack, open-source web framework.",
"title"=>"Ruby on Rails", "updated_on"=>"2007-06-27 02:05:06",
"url"=>"http://www.rubyonrails.org/", "id"=>"1"}
>> article.new_record?
=> nilご意見・ご感想
ありましたら,お気軽にコメントやトラックバック,ブクマコメントなどでどうぞよろしくお願いします.

