File: dataset_methods_spec.rb

package info (click to toggle)
ruby-sequel 5.63.0-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 10,408 kB
  • sloc: ruby: 113,747; makefile: 3
file content (198 lines) | stat: -rw-r--r-- 6,177 bytes parent folder | download | duplicates (4)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
require_relative "spec_helper"

describe Sequel::Model::DatasetMethods, "#destroy"  do
  before do
    @c = Class.new(Sequel::Model(:items)) do
      self::Destroyed = []
      def destroy
        model::Destroyed << self
      end
    end
    @d = @c.dataset
    @d = @d.with_fetch([{:id=>1}, {:id=>2}])
    DB.reset
  end

  it "should instantiate objects in the dataset and call destroy on each" do
    @d.destroy
    @c::Destroyed.collect{|x| x.values}.must_equal [{:id=>1}, {:id=>2}]
  end

  it "should return the number of records destroyed" do
    @d.destroy.must_equal 2
    @d = @d.with_fetch([[{:id=>1}], []])
    @d.destroy.must_equal 1
    @d.destroy.must_equal 0
  end

  it "should use a transaction if use_transactions is true for the model" do
    @c.use_transactions = true
    @d.destroy
    DB.sqls.must_equal ["BEGIN", "SELECT * FROM items", "COMMIT"]
  end

  it "should not use a transaction if use_transactions is false for the model" do
    @c.use_transactions = false
    @d.destroy
    DB.sqls.must_equal ["SELECT * FROM items"]
  end
end

describe Sequel::Model::DatasetMethods, "#as_hash"  do
  before do
    @c = Class.new(Sequel::Model(:items)) do
      set_primary_key :name
    end
    @d = @c.dataset
  end

  it "should result in a hash with primary key value keys and model object values" do
    @d = @d.with_fetch([{:name=>1}, {:name=>2}])
    h = @d.as_hash
    h.must_be_kind_of(Hash)
    a = h.to_a
    a.collect{|x| x[1].class}.must_equal [@c, @c]
    a.sort_by{|x| x[0]}.collect{|x| [x[0], x[1].values]}.must_equal [[1, {:name=>1}], [2, {:name=>2}]]
  end

  it "should be aliased as to_hash" do
    @d = @d.with_fetch([{:name=>1}, {:name=>2}])
    h = @d.to_hash
    h.must_be_kind_of(Hash)
    a = h.to_a
    a.collect{|x| x[1].class}.must_equal [@c, @c]
    a.sort_by{|x| x[0]}.collect{|x| [x[0], x[1].values]}.must_equal [[1, {:name=>1}], [2, {:name=>2}]]
  end

  it "should result in a hash with given value keys and model object values" do
    @d = @d.with_fetch([{:name=>1, :number=>3}, {:name=>2, :number=>4}])
    h = @d.as_hash(:number)
    h.must_be_kind_of(Hash)
    a = h.to_a
    a.collect{|x| x[1].class}.must_equal [@c, @c]
    a.sort_by{|x| x[0]}.collect{|x| [x[0], x[1].values]}.must_equal [[3, {:name=>1, :number=>3}], [4, {:name=>2, :number=>4}]]
  end

  it "should raise an error if the class doesn't have a primary key" do
    @c.no_primary_key
    proc{@d.as_hash}.must_raise(Sequel::Error)
  end
end

