sequel 0.4.4.2 → 0.4.5

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.
@@ -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
+