カテゴリ別 2003年 | 2004年 | 2005年 | 2006年 | 2007年 | 2008年
知り合いサイト: よんだもの / 暴想 / Linuxでやる夫 / 新宿Vipper / 僕だけが幸せになればいいのに。
ActiveRecord の勉強をするのに何か良い題材がないかと考えていましたが、それなりに複雑でそれなりに知っている MovableType のデータベースにします。
MT は mt-load.cgi でテーブル作成済み。
mt-load.cgi を叩くと初期ユーザが作成されますので、まずはそのデータを Ruby+ActiveRecord で表示するところから。
いきなりコードを書いてみます。
#!/usr/bin/env ruby
require 'rubygems'
require_gem 'activerecord'
require 'pp'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "mt",
:password => "mt",
:database => "mt"
)
module MT
class Author < ActiveRecord::Base
end #Author
end #MT
pp MT::Author.find(1)
意図としては
となります。で、これを実行すると、
$ ruby sample.rb
/usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/abstract_adapter.rb:377:in `log': Table 'mt.authors' doesn't exist: SELECT * FROM authors WHERE id = 1 LIMIT 1 (ActiveRecord::StatementInvalid)
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:95:in `execute'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:173:in `select'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:73:in `select_all'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:337:in `find_by_sql'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:330:in `find_all'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:346:in `find_first'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:287:in `find'
from sample.rb:21
などと怒られます。エラーメッセージにも表示されていますが、debug.log に実行しようとした SQL が記録されますので、それを見てみます。
$ tail -1 debug.log MT::Author Load (0.000000) Table 'mt.authors' doesn't exist: SELECT * FROM authors WHERE id = 1 LIMIT 1
データベース mt には authors という名前のテーブルはないと言われています。これは ActiveRecord には、暗黙的なクラス名とテーブル名の命名規則があるためです。上のコードでは Author クラスを定義しましたので、authors テーブルとマッピングしようとします。
mt_author というテーブル名は変えられませんので、Ruby のコードの方で何とかしないといけません。何とかするには ActiveRecord::Base.table_name を使います。上のコードの Author クラス定義部分だけを抜き出してみます。
module MT
class Author < ActiveRecord::Base
def self.table_name
"mt_author"
end
end #Author
end #MT
再び実行してみるとまだエラーです。さっきとはエラーメッセージが違っていますね。
$ ruby sample.rb
/usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/abstract_adapter.rb:377:in `log': Unknown column 'id' in 'where clause': SELECT * FROM mt_author WHERE id = 1 LIMIT 1 (ActiveRecord::StatementInvalid)
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:95:in `execute'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:173:in `select'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/connection_adapters/mysql_adapter.rb:73:in `select_all'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:337:in `find_by_sql'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:330:in `find_all'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:346:in `find_first'
from /usr/lib/ruby/gems/1.8/gems/activerecord-1.7.0/lib/active_record/base.rb:287:in `find'
from sample.rb:24
$ tail -1 debug.log MT::Author Load (0.000000) Unknown column 'id' in 'where clause': SELECT * FROM mt_author WHERE id = 1 LIMIT 1
これは、ActiveRecord はデフォルトでは主キーのカラム名を id とみなすためです。mt_author のスキーマを見てみましょう。
mysql> show fields from mt_author; +-----------------------------+--------------+------+-----+---------+----------------+ | Field | Type | Null | Key | Default | Extra | +-----------------------------+--------------+------+-----+---------+----------------+ | author_id | int(11) | | PRI | NULL | auto_increment | | author_name | varchar(50) | | MUL | | | | author_type | tinyint(4) | | | 0 | | | author_nickname | varchar(50) | YES | | NULL | | | author_password | varchar(60) | | | | | | author_email | varchar(75) | | MUL | | | | author_url | varchar(255) | YES | | NULL | | | author_can_create_blog | tinyint(4) | YES | | NULL | | | author_can_view_log | tinyint(4) | YES | | NULL | | | author_hint | varchar(75) | YES | | NULL | | | author_created_by | int(11) | YES | | NULL | | | author_public_key | text | YES | | NULL | | | author_preferred_language | varchar(50) | YES | | NULL | | | author_remote_auth_username | varchar(50) | YES | | NULL | | | author_remote_auth_token | varchar(50) | YES | | NULL | | +-----------------------------+--------------+------+-----+---------+----------------+ 15 rows in set (0.00 sec)
主キーは author_id ですね。これもデータベースの方は変更できませんから、Ruby+ActiveRecord 側でなんとかしなくてはなりません。で、なんとかするのがこのコードです。
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
主キーの命名規則を指定します。author テーブルの主キーは author_id でしたので、「テーブル名_id」 という規則であるとしています。
これでまた実行すると、、、
$ ruby sample.rb
#<MT::Author:0x2af7c7a4
@attributes=
{"author_remote_auth_token"=>nil,
"author_name"=>"Melody",
"author_can_create_blog"=>"1",
"author_type"=>"1",
"author_nickname"=>nil,
"author_can_view_log"=>"1",
"author_created_by"=>nil,
"author_public_key"=>nil,
"author_id"=>"1",
"author_password"=>"0osHZ.scFVmok",
"author_email"=>"",
"author_remote_auth_username"=>nil,
"author_url"=>nil,
"author_hint"=>nil,
"author_preferred_language"=>"ja"}>
ようやく上手くいきました。
以上で見てきましたように、既に存在しているデータベースに対して ActiveRecord を使って OR マッピングをする場合には、ActiveRecord が想定するデフォルトの命名規則には従っていないことが多いため、定義やオプション設定をする必要があります。どんなパターンに対応できるかは、今のところ ActiveRecord の API で調べるしかないようです。
最終的なコード
#!/usr/bin/env ruby
require 'rubygems'
require_gem 'activerecord'
require 'pp'
require 'logger'
ActiveRecord::Base.logger = Logger.new("debug.log")
ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore
ActiveRecord::Base.establish_connection(
:adapter => "mysql",
:host => "localhost",
:username => "mt",
:password => "mt",
:database => "mt"
)
module MT
class Author < ActiveRecord::Base
def self.table_name
"mt_author"
end
end #Author
end #MT
pp MT::Author.find(1)
最近のコメント:
RSS
![]()
This work is licensed under a
Creative Commons License
(note: text only. w/o web design, citations, (re)distributed softwares).
残念。。。もうこのページの意味分かりませんから<br>そのページに来た私に切腹。。。
MTとActiveRecordの両方から同時にDBにアクセスするのでなければ、DBの構造を見直してActiveRecordの流儀にしたがうのがよいと思います。