sequel 1.4.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -23,7 +23,12 @@ describe Sequel::Model, "many_to_one" do
23
23
  MODEL_DB.reset
24
24
 
25
25
  @c2 = Class.new(Sequel::Model(:nodes)) do
26
- def columns; [:id, :parent_id]; end
26
+ columns :id, :parent_id, :par_parent_id, :blah
27
+ def self.create_new(values)
28
+ obj = self.new(values)
29
+ obj.instance_variable_set(:@new, false)
30
+ obj
31
+ end
27
32
  end
28
33
 
29
34
  @dataset = @c2.dataset
@@ -53,6 +58,21 @@ describe Sequel::Model, "many_to_one" do
53
58
  MODEL_DB.sqls.should == ["SELECT * FROM par_parents WHERE (id = 234) LIMIT 1"]
54
59
  end
55
60
 
61
+ it "should use class inside module if given as a string" do
62
+ module Par
63
+ class Parent < Sequel::Model
64
+ end
65
+ end
66
+
67
+ @c2.many_to_one :par_parent, :class=>"Par::Parent"
68
+
69
+ d = @c2.new(:id => 1, :par_parent_id => 234)
70
+ p = d.par_parent
71
+ p.class.should == Par::Parent
72
+
73
+ MODEL_DB.sqls.should == ["SELECT * FROM parents WHERE (id = 234) LIMIT 1"]
74
+ end
75
+
56
76
  it "should use explicit key if given" do
57
77
  @c2.many_to_one :parent, :class => @c2, :key => :blah
58
78
 
@@ -71,6 +91,21 @@ describe Sequel::Model, "many_to_one" do
71
91
  d.parent.should == nil
72
92
  end
73
93
 
94
+ it "should cache negative lookup" do
95
+ @c2.many_to_one :parent, :class => @c2
96
+ ds = @c2.dataset
97
+ def ds.fetch_rows(sql, &block)
98
+ MODEL_DB.sqls << sql
99
+ end
100
+
101
+ d = @c2.new(:id => 1, :parent_id=>555)
102
+ MODEL_DB.sqls.should == []
103
+ d.parent.should == nil
104
+ MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (id = 555) LIMIT 1']
105
+ d.parent.should == nil
106
+ MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (id = 555) LIMIT 1']
107
+ end
108
+
74
109
  it "should define a setter method" do
75
110
  @c2.many_to_one :parent, :class => @c2
76
111
 
@@ -89,7 +124,7 @@ describe Sequel::Model, "many_to_one" do
89
124
  it "should not persist changes until saved" do
90
125
  @c2.many_to_one :parent, :class => @c2
91
126
 
92
- d = @c2.create(:id => 1)
127
+ d = @c2.create_new(:id => 1)
93
128
  MODEL_DB.reset
94
129
  d.parent = @c2.new(:id => 345)
95
130
  MODEL_DB.sqls.should == []
@@ -100,10 +135,12 @@ describe Sequel::Model, "many_to_one" do
100
135
  it "should set cached instance variable when accessed" do
101
136
  @c2.many_to_one :parent, :class => @c2
102
137
 
103
- d = @c2.create(:id => 1)
138
+ d = @c2.create_new(:id => 1)
104
139
  MODEL_DB.reset
105
140
  d.parent_id = 234
106
- d.instance_variables.include?("@parent").should == false
141
+ d.instance_variable_get("@parent").should == nil
142
+ ds = @c2.dataset
143
+ def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
107
144
  e = d.parent
108
145
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 234) LIMIT 1"]
109
146
  d.instance_variable_get("@parent").should == e
@@ -114,7 +151,7 @@ describe Sequel::Model, "many_to_one" do
114
151
 
115
152
  d = @c2.create(:id => 1)
116
153
  MODEL_DB.reset
117
- d.instance_variables.include?("@parent").should == false
154
+ d.instance_variable_get("@parent").should == nil
118
155
  d.parent = @c2.new(:id => 234)
119
156
  e = d.parent
120
157
  d.instance_variable_get("@parent").should == e
@@ -142,13 +179,64 @@ describe Sequel::Model, "many_to_one" do
142
179
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 234) LIMIT 1"]
143
180
  end
144
181
 
