Create  Edit  Diff  FrontPage  Index  Search  Changes  History  Source  RSS  Note  wikifarm  Login

ActiveRecord

Active Record -- railsにおけるO/Rマッピング

転載元
http://funk.exblog.jp/m2005-02-01#2082044

vendor/activerecord/README

Active Recordは、ビジネスオブジェクトとデータベーステーブルとを接続し、ロジックとデータをひとまとまりとして表現する永続的なドメインモデル(振る舞いとデータをカプセル化した、ドメインのオブジェクトモデル)を生成する。これは、Martin Fowlerによって記述された同名のO/Rマッピング(ORM)パターンの実装である:

「データベースのテーブルやビューの列をラップし、データベースアクセスをカプセル化し、ドメインロジックを追加するオブジェクト」

アソシエーション(関連付け)とインヘリタンス(継承)の欠如という大きな問題を取り除いたことが、Active Recordsのオリジナルパターンへの大きな貢献である。Active Recordは、アソシエーションの欠如に対してはマクロのセットといったシンプルなドメイン言語を追加、インヘリタンスの欠如に対してはSingle Table Inheritance(クラスの継承ヒエラルキーを、様々なクラスの全てのフィールドのためのカラムを持つ1個のテーブルとして表現する)patternを統合し、data mapper(オブジェクト、データベース、mapper自身、それぞれの独立性を維持しながら、オブジェクト-データベース間でのデータの受け渡しをおこなうMappers層)とactive recordアプローチ間の機能ギャップを小さくする。

主要機能の簡単な紹介:

クラス-テーブル間、属性-コラム間の自動マッピング

 class Product < ActiveRecord::Base; end

とすると、以下のようなテーブル"products"に自動的にマッピングされる。

 CREATE TABLE products (
   id int(11) NOT NULL auto_increment,
   name varchar(255),
   PRIMARY KEY (id)
 );

これにより、Product#nameとProduct#name=(new_name)が利用可能になる。

シンプルなメタプログラミングマクロでコントロールされるオブジェクト間アソシエーション

 class Firm < ActiveRecord::Base
   has_many :clients
   has_one :account
   belongs_to :conglomorate
 end

シンプルなメタプログラミングマクロでコントロールされるvalue objectsのアグリゲーション

 class Account < ActiveRecord::Base
   composed_of :balance, :class_name => "Money",
               :mapping => %w(balance amount)
   composed_of :address,
               :mapping => [%w(address_street street), %w(address_city city)]
 end

オブジェクトが新規であるのか既存であるのかに応じて変更可能な妥当性確認ルール

 class Account < ActiveRecord::Base
   validates_presence_of :subdomain, :name, :email_address, :password
   validates_uniqueness_of :subdomain
   validates_acceptance_of :terms_of_service, :on => :create
   validates_confirmation_of :password, :email_address, :on => :create
 end

レコードをリストやツリーのように動作させる機能

 class Item < ActiveRecord::Base
   belongs_to :list
   acts_as_list :scope => :list
 end

 item.move_higher
 item.move_to_bottom

全ライフサイクルにおいて、メソッドやキューとして機能するコールバック(インスタンス化、保存、破壊、認証、等など)

 class Person < ActiveRecord::Base
   def before_destroy # is called just before Person#destroy
     CreditCard.find(credit_card_id).destroy
   end
 end

 class Account < ActiveRecord::Base
   after_find :eager_load, 'self.class.announce(#{id})'
 end

全ライフサイクルに対するオブザーバ

 class CommentObserver < ActiveRecord::Observer
   def after_create(comment) # is called just after Comment#save
     NotificationService.send_email("david@loudthinking.com", comment)
   end
 end

継承階層

 class Company < ActiveRecord::Base; end
 class Firm < Company; end
 class Client < Company; end
 class PriorityClient < Client; end

データベースレベルおよびオブジェクトレベルでのトランザクションのサポート。オブジェクトレベルのトランザクションサポートは、Transaction::Simpleを使って実装されている。

 # Just database transaction
 Account.transaction do
   david.withdrawal(100)
   mary.deposit(100)
 end

 # Database and object transaction
 Account.transaction(david, mary) do
   david.withdrawal(100)
   mary.deposit(100)
 end

コラムへのリフレクション、アソシエーション、アグリゲーション

 reflection = Firm.reflect_on_association(:clients)
 reflection.klass # => Client (class)
 Firm.columns # Returns an array of column descriptors for the firms table

直接操作(サービスを呼ぶかわりに)

So instead of (Hibernate example):

 long pkId = 1234;
 DomesticCat pk = (DomesticCat) sess.load( Cat.class, new Long(pkId) );
 // something interesting involving a cat...
 sess.save(cat);
 sess.flush(); // force the SQL INSERT

Active Recordを使えば、次のようにできる。

 pkId = 1234
 cat = Cat.find(pkId)
 # something even more interesting involving a the same cat...
 cat.save

共有コネクタを使った、シンプルなアダプタ(100行以下)経由のデータベース抽象

 ActiveRecord::Base.establish_connection(:adapter => "sqlite", :dbfile => "dbfile")

 ActiveRecord::Base.establish_connection(
   :adapter => "mysql",
   :host => "localhost",
   :username => "me",
   :password => "secret",
   :database => "activerecord"
 )

Log4rとLoggerでのロギングのサポート

 ActiveRecord::Base.logger = Logger.new(STDOUT)
 ActiveRecord::Base.logger = Log4r::Logger.new("Application Log")

ActiveRecord::Base

lib/active_record/base.rb:

Creation

Conditions

Overwriting default accessors

Accessing attributes before they have been type casted

Dynamic attribute-based finders

Saving arrays, hashes, and other non-mappable objects in text columns

Single table inheritance

  • ひとつの table で継承関係を作る

Reply < Topic みたいなの。

Connection to multiple databases in different models

Exceptions

lib/active_record/associations.rb:

One-to-one associations

Collections

Type safety with ActiveRecord::AssociationTypeMismatch

Options

  • belongs_to
  • has_one
  • has_many
  • has_and_belongs_to_many
Last modified:2005/03/10 12:20:05
Keyword(s):
References:[FrontPage]