persistence 0.0.1.alpha → 0.0.1

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.
Files changed (138) hide show
  1. data/CHANGELOG.md +4 -0
  2. data/README.md +260 -17
  3. data/lib/namespaces.rb +55 -0
  4. data/lib/persistence.rb +38 -3
  5. data/lib/persistence/adapter/abstract.rb +22 -0
  6. data/lib/persistence/adapter/abstract/enable_disable.rb +107 -0
  7. data/lib/persistence/adapter/abstract/primary_key/id_property_string.rb +33 -0
  8. data/lib/persistence/adapter/abstract/primary_key/simple.rb +29 -0
  9. data/lib/persistence/adapter/mock.rb +9 -0
  10. data/lib/persistence/adapter/mock/adapter_interface.rb +102 -0
  11. data/lib/persistence/adapter/mock/bucket.rb +9 -0
  12. data/lib/persistence/adapter/mock/bucket/bucket_interface.rb +260 -0
  13. data/lib/persistence/adapter/mock/bucket/index.rb +9 -0
  14. data/lib/persistence/adapter/mock/bucket/index/index_interface.rb +155 -0
  15. data/lib/persistence/adapter/mock/cursor.rb +9 -0
  16. data/lib/persistence/adapter/mock/cursor/cursor_interface.rb +238 -0
  17. data/lib/persistence/cursor.rb +11 -0
  18. data/lib/persistence/cursor/atomic.rb +110 -0
  19. data/lib/persistence/cursor/cursor_interface.rb +337 -0
  20. data/lib/persistence/exception/block_required.rb +7 -0
  21. data/lib/persistence/exception/conflicting_index_already_declared.rb +7 -0
  22. data/lib/persistence/exception/duplicate_violates_unique_index.rb +7 -0
  23. data/lib/persistence/exception/explicit_index_required.rb +7 -0
  24. data/lib/persistence/exception/indexing_block_failed_to_generate_keys.rb +7 -0
  25. data/lib/persistence/exception/indexing_object_requires_keys.rb +7 -0
  26. data/lib/persistence/exception/key_value_required.rb +7 -0
  27. data/lib/persistence/exception/no_port_enabled.rb +7 -0
  28. data/lib/persistence/object.rb +21 -0
  29. data/lib/persistence/object/autodetermine.rb +74 -0
  30. data/lib/persistence/object/class_instance.rb +1884 -0
  31. data/lib/persistence/object/complex.rb +17 -0
  32. data/lib/persistence/object/complex/array.rb +14 -0
  33. data/lib/persistence/object/complex/array/class_instance.rb +37 -0
  34. data/lib/persistence/object/complex/array/object_instance.rb +54 -0
  35. data/lib/persistence/object/complex/attributes.rb +1808 -0
  36. data/lib/persistence/object/complex/attributes/attributes_array.rb +32 -0
  37. data/lib/persistence/object/complex/attributes/attributes_hash.rb +187 -0
  38. data/lib/persistence/object/complex/attributes/default_atomic_non_atomic.rb +102 -0
  39. data/lib/persistence/object/complex/attributes/hash_to_port.rb +40 -0
  40. data/lib/persistence/object/complex/class_and_object_instance.rb +132 -0
  41. data/lib/persistence/object/complex/class_instance.rb +267 -0
  42. data/lib/persistence/object/complex/complex_object.rb +111 -0
  43. data/lib/persistence/object/complex/hash.rb +14 -0
  44. data/lib/persistence/object/complex/hash/class_instance.rb +40 -0
  45. data/lib/persistence/object/complex/hash/object_instance.rb +63 -0
  46. data/lib/persistence/object/complex/index/attribute_index.rb +10 -0
  47. data/lib/persistence/object/complex/index/attribute_index/attribute_index_interface.rb +43 -0
  48. data/lib/persistence/object/complex/object_instance.rb +469 -0
  49. data/lib/persistence/object/flat.rb +17 -0
  50. data/lib/persistence/object/flat/class_instance.rb +34 -0
  51. data/lib/persistence/object/flat/file.rb +14 -0
  52. data/lib/persistence/object/flat/file/class_instance.rb +122 -0
  53. data/lib/persistence/object/flat/file/contents.rb +7 -0
  54. data/lib/persistence/object/flat/file/file_persistence.rb +147 -0
  55. data/lib/persistence/object/flat/file/object_instance.rb +116 -0
  56. data/lib/persistence/object/flat/file/path.rb +9 -0
  57. data/lib/persistence/object/flat/object_instance.rb +24 -0
  58. data/lib/persistence/object/index.rb +479 -0
  59. data/lib/persistence/object/index/block_index.rb +10 -0
  60. data/lib/persistence/object/index/block_index/block_index_interface.rb +110 -0
  61. data/lib/persistence/object/index/explicit_index.rb +10 -0
  62. data/lib/persistence/object/index/explicit_index/explicit_index_interface.rb +57 -0
  63. data/lib/persistence/object/index_hash.rb +40 -0
  64. data/lib/persistence/object/object_instance.rb +322 -0
  65. data/lib/persistence/object/parse_persistence_args.rb +145 -0
  66. data/lib/persistence/port.rb +9 -0
  67. data/lib/persistence/port/bucket.rb +9 -0
  68. data/lib/persistence/port/bucket/bucket_index.rb +9 -0
  69. data/lib/persistence/port/bucket/bucket_interface.rb +685 -0
  70. data/lib/persistence/port/controller.rb +263 -0
  71. data/lib/persistence/port/port_interface.rb +417 -0
  72. data/lib/requires.rb +146 -0
  73. data/spec/Integration_spec.rb +53 -0
  74. data/spec/Persistence_spec.rb +175 -0
  75. data/spec/example_objects.rb +6 -0
  76. data/spec/example_objects/complex_object.rb +7 -0
  77. data/spec/example_objects/complex_object/array_object.rb +7 -0
  78. data/spec/example_objects/complex_object/hash_object.rb +7 -0
  79. data/spec/example_objects/flat_object.rb +7 -0
  80. data/spec/example_objects/flat_object/file_object.rb +7 -0
  81. data/spec/persistence/adapter/enable_disable_spec.rb +29 -0
  82. data/spec/persistence/adapter/mock/cursor_spec.rb +64 -0
  83. data/spec/persistence/adapter/mock_helpers.rb +27 -0
  84. data/spec/persistence/adapter/mock_helpers/bucket.rb +10 -0
  85. data/spec/persistence/adapter/mock_helpers/integration/dictionary_hash.rb +4 -0
  86. data/spec/persistence/adapter/mock_helpers/integration/note.rb +18 -0
  87. data/spec/persistence/adapter/mock_helpers/integration/notes_array.rb +4 -0
  88. data/spec/persistence/adapter/mock_helpers/integration/user.rb +44 -0
  89. data/spec/persistence/adapter/mock_helpers/integration/user/address.rb +18 -0
  90. data/spec/persistence/adapter/mock_helpers/integration/user/dictionary_entry.rb +12 -0
  91. data/spec/persistence/adapter/mock_helpers/integration/user/sub_account.rb +15 -0
  92. data/spec/persistence/adapter/mock_helpers/object.rb +87 -0
  93. data/spec/persistence/adapter/mock_helpers/port.rb +21 -0
  94. data/spec/persistence/adapter/mock_spec.rb +211 -0
  95. data/spec/persistence/adapter/primary_key/id_property_string_spec.rb +27 -0
  96. data/spec/persistence/adapter/primary_key/simple_spec.rb +19 -0
  97. data/spec/persistence/adapter/spec_abstract/adapter_spec.rb +223 -0
  98. data/spec/persistence/adapter/spec_abstract/cursor_spec.rb +116 -0
  99. data/spec/persistence/cursor/atomic_spec.rb +86 -0
  100. data/spec/persistence/cursor/object_and_class_instance_spec.rb +73 -0
  101. data/spec/persistence/cursor_spec.rb +128 -0
  102. data/spec/persistence/object/complex/attributes/persistence_hash/array_instance_spec.rb +51 -0
  103. data/spec/persistence/object/complex/attributes/persistence_hash/hash_instance_spec.rb +56 -0
  104. data/spec/persistence/object/complex/attributes_spec.rb +1717 -0
  105. data/spec/persistence/object/complex/complex_spec.rb +922 -0
  106. data/spec/persistence/object/complex/index/attribute_index_spec.rb +76 -0
  107. data/spec/persistence/object/flat/bignum_spec.rb +33 -0
  108. data/spec/persistence/object/flat/class_instance_spec.rb +30 -0
  109. data/spec/persistence/object/flat/class_spec.rb +38 -0
  110. data/spec/persistence/object/flat/complex_spec.rb +36 -0
  111. data/spec/persistence/object/flat/false_class_spec.rb +34 -0
  112. data/spec/persistence/object/flat/file/class_instance_spec.rb +54 -0
  113. data/spec/persistence/object/flat/file/object_instance_spec.rb +143 -0
  114. data/spec/persistence/object/flat/file_spec.rb +64 -0
  115. data/spec/persistence/object/flat/fixnum_spec.rb +32 -0
  116. data/spec/persistence/object/flat/float_spec.rb +32 -0
  117. data/spec/persistence/object/flat/indexing_spec.rb +38 -0
  118. data/spec/persistence/object/flat/rational_spec.rb +33 -0
  119. data/spec/persistence/object/flat/regexp_spec.rb +32 -0
  120. data/spec/persistence/object/flat/string_spec.rb +34 -0
  121. data/spec/persistence/object/flat/symbol_spec.rb +32 -0
  122. data/spec/persistence/object/flat/true_class_spec.rb +32 -0
  123. data/spec/persistence/object/indexes/block_index_spec.rb +119 -0
  124. data/spec/persistence/object/indexes/explicit_index_spec.rb +112 -0
  125. data/spec/persistence/object/parse_persistence_args_spec.rb +65 -0
  126. data/spec/persistence/object_spec.rb +310 -0
  127. data/spec/persistence/port/bucket/bucket_interface_spec.rb +146 -0
  128. data/spec/persistence/port/bucket/index/bucket_index_spec.rb +67 -0
  129. data/spec/persistence/port/bucket_spec.rb +20 -0
  130. data/spec/persistence/port/controller_spec.rb +60 -0
  131. data/spec/persistence/port/port_interface_spec.rb +105 -0
  132. metadata +178 -21
  133. data/.gitignore +0 -17
  134. data/Gemfile +0 -4
  135. data/LICENSE +0 -22
  136. data/Rakefile +0 -2
  137. data/lib/persistence/version.rb +0 -3
  138. data/persistence.gemspec +0 -17