182
+ it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
183
+ @c2.many_to_one :parent, :class => @c2
184
+ @c2.one_to_many :children, :class => @c2, :key=>:parent_id
185
+ ds = @c2.dataset
186
+ def ds.fetch_rows(sql, &block)
187
+ MODEL_DB.sqls << sql
188
+ end
189
+
190
+ d = @c2.new(:id => 1)
191
+ e = @c2.new(:id => 2)
192
+ MODEL_DB.sqls.should == []
193
+ d.parent = e
194
+ e.children.should_not(include(d))
195
+ MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (parent_id = 2)']
196
+
197
+ MODEL_DB.reset
198
+ d = @c2.new(:id => 1)
199
+ e = @c2.new(:id => 2)
200
+ e.children.should_not(include(d))
201
+ MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (parent_id = 2)']
202
+ d.parent = e
203
+ e.children.should(include(d))
204
+ MODEL_DB.sqls.should == ['SELECT * FROM nodes WHERE (parent_id = 2)']
205
+ end
206
+
207
+ it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association list if it exists" do
208
+ @c2.many_to_one :parent, :class => @c2
209
+ @c2.one_to_many :children, :class => @c2, :key=>:parent_id
210
+ ds = @c2.dataset
211
+ def ds.fetch_rows(sql, &block)
212
+ MODEL_DB.sqls << sql
213
+ end
214
+
215
+ d = @c2.new(:id => 1)
216
+ e = @c2.new(:id => 2)
217
+ f = @c2.new(:id => 3)
218
+ e.children.should_not(include(d))
219
+ f.children.should_not(include(d))
220
+ MODEL_DB.reset
221
+ d.parent = e
222
+ e.children.should(include(d))
223
+ d.parent = f
224
+ f.children.should(include(d))
225
+ e.children.should_not(include(d))
226
+ d.parent = nil
227
+ f.children.should_not(include(d))
228
+ MODEL_DB.sqls.should == []
229
+ end
230
+
145
231
  it "should have belongs_to alias" do
146
232
  @c2.belongs_to :parent, :class => @c2
147
233
 
148
- d = @c2.create(:id => 1)
234
+ d = @c2.create_new(:id => 1)
149
235
  MODEL_DB.reset
150
236
  d.parent_id = 234
151
- d.instance_variables.include?("@parent").should == false
237
+ d.instance_variable_get("@parent").should == nil
238
+ ds = @c2.dataset
239
+ def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
152
240
  e = d.parent
153
241
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 234) LIMIT 1"]
154
242
  d.instance_variable_get("@parent").should == e
@@ -161,7 +249,7 @@ describe Sequel::Model, "one_to_many" do
161
249
  MODEL_DB.reset
162
250
 
163
251
  @c1 = Class.new(Sequel::Model(:attributes)) do
164
- def columns; [:id, :node_id]; end
252
+ columns :id, :node_id
165
253
  end
166
254
 
167
255
  @c2 = Class.new(Sequel::Model(:nodes)) do
@@ -169,6 +257,7 @@ describe Sequel::Model, "one_to_many" do
169
257
 
170
258
  def self.name; 'Node'; end
171
259
  def self.to_s; 'Node'; end
260
+ columns :id
172
261
  end
173
262
  @dataset = @c2.dataset
174
263
 
@@ -209,6 +298,21 @@ describe Sequel::Model, "one_to_many" do
209
298
  v.model_classes.should == {nil => HistoricalValue}
210
299
  end
211
300
 
301
+ it "should use class inside a module if given as a string" do
302
+ module Historical
303
+ class Value < Sequel::Model
304
+ end
305
+ end
306
+
307
+ @c2.one_to_many :historical_values, :class=>'Historical::Value'
308
+
309
+ n = @c2.new(:id => 1234)
310
+ v = n.historical_values_dataset
311
+ v.should be_a_kind_of(Sequel::Dataset)
312
+ v.sql.should == 'SELECT * FROM values WHERE (node_id = 1234)'
313
+ v.model_classes.should == {nil => Historical::Value}
314
+ end
315
+
212
316
  it "should use explicit key if given" do
213
317
  @c2.one_to_many :attributes, :class => @c1, :key => :nodeid
214
318
 
@@ -340,6 +444,16 @@ describe Sequel::Model, "one_to_many" do
340
444
  a.should == [att]
341
445
  end
342
446
 
447
+ it "should set object to item's reciprocal cached association variable when calling add_" do
448
+ @c2.one_to_many :attributes, :class => @c1
449
+ @c1.many_to_one :node, :class => @c2
450
+
451
+ n = @c2.new(:id => 1234)
452
+ att = @c1.new(:id => 345)
453
+ n.add_attribute(att)
454
+ att.node.should == n
455
+ end
456
+
343
457
  it "should remove item from cached instance variable if it exists when calling remove_" do
344
458
  @c2.one_to_many :attributes, :class => @c1
345
459
 
