Setting up sequel sqlite3 - Ramaze/ramaze GitHub Wiki
Using Sequel (http://sequel.rubyforge.org/) connected to a sqlite3 (http://www.sqlite.org/) file database.
Overview
One of the major advantages of Ramaze is that it does not include database support. Yes, you read that right! We do not have to figure out how to disable or replace a magical database that works by convention. Whoooop! Instead we get to tell it exactly what we want. So let's do it!
Sequel uses the external migration file paradigm for defining the schema, then the models retrieve their schema from the database. So we will need rake tasks for creating, migrating, rolling back the database. These rake tasks will need a URL string for the sequel command line command.
Our models will need a connection to the database. The connection can be established given the URL string for the database.
Ramaze supports two runtime modes by default, :live and :dev. Lets add a third, :test. So our database configuration will need to support the runtime modes.
So given a runtime mode, we need a method that returns the URL connection string. This method needs to be usable by both our ramaze app and our Rakefile.
For the migrations we will need a directory to store them in.
That should be enough to get started.
Directories
∴ mkdir -p db/migrations
∴ mkdir -p db/data
Configuration
Then our arbitrarily chosen db/config.rb file:
require 'sequel'
require 'fileutils'
APP_NAME='the-greatest-app-ever'
module Database
DB_MODES = %w{dev live test}
DB_DIR = File.expand_path('data', File.dirname(__FILE__))
FileUtils.mkdir_p DB_DIR
def self.url(mode)
raise "Unsupported runtime mode (Ramaze.options.mode): #{mode.inspect}" unless DB_MODES.include? mode.to_s
"sqlite://#{DB_DIR}/#{APP_NAME}-#{mode.to_s}.db"
end
end
Rake Tasks
Our new rake tasks the the Rakefile:
require_relative 'db/config'
namespace 'db' do
desc "Run database migrations where mode is: #{Database::DB_MODES.join(', ')}"
task :migrate, :mode do |t, args|
cmd = "sequel -m db/migrations #{Database.url(mode(args[:mode]))}"
puts cmd
puts `#{cmd}`
end
desc 'Zap the database my running all the down migrations'
task :zap, [:mode] do |t, args|
cmd = "sequel -m db/migrations -M 0 #{Database.url(mode(args[:mode]))}"
puts cmd
puts `#{cmd}`
end
desc 'Reset the database then run the migrations'
task :reset, [:mode] => [:zap, :migrate]
end
def mode(arg)
mode = arg
if mode.nil? || mode.strip.empty?
mode = 'dev'
end
mode.to_sym
end
App Initialization
And our current app.rb with the new db hook:
# This file contains your application, it requires dependencies and necessary parts of
# the application.
#
# It will be required from either `config.ru` or `start.rb`
require 'rubygems'
require 'bundler/setup'
require 'ramaze'
# Make sure that Ramaze knows where you are
Ramaze.options.roots = [__DIR__]
Ramaze::Log.loggers = [Logger.new($stdout)]
# The mode defaults to :dev
mode = ENV['Ramaze.options.mode'] || 'dev'
Ramaze.options.mode = mode.to_sym
puts "Ramaze.options.mode => #{Ramaze.options.mode.inspect}"
require_relative 'db/config'
DB = Sequel.connect(Database.url(Ramaze.options.mode))
# Initialize controllers and models
require __DIR__('model/init')
require __DIR__('controller/init')
Test Environment
A small digression, we need to go back to our features/support/env.rb and spec/spec_helper.rb files and replace:
require_relative('../app')
with
require 'ramaze'
ENV['Ramaze.options.mode'] = :test.to_s
require_relative('../app')
First migration
Our first migration will simply create the :users table with :id, :name, and :email columns.
∴ cat db/migrations/001_create_user.rb
Sequel.migration do
up do
create_table(:users) do
primary_key :id
String :name, :null=>false
String :email, :null=>false
end
end
down do
drop_table(:users)
end
end
And running the migration for :test yields:
∴ rake db:migrate[test]
sequel -m db/migrations sqlite:///Volumes/MacHD/Users/royw/projects/the-greatest-app-ever/db/data/the-greatest-app-ever-test.db
Verify:
∴ sqlite3 db/data/the-greatest-app-ever-test.db
SQLite version 3.7.10 2012-01-16 13:28:40
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema
CREATE TABLE `schema_info` (`version` integer DEFAULT (0) NOT NULL);
CREATE TABLE `users` (`id` integer PRIMARY KEY AUTOINCREMENT, `name` varchar(255) NOT NULL, `email` varchar(255) NOT NULL);
sqlite> .quit
User model
Add the User model:
∴ cat model/user.rb
class User < Sequel::Model(:users)
end
Hook into the model/init.rb:
∴ cat model/init.rb
# This file is used for loading all your models. Note that you don't have to actually use
# this file. The great thing about Ramaze is that you're free to change it the way you see
# fit.
# Here go your requires for models:
# require __DIR__('user')
Dir["#{__DIR__}/**/*.rb"].reject{|fn| ['init.rb'].include? File.basename(fn)}.each {|fn| require fn}