@@ -0,0 +1,64 @@
1
+
2
+ require_relative '../../../../lib/persistence.rb'
3
+
4
+ require_relative '../mock_helpers.rb'
5
+
6
+ describe ::Persistence::Adapter::Mock::Cursor do
7
+
8
+ before :all do
9
+
10
+ adapter = ::Persistence::Adapter::Mock.new
11
+
12
+ @objects = [ ]
13
+ @bucket = adapter.persistence_bucket( ::Persistence::Adapter::Abstract::Mock::Object.to_s )
14
+ ::Persistence::Adapter::Abstract::Mock::Object.instance_persistence_bucket = @bucket
15
+ @index = @bucket.create_index( :name, false )
16
+ 5.times do |this_number|
17
+ instance = ::Persistence::Adapter::Abstract::Mock::Object.new
18
+ instance.name = 'Number ' << this_number.to_s
19
+ @bucket.put_object!( instance )
20
+ @bucket.index( :name ).index_object_id( instance.persistence_id, instance.name )
21
+ @objects.push( instance )
22
+ end
23
+
24
+ end
25
+
26
+ ################
27
+ # first #
28
+ # get_key #
29
+ # persisted? #
30
+ # current #
31
+ # next #
32
+ ################
33
+
34
+ it 'it can return an object ID for persistence ID' do
35
+
36
+ # persistence id
37
+ bucket_cursor = @bucket.cursor
38
+ bucket_cursor.first.should == 0
39
+ bucket_cursor.persisted?( 1 ).should == true
40
+ bucket_cursor.current.should == 1
41
+ bucket_cursor.next.should == 2
42
+ bucket_cursor.next.should == 3
43
+ bucket_cursor.next.should == 4
44
+ bucket_cursor.persisted?( 3 ).should == true
45
+ bucket_cursor.persisted?( 2 ).should == true
46
+
47
+ end
48
+
49
+ it 'it can return an object ID for key' do
50
+
51
+ # index
52
+ index_cursor = @index.cursor
53
+ index_cursor.first.should == 0
54
+ index_cursor.persisted?( "Number 1" ).should == true
55
+ index_cursor.current_key.should == "Number 1"
56
+ index_cursor.current.should == 1
57
+ index_cursor.next_key.should == "Number 2"
58
+ index_cursor.next.should == 3
59
+ index_cursor.persisted?( "Number 2" ).should == true
60
+ index_cursor.next.should == 3
61
+
62
+ end
63
+
64
+ end
@@ -0,0 +1,27 @@
1
+
2
+ module ::Persistence::Adapter::Abstract::Mock
3
+ end
4
+
5
+ basepath = 'mock_helpers'
6
+
7
+ files = [
8
+
9
+ 'bucket',
10
+ 'object',
11
+ 'port',
12
+
13
+ 'integration/note',
14
+ 'integration/notes_array',
15
+ 'integration/dictionary_hash',
16
+ 'integration/user',
17
+ 'integration/user/address',
18
+ 'integration/user/dictionary_entry',
19
+ 'integration/user/sub_account'
20
+
21
+ ]
22
+
23
+ files.each do |this_file|
24
+ require_relative( File.join( basepath, this_file ) + '.rb' )
25
+ end
26
+
27
+ require_relative( basepath + '.rb' )
@@ -0,0 +1,10 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::Bucket
3
+
4
+ attr_accessor :name
5
+
6
+ def initialize( name )
7
+ @name = name
8
+ end
9
+
10
+ end
@@ -0,0 +1,4 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::DictionaryHash < ::Hash
3
+ include ::Persistence
4
+ end
@@ -0,0 +1,18 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::Note
3
+
4
+ include ::Persistence
5
+
6
+ attr_atomic_accessor :date, :subject, :content
7
+
8
+ def populate
9
+
10
+ self.date = ::Date.today.to_s
11
+
12
+ self.subject = 'Subject ' + rand( 100000000 ).to_s
13
+
14
+ self.content = 'Content ' + rand( 100000000 ).to_s
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,4 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::NotesArray < ::Array
3
+ include ::Persistence
4
+ end
@@ -0,0 +1,44 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::User
3
+
4
+ include ::Persistence
5
+
6
+ attr_atomic_accessor :username, :firstname, :lastname, :address, :alternate_address, :url, :notes, :dictionary, :subaccount
7
+
8
+ def populate
9
+
10
+ self.username = 'User ' + rand( 100000000 ).to_s
11
+ self.firstname = 'First ' + rand( 100000000 ).to_s
12
+ self.lastname = 'Last ' + rand( 100000000 ).to_s
13
+
14
+ # new visitors have an address
15
+ self.address = ::Persistence::Adapter::Abstract::Mock::User::Address.new
16
+
17
+ ::Persistence::Adapter::Abstract::Mock::User::Address.instance_persistence_bucket
18
+
19
+ # new visitors have an address
20
+ self.alternate_address = ::Persistence::Adapter::Abstract::Mock::User::Address.new
21
+
22
+ self.notes = ::Persistence::Adapter::Abstract::Mock::NotesArray.new
23
+
24
+ new_note = ::Persistence::Adapter::Abstract::Mock::Note.new
25
+ self.notes.push( new_note )
26
+
27
+ self.notes.persist!
28
+
29
+ self.dictionary = ::Persistence::Adapter::Abstract::Mock::DictionaryHash.new
30
+
31
+ new_entry = ::Persistence::Adapter::Abstract::Mock::User::DictionaryEntry.new
32
+ new_entry.populate
33
+ self.dictionary[ 'Some Word ' + rand( 100000000 ).to_s ] = new_entry
34
+ self.dictionary.persist!
35
+
36
+ # self.subaccount = ::Persistence::Adapter::Abstract::Mock::User::SubAccount.new( self )
37
+
38
+ if rand( 100000000 ) > 75000000
39
+ self.url = 'URL ' + rand( 100000000 ).to_s
40
+ end
41
+
42
+ end
43
+
44
+ end
@@ -0,0 +1,18 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::User::Address
3
+
4
+ include ::Persistence
5
+
6
+ attr_atomic_accessor :number, :street, :city, :state, :zipcode
7
+
8
+ def populate
9
+
10
+ self.number = rand( 100000000 )
11
+ self.street = 'Street ' + rand( 100000000 ).to_s
12
+ self.city = 'City ' + rand( 100000000 ).to_s
13
+ self.state = 'State ' + rand( 100000000 ).to_s
14
+ self.zipcode = rand( 10000 ).to_s
15
+
16
+ end
17
+
18
+ end
@@ -0,0 +1,12 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::User::DictionaryEntry < String
3
+
4
+ include ::Persistence
5
+
6
+ def populate
7
+
8
+ replace( 'Some Other Word ' + rand( 100000000 ).to_s )
9
+
10
+ end
11
+
12
+ end
@@ -0,0 +1,15 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::User::SubAccount
3
+
4
+ include ::Persistence
5
+
6
+ attr_atomic_accessor :username, :parent_user
7
+
8
+ def populate( parent_user = nil )
9
+
10
+ self.user = ::Persistence::Adapter::Abstract::Mock::User.new
11
+ self.parent_user = parent_user
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,87 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::Object
3
+
4
+ include ::CascadingConfiguration::Setting
5
+ attr_class_configuration :instance_persistence_bucket, :instance_persistence_port
6
+ attr_local_configuration :adapter, :persistence_bucket, :persistence_port
7
+ attr_instance_setting :persistence_id
8
+ attr_object_configuration :instance_persistence_bucket
9
+ include ::CascadingConfiguration::Hash
10
+
11
+ attr_accessor :value, :name
12
+
13
+ #######################################
14
+ # self.non_atomic_attribute_readers #
15
+ #######################################
16
+
17
+ def self.non_atomic_attribute_readers
18
+ return @non_atomic_attribute_readers ||= [ ]
19
+ end
20
+
21
+ ##############################
22
+ # persistence_hash_to_port #
23
+ ##############################
24
+
25
+ def persistence_hash_to_port
26
+ persistence_hash = { }
27
+ instance_variables.each do |this_variable|
28
+ persistence_hash[ this_variable ] = instance_variable_get( this_variable )
29
+ end
30
+ return persistence_hash
31
+ end
32
+
33
+ ######################
34
+ # persistence_port #
35
+ ######################
36
+
37
+ def persistence_port
38
+ return super || self.class.instance_persistence_port
39
+ end
40
+
41
+ ########################
42
+ # persistence_bucket #
43
+ ########################
44
+
45
+ def persistence_bucket
46
+ return super || self.class.instance_persistence_bucket
47
+ end
48
+
49
+ ###########################
50
+ # load_persistence_hash #
51
+ ###########################
52
+
53
+ def load_persistence_hash( port, persistence_hash )
54
+ persistence_hash.each do |this_variable, this_value|
55
+ instance_variable_set( this_variable, this_value )
56
+ end
57
+ end
58
+
59
+ ##################################
60
+ # non_atomic_attribute_readers #
61
+ ##################################
62
+
63
+ def non_atomic_attribute_readers
64
+ return [ ]
65
+ end
66
+
67
+ ##############################
68
+ # atomic_attribute_readers #
69
+ ##############################
70
+
71
+ def atomic_attribute_readers
72
+ return [ ]
73
+ end
74
+
75
+ ##############
76
+ # persist! #
77
+ ##############
78
+
79
+ def persist!
80
+
81
+ persistence_bucket.put_object!( self )
82
+
83
+ return self
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,21 @@
1
+
2
+ class ::Persistence::Adapter::Abstract::Mock::Port
3
+
4
+ def initialize( name, adapter )
5
+ @name = name
6
+ @adapter = adapter
7
+ end
8
+
9
+ def enable
10
+ @enabled = true
11
+ end
12
+
13
+ def enabled?
14
+ return @enabled
15
+ end
16
+
17
+ def disable
18
+ @enabled = false
19
+ end
20
+
21
+ end
@@ -0,0 +1,211 @@
1
+
2
+ require_relative '../../../lib/persistence.rb'
3
+
4
+ require_relative './mock_helpers.rb'
5
+
6
+ describe ::Persistence::Adapter::Mock do
7
+
8
+ before( :all ) do
9
+ @adapter = ::Persistence::Adapter::Mock.new( '/tmp/persistence_home' )
10
+ @object = ::Persistence::Adapter::Abstract::Mock::Object.new
11
+ @object.persistence_port = ::Persistence::Adapter::Abstract::Mock::Port.new( :test_port, @adapter )
12
+ @object.persistence_port.enable
13
+ @object.persistence_bucket = ::Persistence::Adapter::Abstract::Mock::Bucket.new( @object.class.to_s )
14
+ @object.value = :some_value
15
+ @bucket = @adapter.persistence_bucket( @object.persistence_bucket.name )
16
+ @value_index = nil
17
+ @duplicate_value_index = nil
18
+ end
19
+
20
+ ################
21
+ # initialize #
22
+ # enable #
23
+ # disable #
24
+ # enabled? #
25
+ ################
26
+
27
+ it 'can initialize enabled state, enable, disable, and report whether enabled' do
28
+ @object.persistence_port.instance_eval do
29
+ enabled?.should == true
30
+ disable
31
+ enabled?.should == false
32
+ enable
33
+ enabled?.should == true
34
+ end
35
+ end
36
+
37
+ #################
38
+ # put_object! #
39
+ #################
40
+
41
+ it "can put and get an object with simple properties and sub objects" do
42
+
43
+ # put_object!
44
+ @bucket.put_object!( @object )
45
+ @object.persistence_id.should_not == nil
46
+
47
+ retrieved_object_hash = @bucket.get_object( @object.persistence_id )
48
+ retrieved_object_hash.should == @object.persistence_hash_to_port
49
+
50
+ end
51
+
52
+ ###########
53
+ # count #
54
+ ###########
55
+
56
+ it 'can report how many objects are persisted' do
57
+
58
+ @bucket.count.should == 1
59
+
60
+ end
61
+
62
+ ####################
63
+ # delete_object! #
64
+ ####################
65
+
66
+ it "can delete an object" do
67
+
68
+ # delete_object!
69
+ @bucket.delete_object!( @object.persistence_id )
70
+ @bucket.get_object( @object.persistence_id ).should == nil
71
+
72
+ # now put it back
73
+ @object.persistence_id = nil
74
+ @bucket.put_object!( @object )
75
+ retrieved_object_hash = @bucket.get_object( @object.persistence_id )
76
+ retrieved_object_hash.should == @object.persistence_hash_to_port
77
+
78
+ end
79
+
80
+ ##############################
81
+ # get_bucket_name_for_object_id #
82
+ ##############################
83
+
84
+ it "can get a bucket for a given object ID" do
85
+
86
+ # get_bucket_name_for_object_id
87
+ @adapter.get_bucket_name_for_object_id( @object.persistence_id ).should == @object.persistence_bucket.name
88
+
89
+ end
90
+
91
+ #############################
92
+ # get_class_for_object_id #
93
+ #############################
94
+
95
+ it "can get a class for a given object ID" do
96
+
97
+ # get_class_for_object_id
98
+ @adapter.get_class_for_object_id( @object.persistence_id ).should == @object.class
99
+
100
+ end
101
+
102
+ ####################
103
+ # put_attribute! #
104
+ ####################
105
+
106
+ it "can put a attribute for an object" do
107
+
108
+ # put_attribute!
109
+ primary_key = @bucket.primary_key_for_attribute_name( @object, :attribute )
110
+ @bucket.put_attribute!( @object, primary_key, 'attribute!' )
111
+
112
+ end
113
+
114
+ ###################
115
+ # get_attribute #
116
+ ###################
117
+
118
+ it "can get a attribute for an object" do
119
+
120
+ # get_attribute
121
+ primary_key = @bucket.primary_key_for_attribute_name( @object, :attribute )
122
+ @bucket.get_attribute( @object, primary_key ).should == 'attribute!'
123
+
124
+ end
125
+
126
+ #######################
127
+ # delete_attribute! #
128
+ #######################
129
+
130
+ it "can delete a attribute on an object" do
131
+
132
+ # delete_attribute!
133
+ primary_key = @bucket.primary_key_for_attribute_name( @object, :attribute )
134
+ @bucket.delete_attribute!( @object, primary_key )
135
+ @bucket.get_attribute( @object, primary_key ).should == nil
136
+
137
+ end
138
+
139
+ ##################
140
+ # create_index #
141
+ # has_index? #
142
+ # index #
143
+ ##################
144
+
145
+ it 'can create an index on a class so instances can be retrieved by key and report whether a given index exists' do
146
+ @bucket.create_index( :key, false )
147
+ @bucket.has_index?( :key ).should == true
148
+ @bucket.index( :key ).should_not == nil
149
+ @bucket.create_index( :duplicate_key, true )
150
+ @bucket.has_index?( :duplicate_key ).should == true
151
+ @bucket.index( :duplicate_key ).should_not == nil
152
+ end
153
+
154
+ #########################
155
+ # permits_duplicates? #
156
+ #########################
157
+
158
+ it 'can report whether an index permits duplicate entries' do
159
+ @bucket.index( :key ).permits_duplicates?.should == false
160
+ @bucket.index( :duplicate_key ).permits_duplicates?.should == true
161
+ end
162
+
163
+ ##################
164
+ # index_object #
165
+ ##################
166
+
167
+ it 'can index an object based on a created index so that the object ID can be retrieved by key' do
168
+ @bucket.index( :key ).index_object_id( @object.persistence_id, @object.value )
169
+ @bucket.index( :key ).get_object_id( @object.value ).should == @object.persistence_id
170
+ end
171
+
172
+ ###########
173
+ # count #
174
+ ###########
175
+
176
+ it 'can report how many objects are persisted' do
177
+
178
+ @bucket.index( :key ).count.should == 1
179
+
180
+ end
181
+
182
+ ###################
183
+ # get_object_id #
184
+ ###################
185
+
186
+ it "can get the object ID corresponding to a key in a bucket" do
187
+
188
+ # get_object_id_for_index_and_key
189
+ @bucket.index( :key ).get_object_id( @object.value ).should == @object.persistence_id
190
+
191
+ end
192
+
193
+ ################################
194
+ # delete_keys_for_object_id! #
195
+ ################################
196
+
197
+ it 'can delete index values for an object' do
198
+ @bucket.index( :key ).delete_keys_for_object_id!( @object.persistence_id )
199
+ ( @bucket.index( :key ).get_object_id( @object.value ) ? true : false ).should == false
200
+ end
201
+
202
+ ##################
203
+ # delete_index #
204
+ ##################
205
+
206
+ it 'can delete an index that has been created on a class attribute' do
207
+ @bucket.delete_index( :key )
208
+ @bucket.has_index?( :key ).should == false
209
+ end
210
+
211
+ end