@@ -352,6 +466,18 @@ describe Sequel::Model, "one_to_many" do
352
466
  a.should == []
353
467
  end
354
468
 
469
+ it "should remove item's reciprocal cached association variable when calling remove_" do
470
+ @c2.one_to_many :attributes, :class => @c1
471
+ @c1.many_to_one :node, :class => @c2
472
+
473
+ n = @c2.new(:id => 1234)
474
+ att = @c1.new(:id => 345)
475
+ att.instance_variable_set(:@node, n)
476
+ att.node.should == n
477
+ n.remove_attribute(att)
478
+ att.node.should == nil
479
+ end
480
+
355
481
  it "should have has_many alias" do
356
482
  @c2.has_many :attributes, :class => @c1
357
483
 
@@ -405,6 +531,7 @@ describe Sequel::Model, "many_to_many" do
405
531
  @c1 = Class.new(Sequel::Model(:attributes)) do
406
532
  def self.name; 'Attribute'; end
407
533
  def self.to_s; 'Attribute'; end
534
+ columns :id
408
535
  end
409
536
 
410
537
  @c2 = Class.new(Sequel::Model(:nodes)) do
@@ -412,6 +539,7 @@ describe Sequel::Model, "many_to_many" do
412
539
 
413
540
  def self.name; 'Node'; end
414
541
  def self.to_s; 'Node'; end
542
+ columns :id
415
543
  end
416
544
  @dataset = @c2.dataset
417
545
 
@@ -450,6 +578,22 @@ describe Sequel::Model, "many_to_many" do
450
578
  ].should(include(a.sql))
451
579
  end
452
580
 
581
+ it "should use class inside module if given as a string" do
582
+ module Historical
583
+ class Tag < Sequel::Model
584
+ end
585
+ end
586
+
587
+ @c2.many_to_many :tags, :class=>'::Historical::Tag'
588
+
589
+ n = @c2.new(:id => 1234)
590
+ a = n.tags_dataset
591
+ a.should be_a_kind_of(Sequel::Dataset)
592
+ ['SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234)',
593
+ 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.node_id = 1234) AND (nodes_tags.tag_id = tags.id)'
594
+ ].should(include(a.sql))
595
+ end
596
+
453
597
  it "should use explicit key values and join table if given" do
454
598
  @c2.many_to_many :attributes, :class => @c1, :left_key => :nodeid, :right_key => :attributeid, :join_table => :attribute2node
455
599
 
@@ -495,7 +639,7 @@ describe Sequel::Model, "many_to_many" do
495
639
  end
496
640
 
497
641
  it "should support an array for the select option" do
498
- @c2.many_to_many :attributes, :class => @c1, :select => [:attributes.all, :attribute_nodes__blah2]
642
+ @c2.many_to_many :attributes, :class => @c1, :select => [:attributes.*, :attribute_nodes__blah2]
499
643
 
500
644
  n = @c2.new(:id => 1234)
501
645
  a = n.attributes_dataset
@@ -616,6 +760,17 @@ describe Sequel::Model, "many_to_many" do
616
760
  a.should == [att]
617
761
  end
618
762
 
763
+ it "should add item to reciprocal cached instance variable if it exists when calling add_" do
764
+ @c2.many_to_many :attributes, :class => @c1
765
+ @c1.many_to_many :nodes, :class => @c2
766
+
767
+ n = @c2.new(:id => 1234)
768
+ att = @c1.new(:id => 345)
769
+ att.instance_variable_set(:@nodes, [])
770
+ n.add_attribute(att)
771
+ att.nodes.should == [n]
772
+ end
773
+
619
774
  it "should remove item from cached instance variable if it exists when calling remove_" do
620
775
  @c2.many_to_many :attributes, :class => @c1
621
776
 
@@ -628,6 +783,17 @@ describe Sequel::Model, "many_to_many" do
628
783
  a.should == []
629
784
  end
630
785
 
786
+ it "should remove item from reciprocal cached instance variable if it exists when calling remove_" do
787
+ @c2.many_to_many :attributes, :class => @c1
788
+ @c1.many_to_many :nodes, :class => @c2
789
+
790
+ n = @c2.new(:id => 1234)
791
+ att = @c1.new(:id => 345)
792
+ att.instance_variable_set(:@nodes, [n])
793
+ n.remove_attribute(att)
794
+ att.nodes.should == []
795
+ end
796
+
631
797
  it "should have has_and_belongs_to_many alias" do
632
798
  @c2.has_and_belongs_to_many :attributes, :class => @c1
633
799
 
