aqua 0.1.6

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 (60) hide show
  1. data/.document +5 -0
  2. data/.gitignore +7 -0
  3. data/Aqua.gemspec +121 -0
  4. data/LICENCE_COUCHREST +176 -0
  5. data/LICENSE +20 -0
  6. data/README.rdoc +105 -0
  7. data/Rakefile +83 -0
  8. data/VERSION +1 -0
  9. data/lib/aqua.rb +101 -0
  10. data/lib/aqua/object/config.rb +43 -0
  11. data/lib/aqua/object/extensions/ar_convert.rb +0 -0
  12. data/lib/aqua/object/extensions/ar_style.rb +0 -0
  13. data/lib/aqua/object/extensions/property.rb +0 -0
  14. data/lib/aqua/object/extensions/validation.rb +0 -0
  15. data/lib/aqua/object/pack.rb +306 -0
  16. data/lib/aqua/object/query.rb +18 -0
  17. data/lib/aqua/object/stub.rb +122 -0
  18. data/lib/aqua/object/tank.rb +54 -0
  19. data/lib/aqua/object/unpack.rb +253 -0
  20. data/lib/aqua/store/couch_db/attachments.rb +183 -0
  21. data/lib/aqua/store/couch_db/couch_db.rb +151 -0
  22. data/lib/aqua/store/couch_db/database.rb +186 -0
  23. data/lib/aqua/store/couch_db/design_document.rb +57 -0
  24. data/lib/aqua/store/couch_db/http_client/adapter/rest_client.rb +53 -0
  25. data/lib/aqua/store/couch_db/http_client/rest_api.rb +62 -0
  26. data/lib/aqua/store/couch_db/server.rb +103 -0
  27. data/lib/aqua/store/couch_db/storage_methods.rb +405 -0
  28. data/lib/aqua/store/storage.rb +59 -0
  29. data/lib/aqua/support/initializers.rb +216 -0
  30. data/lib/aqua/support/mash.rb +144 -0
  31. data/lib/aqua/support/set.rb +23 -0
  32. data/lib/aqua/support/string_extensions.rb +121 -0
  33. data/spec/aqua_spec.rb +19 -0
  34. data/spec/object/config_spec.rb +58 -0
  35. data/spec/object/object_fixtures/array_udder.rb +5 -0
  36. data/spec/object/object_fixtures/canned_hash.rb +5 -0
  37. data/spec/object/object_fixtures/gerbilmiester.rb +18 -0
  38. data/spec/object/object_fixtures/grounded.rb +13 -0
  39. data/spec/object/object_fixtures/log.rb +19 -0
  40. data/spec/object/object_fixtures/persistent.rb +12 -0
  41. data/spec/object/object_fixtures/sugar.rb +4 -0
  42. data/spec/object/object_fixtures/user.rb +38 -0
  43. data/spec/object/pack_spec.rb +607 -0
  44. data/spec/object/query_spec.rb +27 -0
  45. data/spec/object/stub_spec.rb +51 -0
  46. data/spec/object/tank_spec.rb +61 -0
  47. data/spec/object/unpack_spec.rb +361 -0
  48. data/spec/spec.opts +3 -0
  49. data/spec/spec_helper.rb +16 -0
  50. data/spec/store/couchdb/attachments_spec.rb +164 -0
  51. data/spec/store/couchdb/couch_db_spec.rb +104 -0
  52. data/spec/store/couchdb/database_spec.rb +161 -0
  53. data/spec/store/couchdb/design_document_spec.rb +43 -0
  54. data/spec/store/couchdb/fixtures_and_data/document_fixture.rb +3 -0
  55. data/spec/store/couchdb/fixtures_and_data/image_attach.png +0 -0
  56. data/spec/store/couchdb/server_spec.rb +96 -0
  57. data/spec/store/couchdb/storage_methods_spec.rb +408 -0
  58. data/utils/code_statistics.rb +134 -0
  59. data/utils/console +11 -0
  60. metadata +136 -0
