rmreで既存のRDBからActiveRecordモデルを生成する

他人の作成したデータベースはテーブルやキーの関係を解きほぐしてモデルを作成するのも大変なので、自動生成したいところです。[rmre](https://github.com/bosko/rmre)はデータベースからrails3のモデルを生成します。ChEMBLを例に、データベースモデルの生成をなぞります。

https://github.com/bosko/rmre

ChEMBL データベース
-----------------
ChEMBLデータベースは、学術論文から化合物の活性を収集して作成されたものです。化合物、実験、活性値、ターゲットタンパク質、文献などの情報が含まれています。[データベースのスキーマ図](
http://ebi.edu.au/ftp/databases/chembl/ChEMBLdb/releases/chembl_19/chembl_19_schema.png)や[スキーマの説明](http://ebi.edu.au/ftp/databases/chembl/ChEMBLdb/releases/chembl_19/chembl_19_schema_documentation.txt)を読むと関係がわかりますが、クエリを書く分には良いのですが、全体のモデルを作成するとなると、テーブルやキーが多いので気合いが要求されるものです。

データベースのセットアップ
-----------------------

[PostgreSQL のダンプファイル](http://ebi.edu.au/ftp/databases/chembl/ChEMBLdb/releases/chembl_19/chembl_19_postgresql.tar.gz) (926MB) をダウンロードして、PostgreSQLにロードします。マシンスペック次第ですが、２時間から８時間程度でロードが完了すると思います。

ロードする時間が勿体ないというかたは、[ロード済みの仮想マシンが配布](http://ebi.edu.au/ftp/databases/chembl/VM/myChEMBL/releases/myChEMBL-19_0/)(vmdk 9.5GB)されているので、そちらを利用することも可能です。

ここで ChEMBL 19のデータは、localhost:5432 の chembl_19 データベースに格納したとします。

モデルの生成
-----------
rmre は各種データベースに対応しているそうなので、-a オプションでここでは、postgresqlを指定します。生成したモデルは -o オプションで指定したディレクトリに１テーブル１ファイルで生成されます。

<pre lang="sh">
rmre -a postgresql -s localhost  --port 5432 -d chembl_19 -u postgres -o chembl_19_model
</pre>

モデルファイルが chembl_19_model ディレクトリに生成されました。
<pre lang="sh">
$ ls chembl_19_model
action_type.rb				component_class.rb			drug_mechanism.rb			protein_classification.rb
activity.rb				component_domain.rb			formulation.rb				protein_family_classification.rb
activity_stds_lookup.rb			component_sequence.rb			ligand_eff.rb				relationship_type.rb
assay.rb				component_synonym.rb			mechanism_ref.rb			research_company.rb
assay_parameter.rb			compound_property.rb			molecule_atc_classification.rb		research_stem.rb
assay_type.rb				compound_record.rb			molecule_dictionary.rb			site_component.rb
atc_classification.rb			compound_structure.rb			molecule_hierarchy.rb			source.rb
binding_site.rb				confidence_score_lookup.rb		molecule_synonym.rb			target_component.rb
bio_component_sequence.rb		curation_lookup.rb			organism_class.rb			target_dictionary.rb
biotherapeutic.rb			data_validity_lookup.rb			parameter_type.rb			target_relation.rb
biotherapeutic_component.rb		defined_daily_dose.rb			predicted_binding_domain.rb		target_type.rb
cell_dictionary.rb			doc.rb					product.rb				usan_stem.rb
chembl_id_lookup.rb			domain.rb				protein_class_synonym.rb		version.rb
</pre>

assay テーブルの生成されたモデル定義 chembl_19_model/assay.rb を見ます。

<pre lang="ruby">
class Assay > ActiveRecord::Base

    self.primary_key = :assay_id

    has_many :assay_parameters, :class_name => 'AssayParameter', :foreign_key => :assay_id    
    has_many :activities, :class_name => 'Activity', :foreign_key => :assay_id    
    belongs_to :assay_type, :class_name => 'AssayType', :foreign_key => :assay_type    
    belongs_to :cell_dictionary, :class_name => 'CellDictionary', :foreign_key => :cell_id    
    belongs_to :chembl_id_lookup, :class_name => 'ChemblIdLookup', :foreign_key => :chembl_id    
    belongs_to :confidence_score_lookup, :class_name => 'ConfidenceScoreLookup', :foreign_key => :confidence_score    
    belongs_to :curation_lookup, :class_name => 'CurationLookup', :foreign_key => :curated_by    
    belongs_to :doc, :class_name => 'Doc', :foreign_key => :doc_id    
    belongs_to :relationship_type, :class_name => 'RelationshipType', :foreign_key => :relationship_type    
    belongs_to :source, :class_name => 'Source', :foreign_key => :src_id    
    belongs_to :target_dictionary, :class_name => 'TargetDictionary', :foreign_key => :tid    
end
</pre>
primary_key、belongs_to、has_manyなどが定義されたことがわかります。

クエリ例
-----
接続とセットアップ、全ての生成されたモデルファイルをrequireします。
<pre lang="ruby">
require 'active_record'
ActiveRecord::Base.establish_connection( {:adapter => 'postgresql', 
                                          :host => 'localhost',
                                          :port => 5432,
                                          :username => 'postgres', 
                                          :password => '', 
                                          :database => 'chembl_19'} )
dir = File.join('chembl_19_model', '*.rb')
Dir.glob(dir) { |file| require file }
</pre>

Assayの説明の取得、ID 1 のAssayレコードを取得して説明を表示します。
<pre lang="ruby">
irb(main):004:0> Assay.find(1).description
=> "The compound was tested for the in vitro inhibition of platelet 12-lipoxygenase at a concentration of 30 uM"
</pre>

Assayの活性値の数
<pre lang="ruby">
irb(main):006:0> Assay.find(1).activities.size
=> 1
</pre>

Assayタイプの説明
<pre lang="ruby">
irb(main):009:0> Assay.find(1).assay_type.assay_desc
=> "Binding"
</pre>

Assayのターゲットの名前
<pre lang="ruby">
irb(main):003:0> Assay.find(1).target_dictionary.pref_name
=> "Arachidonate 12-lipoxygenase"</pre>
</pre>

複数のテーブルのJOINが必要なクエリでも、ActivieRecordで簡単にクエリが書けるようになりました。

まとめ
-----
rmreで既存のRDBからモデルを自動生成してみました。
生成したモデルでクエリを試しました。

研究に利用する場合は、生成したモデルとスキーマを照らし合わせて確認し、必要に会わせてモデルファイルを修正することや、メソッドを追加する必要があるかもしれません。