sequel 0.0.1 → 0.0.2
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/CHANGELOG +14 -1
- data/README +25 -21
- data/Rakefile +4 -3
- data/lib/sequel.rb +6 -2
- data/lib/sequel/database.rb +10 -0
- data/lib/sequel/dataset.rb +52 -4
- data/lib/sequel/model.rb +19 -12
- data/lib/sequel/postgres.rb +3 -21
- data/lib/sequel/schema.rb +2 -0
- data/lib/sequel/sqlite.rb +1 -11
- metadata +7 -10
- data/spec/database_spec.rb +0 -18
- data/spec/dataset_spec.rb +0 -124
- data/spec/postgres_spec.rb +0 -6
data/CHANGELOG
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
*0.0.2*
|
2
|
+
|
3
|
+
* Added Sequel.open as alias to Sequel.connect.
|
4
|
+
|
5
|
+
* Refactored Dataset#where_equal_condition into Dataset#where_condition, allowing arrays and ranges, e.g. posts.filter(:stamp => (3.days.ago)..(1.day.ago)), or posts.filter(:category => ['ruby', 'postgres', 'linux']).
|
6
|
+
|
7
|
+
* Added Model#[]= method for changing column values and Model#save
|
8
|
+
method for saving them.
|
9
|
+
|
10
|
+
* Added Dataset#destroy for deleting each record individually as support for models. Renamed Model#delete to Model#destroy (and Model#destroy_all) ala ActiveRecord.
|
11
|
+
|
12
|
+
* Refactored Dataset#first and Dataset#last code. These methods can now accept the number of records to fetch.
|
13
|
+
|
1
14
|
*0.0.1*
|
2
15
|
|
3
16
|
* More documentation for Dataset.
|
@@ -10,4 +23,4 @@
|
|
10
23
|
|
11
24
|
* Added Database#<< method for executing arbitrary SQL.
|
12
25
|
|
13
|
-
* Imported Sequel code.
|
26
|
+
* Imported Sequel code.
|
data/README
CHANGED
@@ -2,14 +2,6 @@
|
|
2
2
|
|
3
3
|
Sequel is an ORM framework for Ruby. Sequel provides thread safety, connection pooling, and a DSL for constructing queries and table schemas.
|
4
4
|
|
5
|
-
== Sequel vs. ActiveRecord
|
6
|
-
|
7
|
-
Sequel offers the following advantages over ActiveRecord:
|
8
|
-
|
9
|
-
* Better performance with large tables: unlike ActiveRecord, Sequel does not load the entire resultset into memory, but fetches each record separately and implements an Enumerable interface.
|
10
|
-
* Easy construction of queries using a DSL.
|
11
|
-
* Using model classes is possible, but not mandatory.
|
12
|
-
|
13
5
|
== Resources
|
14
6
|
|
15
7
|
* {Project page}[http://code.google.com/p/ruby-sequel/]
|
@@ -24,6 +16,13 @@ To check out the source code:
|
|
24
16
|
== Installation
|
25
17
|
|
26
18
|
sudo gem install sequel
|
19
|
+
|
20
|
+
== Supported Databases
|
21
|
+
|
22
|
+
Sequel currently supports:
|
23
|
+
|
24
|
+
* Postgresql
|
25
|
+
* SQLite 3
|
27
26
|
|
28
27
|
== A Short Tutorial
|
29
28
|
|
@@ -31,19 +30,18 @@ To check out the source code:
|
|
31
30
|
|
32
31
|
There are two ways to create a connection to a database. The easier way is to provide a connection URL:
|
33
32
|
|
34
|
-
DB = Sequel.connect("
|
33
|
+
DB = Sequel.connect("sqlite:///blog.db")
|
35
34
|
|
36
35
|
You can also specify optional parameters, such as the connection pool size:
|
37
36
|
|
38
|
-
DB = Sequel.connect("postgres://postgres:postgres@localhost
|
37
|
+
DB = Sequel.connect("postgres://postgres:postgres@localhost/my_db",
|
39
38
|
:max_connections => 10)
|
40
39
|
|
41
40
|
The second, more verbose, way is to create an instance of a database class:
|
42
41
|
|
43
|
-
DB = Sequel::Postgres::Database.new(:database => 'my_db', :host => 'localhost'
|
44
|
-
:port => 5432)
|
42
|
+
DB = Sequel::Postgres::Database.new(:database => 'my_db', :host => 'localhost')
|
45
43
|
|
46
|
-
|
44
|
+
=== Arbitrary SQL queries
|
47
45
|
|
48
46
|
DB.execute("create table t (a text, b text)")
|
49
47
|
DB.execute("insert into t values ('a', 'b')")
|
@@ -55,9 +53,9 @@ Or more succintly:
|
|
55
53
|
|
56
54
|
=== Creating Datasets
|
57
55
|
|
58
|
-
Dataset is the primary means through which records are retrieved and manipulated. You can create an blank dataset by using the
|
56
|
+
Dataset is the primary means through which records are retrieved and manipulated. You can create an blank dataset by using the dataset method:
|
59
57
|
|
60
|
-
dataset = DB.
|
58
|
+
dataset = DB.dataset
|
61
59
|
|
62
60
|
Or by using the from methods:
|
63
61
|
|
@@ -102,9 +100,13 @@ The simplest way to filter records is to provide a hash of values to match:
|
|
102
100
|
|
103
101
|
You can also specify ranges:
|
104
102
|
|
105
|
-
my_posts = posts.filter(:stamp => 2.weeks.ago..1.week.ago)
|
103
|
+
my_posts = posts.filter(:stamp => (2.weeks.ago)..(1.week.ago))
|
104
|
+
|
105
|
+
Or lists of values:
|
106
|
+
|
107
|
+
my_posts = posts.filter(:category => ['ruby', 'postgres', 'linux'])
|
106
108
|
|
107
|
-
Some adapters will also let you specify Regexps:
|
109
|
+
Some adapters (like postgresql) will also let you specify Regexps:
|
108
110
|
|
109
111
|
my_posts = posts.filter(:category => /ruby/i)
|
110
112
|
|
@@ -120,9 +122,13 @@ You can also specify a custom WHERE clause:
|
|
120
122
|
|
121
123
|
posts.filter('(stamp < ?) AND (author <> ?)', 3.days.ago, author_name)
|
122
124
|
|
123
|
-
===
|
125
|
+
=== Summarizing Records
|
124
126
|
|
125
|
-
|
127
|
+
Counting records is easy:
|
128
|
+
posts.filter(:category => /ruby/i).count
|
129
|
+
|
130
|
+
And you can also query maximum/minimum values:
|
131
|
+
max_value = DB[:history].max(:value)
|
126
132
|
|
127
133
|
=== Ordering Records
|
128
134
|
|
@@ -147,5 +153,3 @@ Or alternatively:
|
|
147
153
|
=== Updating Records
|
148
154
|
|
149
155
|
posts.filter('stamp < ?', 3.days.ago).update(:state => 'archived')
|
150
|
-
|
151
|
-
===
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.0.
|
9
|
+
VERS = "0.0.2"
|
10
10
|
CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
|
11
11
|
RDOC_OPTS = ['--quiet', '--title', "Sequel Documentation",
|
12
12
|
"--opname", "index.html",
|
@@ -40,12 +40,13 @@ spec = Gem::Specification.new do |s|
|
|
40
40
|
s.description = s.summary
|
41
41
|
s.author = "Sharon Rosner"
|
42
42
|
s.email = 'ciconia@gmail.com'
|
43
|
-
s.homepage = 'http://
|
43
|
+
s.homepage = 'http://sequel.rubyforge.org'
|
44
44
|
|
45
45
|
s.add_dependency('metaid')
|
46
46
|
s.required_ruby_version = '>= 1.8.2'
|
47
47
|
|
48
|
-
s.files = %w(COPYING README Rakefile) + Dir.glob("{doc,spec,lib}/**/*")
|
48
|
+
# s.files = %w(COPYING README Rakefile) + Dir.glob("{doc,spec,lib}/**/*")
|
49
|
+
s.files = %w(COPYING README Rakefile) + Dir.glob("{doc,lib}/**/*")
|
49
50
|
|
50
51
|
s.require_path = "lib"
|
51
52
|
end
|
data/lib/sequel.rb
CHANGED
@@ -7,7 +7,11 @@ require File.join(dir, 'dataset')
|
|
7
7
|
require File.join(dir, 'model')
|
8
8
|
|
9
9
|
module Sequel #:nodoc:
|
10
|
-
|
11
|
-
|
10
|
+
class << self
|
11
|
+
def connect(url)
|
12
|
+
Database.connect(url)
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method :open, :connect
|
12
16
|
end
|
13
17
|
end
|
data/lib/sequel/database.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'uri'
|
2
2
|
|
3
3
|
require File.join(File.dirname(__FILE__), 'schema')
|
4
|
+
require File.join(File.dirname(__FILE__), 'dataset')
|
4
5
|
|
5
6
|
module Sequel
|
6
7
|
# A Database object represents a virtual connection to a database.
|
@@ -14,6 +15,11 @@ module Sequel
|
|
14
15
|
def initialize(opts = {})
|
15
16
|
@opts = opts
|
16
17
|
end
|
18
|
+
|
19
|
+
# Returns a blank dataset
|
20
|
+
def dataset
|
21
|
+
Dataset.new(self)
|
22
|
+
end
|
17
23
|
|
18
24
|
# Returns a new dataset with the from method invoked.
|
19
25
|
def from(*args); dataset.from(*args); end
|
@@ -27,6 +33,10 @@ module Sequel
|
|
27
33
|
dataset.from(table)
|
28
34
|
end
|
29
35
|
|
36
|
+
def execute(sql)
|
37
|
+
raise RuntimeError
|
38
|
+
end
|
39
|
+
|
30
40
|
# call-seq:
|
31
41
|
# db.execute(sql)
|
32
42
|
# db << sql
|
data/lib/sequel/dataset.rb
CHANGED
@@ -22,7 +22,7 @@ module Sequel
|
|
22
22
|
class Dataset
|
23
23
|
include Enumerable
|
24
24
|
|
25
|
-
attr_reader :db
|
25
|
+
attr_reader :db, :opts
|
26
26
|
attr_accessor :record_class
|
27
27
|
|
28
28
|
# Constructs a new instance of a dataset with a database instance, initial
|
@@ -94,28 +94,40 @@ module Sequel
|
|
94
94
|
end
|
95
95
|
end
|
96
96
|
|
97
|
+
NULL = "NULL".freeze
|
98
|
+
|
97
99
|
# Returns a literal representation of a value to be used as part
|
98
100
|
# of an SQL expression. This method is overriden in descendants.
|
99
101
|
def literal(v)
|
100
102
|
case v
|
101
103
|
when String: "'%s'" % v
|
104
|
+
when Array: v.empty? ? NULL : v.join(COMMA_SEPARATOR)
|
102
105
|
else v.to_s
|
103
106
|
end
|
104
107
|
end
|
105
108
|
|
106
109
|
AND_SEPARATOR = " AND ".freeze
|
107
110
|
EQUAL_COND = "(%s = %s)".freeze
|
111
|
+
IN_EXPR = "(%s IN (%s))".freeze
|
112
|
+
BETWEEN_EXPR = "(%s BETWEEN %s AND %s)".freeze
|
108
113
|
|
109
114
|
# Formats an equality condition SQL expression.
|
110
|
-
def
|
111
|
-
|
115
|
+
def where_condition(left, right)
|
116
|
+
case right
|
117
|
+
when Range:
|
118
|
+
BETWEEN_EXPR % [field_name(left), literal(right.begin), literal(right.end)]
|
119
|
+
when Array:
|
120
|
+
IN_EXPR % [field_name(left), literal(right)]
|
121
|
+
else
|
122
|
+
EQUAL_COND % [field_name(left), literal(right)]
|
123
|
+
end
|
112
124
|
end
|
113
125
|
|
114
126
|
# Formats a where clause.
|
115
127
|
def where_list(where)
|
116
128
|
case where
|
117
129
|
when Hash:
|
118
|
-
where.map {|kv|
|
130
|
+
where.map {|kv| where_condition(*kv)}.join(AND_SEPARATOR)
|
119
131
|
when Array:
|
120
132
|
fmt = where.shift
|
121
133
|
fmt.gsub('?') {|i| literal(where.shift)}
|
@@ -322,6 +334,42 @@ module Sequel
|
|
322
334
|
def max(field)
|
323
335
|
select(field.MAX).first[:max]
|
324
336
|
end
|
337
|
+
|
338
|
+
LIMIT_1 = {:limit => 1}.freeze
|
339
|
+
|
340
|
+
def limit(l)
|
341
|
+
dup_merge(:limit => l)
|
342
|
+
end
|
343
|
+
|
344
|
+
def first(num = 1)
|
345
|
+
if num == 1
|
346
|
+
first_record
|
347
|
+
else
|
348
|
+
limit(num).all
|
349
|
+
end
|
350
|
+
end
|
351
|
+
|
352
|
+
def last(num = 1)
|
353
|
+
raise RuntimeError, 'No order specified' unless
|
354
|
+
@opts[:order] || (opts && opts[:order])
|
355
|
+
|
356
|
+
l = {:limit => num}
|
357
|
+
opts = {:order => reverse_order(@opts[:order])}.
|
358
|
+
merge(opts ? opts.merge(l) : l)
|
359
|
+
|
360
|
+
if num == 1
|
361
|
+
first_record(opts)
|
362
|
+
else
|
363
|
+
dup_merge(opts).all
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
def destroy
|
368
|
+
raise RuntimeError, 'Dataset not associated with model' unless
|
369
|
+
@record_class
|
370
|
+
|
371
|
+
@db.transaction {each {|r| r.destroy}}
|
372
|
+
end
|
325
373
|
end
|
326
374
|
end
|
327
375
|
|
data/lib/sequel/model.rb
CHANGED
@@ -42,7 +42,7 @@ module Sequel
|
|
42
42
|
rec
|
43
43
|
end
|
44
44
|
|
45
|
-
alias_method :
|
45
|
+
alias_method :destroy, :destroy_and_invalidate_cache
|
46
46
|
alias_method :set, :set_and_update_cache
|
47
47
|
end
|
48
48
|
|
@@ -119,8 +119,8 @@ module Sequel
|
|
119
119
|
self.class.get_hooks(key).each {|h| instance_eval(&h)}
|
120
120
|
end
|
121
121
|
|
122
|
-
def self.
|
123
|
-
get_hooks(:
|
122
|
+
def self.before_destroy(&block)
|
123
|
+
get_hooks(:before_destroy).unshift(block)
|
124
124
|
end
|
125
125
|
|
126
126
|
def self.after_create(&block)
|
@@ -168,13 +168,10 @@ module Sequel
|
|
168
168
|
def self.hash_column(column); dataset.hash_column(primary_key, column); end
|
169
169
|
def self.join(*args); dataset.join(*args); end
|
170
170
|
def self.lock(mode, &block); dataset.lock(mode, &block); end
|
171
|
-
def self.
|
172
|
-
|
173
|
-
db.transaction {dataset.all.each {|r| r.delete}}
|
174
|
-
else
|
175
|
-
dataset.delete
|
176
|
-
end
|
171
|
+
def self.destroy_all
|
172
|
+
has_hooks?(:before_destroy) ? dataset.destroy : dataset.delete
|
177
173
|
end
|
174
|
+
def self.delete_all; dataset.delete; end
|
178
175
|
|
179
176
|
def self.[](key)
|
180
177
|
find key.is_a?(Hash) ? key : {primary_key => key}
|
@@ -188,13 +185,17 @@ module Sequel
|
|
188
185
|
end
|
189
186
|
end
|
190
187
|
|
191
|
-
def
|
188
|
+
def destroy
|
192
189
|
db.transaction do
|
193
|
-
run_hooks(:
|
194
|
-
|
190
|
+
run_hooks(:before_destroy)
|
191
|
+
delete
|
195
192
|
end
|
196
193
|
end
|
197
194
|
|
195
|
+
def delete
|
196
|
+
model.dataset.filter(primary_key => @pkey).delete
|
197
|
+
end
|
198
|
+
|
198
199
|
FIND_BY_REGEXP = /^find_by_(.*)/.freeze
|
199
200
|
FILTER_BY_REGEXP = /^filter_by_(.*)/.freeze
|
200
201
|
|
@@ -227,6 +228,12 @@ module Sequel
|
|
227
228
|
model.dataset.filter(primary_key => @pkey).update(values)
|
228
229
|
@values.merge!(values)
|
229
230
|
end
|
231
|
+
|
232
|
+
def []=(field, value); @values[field] = value; end
|
233
|
+
|
234
|
+
def save
|
235
|
+
model.dataset.filter(primary_key => @pkey).update(@values)
|
236
|
+
end
|
230
237
|
end
|
231
238
|
|
232
239
|
def self.Model(table_name)
|
data/lib/sequel/postgres.rb
CHANGED
@@ -162,9 +162,9 @@ module Sequel
|
|
162
162
|
|
163
163
|
def literal(v)
|
164
164
|
case v
|
165
|
+
when Array: super
|
165
166
|
when Time: v.to_sql_timestamp
|
166
167
|
when Symbol: PGconn.quote(v.to_s)
|
167
|
-
when Array: v.empty? ? EMPTY_ARRAY : v.join(COMMA_SEPARATOR)
|
168
168
|
else
|
169
169
|
PGconn.quote(v)
|
170
170
|
end
|
@@ -173,16 +173,11 @@ module Sequel
|
|
173
173
|
LIKE = '%s ~ %s'.freeze
|
174
174
|
LIKE_CI = '%s ~* %s'.freeze
|
175
175
|
|
176
|
-
|
177
|
-
EMPTY_ARRAY = 'NULL'.freeze
|
178
|
-
|
179
|
-
def where_equal_condition(left, right)
|
176
|
+
def where_condition(left, right)
|
180
177
|
case right
|
181
178
|
when Regexp:
|
182
179
|
(right.casefold? ? LIKE_CI : LIKE) %
|
183
180
|
[field_name(left), PGconn.quote(right.source)]
|
184
|
-
when Array:
|
185
|
-
IN_ARRAY % [field_name(left), literal(right)]
|
186
181
|
else
|
187
182
|
super
|
188
183
|
end
|
@@ -192,21 +187,8 @@ module Sequel
|
|
192
187
|
query_each(select_sql(opts), true, &block)
|
193
188
|
self
|
194
189
|
end
|
195
|
-
|
196
|
-
LIMIT_1 = {:limit => 1}.freeze
|
197
|
-
|
198
|
-
def first(opts = nil)
|
199
|
-
opts = opts ? opts.merge(LIMIT_1) : LIMIT_1
|
200
|
-
query_first(select_sql(opts), true)
|
201
|
-
end
|
202
|
-
|
203
|
-
def last(opts = nil)
|
204
|
-
raise RuntimeError, 'No order specified' unless
|
205
|
-
@opts[:order] || (opts && opts[:order])
|
206
|
-
|
207
|
-
opts = {:order => reverse_order(@opts[:order])}.
|
208
|
-
merge(opts ? opts.merge(LIMIT_1) : LIMIT_1)
|
209
190
|
|
191
|
+
def first_record(opts = nil)
|
210
192
|
query_first(select_sql(opts), true)
|
211
193
|
end
|
212
194
|
|
data/lib/sequel/schema.rb
CHANGED
@@ -11,6 +11,7 @@ module Sequel
|
|
11
11
|
PRIMARY_KEY = ' PRIMARY KEY'.freeze
|
12
12
|
REFERENCES = ' REFERENCES %s'.freeze
|
13
13
|
ON_DELETE = ' ON DELETE %s'.freeze
|
14
|
+
AUTOINCREMENT = ' AUTOINCREMENT'.freeze
|
14
15
|
|
15
16
|
RESTRICT = 'RESTRICT'.freeze
|
16
17
|
CASCADE = 'CASCADE'.freeze
|
@@ -40,6 +41,7 @@ module Sequel
|
|
40
41
|
c << REFERENCES % column[:table] if column[:table]
|
41
42
|
c << ON_DELETE % on_delete_action(column[:on_delete]) if
|
42
43
|
column[:on_delete]
|
44
|
+
c << AUTOINCREMENT if column[:auto_increment]
|
43
45
|
c
|
44
46
|
end
|
45
47
|
|
data/lib/sequel/sqlite.rb
CHANGED
@@ -70,20 +70,10 @@ module Sequel
|
|
70
70
|
|
71
71
|
LIMIT_1 = {:limit => 1}.freeze
|
72
72
|
|
73
|
-
def
|
74
|
-
opts = opts ? opts.merge(LIMIT_1) : LIMIT_1
|
73
|
+
def first_record(opts = nil)
|
75
74
|
@db.result_set(select_sql(opts), @record_class) {|r| return r}
|
76
75
|
end
|
77
76
|
|
78
|
-
def last(opts = nil)
|
79
|
-
raise RuntimeError, 'No order specified' unless
|
80
|
-
@opts[:order] || (opts && opts[:order])
|
81
|
-
|
82
|
-
opts = {:order => reverse_order(@opts[:order])}.
|
83
|
-
merge(opts ? opts.merge(LIMIT_1) : LIMIT_1)
|
84
|
-
@db.result_set(select_sql(opts), @record_class) {|r| return r}
|
85
|
-
end
|
86
|
-
|
87
77
|
def count(opts = nil)
|
88
78
|
@db.single_value(count_sql(opts)).to_i
|
89
79
|
end
|
metadata
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
|
-
rubygems_version: 0.9.
|
2
|
+
rubygems_version: 0.9.0
|
3
3
|
specification_version: 1
|
4
4
|
name: sequel
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2007-03-
|
6
|
+
version: 0.0.2
|
7
|
+
date: 2007-03-18 00:00:00 +02:00
|
8
8
|
summary: ORM framework for Ruby.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
11
11
|
email: ciconia@gmail.com
|
12
|
-
homepage: http://
|
12
|
+
homepage: http://sequel.rubyforge.org
|
13
13
|
rubyforge_project:
|
14
14
|
description: ORM framework for Ruby.
|
15
15
|
autorequire:
|
@@ -33,19 +33,16 @@ files:
|
|
33
33
|
- README
|
34
34
|
- Rakefile
|
35
35
|
- doc/rdoc
|
36
|
-
- spec/database_spec.rb
|
37
|
-
- spec/dataset_spec.rb
|
38
|
-
- spec/postgres_spec.rb
|
39
36
|
- lib/sequel
|
40
37
|
- lib/sequel.rb
|
38
|
+
- lib/sequel/connection_pool.rb
|
39
|
+
- lib/sequel/core_ext.rb
|
40
|
+
- lib/sequel/database.rb
|
41
41
|
- lib/sequel/dataset.rb
|
42
42
|
- lib/sequel/model.rb
|
43
43
|
- lib/sequel/postgres.rb
|
44
44
|
- lib/sequel/schema.rb
|
45
45
|
- lib/sequel/sqlite.rb
|
46
|
-
- lib/sequel/connection_pool.rb
|
47
|
-
- lib/sequel/database.rb
|
48
|
-
- lib/sequel/core_ext.rb
|
49
46
|
- CHANGELOG
|
50
47
|
test_files: []
|
51
48
|
|
data/spec/database_spec.rb
DELETED
@@ -1,18 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '../lib/sequel')
|
2
|
-
|
3
|
-
|
4
|
-
class Sequel::Database
|
5
|
-
attr_accessor :opts
|
6
|
-
end
|
7
|
-
|
8
|
-
context "A new Database" do
|
9
|
-
specify "should accept options and store them in @opts" do
|
10
|
-
opts = :my_options
|
11
|
-
Sequel::Database.new(opts).opts.should_be opts
|
12
|
-
end
|
13
|
-
|
14
|
-
specify "should set opts to empty hash if not specified" do
|
15
|
-
Sequel::Database.new.opts.should == {}
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
data/spec/dataset_spec.rb
DELETED
@@ -1,124 +0,0 @@
|
|
1
|
-
require File.join(File.dirname(__FILE__), '../lib/sequel')
|
2
|
-
|
3
|
-
class sequel::Dataset
|
4
|
-
attr_accessor :db, :opts
|
5
|
-
end
|
6
|
-
|
7
|
-
context "The Dataset Class" do
|
8
|
-
specify "should include the Enumerable mix-in" do
|
9
|
-
Sequel::Dataset.included_modules.should_include Enumerable
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
context "A new Dataset instance" do
|
14
|
-
specify "should store db and opts in @db and @opts" do
|
15
|
-
db = "my db"
|
16
|
-
opts = [1, 2, 3, 4]
|
17
|
-
|
18
|
-
d = Sequel::Dataset.new(db, opts)
|
19
|
-
d.db.should_be db
|
20
|
-
d.opts.should_be opts
|
21
|
-
end
|
22
|
-
|
23
|
-
specify "should set opts to empty hash if ommited" do
|
24
|
-
Sequel::Dataset.new(:db).opts.should == {}
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context "Dataset#dup_merge" do
|
29
|
-
specify "should create a new instance of the same class with merged opts" do
|
30
|
-
subclass = Class.new(Sequel::Dataset)
|
31
|
-
db = "my db"
|
32
|
-
orig = subclass.new(db, {1 => 2, 3 => 4})
|
33
|
-
dup = orig.dup_merge({3 => 5})
|
34
|
-
|
35
|
-
dup.class.should_be subclass
|
36
|
-
dup.opts.should == {1 => 2, 3 => 5}
|
37
|
-
dup.db.should_be db
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context "Dataset#field_name" do
|
42
|
-
setup {@d = Sequel::Dataset.new(:db)}
|
43
|
-
|
44
|
-
specify "should return the argument as is if not a symbol" do
|
45
|
-
@d.field_name(nil).should == nil
|
46
|
-
@d.field_name(1).should == 1
|
47
|
-
@d.field_name('field').should == 'field'
|
48
|
-
end
|
49
|
-
|
50
|
-
specify "should parse fields with underscore without change" do
|
51
|
-
@d.field_name(:node_id).should == 'node_id'
|
52
|
-
end
|
53
|
-
|
54
|
-
specify "should parse double-underscore as dot-notation" do
|
55
|
-
@d.field_name(:posts__id).should == 'posts.id'
|
56
|
-
end
|
57
|
-
|
58
|
-
specify "should parse triple-underscore as AS notation" do
|
59
|
-
@d.field_name(:posts__id___pid).should == 'posts.id AS pid'
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "Dataset#field_list" do
|
64
|
-
setup {@d = Sequel::Dataset.new(:db)}
|
65
|
-
|
66
|
-
specify "should return the sql wildcard if an empty array is specified" do
|
67
|
-
@d.field_list([]).should == '*'
|
68
|
-
end
|
69
|
-
|
70
|
-
specify "should return comma-separated field list if an array is passed" do
|
71
|
-
@d.field_list([:a, :b]).should == 'a, b'
|
72
|
-
end
|
73
|
-
|
74
|
-
specify "should return the argument as is if not an array" do
|
75
|
-
@d.field_list(nil).should_be_nil
|
76
|
-
@d.field_list(23).should_be 23
|
77
|
-
@d.field_list("wowie zowie").should == "wowie zowie"
|
78
|
-
end
|
79
|
-
|
80
|
-
specify "should parse field names using #field_name" do
|
81
|
-
@d.field_list([:posts__author_id, :authors__name]).should ==
|
82
|
-
'posts.author_id, authors.name'
|
83
|
-
|
84
|
-
@d.field_list([:posts__id___pid, :authors__name___aname]).should ==
|
85
|
-
'posts.id AS pid, authors.name AS aname'
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context "Dataset#source_list" do
|
90
|
-
setup {@d = Sequel::Dataset.new(:db)}
|
91
|
-
|
92
|
-
specify "should return the argument if not an array or hash" do
|
93
|
-
@d.source_list(nil).should_be_nil
|
94
|
-
@d.source_list(1).should == 1
|
95
|
-
@d.source_list('hello').should == 'hello'
|
96
|
-
@d.source_list(:symbol).should == :symbol
|
97
|
-
end
|
98
|
-
|
99
|
-
specify "should return comma-separated value if an array is specified" do
|
100
|
-
@d.source_list([1, 2, 3]).should == '1, 2, 3'
|
101
|
-
end
|
102
|
-
end
|
103
|
-
|
104
|
-
context "Dataset DSL: " do
|
105
|
-
specify "#form should create a duplicate dataset with the source argument merged" do
|
106
|
-
subclass = Class.new(Sequel::Dataset)
|
107
|
-
d1 = subclass.new(:db, {:select => '*'})
|
108
|
-
|
109
|
-
d2 = d1.from(:posts)
|
110
|
-
d2.class.should_be subclass
|
111
|
-
d2.opts[:select].should == '*'
|
112
|
-
d2.opts[:from].should == :posts
|
113
|
-
end
|
114
|
-
|
115
|
-
specify "#select should create a duplicate dataset with the select argument merged" do
|
116
|
-
subclass = Class.new(Sequel::Dataset)
|
117
|
-
d1 = subclass.new(:db, {:from => :posts})
|
118
|
-
|
119
|
-
d2 = d1.select(:id, :name)
|
120
|
-
d2.class.should_be subclass
|
121
|
-
d2.opts[:from].should == :posts
|
122
|
-
d2.opts[:select].should == [:id, :name]
|
123
|
-
end
|
124
|
-
end
|