sinatra-sequel 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/COPYING +18 -0
- data/README.md +84 -0
- data/Rakefile +75 -0
- data/lib/sinatra/sequel.rb +62 -0
- data/sinatra-sequel.gemspec +39 -0
- data/spec/spec_sinatra_sequel.rb +58 -0
- metadata +93 -0
data/COPYING
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
Copyright (c) 2009 Ryan Tomayko <tomayko.com/about>
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
of this software and associated documentation files (the "Software"), to
|
5
|
+
deal in the Software without restriction, including without limitation the
|
6
|
+
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
7
|
+
sell copies of the Software, and to permit persons to whom the Software is
|
8
|
+
furnished to do so, subject to the following conditions:
|
9
|
+
|
10
|
+
The above copyright notice and this permission notice shall be included in
|
11
|
+
all copies or substantial portions of the Software.
|
12
|
+
|
13
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
16
|
+
THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
17
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
18
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
Sinatra Sequel Extension
|
2
|
+
========================
|
3
|
+
|
4
|
+
Extends [Sinatra](http://www.sinatrarb.com/) with a variety of extension methods
|
5
|
+
for dealing with a SQL database using the [Sequel ORM](http://sequel.rubyforge.org/).
|
6
|
+
|
7
|
+
Install the `sinatra-sequel` gem along with one of the database adapters:
|
8
|
+
|
9
|
+
sudo gem install sequel sinatra-sequel
|
10
|
+
sudo gem install sqlite3
|
11
|
+
sudo gem install mysql
|
12
|
+
sudo gem install postgres
|
13
|
+
|
14
|
+
I like to split database configuration and migrations out into a separate
|
15
|
+
`database.rb` file and then require it from the main app file, but you can plop
|
16
|
+
the following code in about anywhere and it'll work just fine:
|
17
|
+
|
18
|
+
require 'sinatra'
|
19
|
+
require 'sinatra/sequel'
|
20
|
+
|
21
|
+
# Establish the database connection; or, omit this and use the DATABASE_URL
|
22
|
+
# environment variable as the connection string:
|
23
|
+
set :database, 'sqlite://foo.db'
|
24
|
+
|
25
|
+
# At this point, you can access the Sequel Database object using the
|
26
|
+
# "database" object:
|
27
|
+
puts "the foos table doesn't exist" if !database.table_exists?('foos')
|
28
|
+
|
29
|
+
# define database migrations. pending migrations are run at startup and
|
30
|
+
# are guaranteed to run exactly once per database.
|
31
|
+
migration "create teh foos table" do
|
32
|
+
database.create_table :foos do
|
33
|
+
primary_key :id
|
34
|
+
text :bar
|
35
|
+
integer :baz, :default => 42
|
36
|
+
timestamp :bizzle, :null => false
|
37
|
+
|
38
|
+
index :baz, :unique => true
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# you can also alter tables
|
43
|
+
migration "everything's better with bling" do
|
44
|
+
database.alter_table :foos do
|
45
|
+
drop_column :baz
|
46
|
+
add_column :bling, :float
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# models just work ...
|
51
|
+
class Foo < Sequel::Model
|
52
|
+
many_to_one :bar
|
53
|
+
end
|
54
|
+
|
55
|
+
# see:
|
56
|
+
Foo.filter(:baz => 42).each { |foo| puts(foo.bar.name) }
|
57
|
+
|
58
|
+
# access the database within the context of an HTTP request
|
59
|
+
get '/foos/:id' do
|
60
|
+
@foo = database[:foos].filter(:id => params[:id]).first
|
61
|
+
erb :foos
|
62
|
+
end
|
63
|
+
|
64
|
+
# or, using the model
|
65
|
+
delete '/foos/:id' do
|
66
|
+
@foo = Foo[params[:id]]
|
67
|
+
@foo.delete
|
68
|
+
end
|
69
|
+
|
70
|
+
### Sequel Reference Material
|
71
|
+
|
72
|
+
* The [Sequel README](http://sequel.rubyforge.org/rdoc/files/README_rdoc.html)
|
73
|
+
and [CHEATSHEET](http://sequel.rubyforge.org/rdoc/files/doc/cheat_sheet_rdoc.html)
|
74
|
+
are quite useful.
|
75
|
+
|
76
|
+
* Migrations are a light facade over Sequel's
|
77
|
+
[Schema module](http://sequel.rubyforge.org/rdoc/files/doc/schema_rdoc.html).
|
78
|
+
Like, [create_table](http://sequel.rubyforge.org/rdoc/classes/Sequel/Schema/Generator.html)
|
79
|
+
and [alter_table](http://sequel.rubyforge.org/rdoc/classes/Sequel/Schema/AlterTableGenerator.html).
|
80
|
+
|
81
|
+
* The best reference on Sequel Models is [the README](http://sequel.rubyforge.org/rdoc/files/README_rdoc.html)
|
82
|
+
and the [Associations](http://sequel.rubyforge.org/rdoc/files/doc/advanced_associations_rdoc.html) doc.
|
83
|
+
You might find this post on [many_to_many / one_to_one](http://steamcode.blogspot.com/2009/03/sequel-models-manytoone-onetomany.html)
|
84
|
+
useful.
|
data/Rakefile
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
require 'rake/clean'
|
2
|
+
|
3
|
+
task :default => :spec
|
4
|
+
|
5
|
+
desc 'Run specs'
|
6
|
+
task :spec do
|
7
|
+
sh 'bacon -a'
|
8
|
+
end
|
9
|
+
|
10
|
+
# PACKAGING ============================================================
|
11
|
+
|
12
|
+
# Load the gemspec using the same limitations as github
|
13
|
+
require 'rubygems/specification'
|
14
|
+
$spec = eval(File.read('sinatra-sequel.gemspec'))
|
15
|
+
|
16
|
+
def package(ext='')
|
17
|
+
"pkg/#{$spec.name}-#{$spec.version}" + ext
|
18
|
+
end
|
19
|
+
|
20
|
+
desc 'Build packages'
|
21
|
+
task :package => %w[.gem .tar.gz].map { |ext| package(ext) }
|
22
|
+
|
23
|
+
desc 'Build and install as local gem'
|
24
|
+
task :install => package('.gem') do
|
25
|
+
sh "gem install #{package('.gem')}"
|
26
|
+
end
|
27
|
+
|
28
|
+
directory 'pkg/'
|
29
|
+
CLOBBER.include('pkg')
|
30
|
+
|
31
|
+
file package('.gem') => %W[pkg/ #{$spec.name}.gemspec] + $spec.files do |f|
|
32
|
+
sh "gem build #{$spec.name}.gemspec"
|
33
|
+
mv File.basename(f.name), f.name
|
34
|
+
end
|
35
|
+
|
36
|
+
file package('.tar.gz') => %w[pkg/] + $spec.files do |f|
|
37
|
+
sh <<-SH
|
38
|
+
git archive \
|
39
|
+
--prefix=#{$spec.name}-#{$spec.version}/ \
|
40
|
+
--format=tar \
|
41
|
+
HEAD | gzip > #{f.name}
|
42
|
+
SH
|
43
|
+
end
|
44
|
+
|
45
|
+
# Rubyforge Release / Publish Tasks ==================================
|
46
|
+
|
47
|
+
desc 'Publish gem and tarball to rubyforge'
|
48
|
+
task 'release' => [package('.gem'), package('.tar.gz')] do |t|
|
49
|
+
sh <<-SH
|
50
|
+
rubyforge add_release wink #{$spec.name} #{$spec.version} #{package('.gem')} &&
|
51
|
+
rubyforge add_file wink #{$spec.name} #{$spec.version} #{package('.tar.gz')}
|
52
|
+
SH
|
53
|
+
end
|
54
|
+
|
55
|
+
# rebuild the gemspec manifest and update timestamps.
|
56
|
+
task "#{$spec.name}.gemspec" => FileList['{lib,spec}/**','Rakefile','COPYING','README.md'] do |f|
|
57
|
+
# read spec file and split out manifest section
|
58
|
+
spec = File.read(f.name)
|
59
|
+
head, manifest, tail = spec.split(" # = MANIFEST =\n")
|
60
|
+
# replace version and date
|
61
|
+
head.sub!(/\.date = '.*'/, ".date = '#{Date.today.to_s}'")
|
62
|
+
# determine file list from git ls-files
|
63
|
+
files = `git ls-files`.
|
64
|
+
split("\n").
|
65
|
+
sort.
|
66
|
+
reject{ |file| file =~ /^\./ }.
|
67
|
+
reject { |file| file =~ /^doc/ }.
|
68
|
+
map{ |file| " #{file}" }.
|
69
|
+
join("\n")
|
70
|
+
# piece file back together and write...
|
71
|
+
manifest = " s.files = %w[\n#{files}\n ]\n"
|
72
|
+
spec = [head,manifest,tail].join(" # = MANIFEST =\n")
|
73
|
+
File.open(f.name, 'w') { |io| io.write(spec) }
|
74
|
+
puts "updated #{f.name}"
|
75
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'sinatra/base'
|
3
|
+
require 'sequel'
|
4
|
+
|
5
|
+
module Sinatra
|
6
|
+
module SequelHelper
|
7
|
+
def database
|
8
|
+
options.database
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module SequelExtension
|
13
|
+
def database=(url)
|
14
|
+
@database = nil
|
15
|
+
set :database_url, url
|
16
|
+
database
|
17
|
+
end
|
18
|
+
|
19
|
+
def database
|
20
|
+
@database ||=
|
21
|
+
Sequel.connect(database_url)
|
22
|
+
end
|
23
|
+
|
24
|
+
def sqlite?
|
25
|
+
defined?(Sequel::SQLite::Database) && database.kind_of?(Sequel::SQLite::Database)
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO: wrong!
|
29
|
+
def postgres?
|
30
|
+
! sqlite?
|
31
|
+
end
|
32
|
+
|
33
|
+
def migration(name, &block)
|
34
|
+
create_migrations_table
|
35
|
+
return if database[migrations_table_name].filter(:name => name).count > 0
|
36
|
+
migrations_log.puts "Running migration: #{name}"
|
37
|
+
database.transaction do
|
38
|
+
yield database
|
39
|
+
database[migrations_table_name] << { :name => name, :ran_at => Time.now }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
protected
|
44
|
+
|
45
|
+
def create_migrations_table
|
46
|
+
database.create_table? :migrations do
|
47
|
+
primary_key :id
|
48
|
+
text :name, :null => false, :index => true
|
49
|
+
timestamp :ran_at
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.registered(app)
|
54
|
+
app.set :database_url, lambda { ENV['DATABASE_URL'] || "sqlite://#{environment}.db" }
|
55
|
+
app.set :migrations_table_name, :migrations
|
56
|
+
app.set :migrations_log, lambda { STDOUT }
|
57
|
+
app.helpers SequelHelper
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
register SequelExtension
|
62
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.specification_version = 2 if s.respond_to? :specification_version=
|
3
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
4
|
+
|
5
|
+
s.name = 'sinatra-sequel'
|
6
|
+
s.version = '0.9.0'
|
7
|
+
s.date = '2009-08-08'
|
8
|
+
|
9
|
+
s.description = "Extends Sinatra with Sequel ORM config, migrations, and helpers"
|
10
|
+
s.summary = s.description
|
11
|
+
|
12
|
+
s.authors = ["Ryan Tomayko"]
|
13
|
+
s.email = "rtomayko@gmail.com"
|
14
|
+
|
15
|
+
# = MANIFEST =
|
16
|
+
s.files = %w[
|
17
|
+
COPYING
|
18
|
+
README.md
|
19
|
+
Rakefile
|
20
|
+
lib/sinatra/sequel.rb
|
21
|
+
sinatra-sequel.gemspec
|
22
|
+
spec/spec_sinatra_sequel.rb
|
23
|
+
]
|
24
|
+
# = MANIFEST =
|
25
|
+
|
26
|
+
s.test_files = s.files.select {|path| path =~ /^spec\/.*.rb/ }
|
27
|
+
|
28
|
+
s.extra_rdoc_files = %w[README.md COPYING]
|
29
|
+
s.add_dependency 'sinatra', '>= 0.9.4'
|
30
|
+
s.add_dependency 'sequel', '>= 3.2.0'
|
31
|
+
s.add_development_dependency 'bacon'
|
32
|
+
|
33
|
+
s.has_rdoc = true
|
34
|
+
s.homepage = "http://github.com/rtomayko/sinatra-sequel"
|
35
|
+
s.rdoc_options = ["--line-numbers", "--inline-source", "--title", "Sinatra::Sequel"]
|
36
|
+
s.require_paths = %w[lib]
|
37
|
+
s.rubyforge_project = 'wink'
|
38
|
+
s.rubygems_version = '1.1.1'
|
39
|
+
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
root = File.expand_path(File.dirname(__FILE__) + '/..')
|
2
|
+
$: << "#{root}/lib"
|
3
|
+
|
4
|
+
require 'sinatra/base'
|
5
|
+
require 'sinatra/sequel'
|
6
|
+
|
7
|
+
class MockSinatraApp < Sinatra::Base
|
8
|
+
register Sinatra::SequelExtension
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'A Sinatra app with Sequel extensions' do
|
12
|
+
before {
|
13
|
+
File.unlink 'test.db' rescue nil
|
14
|
+
ENV.delete('DATABASE_URL')
|
15
|
+
@app = Class.new(MockSinatraApp)
|
16
|
+
@app.set :migrations_log, File.open('/dev/null', 'wb')
|
17
|
+
}
|
18
|
+
|
19
|
+
it 'exposes the Sequel database object' do
|
20
|
+
@app.should.respond_to :database
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'uses the DATABASE_URL environment variable if set' do
|
24
|
+
ENV['DATABASE_URL'] = 'sqlite://test-database-url.db'
|
25
|
+
@app.database_url.should.equal 'sqlite://test-database-url.db'
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'uses sqlite://<environment>.db when no DATABASE_URL is defined' do
|
29
|
+
@app.environment = :foo
|
30
|
+
@app.database_url.should.equal "sqlite://foo.db"
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'establishes a database connection when set' do
|
34
|
+
@app.database = 'sqlite://test.db'
|
35
|
+
@app.database.should.respond_to :table_exists?
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'runs database migrations' do
|
39
|
+
@app.database = 'sqlite://test.db'
|
40
|
+
@app.migration 'create the foos table' do |db|
|
41
|
+
db.create_table :foos do
|
42
|
+
primary_key :id
|
43
|
+
text :foo
|
44
|
+
integer :bar
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
@app.database[:migrations].count.should.equal 1
|
49
|
+
@app.database.should.table_exists :foos
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'does not run database migrations more than once' do
|
53
|
+
@app.database = 'sqlite://test.db'
|
54
|
+
@app.migration('this should run once') { }
|
55
|
+
@app.migration('this should run once') { fail }
|
56
|
+
@app.database[:migrations].count.should.equal 1
|
57
|
+
end
|
58
|
+
end
|
metadata
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sinatra-sequel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.9.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Ryan Tomayko
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-08-08 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: sinatra
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.9.4
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: sequel
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 3.2.0
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: bacon
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: "0"
|
44
|
+
version:
|
45
|
+
description: Extends Sinatra with Sequel ORM config, migrations, and helpers
|
46
|
+
email: rtomayko@gmail.com
|
47
|
+
executables: []
|
48
|
+
|
49
|
+
extensions: []
|
50
|
+
|
51
|
+
extra_rdoc_files:
|
52
|
+
- README.md
|
53
|
+
- COPYING
|
54
|
+
files:
|
55
|
+
- COPYING
|
56
|
+
- README.md
|
57
|
+
- Rakefile
|
58
|
+
- lib/sinatra/sequel.rb
|
59
|
+
- sinatra-sequel.gemspec
|
60
|
+
- spec/spec_sinatra_sequel.rb
|
61
|
+
has_rdoc: true
|
62
|
+
homepage: http://github.com/rtomayko/sinatra-sequel
|
63
|
+
licenses: []
|
64
|
+
|
65
|
+
post_install_message:
|
66
|
+
rdoc_options:
|
67
|
+
- --line-numbers
|
68
|
+
- --inline-source
|
69
|
+
- --title
|
70
|
+
- Sinatra::Sequel
|
71
|
+
require_paths:
|
72
|
+
- lib
|
73
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
74
|
+
requirements:
|
75
|
+
- - ">="
|
76
|
+
- !ruby/object:Gem::Version
|
77
|
+
version: "0"
|
78
|
+
version:
|
79
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - ">="
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: "0"
|
84
|
+
version:
|
85
|
+
requirements: []
|
86
|
+
|
87
|
+
rubyforge_project: wink
|
88
|
+
rubygems_version: 1.3.4
|
89
|
+
signing_key:
|
90
|
+
specification_version: 2
|
91
|
+
summary: Extends Sinatra with Sequel ORM config, migrations, and helpers
|
92
|
+
test_files:
|
93
|
+
- spec/spec_sinatra_sequel.rb
|