data/spec/base_spec.rb CHANGED
@@ -6,9 +6,7 @@ describe "Model attribute setters" do
6
6
  MODEL_DB.reset
7
7
 
8
8
  @c = Class.new(Sequel::Model(:items)) do
9
- def columns
10
- [:id, :x, :y]
11
- end
9
+ columns :id, :x, :y
12
10
  end
13
11
  end
14
12
 
@@ -43,6 +41,7 @@ describe "Model#serialize" do
43
41
  @c = Class.new(Sequel::Model(:items)) do
44
42
  no_primary_key
45
43
  serialize :abc
44
+ columns :abc
46
45
  end
47
46
 
48
47
  @c.create(:abc => 1)
@@ -57,6 +56,7 @@ describe "Model#serialize" do
57
56
  it "should support calling after the class is defined" do
58
57
  @c = Class.new(Sequel::Model(:items)) do
59
58
  no_primary_key
59
+ columns :def
60
60
  end
61
61
 
62
62
  @c.serialize :def
@@ -74,6 +74,7 @@ describe "Model#serialize" do
74
74
  @c = Class.new(Sequel::Model(:items)) do
75
75
  no_primary_key
76
76
  serialize :abc, :format => :marshal
77
+ columns :abc
77
78
  end
78
79
 
79
80
  @c.create(:abc => 1)
@@ -88,6 +89,7 @@ describe "Model#serialize" do
88
89
  it "should translate values to and from YAML using accessor methods" do
89
90
  @c = Class.new(Sequel::Model(:items)) do
90
91
  serialize :abc, :def
92
+ columns :abc, :def
91
93
  end
92
94
 
93
95
  ds = @c.dataset
@@ -124,7 +126,7 @@ describe "Model#serialize" do
124
126
  o.abc.should == 1
125
127
  o.def.should == "hello"
126
128
 
127
- o.set(:abc => 23)
129
+ o.update_values(:abc => 23)
128
130
  ds.sqls.should == "UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)"
129
131
 
130
132
  ds.raw = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
@@ -134,21 +136,8 @@ describe "Model#serialize" do
134
136
 
135
137
  end
136
138
 
137
- describe Sequel::Model, "super_dataset" do
138
- setup do
139
- MODEL_DB.reset
140
- class SubClass < Sequel::Model(:items) ; end
141
- end
142
-
143
- it "should call the superclass's dataset" do
144
- SubClass.should_receive(:superclass).exactly(3).times.and_return(Sequel::Model(:items))
145
- Sequel::Model(:items).should_receive(:dataset)
146
- SubClass.super_dataset
147
- end
148
- end
149
-
150
139
  describe Sequel::Model, "dataset" do
151
- setup do
140
+ before do
152
141
  @a = Class.new(Sequel::Model(:items))
153
142
  @b = Class.new(Sequel::Model)
154
143
 
@@ -193,6 +182,36 @@ describe Sequel::Model, "dataset" do
193
182
  end
194
183
  end
195
184
 
185
+ describe Sequel::Model, "def_dataset_method" do
186
+ setup do
187
+ @c = Class.new(Sequel::Model(:items)) do
188
+ @dataset = Object.new
189
+ end
190
+ end
191
+
192
+ it "should add a method to the dataset and model if called with a block argument" do
193
+ @c.instance_eval do
194
+ def_dataset_method(:return_3){3}
195
+ end
196
+ @c.return_3.should == 3
197
+ @c.dataset.return_3.should == 3
198
+ end
199
+
200
+ it "should add all passed methods to the model if called without a block argument" do
201
+ @c.instance_eval do
202
+ def_dataset_method(:return_3, :return_4)
203
+ end
204
+ proc{@c.return_3}.should raise_error(NoMethodError)
205
+ proc{@c.return_4}.should raise_error(NoMethodError)
206
+ @c.dataset.instance_eval do
207
+ def return_3; 3; end
208
+ def return_4; 4; end
209
+ end
210
+ @c.return_3.should == 3
211
+ @c.return_4.should == 4
212
+ end
213
+ end
214
+
196
215
  describe "A model class with implicit table name" do
197
216
  setup do
198
217
  class Donkey < Sequel::Model
data/spec/caching_spec.rb CHANGED
@@ -16,9 +16,7 @@ describe Sequel::Model, "caching" do
16
16
  @c = Class.new(Sequel::Model(:items)) do
17
17
  set_cache cache
18
18
 
19
- def self.columns
20
- [:name, :id]
21
- end
19
+ columns :name, :id
22
20
  end
23
21
 
