sequel_model 0.3.1 → 0.3.2

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.
data/CHANGELOG CHANGED
@@ -1,4 +1,12 @@
1
- === 0.3.1
1
+ === 0.3.2 (2008-01-24)
2
+
3
+ * Added Model#update_with_params method with support for virtual attributes and auto-filtering of unrelated parameters, and changed Model.create_with_params to support virtual attributes (#128).
4
+
5
+ * Cleaned up gem spec (#132).
6
+
7
+ * Removed validations code. Now relying on validations in assistance gem.
8
+
9
+ === 0.3.1 (2008-01-21)
2
10
 
3
11
  * Changed Model.dataset to use inflector to pluralize the class name into the table name. Works in similar fashion to table names in AR or DM.
4
12
 
data/Rakefile CHANGED
@@ -9,7 +9,7 @@ include FileUtils
9
9
  # Configuration
10
10
  ##############################################################################
11
11
  NAME = "sequel_model"
12
- VERS = "0.3.1"
12
+ VERS = "0.3.2"
13
13
  CLEAN.include ["**/.*.sw?", "pkg/*", ".config", "doc/*", "coverage/*"]
14
14
  RDOC_OPTS = [
15
15
  "--quiet",
@@ -57,15 +57,14 @@ spec = Gem::Specification.new do |s|
57
57
  s.required_ruby_version = ">= 1.8.4"
58
58
 
59
59
  case RUBY_PLATFORM
60
- when /mswin/
61
- s.platform = Gem::Platform::CURRENT
62
60
  when /java/
63
61
  s.platform = "jruby"
64
62
  else
65
63
  s.platform = Gem::Platform::RUBY
66
64
  end
67
65
 
68
- s.add_dependency("sequel_core", '>= 0.5')
66
+ s.add_dependency("assistance", '>= 0.1.2')
67
+ s.add_dependency("sequel_core", '>= 1.0')
69
68
 
70
69
  s.files = %w(COPYING README Rakefile) + Dir.glob("{doc,spec,lib}/**/*")
71
70
 
@@ -96,6 +95,9 @@ end
96
95
 
97
96
  task :tag do
98
97
  cwd = FileUtils.pwd
98
+ sh %{rm -rf doc/*}
99
+ sh %{rm -rf pkg/*}
100
+ sh %{rm -rf coverage/*}
99
101
  sh %{cd ../.. && svn copy #{cwd} tags/#{NAME}-#{VERS} && svn commit -m "#{NAME}-#{VERS} tag." tags}
100
102
  end
101
103
 
@@ -135,9 +135,22 @@ module Sequel
135
135
  end
136
136
  end
137
137
 
138
+ # Updates the instance with the supplied values with support for virtual
139
+ # attributes, ignoring any values for which no setter method is available.
140
+ def update_with_params(values)
141
+ c = columns
142
+ values.each do |k, v| m = :"#{k}="
143
+ send(m, v) if c.include?(k) || respond_to?(m)
144
+ end
145
+ save_changes
146
+ end
147
+ alias_method :update_with, :update_with_params
148
+
138
149
  class << self
139
150
  def create_with_params(params)
140
- create(params.reject {|k, v| !columns.include?(k.to_sym)})
151
+ record = new
152
+ record.update_with_params(params)
153
+ record
141
154
  end
142
155
  alias_method :create_with, :create_with_params
143
156
  end
@@ -1,248 +1,8 @@
1
- gem 'assistance', '>= 0.1.1' # because we need Array#extract_options!
1
+ gem 'assistance', '>= 0.1.2' # because we need Validations
2
2
 
3
3
  module Sequel
4
- # The Validatable module provides validation capabilities as a mixin. When
5
- # included into a class, it enhances the class with class and instance
6
- # methods for defining validations and validating class instances.
7
- #
8
- # The Validatable emulates the validation capabilities of ActiveRecord, and
9
- # provides methods for validating acceptance, confirmation, presence, format,
10
- # length and numericality of attributes.
11
- #
12
- # To use validations, you need to include the Validatable module in your
13
- # class:
14
- #
15
- # class MyClass
16
- # include Sequel::Validatable
17
- # validates_length_of :password, :minimum => 6
18
- # end
19
- module Validatable
20
- # Includes the Validatable class methods into the including class.
21
- def self.included(c)
22
- c.extend ClassMethods
23
- end
24
-
25
- # Returns the validation errors associated with the object.
26
- def errors
27
- @errors ||= Errors.new
28
- end
29
-
30
- # Validates the object.
31
- def validate
32
- errors.clear
33
- self.class.validate(self)
34
- end
35
-
36
- # Validates the object and returns true if no errors are reported.
37
- def valid?
38
- validate
39
- errors.empty?
40
- end
41
-
42
- # Validatable::Errors represents validation errors.
43
- class Errors
44
- # Initializes a new instance of validation errors.
45
- def initialize
46
- @errors = Hash.new {|h, k| h[k] = []}
47
- end
48
-
49
- # Returns true if no errors are stored.
50
- def empty?
51
- @errors.empty?
52
- end
53
-
54
- # Clears all errors.
55
- def clear
56
- @errors.clear
57
- end
58
-
59
- # Returns the errors for the given attribute.
60
- def on(att)
61
- @errors[att]
62
- end
63
- alias_method :[], :on
64
-
65
- # Adds an error for the given attribute.
66
- def add(att, msg)
67
- @errors[att] << msg
68
- end
69
-
70
- # Returns an array of fully-formatted error messages.
71
- def full_messages
72
- @errors.inject([]) do |m, kv| att, errors = *kv
73
- errors.each {|e| m << "#{att} #{e}"}
74
- m
75
- end
76
- end
77
- end
78
-
79
- # The Generator class is used to generate validation definitions using
80
- # the validates {} idiom.
81
- class Generator
82
- # Initializes a new generator.
83
- def initialize(receiver ,&block)
84
- @receiver = receiver
85
- instance_eval(&block)
86
- end
87
-
88
- # Delegates method calls to the receiver by calling receiver.validates_xxx.
89
- def method_missing(m, *args)
90
- @receiver.send(:"validates_#{m}", *args)
91
- end
92
- end
93
-
94
- # Validatable class methods.
95
- module ClassMethods
96
- # Defines validations by converting a longhand block into a series of
97
- # shorthand definitions. For example:
98
- #
99
- # class MyClass
100
- # include Sequel::Validatable
101
- # validates do
102
- # length_of :name, :minimum => 6
103
- # length_of :password, :minimum => 8
104
- # end
105
- # end
106
- #
107
- # is equivalent to:
108
- # class MyClass
109
- # include Sequel::Validatable
110
- # validates_length_of :name, :minimum => 6
111
- # validates_length_of :password, :minimum => 8
112
- # end
113
- def validates(&block)
114
- Generator.new(self, &block)
115
- end
116
-
117
- # Returns the validations hash for the class.
118
- def validations
119
- @validations ||= Hash.new {|h, k| h[k] = []}
120
- end
121
-
122
- # Returns true if validations are defined.
123
- def has_validations?
124
- !validations.empty?
125
- end
126
-
127
- # Validates the given instance.
128
- def validate(o)
129
- validations.each do |att, procs|
130
- v = o.send(att)
131
- procs.each {|p| p[o, att, v]}
132
- end
133
- end
134
-
135
- # Adds a validation for each of the given attributes using the supplied
136
- # block. The block must accept three arguments: instance, attribute and
137
- # value, e.g.:
138
- #
139
- # validates_each :name, :password do |object, attribute, value|
140
- # object.errors[attribute] << 'is not nice' unless value.nice?
141
- # end
142
- def validates_each(*atts, &block)
143
- atts.each {|a| validations[a] << block}
144
- end
145
-
146
- # Validates acceptance of an attribute.
147
- def validates_acceptance_of(*atts)
148
- opts = {
149
- :message => 'is not accepted',
150
- :allow_nil => true,
151
- :accept => '1'
152
- }.merge!(atts.extract_options!)
153
-
154
- validates_each(*atts) do |o, a, v|
155
- next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
156
- o.errors[a] << opts[:message] unless v == opts[:accept]
157
- end
158
- end
159
-
160
- # Validates confirmation of an attribute.
161
- def validates_confirmation_of(*atts)
162
- opts = {
163
- :message => 'is not confirmed',
164
- }.merge!(atts.extract_options!)
165
-
166
- validates_each(*atts) do |o, a, v|
167
- next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
168
- c = o.send(:"#{a}_confirmation")
169
- o.errors[a] << opts[:message] unless v == c
170
- end
171
- end
172
-
173
- # Validates the format of an attribute.
174
- def validates_format_of(*atts)
175
- opts = {
176
- :message => 'is invalid',
177
- }.merge!(atts.extract_options!)
178
-
179
- unless opts[:with].is_a?(Regexp)
180
- raise Sequel::Error, "A regular expression must be supplied as the :with option of the options hash"
181
- end
182
-
183
- validates_each(*atts) do |o, a, v|
184
- next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
185
- o.errors[a] << opts[:message] unless v.to_s =~ opts[:with]
186
- end
187
- end
188
-
189
- # Validates the length of an attribute.
190
- def validates_length_of(*atts)
191
- opts = {
192
- :too_long => 'is too long',
193
- :too_short => 'is too short',
194
- :wrong_length => 'is the wrong length'
195
- }.merge!(atts.extract_options!)
196
-
197
- validates_each(*atts) do |o, a, v|
198
- next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
199
- if m = opts[:maximum]
200
- o.errors[a] << (opts[:message] || opts[:too_long]) unless v && v.size <= m
201
- end
202
- if m = opts[:minimum]
203
- o.errors[a] << (opts[:message] || opts[:too_short]) unless v && v.size >= m
204
- end
205
- if i = opts[:is]
206
- o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && v.size == i
207
- end
208
- if w = opts[:within]
209
- o.errors[a] << (opts[:message] || opts[:wrong_length]) unless v && w.include?(v.size)
210
- end
211
- end
212
- end
213
-
214
- NUMBER_RE = /^\d*\.{0,1}\d+$/
215
- INTEGER_RE = /\A[+-]?\d+\Z/
216
-
217
- # Validates whether an attribute is a number.
218
- def validates_numericality_of(*atts)
219
- opts = {
220
- :message => 'is not a number',
221
- }.merge!(atts.extract_options!)
222
-
223
- re = opts[:only_integer] ? INTEGER_RE : NUMBER_RE
224
-
225
- validates_each(*atts) do |o, a, v|
226
- next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
227
- o.errors[a] << opts[:message] unless v.to_s =~ re
228
- end
229
- end
230
-
231
- # Validates the presence of an attribute.
232
- def validates_presence_of(*atts)
233
- opts = {
234
- :message => 'is not present',
235
- }.merge!(atts.extract_options!)
236
-
237
- validates_each(*atts) do |o, a, v|
238
- o.errors[a] << opts[:message] unless v && !v.blank?
239
- end
240
- end
241
- end
242
- end
243
-
244
4
  class Model
245
- include Validatable
5
+ include Validation
246
6
 
247
7
  alias_method :save!, :save
248
8
  def save(*args)
@@ -282,6 +282,43 @@ describe "Model#pk_hash" do
282
282
  end
283
283
  end
284
284
 
285
+ describe Sequel::Model, "update_with_params" do
286
+
287
+ before(:each) do
288
+ MODEL_DB.reset
289
+
290
+ @c = Class.new(Sequel::Model(:items)) do
291
+ def self.columns; [:x, :y]; end
292
+ end
293
+ @o1 = @c.new
294
+ @o2 = @c.new(:id => 5)
295
+ end
296
+
297
+ it "should filter the given params using the model columns" do
298
+ @o1.update_with_params(:x => 1, :z => 2)
299
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
300
+
301
+ MODEL_DB.reset
302
+ @o2.update_with_params(:y => 1, :abc => 2)
303
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
304
+ end
305
+
306
+ it "should be aliased by create_with" do
307
+ @o1.update_with(:x => 1, :z => 2)
308
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (1)"
309
+
310
+ MODEL_DB.reset
311
+ @o2.update_with(:y => 1, :abc => 2)
312
+ MODEL_DB.sqls.first.should == "UPDATE items SET y = 1 WHERE (id = 5)"
313
+ end
314
+
315
+ it "should support virtual attributes" do
316
+ @c.class_def(:blah=) {|v| self.x = v}
317
+ @o1.update_with(:blah => 333)
318
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
319
+ end
320
+ end
321
+
285
322
  describe Sequel::Model, "create_with_params" do
286
323
 
287
324
  before(:each) do
@@ -310,6 +347,11 @@ describe Sequel::Model, "create_with_params" do
310
347
  MODEL_DB.sqls.first.should == "INSERT INTO items (y) VALUES (1)"
311
348
  end
312
349
 
350
+ it "should support virtual attributes" do
351
+ @c.class_def(:blah=) {|v| self.x = v}
352
+ o = @c.create_with(:blah => 333)
353
+ MODEL_DB.sqls.first.should == "INSERT INTO items (x) VALUES (333)"
354
+ end
313
355
  end
314
356
 
315
357
  describe Sequel::Model, "#destroy" do
@@ -1,295 +1,5 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper")
2
2
 
3
- describe "Sequel::Validatable::Errors" do
4
- setup do
5
- @errors = Sequel::Validatable::Errors.new
6
- class Sequel::Validatable::Errors
7
- attr_accessor :errors
8
- end
9
- end
10
-
11
- specify "should be clearable using #clear" do
12
- @errors.errors = {1 => 2, 3 => 4}
13
- @errors.clear
14
- @errors.errors.should == {}
15
- end
16
-
17
- specify "should be empty if no errors are added" do
18
- @errors.should be_empty
19
- @errors[:blah] << "blah"
20
- @errors.should_not be_empty
21
- end
22
-
23
- specify "should return errors for a specific attribute using #on or #[]" do
24
- @errors[:blah].should == []
25
- @errors.on(:blah).should == []
26
-
27
- @errors[:blah] << 'blah'
28
- @errors[:blah].should == ['blah']
29
- @errors.on(:blah).should == ['blah']
30
-
31
- @errors[:bleu].should == []
32
- @errors.on(:bleu).should == []
33
- end
34
-
35
- specify "should accept errors using #[] << or #add" do
36
- @errors[:blah] << 'blah'
37
- @errors[:blah].should == ['blah']
38
-
39
- @errors.add :blah, 'zzzz'
40
- @errors[:blah].should == ['blah', 'zzzz']
41
- end
42
-
43
- specify "should return full messages using #full_messages" do
44
- @errors.full_messages.should == []
45
-
46
- @errors[:blow] << 'blieuh'
47
- @errors[:blow] << 'blich'
48
- @errors[:blay] << 'bliu'
49
- msgs = @errors.full_messages
50
- msgs.size.should == 3
51
- msgs.should include('blow blieuh', 'blow blich', 'blay bliu')
52
- end
53
- end
54
-
55
- describe Sequel::Validatable do
56
- setup do
57
- @c = Class.new do
58
- include Sequel::Validatable
59
-
60
- def self.validates_coolness_of(attr)
61
- validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
62
- end
63
- end
64
-
65
- @d = Class.new do
66
- attr_accessor :errors
67
- def initialize; @errors = Sequel::Validatable::Errors.new; end
68
- end
69
- end
70
-
71
- specify "should respond to validates, validations, has_validations?" do
72
- @c.should respond_to(:validations)
73
- @c.should respond_to(:has_validations?)
74
- end
75
-
76
- specify "should acccept validation definitions using validates_each" do
77
- @c.validates_each(:xx, :yy) {|o, a, v| o.errors[a] << 'too low' if v < 50}
78
-
79
- @c.validations[:xx].size.should == 1
80
- @c.validations[:yy].size.should == 1
81
-
82
- o = @d.new
83
- @c.validations[:xx].first.call(o, :aa, 40)
84
- @c.validations[:yy].first.call(o, :bb, 60)
85
-
86
- o.errors.full_messages.should == ['aa too low']
87
- end
88
-
89
- specify "should return true/false for has_validations?" do
90
- @c.has_validations?.should == false
91
- @c.validates_each(:xx) {1}
92
- @c.has_validations?.should == true
93
- end
94
-
95
- specify "should provide a validates method that takes block with validation definitions" do
96
- @c.validates do
97
- coolness_of :blah
98
- end
99
- @c.validations[:blah].should_not be_empty
100
-
101
- o = @d.new
102
- @c.validations[:blah].first.call(o, :ttt, 40)
103
- o.errors.full_messages.should == ['ttt is not cool']
104
- o.errors.clear
105
- @c.validations[:blah].first.call(o, :ttt, :cool)
106
- o.errors.should be_empty
107
- end
108
- end
109
-
110
- describe "A Validatable instance" do
111
- setup do
112
- @c = Class.new do
113
- attr_accessor :score
114
-
115
- include Sequel::Validatable
116
-
117
- validates_each :score do |o, a, v|
118
- o.errors[a] << 'too low' if v < 87
119
- end
120
- end
121
-
122
- @o = @c.new
123
- end
124
-
125
- specify "should supply a #valid? method that returns true if validations pass" do
126
- @o.score = 50
127
- @o.should_not be_valid
128
- @o.score = 100
129
- @o.should be_valid
130
- end
131
-
132
- specify "should provide an errors object" do
133
- @o.score = 100
134
- @o.should be_valid
135
- @o.errors.should be_empty
136
-
137
- @o.score = 86
138
- @o.should_not be_valid
139
- @o.errors[:score].should == ['too low']
140
- @o.errors[:blah].should be_empty
141
- end
142
- end
143
-
144
- describe Sequel::Validatable::Generator do
145
- setup do
146
- $testit = nil
147
-
148
- @c = Class.new do
149
- include Sequel::Validatable
150
-
151
- def self.validates_blah
152
- $testit = 1324
153
- end
154
- end
155
- end
156
-
157
- specify "should instance_eval the block, sending everything to its receiver" do
158
- Sequel::Validatable::Generator.new(@c) do
159
- blah
160
- end
161
- $testit.should == 1324
162
- end
163
- end
164
-
165
- describe "Sequel validations" do
166
- setup do
167
- @c = Class.new do
168
- attr_accessor :value
169
- include Sequel::Validatable
170
- end
171
- @m = @c.new
172
- end
173
-
174
- specify "should validate acceptance_of" do
175
- @c.validates_acceptance_of :value
176
- @m.should be_valid
177
- @m.value = '1'
178
- @m.should be_valid
179
- end
180
-
181
- specify "should validate acceptance_of with accept" do
182
- @c.validates_acceptance_of :value, :accept => 'true'
183
- @m.value = '1'
184
- @m.should_not be_valid
185
- @m.value = 'true'
186
- @m.should be_valid
187
- end
188
-
189
- specify "should validate acceptance_of with allow_nil => false" do
190
- @c.validates_acceptance_of :value, :allow_nil => false
191
- @m.should_not be_valid
192
- end
193
-
194
- specify "should validate confirmation_of" do
195
- @c.send(:attr_accessor, :value_confirmation)
196
- @c.validates_confirmation_of :value
197
-
198
- @m.value = 'blah'
199
- @m.should_not be_valid
200
-
201
- @m.value_confirmation = 'blah'
202
- @m.should be_valid
203
- end
204
-
205
- specify "should validate format_of" do
206
- @c.validates_format_of :value, :with => /.+_.+/
207
- @m.value = 'abc_'
208
- @m.should_not be_valid
209
- @m.value = 'abc_def'
210
- @m.should be_valid
211
- end
212
-
213
- specify "should raise for validate_format_of without regexp" do
214
- proc {@c.validates_format_of :value}.should raise_error(Sequel::Error)
215
- proc {@c.validates_format_of :value, :with => :blah}.should raise_error(Sequel::Error)
216
- end
217
-
218
- specify "should validate length_of with maximum" do
219
- @c.validates_length_of :value, :maximum => 5
220
- @m.should_not be_valid
221
- @m.value = '12345'
222
- @m.should be_valid
223
- @m.value = '123456'
224
- @m.should_not be_valid
225
- end
226
-
227
- specify "should validate length_of with minimum" do
228
- @c.validates_length_of :value, :minimum => 5
229
- @m.should_not be_valid
230
- @m.value = '12345'
231
- @m.should be_valid
232
- @m.value = '1234'
233
- @m.should_not be_valid
234
- end
235
-
236
- specify "should validate length_of with within" do
237
- @c.validates_length_of :value, :within => 2..5
238
- @m.should_not be_valid
239
- @m.value = '12345'
240
- @m.should be_valid
241
- @m.value = '1'
242
- @m.should_not be_valid
243
- @m.value = '123456'
244
- @m.should_not be_valid
245
- end
246
-
247
- specify "should validate length_of with is" do
248
- @c.validates_length_of :value, :is => 3
249
- @m.should_not be_valid
250
- @m.value = '123'
251
- @m.should be_valid
252
- @m.value = '12'
253
- @m.should_not be_valid
254
- @m.value = '1234'
255
- @m.should_not be_valid
256
- end
257
-
258
- specify "should validate length_of with allow_nil" do
259
- @c.validates_length_of :value, :is => 3, :allow_nil => true
260
- @m.should be_valid
261
- end
262
-
263
- specify "should validate numericality_of" do
264
- @c.validates_numericality_of :value
265
- @m.value = 'blah'
266
- @m.should_not be_valid
267
- @m.value = '123'
268
- @m.should be_valid
269
- @m.value = '123.1231'
270
- @m.should be_valid
271
- end
272
-
273
- specify "should validate numericality_of with only_integer" do
274
- @c.validates_numericality_of :value, :only_integer => true
275
- @m.value = 'blah'
276
- @m.should_not be_valid
277
- @m.value = '123'
278
- @m.should be_valid
279
- @m.value = '123.1231'
280
- @m.should_not be_valid
281
- end
282
-
283
- specify "should validate presence_of" do
284
- @c.validates_presence_of :value
285
- @m.should_not be_valid
286
- @m.value = ''
287
- @m.should_not be_valid
288
- @m.value = 1234
289
- @m.should be_valid
290
- end
291
- end
292
-
293
3
  describe Sequel::Model, "Validations" do
294
4
 
295
5
  before(:all) do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sequel_model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: 0.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sharon Rosner
@@ -9,9 +9,18 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2008-01-21 00:00:00 +02:00
12
+ date: 2008-01-24 00:00:00 +02:00
13
13
  default_executable:
14
14
  dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: assistance
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.1.2
23
+ version:
15
24
  - !ruby/object:Gem::Dependency
16
25
  name: sequel_core
17
26
  version_requirement:
@@ -19,7 +28,7 @@ dependencies:
19
28
  requirements:
20
29
  - - ">="
21
30
  - !ruby/object:Gem::Version
22
- version: "0.5"
31
+ version: "1.0"
23
32
  version:
24
33
  description: Lightweight ORM for Ruby
25
34
  email: ciconia@gmail.com