sequel 0.4.4.2 → 0.4.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -102,6 +102,14 @@ module Sequel
102
102
  }
103
103
  end
104
104
 
105
+ def set_column_default(name, default)
106
+ @operations << {
107
+ :op => :set_column_default,
108
+ :name => name,
109
+ :default => default
110
+ }
111
+ end
112
+
105
113
  def add_index(columns, opts = {})
106
114
  columns = [columns] unless columns.is_a?(Array)
107
115
  @operations << {
@@ -115,6 +115,8 @@ module Sequel
115
115
  "ALTER TABLE #{table} RENAME COLUMN #{literal(op[:name])} TO #{literal(op[:new_name])}"
116
116
  when :set_column_type
117
117
  "ALTER TABLE #{table} ALTER COLUMN #{literal(op[:name])} TYPE #{op[:type]}"
118
+ when :set_column_default
119
+ "ALTER TABLE #{table} ALTER COLUMN #{literal(op[:name])} SET DEFAULT #{literal(op[:default])}"
118
120
  when :add_index
119
121
  index_definition_sql(table, op)
120
122
  when :drop_index
@@ -240,6 +240,7 @@ context "Database#alter_table" do
240
240
  drop_column :bbb
241
241
  rename_column :ccc, :ddd
242
242
  set_column_type :eee, :integer
243
+ set_column_default :hhh, 'abcd'
243
244
 
244
245
  add_index :fff, :unique => true
245
246
  drop_index :ggg
@@ -250,6 +251,7 @@ context "Database#alter_table" do
250
251
  'ALTER TABLE xyz DROP COLUMN bbb',
251
252
  'ALTER TABLE xyz RENAME COLUMN ccc TO ddd',
252
253
  'ALTER TABLE xyz ALTER COLUMN eee TYPE integer',
254
+ "ALTER TABLE xyz ALTER COLUMN hhh SET DEFAULT 'abcd'",
253
255
 
254
256
  'CREATE UNIQUE INDEX xyz_fff_index ON xyz (fff)',
255
257
  'DROP INDEX xyz_ggg_index'
@@ -309,6 +311,19 @@ context "Database#set_column_type" do
309
311
  end
310
312
  end
311
313
 
314
+ context "Database#set_column_default" do
315
+ setup do
316
+ @db = DummyDatabase.new
317
+ end
318
+
319
+ specify "should construct proper SQL" do
320
+ @db.set_column_default :test, :name, 'zyx'
321
+ @db.sqls.should == [
322
+ "ALTER TABLE test ALTER COLUMN name SET DEFAULT 'zyx'"
323
+ ]
324
+ end
325
+ end
326
+
312
327
  context "Database#add_index" do
313
328
  setup do
314
329
  @db = DummyDatabase.new
data/spec/dataset_spec.rb CHANGED
@@ -2375,4 +2375,13 @@ context "Dataset#update_sql" do
2375
2375
  specify "should accept strings" do
2376
2376
  @ds.update_sql("a = b").should == "UPDATE items SET a = b"
2377
2377
  end
2378
+
2379
+ specify "should accept hash with string keys" do
2380
+ @ds.update_sql('c' => 'd').should == "UPDATE items SET c = 'd'"
2381
+ end
2382
+
2383
+ specify "should accept array subscript references" do
2384
+ @ds.update_sql((:day|1) => 'd').should == "UPDATE items SET day[1] = 'd'"
2385
+ end
2386
+
2378
2387
  end
@@ -0,0 +1,148 @@
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
@@ -0,0 +1,148 @@
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
@@ -0,0 +1,105 @@
1
+ describe Sequel::Model, "hooks" do
2
+
3
+ before do
4
+ MODEL_DB.reset
5
+ Sequel::Model.hooks.clear
6
+
7
+ @hooks = %w[
8
+ before_save before_create before_update before_destroy
9
+ after_save after_create after_update after_destroy
10
+ ].select { |hook| !hook.empty? }
11
+ end
12
+
13
+ it "should have hooks for everything" do
14
+ Sequel::Model.methods.should include('hooks')
15
+ Sequel::Model.methods.should include(*@hooks)
16
+ @hooks.each do |hook|
17
+ Sequel::Model.hooks[hook.to_sym].should be_an_instance_of(Array)
18
+ end
19
+ end
20
+
21
+ it "should be inherited" do
22
+ pending 'soon'
23
+
24
+ @hooks.each do |hook|
25
+ Sequel::Model.send(hook.to_sym) { nil }
26
+ end
27
+
28
+ model = Class.new Sequel::Model(:models)
29
+ model.hooks.should == Sequel::Model.hooks
30
+ end
31
+
32
+ it "should run hooks" do
33
+ pending 'soon'
34
+
35
+ test = mock 'Test'
36
+ test.should_receive(:run).exactly(@hooks.length)
37
+
38
+ @hooks.each do |hook|
39
+ Sequel::Model.send(hook.to_sym) { test.run }
40
+ end
41
+
42
+ model = Class.new Sequel::Model(:models)
43
+ model.hooks.should == Sequel::Model.hooks
44
+
45
+ model_instance = model.new
46
+ @hooks.each { |hook| model_instance.run_hooks(hook) }
47
+ end
48
+
49
+ it "should run hooks around save and create" do
50
+ pending 'test execution'
51
+ end
52
+
53
+ it "should run hooks around save and update" do
54
+ pending 'test execution'
55
+ end
56
+
57
+ it "should run hooks around delete" do
58
+ pending 'test execution'
59
+ end
60
+
61
+ end
62
+
63
+ describe "Model.after_create" do
64
+
65
+ before(:each) do
66
+ MODEL_DB.reset
67
+
68
+ @c = Class.new(Sequel::Model(:items)) do
69
+ def columns
70
+ [:id, :x, :y]
71
+ end
72
+ end
73
+
74
+ ds = @c.dataset
75
+ def ds.insert(*args)
76
+ super(*args)
77
+ 1
78
+ end
79
+ end
80
+
81
+ it "should be called after creation" do
82
+ s = []
83
+
84
+ @c.after_create do
85
+ s = MODEL_DB.sqls.dup
86
+ end
87
+
88
+ n = @c.create(:x => 1)
89
+ MODEL_DB.sqls.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
90
+ s.should == ["INSERT INTO items (x) VALUES (1)", "SELECT * FROM items WHERE (id = 1) LIMIT 1"]
91
+ end
92
+
93
+ it "should allow calling save in the hook" do
94
+ @c.after_create do
95
+ values.delete(:x)
96
+ self.id = 2
97
+ save
98
+ end
99
+
100
+ n = @c.create(:id => 1)
101
+ MODEL_DB.sqls.should == ["INSERT INTO items (id) VALUES (1)", "SELECT * FROM items WHERE (id = 1) LIMIT 1", "UPDATE items SET id = 2 WHERE (id = 1)"]
102
+ end
103
+
104
+ end
105
+