loveseat 0.1.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.
@@ -0,0 +1,8 @@
1
+ class Hash
2
+ def to_query
3
+ components = self.map do |k,v|
4
+ [URI.escape(k.to_s), URI.escape(v.to_s)].join('=')
5
+ end
6
+ components.join("&")
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ require 'core_ext/hash.rb'
2
+ require 'rest/resource.rb'
3
+ require 'rest/server.rb'
4
+ require 'rest/document.rb'
5
+ require 'rest/database.rb'
6
+ require 'rest/design_document.rb'
7
+ require 'loveseat/document.rb'
8
+ require 'loveseat/document/dsl.rb'
9
+ require 'loveseat/document/support.rb'
10
+ require 'loveseat/document/instance_adapter.rb'
11
+ require 'loveseat/document/property/base.rb'
12
+ require 'loveseat/document/property/string.rb'
13
+ require 'loveseat/document/property/integer.rb'
14
+ require 'loveseat/document/property/float.rb'
15
+ require 'loveseat/document/property/date.rb'
16
+ require 'loveseat/document/property/time.rb'
17
+ require 'loveseat/document/property/array.rb'
18
+ require 'loveseat/document/property/hash.rb'
19
+ require 'loveseat/document/property/raw.rb'
20
+ require 'loveseat/design_document.rb'
21
+ require 'loveseat/design_document/dsl.rb'
22
+ require 'loveseat/design_document/support.rb'
23
+ require 'loveseat/design_document/view_row.rb'
24
+ require 'loveseat/model.rb'
25
+ require 'loveseat/view_set.rb'
26
+
@@ -0,0 +1,45 @@
1
+ module Loveseat
2
+ module DesignDocument
3
+ Document.add_resolver(/_design\/([A-Za-z:]+)/)
4
+
5
+ def self.setup(klass, options = {}, &block)
6
+ Document.setup(klass, { :support => Support.new(klass, options) }, &block)
7
+ end
8
+
9
+ def self.all(db)
10
+ resource = db._all_docs
11
+ response, body = resource.get(:query => {:startkey => "_design/".to_json,
12
+ :endkey => "_design/\ufff0".to_json,
13
+ :include_docs => true})
14
+ response.value
15
+
16
+ body['rows'].map do |row|
17
+ klass = Document.resolve(row['id'])
18
+ support = Document.registry[klass]
19
+ support.from_hash(row['doc'])
20
+ end
21
+ end
22
+
23
+ def self.view(db, design_document, name, options = {})
24
+ resource = Rest::DesignDocument.new(db, design_document.name)
25
+ view_resource = resource._view(name)
26
+
27
+ keys = options.delete(:keys)
28
+
29
+ response, body = if keys
30
+ view_resource.post(:query => options, :body => {:keys => keys}.to_json)
31
+ else
32
+ view_resource.get(:query => options)
33
+ end
34
+ response.value
35
+
36
+ body['rows'].map do |row|
37
+ ViewRow.from_hash(row)
38
+ end
39
+ end
40
+
41
+ def self.generate_id(klass)
42
+ "_design/#{klass.name}"
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,9 @@
1
+ module Loveseat
2
+ module DesignDocument
3
+ class DSL < Document::DSL
4
+ def view(name, functions = {})
5
+ @support.add_view(name, functions)
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,25 @@
1
+ module Loveseat
2
+ module DesignDocument
3
+ class Support < Document::Support
4
+ def initialize(klass, options = {})
5
+ super(klass, options)
6
+ @dsl = DSL.new(self)
7
+ add_property(:views, Document::Property::Hash, {})
8
+ alter_property(:_id, Document::Property::String, DesignDocument.generate_id(klass))
9
+ end
10
+
11
+ def from_hash(doc)
12
+ object = super(doc)
13
+ object.views = properties[:views][DEFAULT]
14
+ object
15
+ end
16
+
17
+ def add_view(name, options = {})
18
+ type, default = properties[:views]
19
+ default.merge!(
20
+ name => options
21
+ )
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,16 @@
1
+ module Loveseat
2
+ module DesignDocument
3
+ class ViewRow
4
+ Loveseat::Document.setup(self, :abstract => true) do
5
+ string :id
6
+ raw :key
7
+ raw :value
8
+ hash :doc
9
+ end
10
+
11
+ def self.from_hash(doc)
12
+ Document.registry[self.name].from_hash(doc)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,92 @@
1
+ module Loveseat
2
+ module Document
3
+ @@registry = {}
4
+ @@resolvers = [
5
+ /^([A-Za-z:]+):/
6
+ ]
7
+
8
+ def self.registry
9
+ @@registry
10
+ end
11
+
12
+ def self.add_resolver(regexp)
13
+ @@resolvers << regexp
14
+ end
15
+
16
+ def self.next_id(server, klass)
17
+ response, body = server._uuids.get
18
+ response.value
19
+
20
+ uuid = body['uuids'].first
21
+ "#{klass.name}:#{uuid}"
22
+ end
23
+
24
+ def self.resolve(id)
25
+ @@resolvers.each do |regexp|
26
+ match = regexp.match(id)
27
+ if match
28
+ return match[1]
29
+ end
30
+ end
31
+ nil
32
+ end
33
+
34
+ def self.setup(klass, options = {}, &block)
35
+ support = options.delete(:support) ||
36
+ Support.new(klass, options)
37
+ Document.registry[klass.name] = support
38
+ support.dsl.instance_eval(&block)
39
+ support
40
+ end
41
+
42
+ def self.put(db, object)
43
+ klass = ( object.instance_of?(Class) ) ? object : object.class
44
+ support = Document.registry[klass.name]
45
+ raise "Not Registered" if support.nil?
46
+ raise "Abstract Document" if support.abstract?
47
+
48
+ if object._id.nil?
49
+ object._id = next_id(db.server, object.class)
50
+ end
51
+
52
+ resource = Rest::Document.new(db, object._id)
53
+ response, body = resource.put(support.to_doc(object))
54
+
55
+ response.value
56
+
57
+ object._rev = body["rev"]
58
+ object
59
+ end
60
+
61
+ def self.get(db, id)
62
+ resource = Rest::Document.new(db, id)
63
+ response, body = resource.get
64
+ response.value
65
+
66
+ klass = resolve(id)
67
+ support = Document.registry[klass]
68
+ support.from_hash(body)
69
+ end
70
+
71
+ def self.all(db, klass)
72
+ support = Document.registry[klass.name]
73
+ resource = db._all_docs
74
+ response, body = resource.get(:query => {:startkey => "#{klass.name}:".to_json,
75
+ :endkey => "#{klass.name}:\ufff0".to_json,
76
+ :include_docs => true})
77
+ response.value
78
+
79
+ body['rows'].map do |row|
80
+ support.from_hash(row['doc'])
81
+ end
82
+ end
83
+
84
+ def self.delete(db, object)
85
+ resource = Rest::Document.new(db, object._id)
86
+ response, body = resource.delete(:query => {:rev => object._rev})
87
+ response.value
88
+ object._rev = nil
89
+ end
90
+ end
91
+ end
92
+
@@ -0,0 +1,41 @@
1
+ module Loveseat
2
+ module Document
3
+ class DSL
4
+ def initialize(support)
5
+ @support = support
6
+ end
7
+
8
+ def integer(name, default = nil)
9
+ @support.add_property(name, Property::Integer, default)
10
+ end
11
+
12
+ def string(name, default = nil)
13
+ @support.add_property(name, Property::String, default)
14
+ end
15
+
16
+ def float(name, default = nil)
17
+ @support.add_property(name, Property::Float, default)
18
+ end
19
+
20
+ def date(name, default = nil)
21
+ @support.add_property(name, Property::Date, default)
22
+ end
23
+
24
+ def time(name, default = nil)
25
+ @support.add_property(name, Property::Time, default)
26
+ end
27
+
28
+ def hash(name, default = nil)
29
+ @support.add_property(name, Property::Hash, default)
30
+ end
31
+
32
+ def array(name, default = nil)
33
+ @support.add_property(name, Property::Array, default)
34
+ end
35
+
36
+ def raw(name, default = nil)
37
+ @support.add_property(name, Property::Raw, default)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,22 @@
1
+ module Loveseat
2
+ module Document
3
+ class InstanceAdapter
4
+ def initialize(klass)
5
+ @support = Document.registry[klass]
6
+ @klass = klass
7
+ end
8
+
9
+ def [](name)
10
+ property_map[name]
11
+ end
12
+
13
+ def inspect
14
+ "#<Loveseat::Document::InstanceAdapter:#{@klass}>"
15
+ end
16
+
17
+ def property_map
18
+ @property_map ||= @support.generate_property_map
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,15 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Array < Base
5
+ def self.cast(value)
6
+ value.to_a
7
+ end
8
+
9
+ def empty?
10
+ @value.nil? || @value.empty?
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,30 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Base
5
+ attr_reader :value
6
+
7
+ def initialize(default_value = nil)
8
+ @value = cast(default_value)
9
+ end
10
+
11
+ def get
12
+ @value
13
+ end
14
+
15
+ def set(value)
16
+ @value = cast(value)
17
+ end
18
+
19
+ def empty?
20
+ @value.nil?
21
+ end
22
+
23
+ private
24
+ def cast(value)
25
+ self.class.cast(value) unless value.nil?
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,17 @@
1
+ require 'date'
2
+
3
+ module Loveseat
4
+ module Document
5
+ module Property
6
+ class Date < Base
7
+ def self.cast(value)
8
+ if value.is_a?(::Date)
9
+ return value
10
+ end
11
+
12
+ ::Date.parse(value)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Float < Base
5
+ def self.cast(value)
6
+ value.to_f
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Hash < Base
5
+ def self.cast(value)
6
+ value.to_hash
7
+ end
8
+
9
+ def empty?
10
+ @value.nil? || @value.empty?
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,11 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Integer < Base
5
+ def self.cast(value)
6
+ value.to_i
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class Raw < Base
5
+ def self.cast(value)
6
+ value
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Loveseat
2
+ module Document
3
+ module Property
4
+ class String < Base
5
+ def self.cast(value)
6
+ value.to_s
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,17 @@
1
+ require 'time'
2
+
3
+ module Loveseat
4
+ module Document
5
+ module Property
6
+ class Time < Base
7
+ def self.cast(value)
8
+ if value.is_a?(::Time)
9
+ return value
10
+ end
11
+
12
+ ::Time.parse(value)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,106 @@
1
+ module Loveseat
2
+ module Document
3
+ class Support
4
+ attr_accessor :properties, :dsl
5
+
6
+ TYPE = 0
7
+ DEFAULT= 1
8
+
9
+ def initialize(klass, options = {})
10
+ @klass = klass
11
+ @properties = {}
12
+ @dsl = DSL.new(self)
13
+ @abstract = !!options[:abstract]
14
+ @singleton = !!options[:singleton]
15
+
16
+ add_instance_adapter_accessor!
17
+
18
+ unless @abstract
19
+ add_property(:_id, Property::String)
20
+ add_property(:_rev, Property::String)
21
+ end
22
+ end
23
+
24
+ def add_property(name,type,default = nil)
25
+ name = name.to_sym
26
+ alter_property(name,type,default)
27
+ add_instance_methods!(name)
28
+ end
29
+
30
+ def alter_property(name,type,default = nil)
31
+ @properties[name] = [type, default]
32
+ end
33
+
34
+ def to_doc(instance)
35
+ doc = {}
36
+ instance.__loveseat_instance_adapter.property_map.each do |k,v|
37
+ value = v.get
38
+ doc[k] = value unless v.empty?
39
+ end
40
+ doc.to_json
41
+ end
42
+
43
+ def from_hash(doc)
44
+ object = nil
45
+ if singleton?
46
+ object = @klass
47
+ else
48
+ object = @klass.new
49
+ end
50
+ properties.each do |k,v|
51
+ object.send(:"#{k}=", doc[k.to_s])
52
+ end
53
+ object
54
+ end
55
+
56
+ def generate_property_map
57
+ map = {}
58
+ properties.each do |name,value|
59
+ type, default = value
60
+ map[name] = type.new(default)
61
+ end
62
+ map
63
+ end
64
+
65
+ def singleton?
66
+ @singleton
67
+ end
68
+
69
+ def abstract?
70
+ @abstract
71
+ end
72
+
73
+ private
74
+
75
+ def add_instance_adapter_accessor!
76
+ method = <<-SOURCE
77
+ def __loveseat_instance_adapter
78
+ class_name = ( self.instance_of?(Class) ) ? self.name : self.class.name
79
+ @__loveseat_instance_adapter ||= Loveseat::Document::InstanceAdapter.new(class_name)
80
+ end
81
+ SOURCE
82
+ eval_appropriately(method)
83
+ end
84
+
85
+ def add_instance_methods!(method)
86
+ methods = <<-SOURCE
87
+ def #{method}
88
+ __loveseat_instance_adapter["#{method}".to_sym].get
89
+ end
90
+ def #{method}=(value)
91
+ __loveseat_instance_adapter["#{method}".to_sym].set(value)
92
+ end
93
+ SOURCE
94
+ eval_appropriately(methods)
95
+ end
96
+
97
+ def eval_appropriately(arg)
98
+ if singleton?
99
+ @klass.instance_eval(arg)
100
+ else
101
+ @klass.class_eval(arg)
102
+ end
103
+ end
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,42 @@
1
+ module Loveseat
2
+ class Model
3
+ def self.connection=(connection_hash)
4
+ @@server = Rest::Server.new(connection_hash[:host],
5
+ connection_hash[:port],
6
+ connection_hash[:user],
7
+ connection_hash[:password])
8
+ @@database = Rest::Database.new(@@server, connection_hash[:database])
9
+ end
10
+
11
+ def put
12
+ Document.put(self.class.database, self)
13
+ end
14
+
15
+ def delete
16
+ Document.delete(self.class.database, self)
17
+ end
18
+
19
+ def self.get(id)
20
+ unless id[self.name]
21
+ id = [self.name, id].join(':')
22
+ end
23
+ Document.get(self.database, id)
24
+ end
25
+
26
+ def self.all
27
+ Document.all(self.database, self)
28
+ end
29
+
30
+ def self.setup(options = {}, &block)
31
+ Document.setup(self, options, &block)
32
+ end
33
+
34
+ def self.server
35
+ @@server
36
+ end
37
+
38
+ def self.database
39
+ @@database
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,39 @@
1
+ module Loveseat
2
+ class ViewSet < Model
3
+ def self.setup(options = {}, &block)
4
+ options = options.merge(:singleton => true)
5
+ DesignDocument.setup(self, options, &block)
6
+ end
7
+
8
+ def self.view(name, options = {})
9
+ DesignDocument.view(self.database, self, name, options)
10
+ end
11
+
12
+ def self.put
13
+ Document.put(self.database, self)
14
+ end
15
+
16
+ def self.delete
17
+ Document.delete(self.database, self)
18
+ end
19
+
20
+ def self.latest!
21
+ begin
22
+ put
23
+ rescue
24
+ Document.get(self.database, self._id)
25
+ retry
26
+ end
27
+ end
28
+
29
+ def self.get(*args)
30
+ latest!
31
+ end
32
+
33
+ def self.all
34
+ DesignDocument.all(self.database)
35
+ end
36
+
37
+ private :put, :delete
38
+ end
39
+ end
@@ -0,0 +1,18 @@
1
+ module Rest
2
+ class Database < Resource
3
+ attr_reader :server
4
+
5
+ nested_resource :_all_docs
6
+ nested_resource :_revs_limit
7
+ nested_resource :_changes
8
+ nested_resource :_bulk_docs
9
+ nested_resource :_temp_view
10
+ nested_resource :_view_cleanup
11
+ nested_resource :_compact
12
+
13
+ def initialize(server, name)
14
+ @server = server
15
+ super(server.connection, "/#{name}/", server.username, server.password)
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,9 @@
1
+ module Rest
2
+ class DesignDocument < Document
3
+ nested_resource :_view
4
+
5
+ def initialize(database, name)
6
+ super(database, "_design/#{name}")
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,7 @@
1
+ module Rest
2
+ class Document < Resource
3
+ def initialize(database, id)
4
+ super(database.connection, database.nested_resource_path(id), database.server.username, database.server.password)
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,84 @@
1
+ require 'net/http'
2
+ require 'uri'
3
+ require 'json'
4
+
5
+ module Rest
6
+ class Resource
7
+ attr_reader :connection
8
+
9
+ def initialize(connection, path = '/', username=nil, password=nil)
10
+ @connection = connection
11
+ uri = [ 'http://',
12
+ [connection.address,
13
+ connection.port].join(':'),
14
+ path ].join
15
+ @uri = URI.parse(uri)
16
+ @username = username
17
+ @password = password
18
+ end
19
+
20
+ def self.nested_resource(name)
21
+ define_method name.to_sym do |*args|
22
+ resource = [name.to_s, *args.first].compact.join('/')
23
+ Resource.new(@connection, nested_resource_path(resource))
24
+ end
25
+ end
26
+
27
+ def nested_resource_path(nested_resource = '')
28
+ components = @uri.request_uri.split('/')
29
+ components << "" if components.empty?
30
+ components << nested_resource
31
+ components.join('/')
32
+ end
33
+
34
+ def put(options_or_body = '')
35
+ do_request(options_or_body, Net::HTTP::Put)
36
+ end
37
+
38
+ def get(options_or_body = '')
39
+ do_request(options_or_body, Net::HTTP::Get)
40
+ end
41
+
42
+ def delete(options_or_body = '')
43
+ do_request(options_or_body, Net::HTTP::Delete)
44
+ end
45
+
46
+ def post(options_or_body = '')
47
+ do_request(options_or_body, Net::HTTP::Post)
48
+ end
49
+
50
+ private
51
+ def do_request(options_or_body, request_const)
52
+ request_uri = nil
53
+ request_body = nil
54
+ if options_or_body.is_a?(String)
55
+ request_uri = @uri.request_uri
56
+ request_body = options_or_body
57
+ elsif options_or_body.is_a?(Hash)
58
+ uri = @uri.dup
59
+ uri.query = (options_or_body[:query] || {}).to_query
60
+ request_uri = uri.request_uri
61
+ request_body = options_or_body[:body]
62
+ end
63
+ request = request_const.new(request_uri)
64
+ request['Content-Type'] = 'application/json'
65
+
66
+ request.body = if request_body.is_a?(String)
67
+ request_body
68
+ else
69
+ request_body.to_json
70
+ end
71
+
72
+ if @username and @password
73
+ request.basic_auth(@username, @password)
74
+ end
75
+
76
+ response = @connection.start do |http|
77
+ http.request(request)
78
+ end
79
+
80
+ [response, JSON.parse(response.body)]
81
+ end
82
+ end
83
+ end
84
+
@@ -0,0 +1,19 @@
1
+ module Rest
2
+ class Server < Resource
3
+ attr_reader :username
4
+ attr_reader :password
5
+
6
+ nested_resource :_all_dbs
7
+ nested_resource :_config
8
+ nested_resource :_uuids
9
+ nested_resource :_replicate
10
+ nested_resource :_stats
11
+ nested_resource :_active_tasks
12
+
13
+ def initialize(host, port, username=nil, password=nil)
14
+ @username = username
15
+ @password = password
16
+ super(Net::HTTP.new(host, port), '/', username, password)
17
+ end
18
+ end
19
+ end
metadata ADDED
@@ -0,0 +1,107 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: loveseat
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - John MacKenzie
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-12-21 00:00:00 -06:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: json
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - "="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 1
32
+ - 4
33
+ - 6
34
+ version: 1.4.6
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ description: Small, lightweight CouchDB client and object document mapper. Library is meant to be kept lean while still exposing the most powerful features of the database. Took a little inspiration from outoftime/sunspot.
38
+ email: john@nineteeneightd.com
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - lib/core_ext/hash.rb
47
+ - lib/loveseat/design_document/dsl.rb
48
+ - lib/loveseat/design_document/support.rb
49
+ - lib/loveseat/design_document/view_row.rb
50
+ - lib/loveseat/design_document.rb
51
+ - lib/loveseat/document/dsl.rb
52
+ - lib/loveseat/document/instance_adapter.rb
53
+ - lib/loveseat/document/property/array.rb
54
+ - lib/loveseat/document/property/base.rb
55
+ - lib/loveseat/document/property/date.rb
56
+ - lib/loveseat/document/property/float.rb
57
+ - lib/loveseat/document/property/hash.rb
58
+ - lib/loveseat/document/property/integer.rb
59
+ - lib/loveseat/document/property/raw.rb
60
+ - lib/loveseat/document/property/string.rb
61
+ - lib/loveseat/document/property/time.rb
62
+ - lib/loveseat/document/support.rb
63
+ - lib/loveseat/document.rb
64
+ - lib/loveseat/model.rb
65
+ - lib/loveseat/view_set.rb
66
+ - lib/loveseat.rb
67
+ - lib/rest/database.rb
68
+ - lib/rest/design_document.rb
69
+ - lib/rest/document.rb
70
+ - lib/rest/resource.rb
71
+ - lib/rest/server.rb
72
+ has_rdoc: true
73
+ homepage: http://198d.github.com/loveseat
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options: []
78
+
79
+ require_paths:
80
+ - lib
81
+ required_ruby_version: !ruby/object:Gem::Requirement
82
+ none: false
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ hash: 3
87
+ segments:
88
+ - 0
89
+ version: "0"
90
+ required_rubygems_version: !ruby/object:Gem::Requirement
91
+ none: false
92
+ requirements:
93
+ - - ">="
94
+ - !ruby/object:Gem::Version
95
+ hash: 3
96
+ segments:
97
+ - 0
98
+ version: "0"
99
+ requirements: []
100
+
101
+ rubyforge_project:
102
+ rubygems_version: 1.3.7
103
+ signing_key:
104
+ specification_version: 3
105
+ summary: Simple Couch Client / Object Document Mapper
106
+ test_files: []
107
+