Ruby元プログラミング第2版エッセイ
3098 ワード
ターゲット:映画名と映画評論を格納するデータベースを構築するため、データベース内でオブジェクトの永続化を実現するための簡単なコードライブラリを作成することにしました.
最初の試み:コードライブラリを作成し、データベース内の各テーブルをクラスにマッピングし、各レコードをオブジェクトにマッピングします.オブジェクトを作成したり、プロパティにアクセスしたりするたびに、このオブジェクトはSQL文を生成し、データベースに送信します.これらの機能はすべて1つのクラスにカプセル化されています.
classs Entity
attr_reader :table, :ident
def initialize(table, ident)
@table = table
@ident = ident
Database.sql "INSERT INTO #{@table} (id) VALUES (#{@ident})"
end
def set(col, val)
Database.sql "UPDATE #{@table} SET #{col}='#{val}' WHERE id=#{@ident}"
end
def get(col)
Database.sql ("SELECT #{col} FROM #{@table} WHERE id=#{@ident}") [0][0]
end
end
データベースでは、各テーブルにidフィールドがあり、各Entityはこのフィールドの内容とテーブル名を保存します.Entityオブジェクトを作成すると、そのオブジェクトは自分をデータベースに保存し、Entity#setメソッドはSQL文更新フィールドの値を作成し、Entity#getメソッドはSQL文読み出しフィールドの値を作成します.Databaseは、返されるデータセットとして配列の配列を使用します.
Entityクラスを継承して、指定したテーブルをマッピングできます.たとえば、moviesというテーブルをMovieクラスでマップします.
class Movie < Entity
def initialize(ident)
super "movies", ident
end
def title
get "title"
end
def title=(value)
set "title", value
end
def director
get "director"
end
def director=(value)
set "director", value
end
end
Movieクラスの各プロパティには、Movie#titleのようなreaderメソッドとMovie#title=のようなwriterメソッドの2つのメソッドがあります.Rubyコマンドライン解釈器にコマンドを入力すれば、映画をデータベースにロードできます.
movie = Movie.new(1)
movie.title = "SuperMan"
movie.director = "Stabley Kubrick"
しかしRubyには非常に強力なクラスライブラリActive Recordがあります.オブジェクトをデータテーブルにマッピングすることができます.
ではActive Recordで書かれたMovieクラスはどうなっているのでしょうか.
Movieクラス:
class Movie < ActiveRecord::Base
end
OKはこのように簡単で、私たちはActive Record::Baseからサブクラスを継承しています.そのテーブルでMovieオブジェクトをマッピングすることを指定する必要はありません.titleやdirectorなどの見た目の悪い方法もありません.プログラムは同じように動作します.
movie = Movie.create
movie.title = "SuperMan"
movie.title # => "SuperMan"
上のコードは、moviesテーブルのレコードをパッケージしたMovieオブジェクトを作成します.その後、titleフィールドにはMovie#titleとMovie#title=メソッドでアクセスします.これはどのように実現されているのか、Active Recordの動作原理と関係があります.
Active Recordは、クラスの名前を内省メカニズムで表示します.クラス名がMovieなので、Active Recordは自動的にmoviesのテーブルにマッピングされます.△英語の単語の単一複素数を変換する方法を知っています.
では、titleやtitle=のような方法(アクセスと略称する)はどのように処理されているのでしょうか.これがメタプログラミングの妙用です.Active Recordでは、これらのメソッドが自動的に定義されます.Active Record::Baseは実行時にデータベースのテーブルモードを読み込み、moviesテーブルにtitleとdirectorという2つのフィールドがあることを見つけ、同名のプロパティと応答の2つのアクセサを自動的に定義します.つまり、Active Recordは、プログラムの実行時にMovie#titleとMovie#director=を動的に作成する方法である.
Rubyは、実行時に言語コンポーネントにアクセスするだけでなく、変更することもできます.不思議ではないでしょうか.