最近Sequelを使いはじめて、ハマったことについて。
Sequel::Modelを使うと、ARパターンを実現できるので、やってみたいなーと思って、こういうコードを書く。
class Post < Sequel::Model | |
end |
ヤッターモデルの定義ができたよー。さて、アプリケーションクラスからこれを使おうっと。
require 'sinatra/base' | |
require 'sequel' | |
$LOAD_PATH << "." | |
require 'post' | |
class MyApp < Sinatra::Base | |
configure do | |
DB = Sequel.connect("sqlite://sample.db") | |
end | |
end |
さてさて実行……
masa@vardamir> ruby app.rb | |
/Users/masa/.rvm/gems/ruby-2.0.0-p353/gems/sequel-4.5.0/lib/sequel/model/base.rb:226:in `db': No database associated with Sequel::Model: have you called Sequel.connect or Sequel::Model.db= ? (Sequel::Error) | |
from /Users/masa/.rvm/gems/ruby-2.0.0-p353/gems/sequel-4.5.0/lib/sequel/model/base.rb:371:in `inherited' | |
from /Users/masa/devel/hoge/post.rb:1:in `<top (required)>' | |
from /Users/masa/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require' | |
from /Users/masa/.rvm/rubies/ruby-2.0.0-p353/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:55:in `require' | |
from app.rb:4:in `<main>' |
!!突然の死!!
ググるとこんなのが出てくる。
By design, Sequel requires the database connection be set up before model class definition, since it parses the database schema on model class creation. So you should set up your initialization code to connect to the database first.
Sinatra::Modelが設計上の選択としてコネクションを必要とするというのは理由の説明ではあるが、requireしたいんだけど、という質問の答えにはなっていない。問題なのは、requireされたコードがその場で実行されるということなので、解決策としては、requireを遅延させてやることである。かといって、例えばsinatraのconfigureブロックの中でrequireを行うなんてバカなことはやりたくない。
結論としてはautoloadを使う。これで、ファイル管理上の問題を解決できる。
require 'sinatra/base' | |
require 'sequel' | |
$LOAD_PATH << "." | |
autoload :Post, "post" | |
class MyApp < Sinatra::Base | |
configure do | |
DB = Sequel.connect("sqlite://sample.db") | |
end | |
end |