24
22
  $cache_dataset_row = {:name => 'sharon', :id => 1}
@@ -88,6 +86,11 @@ describe Sequel::Model, "caching" do
88
86
  proc {m.cache_key}.should_not raise_error(Sequel::Error)
89
87
  end
90
88
 
89
+ it "should not raise error if trying to save a new record" do
90
+ proc {@c.new(:name=>'blah').save}.should_not raise_error
91
+ proc {@c.create(:name=>'blah')}.should_not raise_error
92
+ end
93
+
91
94
  it "should set the cache when reading from the database" do
92
95
  $sqls.should == []
93
96
  @cache.should be_empty
@@ -109,7 +112,7 @@ describe Sequel::Model, "caching" do
109
112
  m = @c[1]
110
113
  @cache[m.cache_key].should == m
111
114
 
112
- m.set(:name => 'tutu')
115
+ m.update_values(:name => 'tutu')
113
116
  @cache.has_key?(m.cache_key).should be_false
114
117
  $sqls.last.should == "UPDATE items SET name = 'tutu' WHERE (id = 1)"
115
118
 
@@ -9,7 +9,7 @@ describe Sequel::Model, "one_to_one" do
9
9
  end
10
10
 
11
11
  @c2 = Class.new(Sequel::Model(:nodes)) do
12
- def columns; [:id, :parent_id]; end
12
+ columns :id, :parent_id, :blah
13
13
  end
14
14
 
15
15
  @dataset = @c2.dataset
@@ -44,28 +44,6 @@ describe Sequel::Model, "one_to_one" do
44
44
  MODEL_DB.sqls.should == ["SELECT * FROM nodes WHERE (id = 567) LIMIT 1"]
45
45
  end
46
46
 
47
- # the new implementation doesn't support plain datasets as associations
48
- # it "should support plain dataset in the from option" do
49
- # @c2.one_to_one :parent, :from => MODEL_DB[:xyz]
50
- #
51
- # d = @c2.new(:id => 1, :parent_id => 789)
52
- # p = d.parent
53
- # p.class.should == Hash
54
- #
55
- # MODEL_DB.sqls.should == ["SELECT * FROM xyz WHERE (id = 789) LIMIT 1"]
56
- # end
57
-
58
- # the new implementation doesn't support plain datasets as associations
59
- # it "should support table name in the from option" do
60
- # @c2.one_to_one :parent, :from => :abc
61
- #
62
- # d = @c2.new(:id => 1, :parent_id => 789)
63
- # p = d.parent
64
- # p.class.should == Hash
65
- #
66
- # MODEL_DB.sqls.should == ["SELECT * FROM abc WHERE (id = 789) LIMIT 1"]
67
- # end
68
-
69
47
  it "should return nil if key value is nil" do
70
48
  @c2.one_to_one :parent, :from => @c2
71
49
 
@@ -104,6 +82,7 @@ describe Sequel::Model, "one_to_many" do
104
82
  end
105
83
 
106
84
  @c2 = Class.new(Sequel::Model(:nodes)) do
85
+ columns :id
107
86
  end
108
87
  end
109
88
 
@@ -116,32 +95,13 @@ describe Sequel::Model, "one_to_many" do
116
95
  a.sql.should == 'SELECT * FROM attributes WHERE (node_id = 1234)'
117
96
  end
118
97
 
119
- # the new implementation doesn't support plain datasets as associations
120
- # it "should support plain dataset in the from option" do
121
- # @c2.one_to_many :attributes, :from => MODEL_DB[:xyz], :key => :node_id
122
- #
123
- # n = @c2.new(:id => 1234)
124
- # a = n.attributes
125
- # a.should be_a_kind_of(Sequel::Dataset)
126
- # a.sql.should == 'SELECT * FROM xyz WHERE (node_id = 1234)'
127
- # end
128
-
129
- # the new implementation doesn't support plain datasets as associations
130
- # it "should support table name in the from option" do
131
- # @c2.one_to_many :attributes, :from => :abc, :key => :node_id
132
- #
133
- # n = @c2.new(:id => 1234)
134
- # a = n.attributes
135
- # a.should be_a_kind_of(Sequel::Dataset)
136
- # a.sql.should == 'SELECT * FROM abc WHERE (node_id = 1234)'
137
- # end
138
-
139
98
  it "should support implicit key names" do
140
99
  $c1 = @c1
141
100
 
142
101
  module Music
143
102
  class BlueNote < Sequel::Model
144
103
  one_to_many :attributes, :from => $c1
104
+ columns :id
145
105
  end
146
106
  end
147
107