sequel 0.4.1.1 → 0.4.1.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 +10 -0
- data/Rakefile +1 -1
- data/lib/sequel/adapters/odbc.rb +1 -1
- data/lib/sequel/adapters/odbc_mssql.rb +98 -0
- data/lib/sequel/database.rb +1 -0
- data/lib/sequel/dataset/sql.rb +1 -1
- data/lib/sequel/model.rb +2 -45
- data/lib/sequel/model/plugins.rb +29 -0
- data/lib/sequel/model/record.rb +36 -0
- data/spec/model_spec.rb +38 -0
- metadata +4 -2
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 0.4.1.2 (2007-12-04)
|
2
|
+
|
3
|
+
* Changed Model.is to accept variable arity.
|
4
|
+
|
5
|
+
* Implemented plugin loading for model classes.
|
6
|
+
|
7
|
+
* Fixed odbc-mssql and odbc adapters (thanks Dusty.)
|
8
|
+
|
9
|
+
* Implemented odbc-mssql adapter (thanks Dusty.)
|
10
|
+
|
1
11
|
=== 0.4.1.1 (2007-11-27)
|
2
12
|
|
3
13
|
* Fixed #first and #last functionality in Informix::Dataset (thanks Gerardo Santana).
|
data/Rakefile
CHANGED
@@ -6,7 +6,7 @@ require 'fileutils'
|
|
6
6
|
include FileUtils
|
7
7
|
|
8
8
|
NAME = "sequel"
|
9
|
-
VERS = "0.4.1.
|
9
|
+
VERS = "0.4.1.2"
|
10
10
|
CLEAN.include ['**/.*.sw?', 'pkg/*', '.config', 'doc/*', 'coverage/*']
|
11
11
|
RDOC_OPTS = ['--quiet', '--title', "Sequel: Concise ORM for Ruby",
|
12
12
|
"--opname", "index.html",
|
data/lib/sequel/adapters/odbc.rb
CHANGED
@@ -0,0 +1,98 @@
|
|
1
|
+
if !Object.const_defined?('Sequel')
|
2
|
+
require File.join(File.dirname(__FILE__), '../../sequel')
|
3
|
+
end
|
4
|
+
|
5
|
+
if !Sequel.const_defined?('ODBC')
|
6
|
+
require File.join(File.dirname(__FILE__), 'odbc')
|
7
|
+
end
|
8
|
+
|
9
|
+
module Sequel
|
10
|
+
module ODBC
|
11
|
+
module MSSQL
|
12
|
+
class Database < ODBC::Database
|
13
|
+
set_adapter_scheme :odbc_mssql
|
14
|
+
# set_adapter_scheme :"odbc-mssql"
|
15
|
+
|
16
|
+
def dataset(opts = nil)
|
17
|
+
MSSQL::Dataset.new(self, opts)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Dataset < ODBC::Dataset
|
22
|
+
# Allows you to do .nolock on a query
|
23
|
+
def nolock
|
24
|
+
clone_merge(:with => "(NOLOCK)")
|
25
|
+
end
|
26
|
+
|
27
|
+
# Formats a SELECT statement using the given options and the dataset
|
28
|
+
# options.
|
29
|
+
def select_sql(opts = nil)
|
30
|
+
opts = opts ? @opts.merge(opts) : @opts
|
31
|
+
|
32
|
+
if sql = opts[:sql]
|
33
|
+
return sql
|
34
|
+
end
|
35
|
+
|
36
|
+
# ADD TOP to SELECT string for LIMITS
|
37
|
+
if limit = opts[:limit]
|
38
|
+
top = "TOP #{limit} "
|
39
|
+
raise SequelError, "Offset not supported" if opts[:offset]
|
40
|
+
end
|
41
|
+
|
42
|
+
columns = opts[:select]
|
43
|
+
select_columns = columns ? column_list(columns) : WILDCARD
|
44
|
+
|
45
|
+
if distinct = opts[:distinct]
|
46
|
+
distinct_clause = distinct.empty? ? "DISTINCT" : "DISTINCT ON (#{column_list(distinct)})"
|
47
|
+
sql = "SELECT #{top}#{distinct_clause} #{select_columns}"
|
48
|
+
else
|
49
|
+
sql = "SELECT #{top}#{select_columns}"
|
50
|
+
end
|
51
|
+
|
52
|
+
if opts[:from]
|
53
|
+
sql << " FROM #{source_list(opts[:from])}"
|
54
|
+
end
|
55
|
+
|
56
|
+
# ADD WITH to SELECT string for NOLOCK
|
57
|
+
if with = opts[:with]
|
58
|
+
sql << " WITH #{with}"
|
59
|
+
end
|
60
|
+
|
61
|
+
if join = opts[:join]
|
62
|
+
sql << join
|
63
|
+
end
|
64
|
+
|
65
|
+
if where = opts[:where]
|
66
|
+
sql << " WHERE #{where}"
|
67
|
+
end
|
68
|
+
|
69
|
+
if group = opts[:group]
|
70
|
+
sql << " GROUP BY #{column_list(group)}"
|
71
|
+
end
|
72
|
+
|
73
|
+
if order = opts[:order]
|
74
|
+
sql << " ORDER BY #{column_list(order)}"
|
75
|
+
end
|
76
|
+
|
77
|
+
if having = opts[:having]
|
78
|
+
sql << " HAVING #{having}"
|
79
|
+
end
|
80
|
+
|
81
|
+
if union = opts[:union]
|
82
|
+
sql << (opts[:union_all] ? \
|
83
|
+
" UNION ALL #{union.sql}" : " UNION #{union.sql}")
|
84
|
+
elsif intersect = opts[:intersect]
|
85
|
+
sql << (opts[:intersect_all] ? \
|
86
|
+
" INTERSECT ALL #{intersect.sql}" : " INTERSECT #{intersect.sql}")
|
87
|
+
elsif except = opts[:except]
|
88
|
+
sql << (opts[:except_all] ? \
|
89
|
+
" EXCEPT ALL #{except.sql}" : " EXCEPT #{except.sql}")
|
90
|
+
end
|
91
|
+
|
92
|
+
sql
|
93
|
+
end
|
94
|
+
alias_method :sql, :select_sql
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/lib/sequel/database.rb
CHANGED
@@ -257,6 +257,7 @@ module Sequel
|
|
257
257
|
end
|
258
258
|
|
259
259
|
def self.adapter_class(scheme)
|
260
|
+
scheme = scheme.to_s =~ /\-/ ? scheme.to_s.gsub('-', '_').to_sym : scheme.to_sym
|
260
261
|
unless c = @@adapters[scheme.to_sym]
|
261
262
|
require File.join(File.dirname(__FILE__), "adapters/#{scheme}")
|
262
263
|
c = @@adapters[scheme.to_sym]
|
data/lib/sequel/dataset/sql.rb
CHANGED
@@ -420,7 +420,7 @@ module Sequel
|
|
420
420
|
|
421
421
|
sql
|
422
422
|
end
|
423
|
-
|
423
|
+
alias_method :sql, :select_sql
|
424
424
|
|
425
425
|
# Formats an INSERT statement using the given values. If a hash is given,
|
426
426
|
# the resulting statement includes column names. If no values are given,
|
data/lib/sequel/model.rb
CHANGED
@@ -235,21 +235,15 @@ require File.join(File.dirname(__FILE__), 'model/record')
|
|
235
235
|
require File.join(File.dirname(__FILE__), 'model/schema')
|
236
236
|
require File.join(File.dirname(__FILE__), 'model/relations')
|
237
237
|
require File.join(File.dirname(__FILE__), 'model/caching')
|
238
|
+
require File.join(File.dirname(__FILE__), 'model/plugins')
|
238
239
|
|
239
240
|
module Sequel
|
240
241
|
class Model
|
241
|
-
|
242
242
|
# Defines a method that returns a filtered dataset.
|
243
243
|
def self.subset(name, *args, &block)
|
244
244
|
dataset.meta_def(name) {filter(*args, &block)}
|
245
245
|
end
|
246
|
-
|
247
|
-
# Comprehensive description goes here!
|
248
|
-
def primary_key_hash(value)
|
249
|
-
# stock implementation
|
250
|
-
{:id => value}
|
251
|
-
end
|
252
|
-
|
246
|
+
|
253
247
|
# Finds a single record according to the supplied filter, e.g.:
|
254
248
|
#
|
255
249
|
# Ticket.find :author => 'Sharon' # => record
|
@@ -310,42 +304,5 @@ module Sequel
|
|
310
304
|
def self.all
|
311
305
|
dataset.all
|
312
306
|
end
|
313
|
-
|
314
|
-
# Returns value of attribute.
|
315
|
-
def [](column)
|
316
|
-
@values[column]
|
317
|
-
end
|
318
|
-
# Sets value of attribute.
|
319
|
-
def []=(column, value)
|
320
|
-
@values[column] = value
|
321
|
-
end
|
322
|
-
|
323
|
-
# Enumerates through all attributes.
|
324
|
-
#
|
325
|
-
# === Example:
|
326
|
-
# Ticket.find(7).each { |k, v| puts "#{k} => #{v}" }
|
327
|
-
def each(&block)
|
328
|
-
@values.each(&block)
|
329
|
-
end
|
330
|
-
# Returns attribute names.
|
331
|
-
def keys
|
332
|
-
@values.keys
|
333
|
-
end
|
334
|
-
|
335
|
-
# Returns value for <tt>:id</tt> attribute.
|
336
|
-
def id
|
337
|
-
@values[:id]
|
338
|
-
end
|
339
|
-
|
340
|
-
# Compares model instances by values.
|
341
|
-
def ==(obj)
|
342
|
-
(obj.class == model) && (obj.values == @values)
|
343
|
-
end
|
344
|
-
|
345
|
-
# Compares model instances by pkey.
|
346
|
-
def ===(obj)
|
347
|
-
(obj.class == model) && (obj.pk == pk)
|
348
|
-
end
|
349
|
-
|
350
307
|
end
|
351
308
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Sequel
|
2
|
+
module Plugins; end
|
3
|
+
|
4
|
+
class Model
|
5
|
+
class << self
|
6
|
+
# Loads a plugin for use with the model class, passing optional arguments
|
7
|
+
# to the plugin.
|
8
|
+
def is(plugin, *args)
|
9
|
+
plugin_module(plugin).apply(self, *args)
|
10
|
+
end
|
11
|
+
alias_method :is_a, :is
|
12
|
+
|
13
|
+
# Returns the module for the specified plugin. If the module is not
|
14
|
+
# defined, the corresponding plugin gem is automatically loaded.
|
15
|
+
def plugin_module(plugin)
|
16
|
+
module_name = plugin.to_s.gsub(/(^|_)(.)/) {$2.upcase}
|
17
|
+
if not Sequel::Plugins.const_defined?(module_name)
|
18
|
+
require plugin_gem(plugin)
|
19
|
+
end
|
20
|
+
Sequel::Plugins.const_get(module_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns the gem name for the given plugin.
|
24
|
+
def plugin_gem(plugin)
|
25
|
+
"sequel_#{plugin}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
data/lib/sequel/model/record.rb
CHANGED
@@ -2,6 +2,42 @@ module Sequel
|
|
2
2
|
class Model
|
3
3
|
attr_reader :values
|
4
4
|
|
5
|
+
# Returns value of attribute.
|
6
|
+
def [](column)
|
7
|
+
@values[column]
|
8
|
+
end
|
9
|
+
# Sets value of attribute.
|
10
|
+
def []=(column, value)
|
11
|
+
@values[column] = value
|
12
|
+
end
|
13
|
+
|
14
|
+
# Enumerates through all attributes.
|
15
|
+
#
|
16
|
+
# === Example:
|
17
|
+
# Ticket.find(7).each { |k, v| puts "#{k} => #{v}" }
|
18
|
+
def each(&block)
|
19
|
+
@values.each(&block)
|
20
|
+
end
|
21
|
+
# Returns attribute names.
|
22
|
+
def keys
|
23
|
+
@values.keys
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns value for <tt>:id</tt> attribute.
|
27
|
+
def id
|
28
|
+
@values[:id]
|
29
|
+
end
|
30
|
+
|
31
|
+
# Compares model instances by values.
|
32
|
+
def ==(obj)
|
33
|
+
(obj.class == model) && (obj.values == @values)
|
34
|
+
end
|
35
|
+
|
36
|
+
# Compares model instances by pkey.
|
37
|
+
def ===(obj)
|
38
|
+
(obj.class == model) && (obj.pk == pk)
|
39
|
+
end
|
40
|
+
|
5
41
|
# Returns key for primary key.
|
6
42
|
def self.primary_key
|
7
43
|
:id
|
data/spec/model_spec.rb
CHANGED
@@ -1039,4 +1039,42 @@ context "Model magic methods" do
|
|
1039
1039
|
@m.last_by_name('sharon').values.should == {:id => 123, :name => 'hey'}
|
1040
1040
|
@c.sqls.should == ["SELECT * FROM items ORDER BY name DESC LIMIT 1"] * 2
|
1041
1041
|
end
|
1042
|
+
end
|
1043
|
+
|
1044
|
+
module Sequel::Plugins
|
1045
|
+
module Timestamped
|
1046
|
+
def self.apply(m, opts)
|
1047
|
+
m.class_def(:get_stamp) {@values[:stamp]}
|
1048
|
+
m.meta_def(:stamp_opts) {opts}
|
1049
|
+
m.before_save {@values[:stamp] = Time.now}
|
1050
|
+
end
|
1051
|
+
end
|
1052
|
+
end
|
1053
|
+
|
1054
|
+
context "A model using a plugin" do
|
1055
|
+
specify "should fail if the plugin is not found" do
|
1056
|
+
proc do
|
1057
|
+
c = Class.new(Sequel::Model) do
|
1058
|
+
is :something_or_other
|
1059
|
+
end
|
1060
|
+
end.should raise_error(LoadError)
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
specify "should apply the plugin to the class" do
|
1064
|
+
c = nil
|
1065
|
+
proc do
|
1066
|
+
c = Class.new(Sequel::Model) do
|
1067
|
+
is :timestamped, :a => 1, :b => 2
|
1068
|
+
end
|
1069
|
+
end.should_not raise_error(LoadError)
|
1070
|
+
|
1071
|
+
c.should respond_to(:stamp_opts)
|
1072
|
+
c.stamp_opts.should == {:a => 1, :b => 2}
|
1073
|
+
|
1074
|
+
m = c.new
|
1075
|
+
m.should respond_to(:get_stamp)
|
1076
|
+
t = Time.now
|
1077
|
+
m[:stamp] = t
|
1078
|
+
m.get_stamp.should == t
|
1079
|
+
end
|
1042
1080
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sequel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.1.
|
4
|
+
version: 0.4.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sharon Rosner
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2007-
|
12
|
+
date: 2007-12-04 00:00:00 +02:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -82,6 +82,7 @@ files:
|
|
82
82
|
- lib/sequel/adapters/informix.rb
|
83
83
|
- lib/sequel/adapters/mysql.rb
|
84
84
|
- lib/sequel/adapters/odbc.rb
|
85
|
+
- lib/sequel/adapters/odbc_mssql.rb
|
85
86
|
- lib/sequel/adapters/oracle.rb
|
86
87
|
- lib/sequel/adapters/postgres.rb
|
87
88
|
- lib/sequel/adapters/sqlite.rb
|
@@ -105,6 +106,7 @@ files:
|
|
105
106
|
- lib/sequel/model/base.rb
|
106
107
|
- lib/sequel/model/caching.rb
|
107
108
|
- lib/sequel/model/hooks.rb
|
109
|
+
- lib/sequel/model/plugins.rb
|
108
110
|
- lib/sequel/model/record.rb
|
109
111
|
- lib/sequel/model/relations.rb
|
110
112
|
- lib/sequel/model/schema.rb
|