treequel 1.3.0pre384 → 1.3.0
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 +46 -1
- data/History.md +13 -1
- data/Rakefile +1 -0
- data/lib/treequel/branch.rb +1 -1
- data/lib/treequel/exceptions.rb +26 -1
- data/lib/treequel/model/errors.rb +4 -4
- data/lib/treequel/model/schemavalidations.rb +9 -0
- data/lib/treequel/model.rb +72 -17
- data/spec/treequel/branch_spec.rb +9 -0
- data/spec/treequel/model/errors_spec.rb +2 -2
- data/spec/treequel/model/schemavalidations_spec.rb +16 -3
- data/spec/treequel/model_spec.rb +149 -3
- data.tar.gz.sig +0 -0
- metadata +20 -4
- metadata.gz.sig +0 -0
data/ChangeLog
CHANGED
@@ -1,8 +1,53 @@
|
|
1
|
+
2011-01-12 Michael Granger <ged@FaerieMUD.org>
|
2
|
+
|
3
|
+
* lib/treequel/model.rb:
|
4
|
+
Always initialize the dirty flag for Treequel::Model objects.
|
5
|
+
[4a75d892a89d] [github/master, master, tip]
|
6
|
+
|
7
|
+
* lib/treequel/branch.rb, spec/treequel/branch_spec.rb:
|
8
|
+
Fixed a bug in Treequel::Branch that caused non-schema attribute
|
9
|
+
fetches through the index operator to pollute the values cache,
|
10
|
+
which in turn caused Treequel::Model schema validations to fail.
|
11
|
+
[8cee4f66c05d]
|
12
|
+
|
13
|
+
* manual/src/models.page:
|
14
|
+
More work on the manual
|
15
|
+
[1652fd0874ab]
|
16
|
+
|
17
|
+
* lib/treequel/model.rb, spec/treequel/model_spec.rb:
|
18
|
+
Made Treequel::Model#validate run the
|
19
|
+
before_validation/after_validation hooks
|
20
|
+
[55d6b5f34c2b]
|
21
|
+
|
22
|
+
2011-01-11 Michael Granger <ged@FaerieMUD.org>
|
23
|
+
|
24
|
+
* lib/treequel/exceptions.rb, lib/treequel/model.rb,
|
25
|
+
manual/src/models.page, spec/treequel/model_spec.rb:
|
26
|
+
Worked on model hooks and validations; added specs, raise exceptions
|
27
|
+
by default, started adding info to the manual.
|
28
|
+
[2454e05f1302]
|
29
|
+
|
30
|
+
* lib/treequel/model/errors.rb,
|
31
|
+
lib/treequel/model/schemavalidations.rb,
|
32
|
+
spec/treequel/model/errors_spec.rb,
|
33
|
+
spec/treequel/model/schemavalidations_spec.rb:
|
34
|
+
Adding structural-objectClass validation
|
35
|
+
[1b9bd6587cf0]
|
36
|
+
|
37
|
+
* Rakefile:
|
38
|
+
Add sysexits to the list of dev dependencies
|
39
|
+
[54e20f994ef4]
|
40
|
+
|
41
|
+
* Manifest.txt:
|
42
|
+
Rearranged the release manifest a bit to make it easier to check
|
43
|
+
against the source in TextMate
|
44
|
+
[fd358623589a]
|
45
|
+
|
1
46
|
2011-01-10 Michael Granger <ged@FaerieMUD.org>
|
2
47
|
|
3
48
|
* Rakefile:
|
4
49
|
Cleaning up dependencies, adding a note to the post-install
|
5
|
-
[633dfb8ea77a]
|
50
|
+
[633dfb8ea77a]
|
6
51
|
|
7
52
|
* Manifest.txt:
|
8
53
|
Adding the ChangeLog to the release manifest
|
data/History.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
## 1.3.0 [2011-01-
|
1
|
+
## 1.3.0 [2011-01-13] Michael Granger <ged@FaerieMUD.org>
|
2
2
|
|
3
3
|
Enhancements:
|
4
4
|
|
@@ -12,6 +12,17 @@ Enhancements:
|
|
12
12
|
- Treequel::Model#errors
|
13
13
|
- Treequel::Model#revert
|
14
14
|
- Treequel::Model#modified?
|
15
|
+
- Treequel::Model#after_initialize
|
16
|
+
- Treequel::Model#before_validation
|
17
|
+
- Treequel::Model#after_validation
|
18
|
+
- Treequel::Model#before_save
|
19
|
+
- Treequel::Model#before_create
|
20
|
+
- Treequel::Model#before_update
|
21
|
+
- Treequel::Model#after_create
|
22
|
+
- Treequel::Model#after_update
|
23
|
+
- Treequel::Model#after_save
|
24
|
+
- Treequel::Model#before_destroy
|
25
|
+
- Treequel::Model#after_destroy
|
15
26
|
New classes:
|
16
27
|
- Treequel::Model::Errors
|
17
28
|
- Treequel::ValidationFailed
|
@@ -36,6 +47,7 @@ Bugfixes:
|
|
36
47
|
- Check for explicit nil DN in .new
|
37
48
|
- Check for nil parent_dn in #parent
|
38
49
|
- Use 'top' instead of :top as objectClass default
|
50
|
+
- Don't cache attempts to fetch invalid attributes
|
39
51
|
|
40
52
|
|
41
53
|
## 1.2.2 [2010-12-14] Michael Granger <ged@FaerieMUD.org>
|
data/Rakefile
CHANGED
data/lib/treequel/branch.rb
CHANGED
data/lib/treequel/exceptions.rb
CHANGED
@@ -40,9 +40,34 @@ module Treequel
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
######
|
44
|
+
public
|
45
|
+
######
|
46
|
+
|
43
47
|
# @return [Treequel::Model::Errors] the validation errors
|
44
48
|
attr_reader :errors
|
45
|
-
|
49
|
+
|
50
|
+
end # class ValidationFailed
|
51
|
+
|
52
|
+
### Exception class raised when a before_* hooks returns a false value when saving
|
53
|
+
### or destroying a Treequel::Model object.
|
54
|
+
class BeforeHookFailed < Treequel::ModelError
|
55
|
+
|
56
|
+
### Create a new Treequel::BeforeHookFailed exception that indicates that the
|
57
|
+
### specified +hook+ returned a false value.
|
58
|
+
def initialize( hook )
|
59
|
+
@hook = hook.to_sym
|
60
|
+
super "The 'before' hook failed when trying to %s" % [ hook ]
|
61
|
+
end
|
62
|
+
|
63
|
+
######
|
64
|
+
public
|
65
|
+
######
|
66
|
+
|
67
|
+
# The hook that failed
|
68
|
+
attr_reader :hook
|
69
|
+
|
70
|
+
end # class BeforeHookFailed
|
46
71
|
|
47
72
|
end # module Treequel
|
48
73
|
|
@@ -47,11 +47,11 @@ class Treequel::Model::Errors < ::Hash
|
|
47
47
|
end
|
48
48
|
|
49
49
|
|
50
|
-
### Adds an error for the given +
|
51
|
-
### @param [Symbol, #to_sym]
|
50
|
+
### Adds an error for the given +subject+.
|
51
|
+
### @param [Symbol, #to_sym] subject the subject of the error
|
52
52
|
### @param [String] message the description of the error condition
|
53
|
-
def add(
|
54
|
-
self[
|
53
|
+
def add( subject, message )
|
54
|
+
self[ subject ] << message
|
55
55
|
end
|
56
56
|
|
57
57
|
|
@@ -12,12 +12,21 @@ module Treequel::Model::SchemaValidations
|
|
12
12
|
def validate( options={} )
|
13
13
|
return unless options[:with_schema]
|
14
14
|
|
15
|
+
self.validate_structural_objectclass
|
15
16
|
self.validate_must_attributes
|
16
17
|
self.validate_may_attributes
|
17
18
|
self.validate_attribute_syntax
|
18
19
|
end
|
19
20
|
|
20
21
|
|
22
|
+
### Ensure that the object has at least one structural objectClass.
|
23
|
+
def validate_structural_objectclass
|
24
|
+
unless self.object_classes.any? {|oc| oc.structural? }
|
25
|
+
self.errors.add( :entry, "must have at least one structural objectClass" )
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
|
21
30
|
### Validate that all attributes that MUST be included according to the entry's
|
22
31
|
### objectClasses have at least one value.
|
23
32
|
def validate_must_attributes
|
data/lib/treequel/model.rb
CHANGED
@@ -53,6 +53,16 @@ class Treequel::Model < Treequel::Branch
|
|
53
53
|
:with_schema => true,
|
54
54
|
}
|
55
55
|
|
56
|
+
# Defaults for #save options
|
57
|
+
DEFAULT_SAVE_OPTIONS = {
|
58
|
+
:raise_on_failure => true,
|
59
|
+
}
|
60
|
+
|
61
|
+
# Defaults for #destroy options
|
62
|
+
DEFAULT_DESTROY_OPTIONS = {
|
63
|
+
:raise_on_failure => true,
|
64
|
+
}
|
65
|
+
|
56
66
|
|
57
67
|
#################################################################
|
58
68
|
### C L A S S M E T H O D S
|
@@ -191,6 +201,7 @@ class Treequel::Model < Treequel::Branch
|
|
191
201
|
def initialize( directory, dn, entry=nil, from_directory=false )
|
192
202
|
if from_directory
|
193
203
|
super( directory, dn, entry )
|
204
|
+
@dirty = false
|
194
205
|
else
|
195
206
|
super( directory, dn )
|
196
207
|
@values = entry ? symbolify_keys( entry ) : {}
|
@@ -218,6 +229,7 @@ class Treequel::Model < Treequel::Branch
|
|
218
229
|
HOOKS.each do |hook|
|
219
230
|
define_method( hook ) do |*args|
|
220
231
|
self.log.debug "#{hook} default hook called."
|
232
|
+
true
|
221
233
|
end
|
222
234
|
end
|
223
235
|
|
@@ -321,31 +333,36 @@ class Treequel::Model < Treequel::Branch
|
|
321
333
|
### Return +true+ if the model object passes all of its validations.
|
322
334
|
def valid?( opts={} )
|
323
335
|
self.errors.clear
|
324
|
-
|
325
|
-
return false if self.before_validation == false
|
326
|
-
self.validate
|
327
|
-
self.after_validation
|
328
|
-
|
336
|
+
self.validate( opts )
|
329
337
|
return self.errors.empty? ? true : false
|
330
338
|
end
|
331
339
|
|
332
340
|
|
333
|
-
### Validate the object with the specified +options+.
|
341
|
+
### Validate the object with the specified +options+. Appending validation errors onto
|
342
|
+
### the #errors object.
|
334
343
|
### @param [Hash] options options for validation.
|
335
344
|
### @option options [Boolean] :with_schema whether or not to run the schema validations
|
336
345
|
def validate( options={} )
|
337
346
|
options = DEFAULT_VALIDATION_OPTIONS.merge( options )
|
338
347
|
|
348
|
+
self.before_validation or
|
349
|
+
raise Treequel::BeforeHookFailed, :validation
|
339
350
|
self.errors.add( :objectClass, 'must have at least one' ) if self.object_classes.empty?
|
340
351
|
|
341
352
|
super( options )
|
353
|
+
self.after_validation
|
342
354
|
end
|
343
355
|
|
344
356
|
|
345
357
|
### Write any pending changes in the model object to the directory.
|
346
|
-
|
358
|
+
### @param [Hash] opts save options
|
359
|
+
### @option opts [Boolean] :raise_on_failure (true) raise a Treequel::ValidationFailed or
|
360
|
+
### Treequel::BeforeHookFailed if either the validations or before_{save,create}
|
361
|
+
def save( opts={} )
|
362
|
+
opts = DEFAULT_SAVE_OPTIONS.merge( opts )
|
363
|
+
|
347
364
|
self.log.debug "Saving %s..." % [ self.dn ]
|
348
|
-
raise Treequel::ValidationFailed, self.errors unless self.valid?
|
365
|
+
raise Treequel::ValidationFailed, self.errors unless self.valid?( opts )
|
349
366
|
self.log.debug " validation succeeded."
|
350
367
|
|
351
368
|
unless mods = self.modifications
|
@@ -354,24 +371,25 @@ class Treequel::Model < Treequel::Branch
|
|
354
371
|
end
|
355
372
|
|
356
373
|
self.log.debug " got %d modifications." % [ mods.length ]
|
357
|
-
self.before_save( mods ) or
|
374
|
+
self.before_save( mods ) or
|
375
|
+
raise Treequel::BeforeHookFailed, :save
|
358
376
|
|
359
377
|
if self.exists?
|
360
|
-
self.
|
361
|
-
self.before_update( mods ) or return nil
|
362
|
-
self.modify( mods )
|
363
|
-
self.after_update( mods )
|
364
|
-
|
378
|
+
self.update( mods )
|
365
379
|
else
|
366
|
-
self.log.debug " entry doesn't exist: creating..."
|
367
|
-
self.before_create( mods ) or return nil
|
368
380
|
self.create( mods )
|
369
|
-
self.after_create( mods )
|
370
381
|
end
|
371
382
|
|
372
383
|
self.after_save( mods )
|
373
384
|
|
374
385
|
return true
|
386
|
+
rescue Treequel::BeforeHookFailed => err
|
387
|
+
self.log.info( err.message )
|
388
|
+
raise if opts[:raise_on_failure]
|
389
|
+
rescue Treequel::ValidationFailed => err
|
390
|
+
self.log.error( "Save aborted: validation failed." )
|
391
|
+
self.log.info( err.errors.full_messages.join(', ') )
|
392
|
+
raise if opts[:raise_on_failure]
|
375
393
|
end
|
376
394
|
|
377
395
|
|
@@ -437,6 +455,21 @@ class Treequel::Model < Treequel::Branch
|
|
437
455
|
end
|
438
456
|
|
439
457
|
|
458
|
+
### Like #delete, but runs destroy hooks before and after deleting.
|
459
|
+
def destroy( opts={} )
|
460
|
+
opts = DEFAULT_DESTROY_OPTIONS.merge( opts )
|
461
|
+
|
462
|
+
self.before_destroy or raise Treequel::BeforeHookFailed, :destroy
|
463
|
+
self.delete
|
464
|
+
self.after_destroy
|
465
|
+
|
466
|
+
return true
|
467
|
+
rescue Treequel::BeforeHookFailed => err
|
468
|
+
self.log.info( err.message )
|
469
|
+
raise if opts[:raise_on_failure]
|
470
|
+
end
|
471
|
+
|
472
|
+
|
440
473
|
### Override Branch#search to inject the 'objectClass' attribute to the
|
441
474
|
### selected attribute list if there is one.
|
442
475
|
def search( scope=:subtree, filter='(objectClass=*)', parameters={}, &block )
|
@@ -493,6 +526,28 @@ class Treequel::Model < Treequel::Branch
|
|
493
526
|
end
|
494
527
|
|
495
528
|
|
529
|
+
### Update the object's entry with the specified +mods+.
|
530
|
+
### @param [Array<LDAP::Mod>] mods the modifications to make
|
531
|
+
def update( mods )
|
532
|
+
self.log.debug " entry already exists: updating..."
|
533
|
+
self.before_update( mods ) or
|
534
|
+
raise Treequel::BeforeHookFailed, :update
|
535
|
+
self.modify( mods )
|
536
|
+
self.after_update( mods )
|
537
|
+
end
|
538
|
+
|
539
|
+
|
540
|
+
### Create the entry for the object, using the specified +mods+ to set the attributes.
|
541
|
+
### @param [Array<LDAP::Mod>] mods the modifications to set attributes
|
542
|
+
def create( mods )
|
543
|
+
self.log.debug " entry doesn't exist: creating..."
|
544
|
+
self.before_create( mods ) or
|
545
|
+
raise Treequel::BeforeHookFailed, :create
|
546
|
+
super( mods )
|
547
|
+
self.after_create( mods )
|
548
|
+
end
|
549
|
+
|
550
|
+
|
496
551
|
### Delete specific key/value +pairs+ from the entry.
|
497
552
|
### @param [Hash] pairs key/value pairs to delete from the entry.
|
498
553
|
def delete_specific_values( pairs )
|
@@ -801,6 +801,15 @@ describe Treequel::Branch do
|
|
801
801
|
2.times { @branch[ :description ] }
|
802
802
|
end
|
803
803
|
|
804
|
+
it "doesn't cache nil values that don't correspond to an attribute type in the schema" do
|
805
|
+
@conn.should_receive( :search_ext2 ).
|
806
|
+
with( TEST_HOSTS_DN, LDAP::LDAP_SCOPE_BASE, "(objectClass=*)" ).
|
807
|
+
and_return([ @entry ])
|
808
|
+
|
809
|
+
@branch[ :string_beans ]
|
810
|
+
@branch.instance_variable_get( :@values ).should_not have_key( :string_beans )
|
811
|
+
end
|
812
|
+
|
804
813
|
it "freezes the values fetched from its entry by default to prevent accidental " +
|
805
814
|
"in-place modification" do
|
806
815
|
@conn.should_receive( :search_ext2 ).
|
@@ -47,8 +47,8 @@ describe Treequel::Model::Errors do
|
|
47
47
|
|
48
48
|
it "knows how many errors there are" do
|
49
49
|
@errors.add( :l, "is not valid" )
|
50
|
-
@errors.add( :description, "must " )
|
51
|
-
@errors.add( :description, "must have at least one
|
50
|
+
@errors.add( :description, "must be this tall to ride" )
|
51
|
+
@errors.add( :description, "must have at least one value" )
|
52
52
|
|
53
53
|
@errors.count.should == 3
|
54
54
|
end
|
@@ -45,10 +45,23 @@ describe Treequel::Model::SchemaValidations do
|
|
45
45
|
# MUST ( sn $ cn )
|
46
46
|
# MAY ( userPassword $ telephoneNumber $ seeAlso $ description ) )
|
47
47
|
|
48
|
+
it "adds an error if the object doesn't have at least one structural objectClass" do
|
49
|
+
@conn.stub( :search_ext2 ).and_return( [] )
|
50
|
+
@modelobj.object_class = ['ipHost', 'ieee802device']
|
51
|
+
@modelobj.cn = 'testhost'
|
52
|
+
@modelobj.ip_host_number = '127.0.0.1'
|
53
|
+
|
54
|
+
@modelobj.should_not be_valid()
|
55
|
+
@modelobj.errors.should have( 1 ).member
|
56
|
+
@modelobj.errors.full_messages.
|
57
|
+
should include( 'entry must have at least one structural objectClass' )
|
58
|
+
end
|
59
|
+
|
48
60
|
it "adds an error if the object doesn't have at least one value for all of its MUST attributes" do
|
49
61
|
@conn.stub( :search_ext2 ).and_return( [] )
|
50
62
|
@modelobj.object_class = 'person'
|
51
|
-
|
63
|
+
|
64
|
+
@modelobj.should_not be_valid()
|
52
65
|
@modelobj.errors.should have( 2 ).members
|
53
66
|
@modelobj.errors.full_messages.should include( 'cn MUST have at least one value' )
|
54
67
|
@modelobj.errors.full_messages.should include( 'sn MUST have at least one value' )
|
@@ -66,7 +79,7 @@ describe Treequel::Model::SchemaValidations do
|
|
66
79
|
|
67
80
|
# ..then remove the objectclass that grants it and validate
|
68
81
|
@modelobj.object_class -= ['inetOrgPerson']
|
69
|
-
@modelobj.
|
82
|
+
@modelobj.should_not be_valid()
|
70
83
|
|
71
84
|
@modelobj.errors.full_messages.
|
72
85
|
should == [%{displayName is not allowed by entry's objectClasses}]
|
@@ -92,7 +105,7 @@ describe Treequel::Model::SchemaValidations do
|
|
92
105
|
@modelobj.uid_number = "something that's not a number"
|
93
106
|
@modelobj.gid_number = "also not a number"
|
94
107
|
|
95
|
-
@modelobj.
|
108
|
+
@modelobj.should_not be_valid()
|
96
109
|
|
97
110
|
@modelobj.errors.should have( 2 ).members
|
98
111
|
@modelobj.errors.full_messages.should include( "uidNumber isn't a valid Integer value" )
|
data/spec/treequel/model_spec.rb
CHANGED
@@ -446,7 +446,53 @@ describe Treequel::Model do
|
|
446
446
|
end
|
447
447
|
|
448
448
|
it "knows if any validation errors have been encountered" do
|
449
|
-
@obj.errors.should be_a(
|
449
|
+
@obj.errors.should be_a( Treequel::Model::Errors )
|
450
|
+
end
|
451
|
+
|
452
|
+
it "can delete its entry with callbacks" do
|
453
|
+
class << @obj; attr_reader :callbacks; end
|
454
|
+
@obj.instance_variable_set( :@callbacks, [] )
|
455
|
+
def @obj.before_destroy
|
456
|
+
self.callbacks << :before_destroy
|
457
|
+
end
|
458
|
+
def @obj.after_destroy
|
459
|
+
self.callbacks << :after_destroy
|
460
|
+
end
|
461
|
+
|
462
|
+
@conn.should_receive( :delete ).with( @obj.dn )
|
463
|
+
|
464
|
+
@obj.destroy
|
465
|
+
@obj.callbacks.should == [ :before_destroy, :after_destroy ]
|
466
|
+
end
|
467
|
+
|
468
|
+
it "doesn't delete its entry if the destroy callback returns something falseish" do
|
469
|
+
def @obj.before_destroy
|
470
|
+
false
|
471
|
+
end
|
472
|
+
def @obj.after_destroy
|
473
|
+
fail "shouldn't call the after_destroy hook, either"
|
474
|
+
end
|
475
|
+
|
476
|
+
@conn.should_not_receive( :delete )
|
477
|
+
|
478
|
+
expect {
|
479
|
+
@obj.destroy
|
480
|
+
}.to raise_error( Treequel::BeforeHookFailed, /destroy/i )
|
481
|
+
end
|
482
|
+
|
483
|
+
it "doesn't raise a BeforeHookFailed if destroyed without :raise_on_failure" do
|
484
|
+
def @obj.before_destroy
|
485
|
+
false
|
486
|
+
end
|
487
|
+
|
488
|
+
@conn.should_not_receive( :delete )
|
489
|
+
|
490
|
+
result = nil
|
491
|
+
expect {
|
492
|
+
result = @obj.destroy( :raise_on_failure => false )
|
493
|
+
}.to_not raise_error()
|
494
|
+
|
495
|
+
result.should be_false()
|
450
496
|
end
|
451
497
|
|
452
498
|
|
@@ -501,6 +547,54 @@ describe Treequel::Model do
|
|
501
547
|
@obj.save
|
502
548
|
end
|
503
549
|
|
550
|
+
|
551
|
+
it "calls update hooks when saved" do
|
552
|
+
class << @obj; attr_reader :callbacks; end
|
553
|
+
@obj.instance_variable_set( :@callbacks, [] )
|
554
|
+
def @obj.before_update( mods )
|
555
|
+
self.callbacks << :before_update
|
556
|
+
end
|
557
|
+
def @obj.after_update( mods )
|
558
|
+
self.callbacks << :after_update
|
559
|
+
end
|
560
|
+
|
561
|
+
@conn.should_receive( :modify )
|
562
|
+
|
563
|
+
@obj.save
|
564
|
+
@obj.callbacks.should == [ :before_update, :after_update ]
|
565
|
+
end
|
566
|
+
|
567
|
+
it "doesn't modify its entry if the before_update callback returns something falseish" do
|
568
|
+
def @obj.before_update( mods )
|
569
|
+
false
|
570
|
+
end
|
571
|
+
def @obj.after_update( mods )
|
572
|
+
fail "shouldn't call the after_update hook, either"
|
573
|
+
end
|
574
|
+
|
575
|
+
@conn.should_not_receive( :modify )
|
576
|
+
|
577
|
+
expect {
|
578
|
+
@obj.save
|
579
|
+
}.to raise_error( Treequel::BeforeHookFailed, /update/i )
|
580
|
+
end
|
581
|
+
|
582
|
+
it "doesn't raise a BeforeHookFailed if saved without :raise_on_failure" do
|
583
|
+
def @obj.before_update( mods )
|
584
|
+
false
|
585
|
+
end
|
586
|
+
|
587
|
+
@conn.stub( :search_ext2 ).with( @obj.dn, LDAP::LDAP_SCOPE_BASE, "(objectClass=*)" ).
|
588
|
+
and_return( [] )
|
589
|
+
@conn.should_not_receive( :modify )
|
590
|
+
|
591
|
+
result = nil
|
592
|
+
expect {
|
593
|
+
result = @obj.save( :raise_on_failure => false )
|
594
|
+
}.to_not raise_error()
|
595
|
+
|
596
|
+
result.should be_false()
|
597
|
+
end
|
504
598
|
end
|
505
599
|
|
506
600
|
|
@@ -593,11 +687,11 @@ describe Treequel::Model do
|
|
593
687
|
|
594
688
|
it "creates the entry in the directory when saved" do
|
595
689
|
@conn.stub( :search_ext2 ).
|
596
|
-
with(
|
690
|
+
with( @obj.dn, LDAP::LDAP_SCOPE_BASE, '(objectClass=*)').
|
597
691
|
and_return( [] )
|
598
692
|
|
599
693
|
@conn.should_receive( :add ).
|
600
|
-
with(
|
694
|
+
with( @obj.dn, [
|
601
695
|
ldap_mod_add("cn", "James"),
|
602
696
|
ldap_mod_add("displayName", "J. Random Hacker"),
|
603
697
|
ldap_mod_add("gidNumber", "200"),
|
@@ -612,6 +706,58 @@ describe Treequel::Model do
|
|
612
706
|
@obj.save
|
613
707
|
end
|
614
708
|
|
709
|
+
it "calls creation hooks when saved" do
|
710
|
+
class << @obj; attr_reader :callbacks; end
|
711
|
+
@obj.instance_variable_set( :@callbacks, [] )
|
712
|
+
def @obj.before_create( mods )
|
713
|
+
self.callbacks << :before_create
|
714
|
+
end
|
715
|
+
def @obj.after_create( mods )
|
716
|
+
self.callbacks << :after_create
|
717
|
+
end
|
718
|
+
|
719
|
+
@conn.stub( :search_ext2 ).with( @obj.dn, LDAP::LDAP_SCOPE_BASE, "(objectClass=*)" ).
|
720
|
+
and_return( [] )
|
721
|
+
@conn.should_receive( :add )
|
722
|
+
|
723
|
+
@obj.save
|
724
|
+
@obj.callbacks.should == [ :before_create, :after_create ]
|
725
|
+
end
|
726
|
+
|
727
|
+
it "doesn't add its entry if the before_create callback returns something falseish" do
|
728
|
+
def @obj.before_create( mods )
|
729
|
+
false
|
730
|
+
end
|
731
|
+
def @obj.after_create( mods )
|
732
|
+
fail "shouldn't call the after_create hook, either"
|
733
|
+
end
|
734
|
+
|
735
|
+
@conn.stub( :search_ext2 ).with( @obj.dn, LDAP::LDAP_SCOPE_BASE, "(objectClass=*)" ).
|
736
|
+
and_return( [] )
|
737
|
+
@conn.should_not_receive( :add )
|
738
|
+
|
739
|
+
expect {
|
740
|
+
@obj.save
|
741
|
+
}.to raise_error( Treequel::BeforeHookFailed, /create/i )
|
742
|
+
end
|
743
|
+
|
744
|
+
it "doesn't raise a BeforeHookFailed if saved without :raise_on_failure" do
|
745
|
+
def @obj.before_create( mods )
|
746
|
+
false
|
747
|
+
end
|
748
|
+
|
749
|
+
@conn.stub( :search_ext2 ).with( @obj.dn, LDAP::LDAP_SCOPE_BASE, "(objectClass=*)" ).
|
750
|
+
and_return( [] )
|
751
|
+
@conn.should_not_receive( :add )
|
752
|
+
|
753
|
+
result = nil
|
754
|
+
expect {
|
755
|
+
result = @obj.save( :raise_on_failure => false )
|
756
|
+
}.to_not raise_error()
|
757
|
+
|
758
|
+
result.should be_false()
|
759
|
+
end
|
760
|
+
|
615
761
|
end
|
616
762
|
|
617
763
|
end
|
data.tar.gz.sig
CHANGED
Binary file
|
metadata
CHANGED
@@ -7,7 +7,7 @@ version: !ruby/object:Gem::Version
|
|
7
7
|
- 1
|
8
8
|
- 3
|
9
9
|
- 0
|
10
|
-
version: 1.3.
|
10
|
+
version: 1.3.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Michael Granger
|
@@ -36,7 +36,7 @@ cert_chain:
|
|
36
36
|
cmlhXe46pZNJgWKbxZah85jIjx95hR8vOI+NAM5iH9kOqK13DrxacTKPhqj5PjwF
|
37
37
|
-----END CERTIFICATE-----
|
38
38
|
|
39
|
-
date: 2011-01-
|
39
|
+
date: 2011-01-13 00:00:00 -08:00
|
40
40
|
default_executable:
|
41
41
|
dependencies:
|
42
42
|
- !ruby/object:Gem::Dependency
|
@@ -136,9 +136,25 @@ dependencies:
|
|
136
136
|
type: :development
|
137
137
|
version_requirements: *id006
|
138
138
|
- !ruby/object:Gem::Dependency
|
139
|
-
name:
|
139
|
+
name: sysexits
|
140
140
|
prerelease: false
|
141
141
|
requirement: &id007 !ruby/object:Gem::Requirement
|
142
|
+
none: false
|
143
|
+
requirements:
|
144
|
+
- - ~>
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
hash: 19
|
147
|
+
segments:
|
148
|
+
- 1
|
149
|
+
- 0
|
150
|
+
- 2
|
151
|
+
version: 1.0.2
|
152
|
+
type: :development
|
153
|
+
version_requirements: *id007
|
154
|
+
- !ruby/object:Gem::Dependency
|
155
|
+
name: hoe
|
156
|
+
prerelease: false
|
157
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
142
158
|
none: false
|
143
159
|
requirements:
|
144
160
|
- - ">="
|
@@ -150,7 +166,7 @@ dependencies:
|
|
150
166
|
- 0
|
151
167
|
version: 2.8.0
|
152
168
|
type: :development
|
153
|
-
version_requirements: *
|
169
|
+
version_requirements: *id008
|
154
170
|
description: |-
|
155
171
|
Treequel is an LDAP toolkit for Ruby. It is intended to allow quick, easy
|
156
172
|
access to LDAP directories in a manner consistent with LDAP's hierarchical,
|
metadata.gz.sig
CHANGED
Binary file
|