Muto Masayuki Archive Tags

Sequel::Modelを使うときはautoloadする

20 December 2013

最近Sequelを使いはじめて、ハマったことについて。

Sequel::Modelを使うと、ARパターンを実現できるので、やってみたいなーと思って、こういうコードを書く。

class Post < Sequel::Model
end
view raw post.rb hosted with ❤ by GitHub

ヤッターモデルの定義ができたよー。さて、アプリケーションクラスからこれを使おうっと。

require 'sinatra/base'
require 'sequel'
$LOAD_PATH << "."
require 'post'
class MyApp < Sinatra::Base
configure do
DB = Sequel.connect("sqlite://sample.db")
end
end
view raw app.rb hosted with ❤ by GitHub

さてさて実行……

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>'
view raw gistfile1.txt hosted with ❤ by GitHub

!!突然の死!!

ググるとこんなのが出てくる。

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
view raw app-autoload.rb hosted with ❤ by GitHub
Fork me on GitHub