describe Sequel::Model::DatasetMethods  do
  before do
    @c = Class.new(Sequel::Model(:items))
    @c.columns :id
    @c.db.reset
  end

  it "#first should handle no primary key" do
    @c.no_primary_key
    @c.first.must_be_kind_of(@c)
    @c.db.sqls.must_equal ['SELECT * FROM items LIMIT 1']
  end

  it "#last should reverse order by primary key if not already ordered" do
    @c.last.must_be_kind_of(@c)
    @c.db.sqls.must_equal ['SELECT * FROM items ORDER BY id DESC LIMIT 1']
    @c.where(:id=>2).last(:foo=>2){{bar=>3}}.must_be_kind_of(@c)
    @c.db.sqls.must_equal ['SELECT * FROM items WHERE ((id = 2) AND (foo = 2) AND (bar = 3)) ORDER BY id DESC LIMIT 1']
  end

  it "#last should use existing order if there is one" do
    @c.order(:foo).last.must_be_kind_of(@c)
    @c.db.sqls.must_equal ['SELECT * FROM items ORDER BY foo DESC LIMIT 1']
  end

  it "#last should handle a composite primary key" do
    @c.set_primary_key [:id1, :id2]
    @c.last.must_be_kind_of(@c)
    @c.db.sqls.must_equal ['SELECT * FROM items ORDER BY id1 DESC, id2 DESC LIMIT 1']
  end

  it "#last should raise an error if no primary key" do
    @c.no_primary_key
    proc{@c.last}.must_raise(Sequel::Error)
  end

  it "#paged_each should order by primary key if not already ordered" do
    @c.paged_each{|r| r.must_be_kind_of(@c)}
    @c.db.sqls.must_equal ['BEGIN', 'SELECT * FROM items ORDER BY id LIMIT 1000 OFFSET 0', 'COMMIT']
    @c.paged_each(:rows_per_fetch=>5){|r|}
    @c.db.sqls.must_equal ['BEGIN', 'SELECT * FROM items ORDER BY id LIMIT 5 OFFSET 0', 'COMMIT']
  end

  it "#paged_each should use existing order if there is one" do
    @c.order(:foo).paged_each{|r| r.must_be_kind_of(@c)}
    @c.db.sqls.must_equal ['BEGIN', 'SELECT * FROM items ORDER BY foo LIMIT 1000 OFFSET 0', 'COMMIT']
  end

  it "#paged_each should handle a composite primary key" do
    @c.set_primary_key [:id1, :id2]
    @c.paged_each{|r| r.must_be_kind_of(@c)}
    @c.db.sqls.must_equal ['BEGIN', 'SELECT * FROM items ORDER BY id1, id2 LIMIT 1000 OFFSET 0', 'COMMIT']
  end

  it "#paged_each should raise an error if no primary key" do
    @c.no_primary_key
    proc{@c.paged_each{|r| }}.must_raise(Sequel::Error)
  end
end 

describe Sequel::Model::DatasetMethods, "#where_all"  do
  before do
    @c = Class.new(Sequel::Model(DB[:items].freeze))
    DB.reset
  end

  it "should filter dataset with condition, and return related rows" do
    5.times do
      @c.where_all(:id=>1).must_equal [@c.load(:id=>1, :x=>1)]
      @c.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
    end
  end

  it "should yield each row to the given block" do
    5.times do
      a = []
      @c.where_all(:id=>1){|r| a << r}.must_equal [@c.load(:id=>1, :x=>1)]
      a.must_equal [@c.load(:id=>1, :x=>1)]
      @c.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
    end
  end
end

describe Sequel::Model::DatasetMethods, "#where_each"  do
  before do
    @c = Class.new(Sequel::Model(DB[:items].freeze))
    DB.reset
  end

  it "should yield each row to the given block" do
    5.times do
      a = []
      @c.where_each(:id=>1){|r| a << r}
      a.must_equal [@c.load(:id=>1, :x=>1)]
      @c.db.sqls.must_equal ['SELECT * FROM items WHERE (id = 1)']
    end
  end
end

describe Sequel::Model::DatasetMethods, "#where_single_value"  do
  before do
    @c = Class.new(Sequel::Model(DB[:items].freeze))
    @c.class_eval do
      dataset_module do
        select :only_id, :id
      end
    end
    DB.reset
  end

  it "should return single value" do
    5.times do
      @c.only_id.where_single_value(:id=>1).must_equal 1
      @c.db.sqls.must_equal ['SELECT id FROM items WHERE (id = 1) LIMIT 1']
    end
  end
end