data/spec/spec.opts ADDED
@@ -0,0 +1,3 @@
1
+ --colour
2
+ --format specdoc
3
+ --loadby mtime
@@ -0,0 +1,16 @@
1
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
+ require 'aqua'
4
+ require 'spec'
5
+ require 'spec/autorun'
6
+
7
+
8
+ def require_fixtures
9
+ Dir[ File.dirname(__FILE__) + "/object/object_fixtures/**/*.rb" ].each do |file|
10
+ require file
11
+ end
12
+ end
13
+
14
+
15
+ Spec::Runner.configure do |config|
16
+ end
@@ -0,0 +1,164 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ Aqua.set_storage_engine('CouchDB') # to initialize the Aqua::Store namespace
4
+ require File.dirname(__FILE__) + '/fixtures_and_data/document_fixture' # Document ... a Mash with the collection of methods
5
+
6
+ # Conveniences for typing with tests ...
7
+ CouchDB = Aqua::Store::CouchDB unless defined?( CouchDB )
8
+ Attachments = CouchDB::Attachments unless defined?( Attachments )
9
+
10
+ describe CouchDB::Attachments do
11
+ before(:each) do
12
+ Aqua::Storage.database.delete_all
13
+ @doc = Document.new(:id => 'attachments_doc')
14
+ @attachments = Attachments.new( @doc )
15
+ @file = File.new( File.dirname( __FILE__ ) + '/fixtures_and_data/image_attach.png' )
16
+ end
17
+
18
+ describe 'initialization' do
19
+ it 'should initialize with a document uri' do
20
+ lambda{ Attachments.new }.should raise_error( ArgumentError )
21
+ lambda{ Attachments.new( @doc )}.should_not raise_error( ArgumentError )
22
+ end
23
+
24
+ it 'should initialize with an optional hash' do
25
+ lambda{ Attachments.new( @doc, {:my_file => @file})}.should_not raise_error( ArgumentError )
26
+ end
27
+
28
+ it 'when initializing with a hash, it should check that each key is a string and each value is a file' do
29
+ lambda{ Attachments.new( @doc, { 1 => @file }) }.should raise_error( ArgumentError )
30
+ lambda{ Attachments.new( @doc, {:my_file => 1}) }.should raise_error( ArgumentError )
31
+ end
32
+
33
+ it 'document should be an object reference to the original document, not a dup' do
34
+ @attachments.document.should === @doc
35
+ end
36
+ end
37
+
38
+ describe 'attachment_uri' do
39
+ it 'should raise an error if the document has no id' do
40
+ attachments = Attachments.new( Document.new )
41
+ attachments.add( :my_file, @file )
42
+ lambda{ attachments.uri_for( :my_file ) }.should raise_error( ArgumentError )
43
+ end
44
+
45
+ it 'should not include revision information if the document is new' do
46
+ @attachments.add( :my_file, @file )
47
+ @attachments.uri_for( :my_file ).should_not include( '?rev=')
48
+ end
49
+
50
+ it 'should include revision information if the document has been saved' do
51
+ @doc.save!
52
+ @attachments.add( :my_file, @file )
53
+ @attachments.uri_for( :my_file ).should include( '?rev=')
54
+ end
55
+
56
+ it 'should construct a valid attachment uri' do
57
+ @attachments.add(:my_file, @file )
58
+ @attachments.uri_for( :my_file ).should == "http://127.0.0.1:5984/aqua/attachments_doc/my_file"
59
+ end
60
+
61
+ it 'should construct a get attachment uri without the revision information' do
62
+ @doc.save!
63
+ @attachments.add( :my_file, @file )
64
+ @attachments.uri_for( :my_file, false ).should_not include( '?rev=')
65
+ end
66
+ end
67
+
68
+ describe 'adding attachments' do
69
+ it 'should have a method #add that takes a name and a file' do
70
+ @attachments.should respond_to( :add )
71
+ lambda{ @attachments.add }.should raise_error( ArgumentError )
72
+ lambda{ @attachments.add( :my_file ) }.should raise_error( ArgumentError )
73
+ lambda{ @attachments.add( :my_file, :not_a_file ) }.should raise_error( ArgumentError )
74
+ lambda{ @attachments.add( [], @file ) }.should raise_error( ArgumentError )
75
+ lambda{ @attachments.add( :my_file, @file ) }.should_not raise_error( ArgumentError )
76
+ end
77
+
78
+ it 'should add a valid hash to the attachments container' do
79
+ @attachments.add( :my_file, @file )
80
+ @attachments[:my_file].should == @file
81
+ end
82
+
83
+ it 'should save the attachment to the database' do
84
+ lambda{ @attachments.add!( :my_file, @file ) }.should_not raise_error
85
+ lambda{ CouchDB.get( @attachments.uri_for(:my_file) ) }.should_not raise_error
86
+ end
87
+
88
+ it 'should have the right mime-type after addition to database' do
89
+ @attachments.add!( :my_file, @file )
90
+ attach_hash = CouchDB.get( @attachments.uri_for(:my_file) )
91
+ attach_hash['content_type'].should == 'image/png'
92
+ end
93
+ end
94
+
95
+ describe 'removing attachments' do
96
+ it '#delete should delete an attachment from the collection' do
97
+ @attachments.add( :my_file, @file )
98
+ @attachments.delete( :my_file ).should == @file
99
+ @attachments[:my_file].should be_nil
100
+ end
101
+
102
+ it '#delete! should remove an attachment from the collection and database' do
103
+ @attachments.add!( :my_file, @file )
104
+ @attachments.delete!( :my_file )
105
+ lambda{ CouchDB.get( @attachments.uri_for(:my_file) ) }.should raise_error #( Aqua::ObjectNotFound )
106
+ end
107
+ end
108
+
109
+ describe 'retrieving attachments' do
110
+ it 'should return a file if found locally' do
111
+ @attachments.add!( :my_file, @file )
112
+ @attachments.should_not_receive(:get!)
113
+ @attachments.get(:my_file).should == @file
114
+ end
115
+
116
+ it 'should request a file from the database when not found locally' do
117
+ @attachments.add!( :my_file, @file )
118
+ @attachments.delete( :my_file ) # just deletes the local reference
119
+ @attachments.should_receive(:get!)
120
+ @attachments.get(:my_file)
121
+ end
122
+
123
+ it 'should return a Tempfile from the database' do
124
+ @attachments.add!( :my_file, @file )
125
+ @attachments.delete( :my_file ) # just deletes the local reference
126
+ @attachments.get(:my_file).class.should == Tempfile
127
+ end
128
+
129
+ it 'should have the same data as the original file' do
130
+ @attachments.add!( :my_file, @file )
131
+ file = @attachments.get!(:my_file)
132
+ file.read.should == @file.read
133
+ end
134
+
135
+ it 'should stream an attachment' do
136
+ @attachments.add!( :my_file, @file )
137
+ data = @attachments.get!( :my_file, true )
138
+ data.should_not be_nil
139
+ data.should_not be_empty
140
+ data.should == @file.read
141
+ end
142
+ end
143
+
144
+ describe 'packing all files' do
145
+ before(:each) do
146
+ @attachments.add( :my_file, @file )
147
+ @attachments.add( 'dup.png', @file )
148
+ @pack = @attachments.pack
149
+ end
150
+
151
+ it 'should pack all the added files' do
152
+ @pack.keys.sort.should == ['dup.png', 'my_file']
153
+ end
154
+
155
+ it 'should have correct keys for each attachment' do
156
+ @pack['dup.png'].keys.sort.should include( 'content_type', 'data' )
157
+ end
158
+
159
+ it 'should have the correct mime type' do
160
+ @pack['dup.png']['content_type'].should == 'image/png'
161
+ end
162
+ end
163
+
164
+ end
@@ -0,0 +1,104 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ Aqua.set_storage_engine('CouchDB') # to initialize the Aqua::Store namespace
4
+ CouchDB = Aqua::Store::CouchDB unless defined?( CouchDB )
5
+ describe CouchDB do
6
+ describe 'http_client setup' do
7
+ describe 'autoloading' do
8
+ it 'should not raise an error loading the default adapter' do
9
+ lambda{ CouchDB.set_http_adapter }.should_not raise_error
10
+ end
11
+
12
+ it 'should add rest methods to the Aqua module' do
13
+ CouchDB.set_http_adapter
14
+ CouchDB.should respond_to(:get)
15
+ end
16
+ end
17
+
18
+ describe 'manual loading of an alternate library' do
19
+ # TODO: when there is an alternate library
20
+ end
21
+ end
22
+
23
+ describe 'servers' do
24
+ before(:all) do
25
+ CouchDB.servers.delete(:all)
26
+ end
27
+
28
+ it 'should #clear_servers' do
29
+ CouchDB.clear_servers
30
+ CouchDB.servers.should == {}
31
+ end
32
+
33
+ it '#servers should return an empty hash by default' do
34
+ CouchDB.servers.should == {}
35
+ end
36
+
37
+ it 'should create a default server if no argument is passed' do
38
+ server = CouchDB.server
39
+ server.should_not be_nil
40
+ CouchDB.servers.should_not be_empty
41
+ CouchDB.servers[:aqua].should == server
42
+ server.namespace.should == 'aqua'
43
+ end
44
+
45
+ it 'should add servers when a symbol is requested that is not found as a servers key' do
46
+ server = CouchDB.server(:users)
47
+ CouchDB.servers.size.should == 2
48
+ CouchDB.servers[:users].should == server
49
+ server.namespace.should == 'users'
50
+ end
51
+
52
+ it 'should not duplicate servers' do
53
+ CouchDB.server(:users)
54
+ CouchDB.servers.size.should == 2
55
+ CouchDB.server
56
+ CouchDB.servers.size.should == 2
57
+ end
58
+
59
+ it 'should list the servers in use' do
60
+ CouchDB.server(:noodle)
61
+ CouchDB.servers.size.should == 3
62
+ CouchDB.servers.each do |key, server|
63
+ server.class.should == Aqua::Store::CouchDB::Server
64
+ end
65
+ end
66
+
67
+ it 'should allow the addition of customized servers' do
68
+ new_host = 'http://newhost.com:8888'
69
+ CouchDB.servers[:custom] = CouchDB::Server.new( :server => new_host )
70
+ CouchDB.servers.size.should == 4
71
+ CouchDB.servers[:custom].uri.should == new_host
72
+ end
73
+ end
74
+
75
+ describe 'text helper methods' do
76
+ describe 'escaping names' do
77
+ it 'should escape :: module/class separators with a double underscore __' do
78
+ string = CouchDB.escape('not::kosher')
79
+ string.should == 'not__kosher'
80
+ end
81
+
82
+ it 'should remove non alpha-numeric, hyphen, underscores from a string' do
83
+ string = CouchDB.escape('&not_!kosher*%')
84
+ string.should == 'not_kosher'
85
+ end
86
+ end
87
+
88
+ describe 'paramify_url' do
89
+ it 'should build a query filled url from a base url and a params hash' do
90
+ url = CouchDB.paramify_url( 'http://localhost:5984', {:gerbil => true, :keys => 'you_know_it'} )
91
+ url.should match(/\?/)
92
+ url.should match(/&/)
93
+ url.should match(/keys=you_know_it/)
94
+ url.should match(/gerbil=true/)
95
+ end
96
+ end
97
+ end
98
+
99
+ describe 'database strategies' do
100
+ # TODO: figure this out
101
+ end
102
+
103
+ end
104
+
@@ -0,0 +1,161 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../../spec_helper')
2
+
3
+ Aqua.set_storage_engine('CouchDB') # to initialize the Aqua::Store namespace
4
+ # Conveniences for typing with tests ...
5
+ CouchDB = Aqua::Store::CouchDB unless defined?( CouchDB )
6
+ Database = CouchDB::Database unless defined?( Database )
7
+ Server = CouchDB::Server unless defined?( Server)
8
+
9
+ describe 'Aqua::Store::CouchDB::Database' do
10
+ describe 'initialization' do
11
+ describe 'name' do
12
+ it 'should not require name for initialization' do
13
+ lambda{ Database.new }.should_not raise_error( ArgumentError )
14
+ end
15
+
16
+ it 'should escape the name, when one is provided' do
17
+ db = Database.new('&not::kosher*%')
18
+ db.name.should == 'not__kosher'
19
+ end
20
+ end
21
+
22
+ describe 'server' do
23
+ it 'should default to CouchDB\'s default server if no server option is provided' do
24
+ db = Database.new
25
+ db.server.should_not be_nil
26
+ db.server.class.should == Aqua::Store::CouchDB::Server
27
+ db.server.uri.should == 'http://127.0.0.1:5984'
28
+ db.server.namespace.should == 'aqua'
29
+ end
30
+
31
+ it 'a custom server held in CouchDB can be used' do
32
+ new_host = 'http://newhost.com:8888'
33
+ CouchDB.servers[:customized] = CouchDB::Server.new( :server => new_host )
34
+ db = Database.new('things', :server => :customized )
35
+ db.server.uri.should == new_host
36
+ end
37
+ end
38
+
39
+ describe 'uri' do
40
+ it 'should use the server namespace as the path when no name is provided' do
41
+ db = Database.new
42
+ db.name.should == nil
43
+ db.uri.should == "http://127.0.0.1:5984/aqua"
44
+ end
45
+
46
+ it 'should use the default server namespace and the name in the path when a name is provided but server info is not' do
47
+ db = Database.new('things')
48
+ db.name.should == 'things'
49
+ db.uri.should == 'http://127.0.0.1:5984/aqua_things'
50
+ end
51
+
52
+ it 'should use the server namespace provided and the name in the path when a name and server symbol are provided' do
53
+ db = Database.new('things', :server => :not_so_aqua )
54
+ db.uri.should == 'http://127.0.0.1:5984/not_so_aqua_things'
55
+ end
56
+
57
+ it 'should user a custome database\'s namespace along with the name in a path if both are provided' do
58
+ server = Server.new(:namespace => 'different')
59
+ db = Database.new('things', :server => server )
60
+ db.uri.should == 'http://127.0.0.1:5984/different_things'
61
+ end
62
+ end
63
+ end
64
+
65
+ describe 'create' do
66
+ before(:each) do
67
+ CouchDB.delete( Database.new('things').uri ) rescue nil
68
+ end
69
+
70
+ it 'should create a couchdb database for this instance if it doesn\'t yet exist' do
71
+ db = Database.create('things')
72
+ db.should be_exists
73
+ end
74
+
75
+ it 'create should not return false if the database already exists' do
76
+ db = Database.create('things')
77
+ db.should_not be( false )
78
+ end
79
+
80
+ it 'create should return false if an HTTP error occurs' do
81
+ CouchDB.should_receive(:put).and_raise( CouchDB::RequestFailed )
82
+ db = Database.create('things')
83
+ db.should == false
84
+ end
85
+
86
+ it 'create! should create and return a couchdb database if it doesn\'t yet exist' do
87
+ Database.new('things').should_not be_exists
88
+ db = Database.create!('things')
89
+ db.should be_exists
90
+ end
91
+
92
+ it 'create! should not raise an error if the database already exists' do
93
+ Database.create('things')
94
+ lambda{ Database.create!('things') }.should_not raise_error
95
+ end
96
+
97
+ it 'create should raise an error if an HTTP error occurs' do
98
+ CouchDB.should_receive(:put).and_raise( CouchDB::RequestFailed )
99
+ lambda{ Database.create!('things') }.should raise_error
100
+ end
101
+ end
102
+
103
+ describe 'misc managment stuff' do
104
+ before(:each) do
105
+ CouchDB.delete( Database.new('things').uri ) rescue nil
106
+ end
107
+
108
+ it '#exists? should be false if the database doesn\'t yet exist in CouchDB land' do
109
+ db = Database.new('things')
110
+ db.should_not be_exists
111
+ end
112
+
113
+ it '#exists? should be true if the database does exist in CouchDB land' do
114
+ db = Database.create('things')
115
+ db.should be_exists
116
+ end
117
+
118
+ it '#info raise an error if the database doesn\'t exist' do
119
+ db = Database.new('things')
120
+ db.delete
121
+ lambda{ db.info }.should raise_error( CouchDB::ResourceNotFound )
122
+ end
123
+
124
+ it '#info should provide a hash of detail if it exists' do
125
+ db = Database.create('things')
126
+ info = db.info
127
+ info.class.should == Hash
128
+ info['db_name'].should == 'aqua_things'
129
+ end
130
+ end
131
+
132
+ describe 'deleting' do
133
+ it 'should #delete itself' do
134
+ db = Database.create('things')
135
+ db.should be_exists
136
+ db.delete
137
+ db.should_not be_exist
138
+ end
139
+
140
+ it '#delete should return nil if it doesn\'t exist' do
141
+ db = Database.new('things')
142
+ db.should_not be_exists
143
+ lambda{ db.delete }.should_not raise_error
144
+ db.delete.should be_nil
145
+ end
146
+
147
+ it 'should #delete! itself' do
148
+ db = Database.create('things')
149
+ db.should be_exists
150
+ db.delete!
151
+ db.should_not be_exist
152
+ end
153
+
154
+ it '#delete! should raise an error if the database doesn\'t exist' do
155
+ db = Database.new('things')
156
+ db.should_not be_exists
157
+ lambda{ db.delete! }.should raise_error
158
+ end
159
+ end
160
+
161
+ end