sequel 0.4.5 → 0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,107 +0,0 @@
1
- module Sequel
2
- class Model
3
- ID_POSTFIX = '_id'.freeze
4
-
5
- # Creates a 1-1 relationship by defining an association method, e.g.:
6
- #
7
- # class Session < Sequel::Model(:sessions)
8
- # end
9
- #
10
- # class Node < Sequel::Model(:nodes)
11
- # one_to_one :producer, :from => Session
12
- # # which is equivalent to
13
- # def producer
14
- # Session[producer_id] if producer_id
15
- # end
16
- # end
17
- #
18
- # You can also set the foreign key explicitly by including a :key option:
19
- #
20
- # one_to_one :producer, :from => Session, :key => :producer_id
21
- #
22
- # The one_to_one macro also creates a setter, which accepts nil, a hash or
23
- # a model instance, e.g.:
24
- #
25
- # p = Producer[1234]
26
- # node = Node[:path => '/']
27
- # node.producer = p
28
- # node.producer_id #=> 1234
29
- #
30
- def self.one_to_one(name, opts)
31
- # deprecation
32
- if opts[:class]
33
- warn "The :class option has been deprecated. Please use :from instead."
34
- opts[:from] = opts[:class]
35
- end
36
-
37
- from = opts[:from]
38
- from || (raise Error, "No association source defined (use :from option)")
39
- key = opts[:key] || (name.to_s + ID_POSTFIX).to_sym
40
-
41
- setter_name = "#{name}=".to_sym
42
-
43
- case from
44
- when Symbol
45
- class_def(name) {(k = @values[key]) ? db[from][:id => k] : nil}
46
- when Sequel::Dataset
47
- class_def(name) {(k = @values[key]) ? from[:id => k] : nil}
48
- else
49
- class_def(name) {(k = @values[key]) ? from[k] : nil}
50
- end
51
- class_def(setter_name) do |v|
52
- case v
53
- when nil
54
- set(key => nil)
55
- when Sequel::Model
56
- set(key => v.pk)
57
- when Hash
58
- set(key => v[:id])
59
- end
60
- end
61
-
62
- # define_method name, &eval(ONE_TO_ONE_PROC % [key, from])
63
- end
64
-
65
- # Creates a 1-N relationship by defining an association method, e.g.:
66
- #
67
- # class Book < Sequel::Model(:books)
68
- # end
69
- #
70
- # class Author < Sequel::Model(:authors)
71
- # one_to_many :books, :from => Book
72
- # # which is equivalent to
73
- # def books
74
- # Book.filter(:author_id => id)
75
- # end
76
- # end
77
- #
78
- # You can also set the foreign key explicitly by including a :key option:
79
- #
80
- # one_to_many :books, :from => Book, :key => :author_id
81
- #
82
- def self.one_to_many(name, opts)
83
- # deprecation
84
- if opts[:class]
85
- warn "The :class option has been deprecated. Please use :from instead."
86
- opts[:from] = opts[:class]
87
- end
88
- # deprecation
89
- if opts[:on]
90
- warn "The :on option has been deprecated. Please use :key instead."
91
- opts[:key] = opts[:on]
92
- end
93
-
94
-
95
- from = opts[:from]
96
- from || (raise Error, "No association source defined (use :from option)")
97
- key = opts[:key] || (self.to_s + ID_POSTFIX).to_sym
98
-
99
- case from
100
- when Symbol
101
- class_def(name) {db[from].filter(key => pk)}
102
- else
103
- class_def(name) {from.filter(key => pk)}
104
- end
105
- end
106
- end
107
- end
@@ -1,52 +0,0 @@
1
- module Sequel
2
- class Model
3
- # Defines a table schema (see Schema::Generator for more information).
4
- #
5
- # This is only needed if you want to use the create_table or drop_table
6
- # methods.
7
- def self.set_schema(name = nil, &block)
8
- name ? set_dataset(db[name]) : name = table_name
9
- @schema = Schema::Generator.new(db, &block)
10
- if @schema.primary_key_name
11
- set_primary_key @schema.primary_key_name
12
- end
13
- end
14
-
15
- # Returns table schema for direct descendant of Model.
16
- def self.schema
17
- @schema || ((superclass != Model) && (superclass.schema))
18
- end
19
-
20
- # Returns name of table.
21
- def self.table_name
22
- dataset.opts[:from].first
23
- end
24
-
25
- # Returns true if table exists, false otherwise.
26
- def self.table_exists?
27
- db.table_exists?(table_name)
28
- end
29
-
30
- # Creates table.
31
- def self.create_table
32
- db.create_table_sql_list(table_name, *schema.create_info).each {|s| db << s}
33
- end
34
-
35
- # Drops table.
36
- def self.drop_table
37
- db.execute db.drop_table_sql(table_name)
38
- end
39
-
40
- # Like create_table but invokes drop_table when table_exists? is true.
41
- def self.create_table!
42
- drop_table if table_exists?
43
- create_table
44
- end
45
-
46
- # Deprecated, use create_table! instead.
47
- def self.recreate_table
48
- warn "Model.recreate_table is deprecated. Please use Model.create_table! instead."
49
- create_table!
50
- end
51
- end
52
- end
@@ -1,117 +0,0 @@
1
- module Sequel
2
- class Model
3
- # =Basic Sequel Validations
4
- #
5
- # Sequel validations are based on the Validatable gem http://validatable.rubyforge.org/
6
- #
7
- # To assign default validations to a sequel model:
8
- #
9
- # class MyModel < SequelModel(:items)
10
- # validates do
11
- # format_of...
12
- # presence_of...
13
- # acceptance_of...
14
- # confirmation_of...
15
- # length_of...
16
- # true_for...
17
- # numericality_of...
18
- # format_of...
19
- # validates_base...
20
- # validates_each...
21
- # end
22
- # end
23
- #
24
- # You may also perform the usual 'longhand' way to assign default model validates
25
- # directly within the model class itself:
26
- #
27
- # class MyModel < SequelModel(:items)
28
- # validates_format_of...
29
- # validates_presence_of...
30
- # validates_acceptance_of...
31
- # validates_confirmation_of...
32
- # validates_length_of...
33
- # validates_true_for...
34
- # validates_numericality_of...
35
- # validates_format_of...
36
- # validates_base...
37
- # validates_each...
38
- # end
39
- #
40
- # Each validation allows for arguments:
41
- # TODO: fill the argument options in here
42
- #
43
- # =Advanced Sequel Validations
44
- #
45
- # TODO: verify that advanced validates work as stated (aka write specs)
46
- # NOTE: experimental
47
- #
48
- # To store validates for conditional usage simply specify a name with which to store them
49
- # class User < Sequel::Model
50
- #
51
- # # This set of validates becomes stored as :default and gets injected into the model.
52
- # validates do
53
- # # standard validates calls
54
- # end
55
- #
56
- # validates(:registration) do
57
- # # user registration specific validates
58
- # end
59
- #
60
- # validates(:promotion) do
61
- # # user promotion validates
62
- # end
63
- #
64
- # end
65
- #
66
- # To use the above validates:
67
- #
68
- # @user.valid? # Runs the default validations only.
69
- # @user.valid?(:registration) # Runs both default and registration validations
70
- # @user.valid?(:promotion) # Runs both default and promotion validations
71
- #
72
- # You may determine whether the model has validates via:
73
- #
74
- # has_validations? # will return true / false based on existence of validations on the model.
75
- #
76
- # You may also retrieve the validations block if needed:
77
- #
78
- # validates(:registration) # returns the registration validation block.
79
- #
80
- # validates() method parameters:
81
- # a validations block - runs the validations block on the model & stores as :default
82
- # a name and a validations block - stores the block under the name
83
- # a name - returns a stored block of that name or nil
84
- # nothing - returns true / false based on if validations exist for the model.
85
- #
86
- module Validations
87
- class Generator
88
- def initialize(model_class ,&block)
89
- @model_class = model_class
90
- instance_eval(&block)
91
- end
92
-
93
- def method_missing(method, *args)
94
- method = :"validates_#{method}"
95
- @model_class.send(method, *args)
96
- end
97
- end
98
- end
99
-
100
- begin
101
- require "validatable"
102
- include ::Validatable
103
- def self.validates(&block)
104
- Validations::Generator.new(self, &block)
105
- end
106
- # return true if there are validations stored, false otherwise
107
- def self.has_validations?
108
- validations.length > 0 ? true : false
109
- end
110
- rescue LoadError
111
- STDERR.puts <<-MESSAGE
112
- Install the validatable gem in order to use Sequel Model validations
113
- If you would like model validations to work, install the validatable gem
114
- MESSAGE
115
- end
116
- end
117
- end
@@ -1,148 +0,0 @@
1
- describe "Model attribute setters" do
2
-
3
- before(:each) do
4
- MODEL_DB.reset
5
-
6
- @c = Class.new(Sequel::Model(:items)) do
7
- def columns
8
- [:id, :x, :y]
9
- end
10
- end
11
- end
12
-
13
- it "should mark the column value as changed" do
14
- o = @c.new
15
- o.changed_columns.should == []
16
-
17
- o.x = 2
18
- o.changed_columns.should == [:x]
19
-
20
- o.y = 3
21
- o.changed_columns.should == [:x, :y]
22
-
23
- o.changed_columns.clear
24
-
25
- o[:x] = 2
26
- o.changed_columns.should == [:x]
27
-
28
- o[:y] = 3
29
- o.changed_columns.should == [:x, :y]
30
- end
31
-
32
- end
33
-
34
- describe "Model#serialize" do
35
-
36
- before(:each) do
37
- MODEL_DB.reset
38
- end
39
-
40
- it "should translate values to YAML when creating records" do
41
- @c = Class.new(Sequel::Model(:items)) do
42
- no_primary_key
43
- serialize :abc
44
- end
45
-
46
- @c.create(:abc => 1)
47
- @c.create(:abc => "hello")
48
-
49
- MODEL_DB.sqls.should == [ \
50
- "INSERT INTO items (abc) VALUES ('--- 1\n')", \
51
- "INSERT INTO items (abc) VALUES ('--- hello\n')", \
52
- ]
53
- end
54
-
55
- it "should support calling after the class is defined" do
56
- @c = Class.new(Sequel::Model(:items)) do
57
- no_primary_key
58
- end
59
-
60
- @c.serialize :def
61
-
62
- @c.create(:def => 1)
63
- @c.create(:def => "hello")
64
-
65
- MODEL_DB.sqls.should == [ \
66
- "INSERT INTO items (def) VALUES ('--- 1\n')", \
67
- "INSERT INTO items (def) VALUES ('--- hello\n')", \
68
- ]
69
- end
70
-
71
- it "should support using the Marshal format" do
72
- @c = Class.new(Sequel::Model(:items)) do
73
- no_primary_key
74
- serialize :abc, :format => :marshal
75
- end
76
-
77
- @c.create(:abc => 1)
78
- @c.create(:abc => "hello")
79
-
80
- MODEL_DB.sqls.should == [ \
81
- "INSERT INTO items (abc) VALUES ('\004\bi\006')", \
82
- "INSERT INTO items (abc) VALUES ('\004\b\"\nhello')", \
83
- ]
84
- end
85
-
86
- it "should translate values to and from YAML using accessor methods" do
87
- @c = Class.new(Sequel::Model(:items)) do
88
- serialize :abc, :def
89
- end
90
-
91
- ds = @c.dataset
92
- ds.extend(Module.new {
93
- attr_accessor :raw
94
-
95
- def fetch_rows(sql, &block)
96
- block.call(@raw)
97
- end
98
-
99
- @@sqls = nil
100
-
101
- def insert(*args)
102
- @@sqls = insert_sql(*args)
103
- end
104
-
105
- def update(*args)
106
- @@sqls = update_sql(*args)
107
- end
108
-
109
- def sqls
110
- @@sqls
111
- end
112
-
113
- def columns
114
- [:id, :abc, :def]
115
- end
116
- }
117
- )
118
-
119
- ds.raw = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
120
- o = @c.first
121
- o.id.should == 1
122
- o.abc.should == 1
123
- o.def.should == "hello"
124
-
125
- o.set(:abc => 23)
126
- ds.sqls.should == "UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)"
127
-
128
- ds.raw = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
129
- o = @c.create(:abc => [1, 2, 3])
130
- ds.sqls.should == "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')"
131
- end
132
-
133
- end
134
-
135
- describe Sequel::Model, "super_dataset" do
136
-
137
- before(:each) do
138
- MODEL_DB.reset
139
- class SubClass < Sequel::Model(:items) ; end
140
- end
141
-
142
- it "should call the superclass's dataset" do
143
- SubClass.should_receive(:superclass).exactly(3).times.and_return(Sequel::Model(:items))
144
- Sequel::Model(:items).should_receive(:dataset)
145
- SubClass.super_dataset
146
- end
147
-
148
- end
@@ -1,148 +0,0 @@
1
- describe Sequel::Model, "caching" do
2
-
3
- before(:each) do
4
- MODEL_DB.reset
5
-
6
- @cache_class = Class.new(Hash) do
7
- attr_accessor :ttl
8
- def set(k, v, ttl); self[k] = v; @ttl = ttl; end
9
- def get(k); self[k]; end
10
- end
11
- cache = @cache_class.new
12
- @cache = cache
13
-
14
- @c = Class.new(Sequel::Model(:items)) do
15
- set_cache cache
16
-
17
- def self.columns
18
- [:name, :id]
19
- end
20
- end
21
-
22
- $cache_dataset_row = {:name => 'sharon', :id => 1}
23
- @dataset = @c.dataset
24
- $sqls = []
25
- @dataset.extend(Module.new {
26
- def fetch_rows(sql)
27
- $sqls << sql
28
- yield $cache_dataset_row
29
- end
30
-
31
- def update(values)
32
- $sqls << update_sql(values)
33
- $cache_dataset_row.merge!(values)
34
- end
35
-
36
- def delete
37
- $sqls << delete_sql
38
- end
39
- })
40
- end
41
-
42
- it "should set the model's cache store" do
43
- @c.cache_store.should be(@cache)
44
- end
45
-
46
- it "should have a default ttl of 3600" do
47
- @c.cache_ttl.should == 3600
48
- end
49
-
50
- it "should take a ttl option" do
51
- @c.set_cache @cache, :ttl => 1234
52
- @c.cache_ttl.should == 1234
53
- end
54
-
55
- it "should offer a set_cache_ttl method for setting the ttl" do
56
- @c.cache_ttl.should == 3600
57
- @c.set_cache_ttl 1234
58
- @c.cache_ttl.should == 1234
59
- end
60
-
61
- it "should generate a cache key appropriate to the class" do
62
- m = @c.new
63
- m.values[:id] = 1
64
- m.cache_key.should == "#{m.class}:1"
65
-
66
- # custom primary key
67
- @c.set_primary_key :ttt
68
- m = @c.new
69
- m.values[:ttt] = 333
70
- m.cache_key.should == "#{m.class}:333"
71
-
72
- # composite primary key
73
- @c.set_primary_key [:a, :b, :c]
74
- m = @c.new
75
- m.values[:a] = 123
76
- m.values[:c] = 456
77
- m.values[:b] = 789
78
- m.cache_key.should == "#{m.class}:123,789,456"
79
- end
80
-
81
- it "should raise error if attempting to generate cache_key and primary key value is null" do
82
- m = @c.new
83
- proc {m.cache_key}.should raise_error(Sequel::Error)
84
-
85
- m.values[:id] = 1
86
- proc {m.cache_key}.should_not raise_error(Sequel::Error)
87
- end
88
-
89
- it "should set the cache when reading from the database" do
90
- $sqls.should == []
91
- @cache.should be_empty
92
-
93
- m = @c[1]
94
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
95
- m.values.should == $cache_dataset_row
96
- @cache[m.cache_key].should == m
97
-
98
- # read from cache
99
- m2 = @c[1]
100
- $sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
101
- m2.should == m
102
- m2.values.should == $cache_dataset_row
103
- end
104
-
105
- it "should delete the cache when writing to the database" do
106
- # fill the cache
107
- m = @c[1]
108
- @cache[m.cache_key].should == m
109
-
110
- m.set(:name => 'tutu')
111
- @cache.has_key?(m.cache_key).should be_false
112
- $sqls.last.should == "UPDATE items SET name = 'tutu' WHERE (id = 1)"
113
-
114
- m = @c[1]
115
- @cache[m.cache_key].should == m
116
- m.name = 'hey'
117
- m.save
118
- @cache.has_key?(m.cache_key).should be_false
119
- $sqls.last.should == "UPDATE items SET name = 'hey', id = 1 WHERE (id = 1)"
120
- end
121
-
122
- it "should delete the cache when deleting the record" do
123
- # fill the cache
124
- m = @c[1]
125
- @cache[m.cache_key].should == m
126
-
127
- m.delete
128
- @cache.has_key?(m.cache_key).should be_false
129
- $sqls.last.should == "DELETE FROM items WHERE (id = 1)"
130
- end
131
-
132
- it "should support #[] as a shortcut to #find with hash" do
133
- m = @c[:id => 3]
134
- @cache[m.cache_key].should be_nil
135
- $sqls.last.should == "SELECT * FROM items WHERE (id = 3) LIMIT 1"
136
-
137
- m = @c[1]
138
- @cache[m.cache_key].should == m
139
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
140
- "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
141
-
142
- @c[:id => 4]
143
- $sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
144
- "SELECT * FROM items WHERE (id = 1) LIMIT 1", \
145
- "SELECT * FROM items WHERE (id = 4) LIMIT 1"]
146
- end
147
-
148
- end