treequel 1.3.0pre384 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|