sequel 0.2.1.1 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +76 -0
- data/Rakefile +1 -1
- data/lib/sequel.rb +1 -1
- data/lib/sequel/ado.rb +17 -0
- data/lib/sequel/array_keys.rb +233 -0
- data/lib/sequel/connection_pool.rb +14 -0
- data/lib/sequel/core_ext.rb +3 -3
- data/lib/sequel/database.rb +25 -7
- data/lib/sequel/dataset.rb +46 -15
- data/lib/sequel/dataset/convenience.rb +27 -2
- data/lib/sequel/dataset/sequelizer.rb +2 -2
- data/lib/sequel/dataset/sql.rb +49 -18
- data/lib/sequel/dbi.rb +17 -0
- data/lib/sequel/model.rb +276 -82
- data/lib/sequel/model/base.rb +41 -30
- data/lib/sequel/model/caching.rb +42 -0
- data/lib/sequel/model/hooks.rb +113 -27
- data/lib/sequel/model/record.rb +78 -21
- data/lib/sequel/model/relations.rb +5 -0
- data/lib/sequel/model/schema.rb +11 -1
- data/lib/sequel/mysql.rb +61 -17
- data/lib/sequel/odbc.rb +42 -1
- data/lib/sequel/postgres.rb +45 -0
- data/lib/sequel/pretty_table.rb +14 -11
- data/lib/sequel/schema/schema_generator.rb +9 -3
- data/lib/sequel/sqlite.rb +33 -1
- data/spec/adapters/mysql_spec.rb +69 -15
- data/spec/adapters/postgres_spec.rb +66 -12
- data/spec/adapters/sqlite_spec.rb +113 -1
- data/spec/array_keys_spec.rb +544 -0
- data/spec/connection_pool_spec.rb +83 -0
- data/spec/database_spec.rb +81 -2
- data/spec/dataset_spec.rb +227 -9
- data/spec/model_spec.rb +392 -68
- data/spec/schema_spec.rb +7 -0
- metadata +5 -2
data/spec/model_spec.rb
CHANGED
@@ -2,90 +2,154 @@ require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
2
2
|
|
3
3
|
Sequel::Model.db = MODEL_DB = MockDatabase.new
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
describe Sequel::Model do
|
6
|
+
|
7
|
+
it "should have class method aliased as model" do
|
8
|
+
Sequel::Model.instance_methods.should include('model')
|
9
|
+
|
10
|
+
model_a = Class.new Sequel::Model
|
11
|
+
model_a.new.model.should be(model_a)
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should be associated with a dataset" do
|
15
|
+
model_a = Class.new(Sequel::Model) { set_dataset MODEL_DB[:as] }
|
10
16
|
|
11
|
-
|
12
|
-
|
17
|
+
model_a.dataset.should be_a_kind_of(MockDataset)
|
18
|
+
model_a.dataset.opts[:from].should == [:as]
|
13
19
|
|
14
|
-
|
15
|
-
set_dataset MODEL_DB[:zzz]
|
16
|
-
end
|
20
|
+
model_b = Class.new(Sequel::Model) { set_dataset MODEL_DB[:bs] }
|
17
21
|
|
18
|
-
|
19
|
-
|
20
|
-
|
22
|
+
model_b.dataset.should be_a_kind_of(MockDataset)
|
23
|
+
model_b.dataset.opts[:from].should == [:bs]
|
24
|
+
|
25
|
+
model_a.dataset.opts[:from].should == [:as]
|
21
26
|
end
|
27
|
+
|
22
28
|
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
@m.primary_key.should == :id
|
30
|
+
describe Sequel::Model, 'w/ primary key' do
|
31
|
+
|
32
|
+
it "should default to ':id'" do
|
33
|
+
model_a = Class.new Sequel::Model
|
34
|
+
model_a.primary_key.should be_equal(:id)
|
30
35
|
end
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
end
|
36
|
-
|
37
|
-
@m.primary_key.should == :xxx
|
36
|
+
|
37
|
+
it "should be changed through 'set_primary_key'" do
|
38
|
+
model_a = Class.new(Sequel::Model) { set_primary_key :a }
|
39
|
+
model_a.primary_key.should be_equal(:a)
|
38
40
|
end
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
41
|
+
|
42
|
+
it "should support multi argument composite keys" do
|
43
|
+
model_a = Class.new(Sequel::Model) { set_primary_key :a, :b }
|
44
|
+
model_a.primary_key.should be_eql([:a, :b])
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should accept single argument composite keys" do
|
48
|
+
model_a = Class.new(Sequel::Model) { set_primary_key [:a, :b] }
|
49
|
+
model_a.primary_key.should be_eql([:a, :b])
|
45
50
|
end
|
51
|
+
|
46
52
|
end
|
47
53
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
54
|
+
describe Sequel::Model, 'w/o primary key' do
|
55
|
+
|
56
|
+
it "should return nil for primary key" do
|
57
|
+
Class.new(Sequel::Model) { no_primary_key }.primary_key.should be_nil
|
53
58
|
end
|
54
|
-
|
55
|
-
|
56
|
-
|
59
|
+
|
60
|
+
it "should raise a SequelError on 'this'" do
|
61
|
+
instance = Class.new(Sequel::Model) { no_primary_key }.new
|
62
|
+
proc { instance.this }.should raise_error(SequelError)
|
57
63
|
end
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
describe Sequel::Model, 'with this' do
|
68
|
+
|
69
|
+
before { @example = Class.new Sequel::Model(:examples) }
|
70
|
+
|
71
|
+
it "should return a dataset identifying the record" do
|
72
|
+
instance = @example.new :id => 3
|
73
|
+
instance.this.sql.should be_eql("SELECT * FROM examples WHERE (id = 3) LIMIT 1")
|
62
74
|
end
|
75
|
+
|
76
|
+
it "should support arbitary primary keys" do
|
77
|
+
@example.set_primary_key :a
|
78
|
+
|
79
|
+
instance = @example.new :a => 3
|
80
|
+
instance.this.sql.should be_eql("SELECT * FROM examples WHERE (a = 3) LIMIT 1")
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should support composite primary keys" do
|
84
|
+
@example.set_primary_key :x, :y
|
85
|
+
instance = @example.new :x => 4, :y => 5
|
86
|
+
|
87
|
+
parts = ['SELECT * FROM examples WHERE %s LIMIT 1',
|
88
|
+
'(x = 4) AND (y = 5)', '(y = 5) AND (x = 4)'
|
89
|
+
].map { |expr| Regexp.escape expr }
|
90
|
+
regexp = Regexp.new parts.first % "(?:#{parts[1]}|#{parts[2]})"
|
91
|
+
|
92
|
+
instance.this.sql.should match(regexp)
|
93
|
+
end
|
94
|
+
|
63
95
|
end
|
64
96
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
97
|
+
describe Sequel::Model, 'with hooks' do
|
98
|
+
|
99
|
+
before do
|
100
|
+
MODEL_DB.reset
|
101
|
+
Sequel::Model.hooks.clear
|
102
|
+
|
103
|
+
@hooks = %w{
|
104
|
+
before_save before_create before_update before_destroy
|
105
|
+
after_save after_create after_update after_destroy
|
106
|
+
}.select { |hook| !hook.empty? }
|
69
107
|
end
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
108
|
+
|
109
|
+
it "should have hooks for everything" do
|
110
|
+
Sequel::Model.methods.should include('hooks')
|
111
|
+
Sequel::Model.methods.should include(*@hooks)
|
112
|
+
@hooks.each do |hook|
|
113
|
+
Sequel::Model.hooks[hook.to_sym].should be_an_instance_of(Array)
|
114
|
+
end
|
74
115
|
end
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
116
|
+
it "should be inherited" do
|
117
|
+
pending 'soon'
|
118
|
+
|
119
|
+
@hooks.each do |hook|
|
120
|
+
Sequel::Model.send(hook.to_sym) { nil }
|
121
|
+
end
|
122
|
+
|
123
|
+
model = Class.new Sequel::Model(:models)
|
124
|
+
model.hooks.should == Sequel::Model.hooks
|
81
125
|
end
|
82
|
-
|
83
|
-
specify "should support composite primary keys" do
|
84
|
-
@m.set_primary_key [:x, :y]
|
85
|
-
o = @m.new(:x => 4, :y => 5)
|
86
126
|
|
87
|
-
|
127
|
+
it "should run hooks" do
|
128
|
+
pending 'soon'
|
129
|
+
|
130
|
+
test = mock 'Test'
|
131
|
+
test.should_receive(:run).exactly(@hooks.length)
|
132
|
+
|
133
|
+
@hooks.each do |hook|
|
134
|
+
Sequel::Model.send(hook.to_sym) { test.run }
|
135
|
+
end
|
136
|
+
|
137
|
+
model = Class.new Sequel::Model(:models)
|
138
|
+
model.hooks.should == Sequel::Model.hooks
|
139
|
+
|
140
|
+
model_instance = model.new
|
141
|
+
@hooks.each { |hook| model_instance.run_hooks(hook) }
|
142
|
+
end
|
143
|
+
it "should run hooks around save and create" do
|
144
|
+
pending 'test execution'
|
145
|
+
end
|
146
|
+
it "should run hooks around save and update" do
|
147
|
+
pending 'test execution'
|
88
148
|
end
|
149
|
+
it "should run hooks around delete" do
|
150
|
+
pending 'test execution'
|
151
|
+
end
|
152
|
+
|
89
153
|
end
|
90
154
|
|
91
155
|
context "A new model instance" do
|
@@ -214,7 +278,7 @@ context "A model class without a primary key" do
|
|
214
278
|
i = nil
|
215
279
|
proc {i = @c.create(:x => 1)}.should_not raise_error
|
216
280
|
i.class.should be(@c)
|
217
|
-
i.values.should == {:x => 1}
|
281
|
+
i.values.to_hash.should == {:x => 1}
|
218
282
|
|
219
283
|
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1);']
|
220
284
|
end
|
@@ -325,6 +389,7 @@ context "Model#serialize" do
|
|
325
389
|
o.set(:abc => 23)
|
326
390
|
ds.sqls.should == "UPDATE items SET abc = '#{23.to_yaml}' WHERE (id = 1)"
|
327
391
|
|
392
|
+
ds.raw = {:id => 1, :abc => "--- 1\n", :def => "--- hello\n"}
|
328
393
|
o = @c.create(:abc => [1, 2, 3])
|
329
394
|
ds.sqls.should == "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}');"
|
330
395
|
end
|
@@ -377,9 +442,6 @@ context "Model#new?" do
|
|
377
442
|
MODEL_DB.reset
|
378
443
|
|
379
444
|
@c = Class.new(Sequel::Model(:items)) do
|
380
|
-
def columns
|
381
|
-
[:id, :x, :y]
|
382
|
-
end
|
383
445
|
end
|
384
446
|
end
|
385
447
|
|
@@ -436,5 +498,267 @@ context "Model.after_create" do
|
|
436
498
|
end
|
437
499
|
end
|
438
500
|
|
439
|
-
context "Model.
|
501
|
+
context "Model.subset" do
|
502
|
+
setup do
|
503
|
+
MODEL_DB.reset
|
504
|
+
|
505
|
+
@c = Class.new(Sequel::Model(:items)) do
|
506
|
+
def columns
|
507
|
+
[:id, :x, :y]
|
508
|
+
end
|
509
|
+
end
|
510
|
+
end
|
511
|
+
|
512
|
+
specify "should create a filter on the underlying dataset" do
|
513
|
+
proc {@c.new_only}.should raise_error(NoMethodError)
|
514
|
+
|
515
|
+
@c.subset(:new_only) {:age == 'new'}
|
516
|
+
|
517
|
+
@c.new_only.sql.should == "SELECT * FROM items WHERE (age = 'new')"
|
518
|
+
@c.dataset.new_only.sql.should == "SELECT * FROM items WHERE (age = 'new')"
|
519
|
+
|
520
|
+
@c.subset(:pricey) {:price > 100}
|
521
|
+
|
522
|
+
@c.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
523
|
+
@c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
524
|
+
|
525
|
+
# check if subsets are composable
|
526
|
+
@c.pricey.new_only.sql.should == "SELECT * FROM items WHERE (price > 100) AND (age = 'new')"
|
527
|
+
@c.new_only.pricey.sql.should == "SELECT * FROM items WHERE (age = 'new') AND (price > 100)"
|
528
|
+
end
|
529
|
+
end
|
530
|
+
|
531
|
+
context "Model.find" do
|
532
|
+
setup do
|
533
|
+
MODEL_DB.reset
|
534
|
+
|
535
|
+
@c = Class.new(Sequel::Model(:items)) do
|
536
|
+
def self.columns
|
537
|
+
[:name, :id]
|
538
|
+
end
|
539
|
+
end
|
540
|
+
|
541
|
+
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
542
|
+
@dataset = @c.dataset
|
543
|
+
$sqls = []
|
544
|
+
@dataset.extend(Module.new {
|
545
|
+
def fetch_rows(sql)
|
546
|
+
$sqls << sql
|
547
|
+
yield $cache_dataset_row
|
548
|
+
end
|
549
|
+
})
|
550
|
+
end
|
551
|
+
|
552
|
+
specify "should return the first record matching the given filter" do
|
553
|
+
@c.find(:name => 'sharon').should be_a_kind_of(@c)
|
554
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
|
555
|
+
|
556
|
+
@c.find {"name LIKE 'abc%'".lit}.should be_a_kind_of(@c)
|
557
|
+
$sqls.last.should == "SELECT * FROM items WHERE name LIKE 'abc%' LIMIT 1"
|
558
|
+
end
|
559
|
+
|
560
|
+
specify "should accept filter blocks" do
|
561
|
+
@c.find {:id == 1}.should be_a_kind_of(@c)
|
562
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
563
|
+
|
564
|
+
@c.find {:x > 1 && :y < 2}.should be_a_kind_of(@c)
|
565
|
+
$sqls.last.should == "SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
context "Model.[]" do
|
570
|
+
setup do
|
571
|
+
MODEL_DB.reset
|
572
|
+
|
573
|
+
@c = Class.new(Sequel::Model(:items)) do
|
574
|
+
def self.columns
|
575
|
+
[:name, :id]
|
576
|
+
end
|
577
|
+
end
|
578
|
+
|
579
|
+
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
580
|
+
@dataset = @c.dataset
|
581
|
+
$sqls = []
|
582
|
+
@dataset.extend(Module.new {
|
583
|
+
def fetch_rows(sql)
|
584
|
+
$sqls << sql
|
585
|
+
yield $cache_dataset_row
|
586
|
+
end
|
587
|
+
})
|
588
|
+
end
|
589
|
+
|
590
|
+
specify "should return the first record for the given pk" do
|
591
|
+
@c[1].should be_a_kind_of(@c)
|
592
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
593
|
+
@c[9999].should be_a_kind_of(@c)
|
594
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 9999) LIMIT 1"
|
595
|
+
end
|
596
|
+
|
597
|
+
specify "should work correctly for custom primary key" do
|
598
|
+
@c.set_primary_key :name
|
599
|
+
@c['sharon'].should be_a_kind_of(@c)
|
600
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
|
601
|
+
end
|
602
|
+
|
603
|
+
specify "should work correctly for composite primary key" do
|
604
|
+
@c.set_primary_key [:node_id, :kind]
|
605
|
+
@c[3921, 201].should be_a_kind_of(@c)
|
606
|
+
$sqls.last.should =~ \
|
607
|
+
/^SELECT \* FROM items WHERE (\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\)) LIMIT 1$/
|
608
|
+
end
|
609
|
+
|
610
|
+
specify "should act as shortcut to find if a hash is given" do
|
611
|
+
@c[:id => 1].should be_a_kind_of(@c)
|
612
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
613
|
+
|
614
|
+
@c[:name => ['abc', 'def']].should be_a_kind_of(@c)
|
615
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name IN ('abc', 'def')) LIMIT 1"
|
616
|
+
end
|
617
|
+
end
|
618
|
+
|
619
|
+
context "A cached model" do
|
620
|
+
setup do
|
621
|
+
MODEL_DB.reset
|
622
|
+
|
623
|
+
@cache_class = Class.new(Hash) do
|
624
|
+
attr_accessor :ttl
|
625
|
+
def set(k, v, ttl); self[k] = v; @ttl = ttl; end
|
626
|
+
def get(k); self[k]; end
|
627
|
+
end
|
628
|
+
cache = @cache_class.new
|
629
|
+
@cache = cache
|
630
|
+
|
631
|
+
@c = Class.new(Sequel::Model(:items)) do
|
632
|
+
set_cache cache
|
633
|
+
|
634
|
+
def self.columns
|
635
|
+
[:name, :id]
|
636
|
+
end
|
637
|
+
end
|
638
|
+
|
639
|
+
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
640
|
+
@dataset = @c.dataset
|
641
|
+
$sqls = []
|
642
|
+
@dataset.extend(Module.new {
|
643
|
+
def fetch_rows(sql)
|
644
|
+
$sqls << sql
|
645
|
+
yield $cache_dataset_row
|
646
|
+
end
|
647
|
+
|
648
|
+
def update(values)
|
649
|
+
$sqls << update_sql(values)
|
650
|
+
$cache_dataset_row.merge!(values)
|
651
|
+
end
|
652
|
+
|
653
|
+
def delete
|
654
|
+
$sqls << delete_sql
|
655
|
+
end
|
656
|
+
})
|
657
|
+
end
|
658
|
+
|
659
|
+
specify "should set the model's cache store" do
|
660
|
+
@c.cache_store.should be(@cache)
|
661
|
+
end
|
662
|
+
|
663
|
+
specify "should have a default ttl of 3600" do
|
664
|
+
@c.cache_ttl.should == 3600
|
665
|
+
end
|
666
|
+
|
667
|
+
specify "should take a ttl option" do
|
668
|
+
@c.set_cache @cache, :ttl => 1234
|
669
|
+
@c.cache_ttl.should == 1234
|
670
|
+
end
|
671
|
+
|
672
|
+
specify "should offer a set_cache_ttl method for setting the ttl" do
|
673
|
+
@c.cache_ttl.should == 3600
|
674
|
+
@c.set_cache_ttl 1234
|
675
|
+
@c.cache_ttl.should == 1234
|
676
|
+
end
|
677
|
+
|
678
|
+
specify "should generate a cache key appropriate to the class" do
|
679
|
+
m = @c.new
|
680
|
+
m.values[:id] = 1
|
681
|
+
m.cache_key.should == "#{m.class}:1"
|
682
|
+
|
683
|
+
# custom primary key
|
684
|
+
@c.set_primary_key :ttt
|
685
|
+
m = @c.new
|
686
|
+
m.values[:ttt] = 333
|
687
|
+
m.cache_key.should == "#{m.class}:333"
|
688
|
+
|
689
|
+
# composite primary key
|
690
|
+
@c.set_primary_key [:a, :b, :c]
|
691
|
+
m = @c.new
|
692
|
+
m.values[:a] = 123
|
693
|
+
m.values[:c] = 456
|
694
|
+
m.values[:b] = 789
|
695
|
+
m.cache_key.should == "#{m.class}:123,789,456"
|
696
|
+
end
|
697
|
+
|
698
|
+
specify "should raise error if attempting to generate cache_key and primary key value is null" do
|
699
|
+
m = @c.new
|
700
|
+
proc {m.cache_key}.should raise_error(SequelError)
|
701
|
+
|
702
|
+
m.values[:id] = 1
|
703
|
+
proc {m.cache_key}.should_not raise_error(SequelError)
|
704
|
+
end
|
705
|
+
|
706
|
+
specify "should set the cache when reading from the database" do
|
707
|
+
$sqls.should == []
|
708
|
+
@cache.should be_empty
|
709
|
+
|
710
|
+
m = @c[1]
|
711
|
+
$sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
|
712
|
+
m.values.should == $cache_dataset_row
|
713
|
+
@cache[m.cache_key].should == m
|
714
|
+
|
715
|
+
# read from cache
|
716
|
+
m2 = @c[1]
|
717
|
+
$sqls.should == ['SELECT * FROM items WHERE (id = 1) LIMIT 1']
|
718
|
+
m2.should == m
|
719
|
+
m2.values.should == $cache_dataset_row
|
720
|
+
end
|
721
|
+
|
722
|
+
specify "should delete the cache when writing to the database" do
|
723
|
+
# fill the cache
|
724
|
+
m = @c[1]
|
725
|
+
@cache[m.cache_key].should == m
|
726
|
+
|
727
|
+
m.set(:name => 'tutu')
|
728
|
+
@cache.has_key?(m.cache_key).should be_false
|
729
|
+
$sqls.last.should == "UPDATE items SET name = 'tutu' WHERE (id = 1)"
|
730
|
+
|
731
|
+
m = @c[1]
|
732
|
+
@cache[m.cache_key].should == m
|
733
|
+
m.name = 'hey'
|
734
|
+
m.save
|
735
|
+
@cache.has_key?(m.cache_key).should be_false
|
736
|
+
$sqls.last.should == "UPDATE items SET name = 'hey', id = 1 WHERE (id = 1)"
|
737
|
+
end
|
738
|
+
|
739
|
+
specify "should delete the cache when deleting the record" do
|
740
|
+
# fill the cache
|
741
|
+
m = @c[1]
|
742
|
+
@cache[m.cache_key].should == m
|
743
|
+
|
744
|
+
m.delete
|
745
|
+
@cache.has_key?(m.cache_key).should be_false
|
746
|
+
$sqls.last.should == "DELETE FROM items WHERE (id = 1)"
|
747
|
+
end
|
748
|
+
|
749
|
+
specify "should support #[] as a shortcut to #find with hash" do
|
750
|
+
m = @c[:id => 3]
|
751
|
+
@cache[m.cache_key].should be_nil
|
752
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 3) LIMIT 1"
|
753
|
+
|
754
|
+
m = @c[1]
|
755
|
+
@cache[m.cache_key].should == m
|
756
|
+
$sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
|
757
|
+
"SELECT * FROM items WHERE (id = 1) LIMIT 1"]
|
758
|
+
|
759
|
+
@c[:id => 4]
|
760
|
+
$sqls.should == ["SELECT * FROM items WHERE (id = 3) LIMIT 1", \
|
761
|
+
"SELECT * FROM items WHERE (id = 1) LIMIT 1", \
|
762
|
+
"SELECT * FROM items WHERE (id = 4) LIMIT 1"]
|
763
|
+
end
|
440
764
|
end
|