File: validations_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 (233 lines) | stat: -rw-r--r-- 6,598 bytes parent folder | download | duplicates (2)
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
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
require_relative "spec_helper"

describe Sequel::Model::Errors do
  before do
    @errors = Sequel::Model::Errors.new
  end
  
  it "should be clearable using #clear" do
    @errors.add(:a, 'b')
    @errors.must_equal(:a=>['b'])
    @errors.clear
    @errors.must_equal({})
  end
  
  it "should be empty if there are no errors" do
    @errors.must_be :empty?
  end
  
  it "should not be empty if there are errors" do
    @errors.add(:blah, "blah")
    @errors.wont_be :empty?
  end
  
  it "should return an array of errors for a specific attribute using #on if there are errors" do
    @errors.add(:blah, 'blah')
    @errors.on(:blah).must_equal ['blah']
  end
  
  it "should return nil using #on if there are no errors for that attribute" do
    @errors.on(:blah).must_be_nil
  end
  
  it "should accept errors using #add" do
    @errors.add :blah, 'zzzz'
    @errors[:blah].must_equal ['zzzz']
  end
  
  it "should return full messages using #full_messages" do
    @errors.full_messages.must_equal []
    
    @errors.add(:blow, 'blieuh')
    @errors.add(:blow, 'blich')
    @errors.add(:blay, 'bliu')
    msgs = @errors.full_messages
    msgs.sort.must_equal ['blay bliu', 'blow blich', 'blow blieuh']
  end

  it "should not add column names for LiteralStrings" do
    @errors.full_messages.must_equal []
    
    @errors.add(:blow, 'blieuh')
    @errors.add(:blow, Sequel.lit('blich'))
    @errors.add(:blay, 'bliu')
    msgs = @errors.full_messages
    msgs.sort.must_equal ['blay bliu', 'blich', 'blow blieuh']
  end

  it "should allow for customizing #full_messages via #full_message if not a LiteralString" do
    @errors.full_messages.must_equal []
    
    def @errors.full_message(attribute, msg)
      "#{attribute.class}-#{msg}-#{attribute.inspect}"
    end
    @errors.add(:blow, 'blieuh')
    @errors.add(:blow, Sequel.lit('blich'))
    @errors.add(:blay, 'bliu')
    msgs = @errors.full_messages
    msgs.sort.must_equal ['Symbol-blieuh-:blow', 'Symbol-bliu-:blay', 'blich']
  end

  it "should return the number of error messages using #count" do
    @errors.count.must_equal 0
    @errors.add(:a, 'b')
    @errors.count.must_equal 1
    @errors.add(:a, 'c')
    @errors.count.must_equal 2
    @errors.add(:b, 'c')
    @errors.count.must_equal 3
  end

  it "should return the array of error messages for a given attribute using #on" do
    @errors.add(:a, 'b')
    @errors.on(:a).must_equal ['b']
    @errors.add(:a, 'c')
    @errors.on(:a).must_equal ['b', 'c']
    @errors.add(:b, 'c')
    @errors.on(:a).must_equal ['b', 'c']
  end

  it "should return nil if there are no error messages for a given attribute using #on" do
    @errors.on(:a).must_be_nil
    @errors.add(:b, 'b')
    @errors.on(:a).must_be_nil
  end
end

describe Sequel::Model do
  before do
    @c = Class.new(Sequel::Model) do
      columns :score
      def validate
        errors.add(:score, 'too low') if score < 87
      end
    end
    
    @o = @c.new
  end
  
  it "should supply a #valid? method that returns true if validations pass" do
    @o.score = 50
    @o.wont_be :valid?
    @o.score = 100
    @o.must_be :valid?
  end
  
  it "should provide an errors object" do
    @o.score = 100
    @o.must_be :valid?
    @o.errors.must_be :empty?
    
    @o.score = 86
    @o.wont_be :valid?
    @o.errors[:score].must_equal ['too low']
    @o.errors.on(:blah).must_be_nil
  end
  
  it "should allow raising of ValidationFailed with a Model instance with errors" do
    @o.errors.add(:score, 'is too low')
    begin
      raise Sequel::ValidationFailed, @o
    rescue Sequel::ValidationFailed => e
    end
    e.model.must_be_same_as(@o)
    e.errors.must_be_same_as(@o.errors)
    e.message.must_equal 'score is too low'
  end
  
  it "should allow raising of ValidationFailed with an Errors instance" do
    @o.errors.add(:score, 'is too low')
    begin
      raise Sequel::ValidationFailed, @o.errors
    rescue Sequel::ValidationFailed => e
    end
    e.model.must_be_nil
    e.errors.must_be_same_as(@o.errors)
    e.message.must_equal 'score is too low'
  end

  it "should allow raising of ValidationFailed with a string" do
    proc{raise Sequel::ValidationFailed, "no reason"}.must_raise(Sequel::ValidationFailed, "no reason")
  end
end

describe "Model#save" do
  before do
    @c = Class.new(Sequel::Model(:people)) do
      columns :id, :x

      def validate
        errors.add(:id, 'blah') unless x == 7
      end
    end
    @m = @c.load(:id => 4, :x=>6)
    DB.reset
  end

  it "should save only if validations pass" do
    @m.raise_on_save_failure = false
    @m.wont_be :valid?
    @m.save
    DB.sqls.must_be :empty?
    
    @m.x = 7
    @m.must_be :valid?
    @m.save.wont_equal false
    DB.sqls.must_equal ['UPDATE people SET x = 7 WHERE (id = 4)']
  end
  
  it "should skip validations if the :validate=>false option is used" do
    @m.raise_on_save_failure = false
    @m.wont_be :valid?
    @m.save(:validate=>false)
    DB.sqls.must_equal ['UPDATE people SET x = 6 WHERE (id = 4)']
  end

  it "should skip validations if the skip_validation_on_save! method is used" do
    @m.raise_on_save_failure = false
    @m.wont_be :valid?
    @m.skip_validation_on_next_save!
    @m.save
    DB.sqls.must_equal ['UPDATE people SET x = 6 WHERE (id = 4)']
  end

  it "should not skip future validations if the skip_validation_on_save! method is used" do
    @m.wont_be :valid?
    @m.skip_validation_on_next_save!
    @m.save
    DB.sqls.must_equal ['UPDATE people SET x = 6 WHERE (id = 4)']
    proc{@m.save}.must_raise Sequel::ValidationFailed

    @m.skip_validation_on_next_save!
    @m.save
    DB.sqls.must_equal ['UPDATE people SET x = 6 WHERE (id = 4)']
  end

  it "should skip validations if the skip_validation_on_save! method is used and :validate=>true option is used" do
    @m.wont_be :valid?
    @m.skip_validation_on_next_save!
    @m.save(:validate=>true)
    DB.sqls.must_equal ['UPDATE people SET x = 6 WHERE (id = 4)']
  end

  it "should raise error if validations fail and raise_on_save_failure is true" do
    begin
      @m.save
    rescue Sequel::ValidationFailed => e
      e.model.must_be_same_as(@m)
      e.errors.must_be_same_as(@m.errors)
    else
      raise
    end
  end

  it "should raise error if validations fail and :raise_on_failure option is true" do
    @m.raise_on_save_failure = false
    proc{@m.save(:raise_on_failure => true)}.must_raise(Sequel::ValidationFailed)
  end

  it "should return nil if validations fail and raise_on_save_faiure is false" do
    @m.raise_on_save_failure = false
    @m.save.must_be_nil
  end
end