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は、実行時に言語コンポーネントにアクセスするだけでなく、変更することもできます.不思議ではないでしょうか.