ShyCouch 0.0.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/.document +5 -0
- data/Gemfile +14 -0
- data/Gemfile.lock +36 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +36 -0
- data/Rakefile +55 -0
- data/ShyCouch.gemspec +75 -0
- data/VERSION +1 -0
- data/lib/ShyCouch.rb +358 -0
- data/test/helper.rb +18 -0
- data/test/old-test.rb +10 -0
- data/test/old-tests.rb +89 -0
- data/test/test_ShyCouch.rb +28 -0
- data/test/test_camping_integration.rb +15 -0
- data/test/test_couch_document.rb +141 -0
- data/test/test_couchdb_api.rb +18 -0
- data/test/test_couchdb_factory.rb +15 -0
- data/test/test_fields.rb +26 -0
- metadata +147 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "bundler", "~> 1.0.0"
|
10
|
+
gem "jeweler", "~> 1.6.4"
|
11
|
+
gem "rcov", ">= 0"
|
12
|
+
gem "sourcify", "~> 0.5.0"
|
13
|
+
gem "ShyRubyJS"
|
14
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
ShyRubyJS (0.0.1)
|
5
|
+
sourcify (~> 0)
|
6
|
+
file-tail (1.0.6)
|
7
|
+
spruz (~> 0.2)
|
8
|
+
git (1.2.5)
|
9
|
+
jeweler (1.6.4)
|
10
|
+
bundler (~> 1.0)
|
11
|
+
git (>= 1.2.5)
|
12
|
+
rake
|
13
|
+
rake (0.8.7)
|
14
|
+
rcov (0.9.10)
|
15
|
+
ruby2ruby (1.2.5)
|
16
|
+
ruby_parser (~> 2.0)
|
17
|
+
sexp_processor (~> 3.0)
|
18
|
+
ruby_parser (2.0.6)
|
19
|
+
sexp_processor (~> 3.0)
|
20
|
+
sexp_processor (3.0.5)
|
21
|
+
sourcify (0.5.0)
|
22
|
+
file-tail (>= 1.0.5)
|
23
|
+
ruby2ruby (>= 1.2.5)
|
24
|
+
ruby_parser (>= 2.0.5)
|
25
|
+
sexp_processor (>= 3.0.5)
|
26
|
+
spruz (0.2.12)
|
27
|
+
|
28
|
+
PLATFORMS
|
29
|
+
ruby
|
30
|
+
|
31
|
+
DEPENDENCIES
|
32
|
+
ShyRubyJS
|
33
|
+
bundler (~> 1.0.0)
|
34
|
+
jeweler (~> 1.6.4)
|
35
|
+
rcov
|
36
|
+
sourcify (~> 0.5.0)
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Cerales
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
= ShyCouch
|
2
|
+
|
3
|
+
ShyCouch is a Ruby library for CouchDB. It's a data persistence layer that uses native objects and a simple query language, designed primarily to replace ActiveRecord in micro-frameworks like Camping. A Python version is forthcoming.
|
4
|
+
|
5
|
+
I'm mainly putting this up for feedback at the moment. It's a complete mess, I haven't figured out where
|
6
|
+
|
7
|
+
ShyCouch does not come with an elaborate query language. It'll automatically create an 'all' query for all your models (don't use it unless you have a really good excuse not to write a custom query, doing the filtering at the application layer is hell slow), but aside from that you have to write your own map and reduce functions.
|
8
|
+
|
9
|
+
= Usage
|
10
|
+
|
11
|
+
erghgrehg TODO
|
12
|
+
|
13
|
+
= Map/Reduce
|
14
|
+
|
15
|
+
ShyCouch uses the related ShyRubyJS library to parse Ruby blocks as JavaScript. This means you can do this:
|
16
|
+
|
17
|
+
map {
|
18
|
+
def function(doc)
|
19
|
+
if doc.kind == "post" and !doc.hidden
|
20
|
+
emit(doc)
|
21
|
+
end
|
22
|
+
}
|
23
|
+
|
24
|
+
and you'll get this:
|
25
|
+
|
26
|
+
function ( doc ) {
|
27
|
+
if( doc.kind.==("post") && !doc.hidden ) {
|
28
|
+
emit(doc)
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
== Copyright
|
33
|
+
|
34
|
+
Copyright (c) 2011 Cerales. See LICENSE.txt for
|
35
|
+
further details.
|
36
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "ShyCouch"
|
18
|
+
gem.homepage = "http://github.com/Cerales/ShyCouch"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Ruby API for CouchDB, designed to work with the Camping micro-framework.}
|
21
|
+
gem.description = %Q{Ruby API for CouchDB, designed to work with the Camping micro-framework.}
|
22
|
+
gem.email = "danbryan@gmail.com"
|
23
|
+
gem.authors = ["Shy Inc.", "Daniel Bryan", "Cerales"]
|
24
|
+
gem.add_dependency "ShyRubyJS"
|
25
|
+
gem.add_dependency "sourcify", ">=0"
|
26
|
+
# dependencies defined in Gemfile
|
27
|
+
end
|
28
|
+
Jeweler::RubygemsDotOrgTasks.new
|
29
|
+
|
30
|
+
require 'rake/testtask'
|
31
|
+
Rake::TestTask.new(:test) do |test|
|
32
|
+
test.libs << 'lib' << 'test'
|
33
|
+
test.pattern = 'test/**/test_*.rb'
|
34
|
+
test.verbose = true
|
35
|
+
end
|
36
|
+
|
37
|
+
require 'rcov/rcovtask'
|
38
|
+
Rcov::RcovTask.new do |test|
|
39
|
+
test.libs << 'test'
|
40
|
+
test.pattern = 'test/**/test_*.rb'
|
41
|
+
test.verbose = true
|
42
|
+
test.rcov_opts << '--exclude "gems/*"'
|
43
|
+
end
|
44
|
+
|
45
|
+
task :default => :test
|
46
|
+
|
47
|
+
require 'rake/rdoctask'
|
48
|
+
Rake::RDocTask.new do |rdoc|
|
49
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
50
|
+
|
51
|
+
rdoc.rdoc_dir = 'rdoc'
|
52
|
+
rdoc.title = "ShyCouch #{version}"
|
53
|
+
rdoc.rdoc_files.include('README*')
|
54
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
55
|
+
end
|
data/ShyCouch.gemspec
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ShyCouch}
|
8
|
+
s.version = "0.0.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = [%q{Shy Inc.}, %q{Daniel Bryan}, %q{Cerales}]
|
12
|
+
s.date = %q{2011-08-14}
|
13
|
+
s.description = %q{Ruby API for CouchDB, designed to work with the Camping micro-framework.}
|
14
|
+
s.email = %q{danbryan@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"LICENSE.txt",
|
17
|
+
"README.rdoc"
|
18
|
+
]
|
19
|
+
s.files = [
|
20
|
+
".document",
|
21
|
+
"Gemfile",
|
22
|
+
"Gemfile.lock",
|
23
|
+
"LICENSE.txt",
|
24
|
+
"README.rdoc",
|
25
|
+
"Rakefile",
|
26
|
+
"ShyCouch.gemspec",
|
27
|
+
"VERSION",
|
28
|
+
"lib/ShyCouch.rb",
|
29
|
+
"test/helper.rb",
|
30
|
+
"test/old-test.rb",
|
31
|
+
"test/old-tests.rb",
|
32
|
+
"test/test_ShyCouch.rb",
|
33
|
+
"test/test_camping_integration.rb",
|
34
|
+
"test/test_couch_document.rb",
|
35
|
+
"test/test_couchdb_api.rb",
|
36
|
+
"test/test_couchdb_factory.rb",
|
37
|
+
"test/test_fields.rb"
|
38
|
+
]
|
39
|
+
s.homepage = %q{http://github.com/Cerales/ShyCouch}
|
40
|
+
s.licenses = [%q{MIT}]
|
41
|
+
s.require_paths = [%q{lib}]
|
42
|
+
s.rubygems_version = %q{1.8.6}
|
43
|
+
s.summary = %q{Ruby API for CouchDB, designed to work with the Camping micro-framework.}
|
44
|
+
|
45
|
+
if s.respond_to? :specification_version then
|
46
|
+
s.specification_version = 3
|
47
|
+
|
48
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
49
|
+
s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
|
50
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.6.4"])
|
51
|
+
s.add_development_dependency(%q<rcov>, [">= 0"])
|
52
|
+
s.add_development_dependency(%q<sourcify>, ["~> 0.5.0"])
|
53
|
+
s.add_development_dependency(%q<ShyRubyJS>, [">= 0"])
|
54
|
+
s.add_runtime_dependency(%q<ShyRubyJS>, [">= 0"])
|
55
|
+
s.add_runtime_dependency(%q<sourcify>, [">= 0"])
|
56
|
+
else
|
57
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
58
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
59
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
60
|
+
s.add_dependency(%q<sourcify>, ["~> 0.5.0"])
|
61
|
+
s.add_dependency(%q<ShyRubyJS>, [">= 0"])
|
62
|
+
s.add_dependency(%q<ShyRubyJS>, [">= 0"])
|
63
|
+
s.add_dependency(%q<sourcify>, [">= 0"])
|
64
|
+
end
|
65
|
+
else
|
66
|
+
s.add_dependency(%q<bundler>, ["~> 1.0.0"])
|
67
|
+
s.add_dependency(%q<jeweler>, ["~> 1.6.4"])
|
68
|
+
s.add_dependency(%q<rcov>, [">= 0"])
|
69
|
+
s.add_dependency(%q<sourcify>, ["~> 0.5.0"])
|
70
|
+
s.add_dependency(%q<ShyRubyJS>, [">= 0"])
|
71
|
+
s.add_dependency(%q<ShyRubyJS>, [">= 0"])
|
72
|
+
s.add_dependency(%q<sourcify>, [">= 0"])
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.0
|
data/lib/ShyCouch.rb
ADDED
@@ -0,0 +1,358 @@
|
|
1
|
+
# July 2011
|
2
|
+
# This is a small Ruby layer for working with CouchDB
|
3
|
+
# Built primarily to allow Camping apps to use CouchDB for data persistence
|
4
|
+
# ShyRubyJS is library used to build map and reduce functions from Ruby blocks
|
5
|
+
|
6
|
+
require 'net/http'
|
7
|
+
require 'json'
|
8
|
+
require 'resolv'
|
9
|
+
require 'shyrubyjs'
|
10
|
+
|
11
|
+
module Kernel
|
12
|
+
def shycouch
|
13
|
+
$database = ShyCouch::Connection.Create
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
module ShyCouch
|
18
|
+
|
19
|
+
attr_accessor :database
|
20
|
+
|
21
|
+
class Connection
|
22
|
+
def self.Create(settings=nil)
|
23
|
+
settings = $settings unless settings
|
24
|
+
database = CouchDBAPI.new(settings["db"]["host"], settings["db"]["port"], settings["db"]["name"], settings["db"]["user"], settings["db"]["password"])
|
25
|
+
puts database.connect unless database.connect["ok"]
|
26
|
+
database.create unless database.on_server?
|
27
|
+
return database
|
28
|
+
end
|
29
|
+
|
30
|
+
def push_generic_views
|
31
|
+
#TODO
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
module Data
|
37
|
+
class Model < Hash
|
38
|
+
# takes hash that will be the document contents as well as an array of expected keys for validation
|
39
|
+
# todo - enforce keys that work as attrs
|
40
|
+
|
41
|
+
def initialize(hash=nil, requirements)
|
42
|
+
@requirements = requirements
|
43
|
+
merge!(hash) if hash
|
44
|
+
raise TypeError unless valid? #TODO - should raise a more specific and useful error
|
45
|
+
end
|
46
|
+
|
47
|
+
def method_missing(name, *args)
|
48
|
+
# Makes the object behave as if the hash keys are instance properties with attr_accessors
|
49
|
+
if name.to_s
|
50
|
+
if name[name.length-1] == "="
|
51
|
+
key = name[0, name.length-1]
|
52
|
+
if self.key?(key)
|
53
|
+
self[key] = args
|
54
|
+
return args
|
55
|
+
end
|
56
|
+
else
|
57
|
+
return self[name.to_s] unless !self[name.to_s]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
super
|
61
|
+
end
|
62
|
+
|
63
|
+
def respond_to?(method)
|
64
|
+
# so that testing for whether it responds to a method is equivalent to testing for the existence of a key
|
65
|
+
return true if self.key?(method.to_s)
|
66
|
+
super
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
class CouchDocument < Model
|
71
|
+
class << self
|
72
|
+
# allows instance.class.requirements to be called
|
73
|
+
attr_accessor :requirements
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize(hash={})
|
77
|
+
# Assumes that the "kind" is the class name unless explicitly stated otherwise
|
78
|
+
# TODO - maybe just force it to be the class name no matter what tbh
|
79
|
+
hash["kind"] = self.class.to_s unless hash["kind"]
|
80
|
+
super(hash, @requirements)
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.all
|
84
|
+
database = CouchDatabase.new($settings)
|
85
|
+
database.get()
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.requires(*requirements)
|
89
|
+
@requirements = requirements
|
90
|
+
end
|
91
|
+
|
92
|
+
def add_key(key, value=nil)
|
93
|
+
# The attr value assignment operator has been overriden, but it checks for the existence of a key.
|
94
|
+
# And therefore the user has to explicitly call this method first.
|
95
|
+
self[key] = value
|
96
|
+
end
|
97
|
+
|
98
|
+
def attr_keys
|
99
|
+
# returns the keys for all the attrs that aren't the id or rev
|
100
|
+
attr_keys = []
|
101
|
+
self.map { |k,v|
|
102
|
+
attr_keys << k unless k == "_id" or k == "_rev"
|
103
|
+
}
|
104
|
+
return attr_keys
|
105
|
+
end
|
106
|
+
|
107
|
+
def _requirements
|
108
|
+
#TODO - hm
|
109
|
+
return self.class.requirements
|
110
|
+
end
|
111
|
+
|
112
|
+
def pull(database=nil)
|
113
|
+
database = $database unless database
|
114
|
+
new_doc = database.pull_document(self)
|
115
|
+
if new_doc
|
116
|
+
self.clear
|
117
|
+
self.merge! new_doc
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def push(database = nil)
|
122
|
+
# assumes $database unless it receives a database argument
|
123
|
+
database = $database unless database
|
124
|
+
res = database.push_document(self)
|
125
|
+
self["_id"] = res["id"]
|
126
|
+
self["_rev"] = res["rev"]
|
127
|
+
return res
|
128
|
+
end
|
129
|
+
|
130
|
+
def valid?; to_json ? true : false; end
|
131
|
+
|
132
|
+
def to_json
|
133
|
+
JSON::generate(self)
|
134
|
+
rescue JSON::GeneratorError
|
135
|
+
false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
module Fields
|
141
|
+
#TODO - lightweight validation framework
|
142
|
+
|
143
|
+
class Email_Addr < String
|
144
|
+
def valid?
|
145
|
+
# Valid if: one and only one '@'; at least one "." after the '@'; an mx record can be resolved at the domain
|
146
|
+
valid_address? and valid_domain?
|
147
|
+
end
|
148
|
+
def valid_address?
|
149
|
+
self.split("@").length == 2 and self.split("@")[1].split(".").length >= 2
|
150
|
+
|
151
|
+
end
|
152
|
+
def valid_domain?
|
153
|
+
domain = self.match(/\@(.+)/)[1]
|
154
|
+
Resolv::DNS.open { |dns| dns.getresources(domain, Resolv::DNS::Resource::IN::MX) }.size > 0 ? true : false
|
155
|
+
rescue Resolv::ResolvError
|
156
|
+
false
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
#TODO - split this stuff into modules too
|
162
|
+
class CouchDBAPI
|
163
|
+
def initialize(host, port, name, user, password)
|
164
|
+
@host, @port, @name, @user, @password = host, port, name, user, password
|
165
|
+
@views = []
|
166
|
+
@server = CouchServerConnection.allocate
|
167
|
+
end
|
168
|
+
#
|
169
|
+
# def initialize(*settings)
|
170
|
+
# @host, @port, @name, @user, @password = settings["db"]["host"], settings["db"]["port"], settings["db"]["name"], settings["db"]["user"], settings["db"]["password"]
|
171
|
+
# end
|
172
|
+
|
173
|
+
attr_accessor :server, :name, :host, :port, :views
|
174
|
+
|
175
|
+
def connect
|
176
|
+
@server = CouchServerConnection.new({"host"=>@host, "port"=>@port, "user"=>@user, "password"=>@password})
|
177
|
+
if @server.responds?
|
178
|
+
return {"ok"=>true, "message"=>"Successfully connected to the couch database at #{@host}: #{@port}."}
|
179
|
+
else
|
180
|
+
return {"ok"=>false, "message"=>"Could not connect to the couch database."}
|
181
|
+
end
|
182
|
+
end
|
183
|
+
def delete_database
|
184
|
+
@server.delete_db(self.name)
|
185
|
+
end
|
186
|
+
def server_responds?; return @server.responds?; end
|
187
|
+
|
188
|
+
def on_server?
|
189
|
+
@server.has_database?(@name)
|
190
|
+
end
|
191
|
+
|
192
|
+
def create
|
193
|
+
@server.create_db(@name)
|
194
|
+
end
|
195
|
+
def get_document(id)
|
196
|
+
@server.get_document(@name, id)
|
197
|
+
end
|
198
|
+
def all_docs
|
199
|
+
get_document('_all_docs').rows.map { |doc|
|
200
|
+
get_document(doc["id"])
|
201
|
+
}
|
202
|
+
end
|
203
|
+
def all_docs_with(attribute, value=nil)
|
204
|
+
#TODO - change this to build a couch map query, cache it in couch then call it
|
205
|
+
# maybe?!?!
|
206
|
+
docs = []
|
207
|
+
all_docs.each do |doc|
|
208
|
+
if value
|
209
|
+
docs << doc if doc[attribute] == value
|
210
|
+
else
|
211
|
+
docs << doc if doc[attribute]
|
212
|
+
end
|
213
|
+
end
|
214
|
+
return docs
|
215
|
+
rescue NameError
|
216
|
+
end
|
217
|
+
def uri
|
218
|
+
return "http://#{host}/#{port}/#{name}"
|
219
|
+
end
|
220
|
+
|
221
|
+
def pull_document(document)
|
222
|
+
@server.push_document(self.name, document)
|
223
|
+
end
|
224
|
+
|
225
|
+
def push_document(document)
|
226
|
+
@server.push_document(self.name, document)
|
227
|
+
end
|
228
|
+
|
229
|
+
def designs
|
230
|
+
@server.pull_all_design_docs(self.name)
|
231
|
+
end
|
232
|
+
|
233
|
+
def views
|
234
|
+
designs.map{ |d| d["views"] }
|
235
|
+
end
|
236
|
+
|
237
|
+
private
|
238
|
+
class CouchServerConnection
|
239
|
+
def initialize(args, options=nil)#host, port, user, password, options = nil)
|
240
|
+
@host = args["host"]
|
241
|
+
@port = args["port"]
|
242
|
+
@user = args["user"]
|
243
|
+
@password = args["password"]
|
244
|
+
@options = options
|
245
|
+
end
|
246
|
+
|
247
|
+
def responds?
|
248
|
+
if get('/')['couchdb'] == "Welcome"
|
249
|
+
true
|
250
|
+
else
|
251
|
+
false
|
252
|
+
end
|
253
|
+
rescue Errno::ECONNREFUSED
|
254
|
+
false
|
255
|
+
end
|
256
|
+
|
257
|
+
def has_database?(db_name)
|
258
|
+
get("/#{db_name}/")
|
259
|
+
true
|
260
|
+
rescue RuntimeError => error
|
261
|
+
false
|
262
|
+
end
|
263
|
+
|
264
|
+
#defining the get and delete methods
|
265
|
+
['get', 'delete'].each do |name|
|
266
|
+
define_method name do |uri|
|
267
|
+
response = request(Net::HTTP.const_get(name.capitalize).new(uri)).body
|
268
|
+
JSON.parse(response)
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
def get_database_info(db_name)
|
273
|
+
get("/#{db+name}/")
|
274
|
+
end
|
275
|
+
|
276
|
+
def pull_all_design_docs(db_name)
|
277
|
+
pull_all_doc_ids(db_name).map { get_document(db_name, id) if id[0,7] == "_design" }
|
278
|
+
end
|
279
|
+
|
280
|
+
def pull_all_doc_ids(db_name)
|
281
|
+
get("/#{db_name}/_all_docs")["rows"].map { |doc| doc["id"] }
|
282
|
+
end
|
283
|
+
|
284
|
+
def all_docs_from_database(db_name)
|
285
|
+
pull_all_doc_ids(db_name).map { |id| Data::CouchDocument.new(get("/#{db_name}/#{id}")) }
|
286
|
+
end
|
287
|
+
|
288
|
+
def get_document(db_name, id)
|
289
|
+
document = Data::CouchDocument.new(get("/#{db_name}/#{id}"))
|
290
|
+
end
|
291
|
+
|
292
|
+
def delete_document(db_name, id)
|
293
|
+
delete("/#{db_name}/#{id}")
|
294
|
+
end
|
295
|
+
|
296
|
+
# Haven't decided whether PUT/POST should take a CouchDocument or a JSON string.
|
297
|
+
def put( uri, json = nil )
|
298
|
+
#TODO - make this private
|
299
|
+
req = Net::HTTP::Put.new(uri)
|
300
|
+
req["content-type"] = "application/json"
|
301
|
+
req.body = json unless json == nil
|
302
|
+
JSON.parse(request(req).body)
|
303
|
+
end
|
304
|
+
|
305
|
+
def post(uri, json = nil)
|
306
|
+
# couch uses POST for new documents and gives them an ID
|
307
|
+
req = Net::HTTP::Post.new(uri)
|
308
|
+
req["content-type"] = "application/json"
|
309
|
+
req.body = json unless json == nil
|
310
|
+
JSON.parse(request(req).body)
|
311
|
+
#TODO - return success more meaningfully maybe?
|
312
|
+
end
|
313
|
+
|
314
|
+
def pull_document(db_name, document)
|
315
|
+
document = Data::CouchDocument.new(get("/#{db_name}/#{id}"))
|
316
|
+
end
|
317
|
+
|
318
|
+
def push_document(db_name, document)
|
319
|
+
raise TypeError unless document.class == Data::CouchDocument
|
320
|
+
raise JSON::GeneratorError unless document.valid?
|
321
|
+
if document["_rev"]
|
322
|
+
put("/#{db_name}/#{document._id}?rev=#{document._rev}/", document.to_json)
|
323
|
+
else
|
324
|
+
post("/#{db_name}/", document.to_json)
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
def create_db(db_name)
|
329
|
+
put("/#{db_name}/")
|
330
|
+
end
|
331
|
+
def delete_db(db_name)
|
332
|
+
delete("/#{db_name}/")
|
333
|
+
end
|
334
|
+
|
335
|
+
def UUID
|
336
|
+
get('/_uuids/')['uuids'][0]
|
337
|
+
end
|
338
|
+
|
339
|
+
private
|
340
|
+
|
341
|
+
def handle_error(req, res)
|
342
|
+
raise RuntimeError.new("#{res.code}:#{res.message}\nMETHOD:#{req.method}\nURI:#{req.path}\n#{res.body}")
|
343
|
+
end
|
344
|
+
|
345
|
+
def request(req)
|
346
|
+
res = Net::HTTP.start(@host, @port) { |http|
|
347
|
+
req.basic_auth(@user, @password) if @user and @password
|
348
|
+
http.request(req)
|
349
|
+
}
|
350
|
+
unless res.kind_of?(Net::HTTPSuccess)
|
351
|
+
handle_error(req, res)
|
352
|
+
end
|
353
|
+
res
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
end
|
358
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
begin
|
4
|
+
Bundler.setup(:default, :development)
|
5
|
+
rescue Bundler::BundlerError => e
|
6
|
+
$stderr.puts e.message
|
7
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
8
|
+
exit e.status_code
|
9
|
+
end
|
10
|
+
require 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'ShyCouch'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
data/test/old-test.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
require '~/dev/shycouch/shycouch'
|
2
|
+
require '~/dev/shycouch/shycouchtests'
|
3
|
+
require 'irb'
|
4
|
+
|
5
|
+
ShyCouchTests::test_up
|
6
|
+
ShyCouchTests::test_down
|
7
|
+
message = "Test methods: "
|
8
|
+
message += ShyCouchTests::singleton_methods.map { |m| "ShyCouchTests::#{m}"}.join(', ')
|
9
|
+
puts message
|
10
|
+
IRB.start
|
data/test/old-tests.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
require '~/dev/shycouch/shycouch'
|
2
|
+
module ShyCouchTests
|
3
|
+
def self.test_up
|
4
|
+
begin
|
5
|
+
# set everything up
|
6
|
+
$t_database, $t_id, $t_document = ShyCouch::CouchDatabase.allocate, "", ShyCouch::Data::CouchDocument.new
|
7
|
+
|
8
|
+
#set up the database
|
9
|
+
setup_database
|
10
|
+
setup_document
|
11
|
+
test_model
|
12
|
+
test_doc_kinds
|
13
|
+
# check that everything at least exists
|
14
|
+
result = if $t_database and $t_database.server and $t_id and $t_document #and $test_doc_kinds.length == 1
|
15
|
+
{"ok"=>true,"message"=>"Test environment appears to work","database"=>"$t_database",
|
16
|
+
"server connection"=>"$t_database.server","test doc id"=>"$t_id", "test document"=>"$t_doc",
|
17
|
+
"test doc model"=>"$t_model"}
|
18
|
+
else
|
19
|
+
{"ok"=>false,"message"=>"Test environment appears not to be working","database"=>$t_database,
|
20
|
+
"server connection"=>$t_database.server,"test doc id"=>$t_id,"test document"=>$t_doc}
|
21
|
+
end
|
22
|
+
rescue Errno::ECONNREFUSED
|
23
|
+
result = {"ok"=>false, "message"=>"""Server Connection refused.
|
24
|
+
Is CouchDB running at http://#{$t_database.host}:#{$t_database.port} ?"""}
|
25
|
+
end
|
26
|
+
result.each do |k, v| puts "#{k}: #{v}"; end
|
27
|
+
result["ok"]
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.test_down
|
31
|
+
$t_database.server.delete_db('test')
|
32
|
+
$t_database = nil
|
33
|
+
$t_id = nil
|
34
|
+
$t_doc = nil
|
35
|
+
result = {"ok"=>true, "message"=>"Test environment has been brought down."}
|
36
|
+
result.each do|k, v| puts "#{k}: #{v}"; end
|
37
|
+
end
|
38
|
+
|
39
|
+
class TestModel < ShyCouch::Data::CouchDocument
|
40
|
+
def initialize hash
|
41
|
+
requirements = {
|
42
|
+
"me"=>String,
|
43
|
+
"you"=>Array
|
44
|
+
}
|
45
|
+
super hash, requirements
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def self.setup_database
|
52
|
+
settings = {
|
53
|
+
"db"=> {
|
54
|
+
"host" => "localhost",
|
55
|
+
"port" => 5984,
|
56
|
+
"name" => "test",
|
57
|
+
"user" => "cerales",
|
58
|
+
"password" => "password"
|
59
|
+
},
|
60
|
+
}
|
61
|
+
$t_database = ShyCouch::Create.go(settings)
|
62
|
+
raise Errno::ECONNREFUSED unless $t_database.connect["ok"]
|
63
|
+
$t_database.create_on_server unless $t_database.exists_on_server?
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.setup_document
|
67
|
+
if $t_database.all_docs.length == 0
|
68
|
+
emptyDoc = ShyCouch::Data::CouchDocument.new
|
69
|
+
#$t_id = $t_database.server.push_document($t_database, emptyDoc)["id"]
|
70
|
+
$t_id = $t_database.push_document(emptyDoc)["id"]
|
71
|
+
else
|
72
|
+
$t_id = $t_database.all_docs[0]["id"]
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
def self.test_doc_kinds
|
77
|
+
doc = ShyCouch::Data::CouchDocument.new.merge!("kind"=>"test")
|
78
|
+
doc2 = ShyCouch::Data::CouchDocument.new.merge!("kind"=>"nope")
|
79
|
+
doc3 = ShyCouch::Data::CouchDocument.new.merge!("kind"=>"not me!")
|
80
|
+
$t_database.push_document(doc)
|
81
|
+
$t_database.push_document(doc2)
|
82
|
+
$t_database.push_document(doc3)
|
83
|
+
$t_doc_kind = $t_database.all_docs_with("kind", "not me!")
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.test_model
|
87
|
+
$t_document.merge!($t_database.get_document($t_id))
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch'
|
3
|
+
|
4
|
+
# Most of these tests require a working CouchDB installation to be up and running.
|
5
|
+
# All the tests that expect to work with the database will use the settings defined below.
|
6
|
+
|
7
|
+
# Settings for a database that is set up and working, with an admin user
|
8
|
+
$settings = {
|
9
|
+
"db"=> {
|
10
|
+
"host" => "localhost",
|
11
|
+
"port" => 5984,
|
12
|
+
"name" => "test",
|
13
|
+
"user" => "cerales",
|
14
|
+
"password" => "password"
|
15
|
+
},
|
16
|
+
}
|
17
|
+
|
18
|
+
# test ShyCouch::CouchDBAPI
|
19
|
+
require_relative 'test_couchdb_api'
|
20
|
+
|
21
|
+
# test ShyCouch::Fields
|
22
|
+
# some of the tests in here are disabled cos they involve attempting to resolve a bad domain name
|
23
|
+
require_relative 'test_fields'
|
24
|
+
|
25
|
+
# test ShyCouch::Data::CouchDocument
|
26
|
+
require_relative 'test_couch_document'
|
27
|
+
|
28
|
+
require_relative 'test_camping_integration'
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class CampingIntegrationTests
|
5
|
+
|
6
|
+
class TestModelInheritence < Test::Unit::TestCase
|
7
|
+
|
8
|
+
class InheritanceTest < ShyCouch::Data::CouchDocument; end
|
9
|
+
def test_document_kind_assignment
|
10
|
+
m = InheritanceTest.new
|
11
|
+
assert_equal(InheritanceTest.to_s, m.kind)
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,141 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class CouchDocumentTests# < Test::Unit::TestCase
|
5
|
+
|
6
|
+
class TestDocumentCreation < Test::Unit::TestCase
|
7
|
+
def setup
|
8
|
+
valid_settings = $settings
|
9
|
+
@database = ShyCouch::Connection.Create(valid_settings)
|
10
|
+
end
|
11
|
+
def teardown
|
12
|
+
@database.delete_database
|
13
|
+
@database = nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_create_from_empty_hash
|
17
|
+
# should be able to create a couch doc with a hash argument
|
18
|
+
hash = {}
|
19
|
+
couch_document = ShyCouch::Data::CouchDocument.new(hash)
|
20
|
+
assert_kind_of(ShyCouch::Data::CouchDocument, couch_document)
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_create_from_hash
|
24
|
+
# should be able to create a couch doc with a hash argument
|
25
|
+
hash = {"id" => "rejrandomrandomfhdjf", "rev"=>"1000000", "message"=>"up in here yo"}
|
26
|
+
couch_document = ShyCouch::Data::CouchDocument.new(hash)
|
27
|
+
assert_kind_of(ShyCouch::Data::CouchDocument, couch_document)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_create_from_string
|
31
|
+
# Ensure no doc creation with fixnum argument
|
32
|
+
string = "hehe i'm all over here you know"
|
33
|
+
assert_raises IndexError do
|
34
|
+
doc = ShyCouch::Data::CouchDocument.new(string)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_create_from_fixnum
|
39
|
+
# Ensure no doc creation with fixnum argument
|
40
|
+
fixnum = 1
|
41
|
+
assert_raises TypeError do
|
42
|
+
doc = ShyCouch::Data::CouchDocument.new(fixnum)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
class TestDocumentPulling < Test::Unit::TestCase
|
49
|
+
#TODO
|
50
|
+
end
|
51
|
+
|
52
|
+
class TestDocumentPushing < Test::Unit::TestCase
|
53
|
+
# assumes success of the stuff in TestDocumentPulling
|
54
|
+
def setup
|
55
|
+
valid_settings = $settings
|
56
|
+
$database = ShyCouch::Connection.Create(valid_settings)
|
57
|
+
|
58
|
+
@valid_documents = [
|
59
|
+
ShyCouch::Data::CouchDocument.new({"kind"=>"post", "message"=>"BUY TRAMADOL ONLINE!!"}),
|
60
|
+
ShyCouch::Data::CouchDocument.new({"kind"=>"comment",
|
61
|
+
"message"=>"gry gry online gry gry online gry gry online gry gry online gry gry online "}),
|
62
|
+
ShyCouch::Data::CouchDocument.new({"kind"=>"tag", "name"=>"FREE CANADIAN PRESCRIPTION DRUGS"}),
|
63
|
+
ShyCouch::Data::CouchDocument.new({"kind"=>"helpers",
|
64
|
+
"helpers"=>["helper", "bad helper", "terrible helper", "this isn't helping"],
|
65
|
+
"actually_helpful"=>false, "times_helped"=>0}),
|
66
|
+
]
|
67
|
+
@existing_valid_documents = [
|
68
|
+
ShyCouch::Data::CouchDocument.new("whatever"=>"yep"),
|
69
|
+
ShyCouch::Data::CouchDocument.new("is_a_document"=>true, "number_of_docs_this_is"=>1)
|
70
|
+
].each { |doc|
|
71
|
+
doc.push
|
72
|
+
}
|
73
|
+
@invalid_documents = nil # make sure user can't set rev maybe? or is that legal?
|
74
|
+
end
|
75
|
+
def teardown
|
76
|
+
$database.delete_database
|
77
|
+
$database = nil
|
78
|
+
# delete the database
|
79
|
+
end
|
80
|
+
|
81
|
+
def test_keys_as_attr_accessors
|
82
|
+
# tests that if there is a "phone" key on "doc" object you can do doc.phone
|
83
|
+
@valid_documents.each { |doc|
|
84
|
+
doc.keys.each { |key|
|
85
|
+
assert_respond_to(doc, key)
|
86
|
+
}
|
87
|
+
}
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_push_new_documents
|
91
|
+
@valid_documents.each { |doc|
|
92
|
+
# put the document on the server, grab the server's response
|
93
|
+
res = doc.push
|
94
|
+
# check that the server included "ok"=>true in its response
|
95
|
+
assert(res["ok"])
|
96
|
+
# check that the doc now has an id and a rev
|
97
|
+
assert(doc["_id"])
|
98
|
+
assert(doc["_rev"])
|
99
|
+
# get the new doc
|
100
|
+
newDoc = $database.get_document(doc._id)
|
101
|
+
# test equality of all the attributes aside from id and rev on the new document
|
102
|
+
doc.attr_keys.each { |k|
|
103
|
+
assert_equal(doc["k"], newDoc["k"])
|
104
|
+
}
|
105
|
+
}
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_change_existing_documents
|
109
|
+
@existing_valid_documents.each { |doc|
|
110
|
+
# add some more attributes
|
111
|
+
assert(doc._rev)
|
112
|
+
doc.add_key("owner", "the guvvmint")
|
113
|
+
doc.add_key("buttonCount")
|
114
|
+
doc.add_key("friends")
|
115
|
+
doc.buttonCount = 5
|
116
|
+
doc.friends = ["alan", "alex", "all me other mates"]
|
117
|
+
|
118
|
+
res = doc.push
|
119
|
+
assert(res["ok"])
|
120
|
+
|
121
|
+
# pull it from the database again
|
122
|
+
checkDoc = $database.get_document(doc._id)
|
123
|
+
|
124
|
+
# check that the one from the database has all the new attributes
|
125
|
+
assert_equal(doc.owner, checkDoc.owner)
|
126
|
+
assert_equal(doc.buttonCount, checkDoc.buttonCount)
|
127
|
+
assert_equal(doc.friends, checkDoc.friends)
|
128
|
+
}
|
129
|
+
end
|
130
|
+
|
131
|
+
def test_illegal_change_to_rev
|
132
|
+
@existing_valid_documents.each { |doc|
|
133
|
+
doc._rev = "hurr"
|
134
|
+
assert_raises RuntimeError do
|
135
|
+
res = doc.push
|
136
|
+
end
|
137
|
+
}
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class TestCouchDBAPI < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
valid_settings = $settings
|
7
|
+
$database = ShyCouch::Connection.Create(valid_settings)
|
8
|
+
end
|
9
|
+
|
10
|
+
def teardown
|
11
|
+
$database.delete_database
|
12
|
+
$database = nil
|
13
|
+
end
|
14
|
+
|
15
|
+
def test_connection
|
16
|
+
assert_equal(true, $database.connect["ok"])
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class TestCouchDBFactory < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@valid_settings = $settings
|
7
|
+
end
|
8
|
+
|
9
|
+
def teardown
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_create_database
|
13
|
+
assert_kind_of(ShyCouch::CouchDBAPI, ShyCouch::Create.go(@valid_settings))
|
14
|
+
end
|
15
|
+
end
|
data/test/test_fields.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require_relative '../lib/ShyCouch.rb'
|
3
|
+
|
4
|
+
class TestEmailField < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
@valid_emails = ['bigbeggar@gmail.com', 'helpmeout@bigpond.com'] # more!
|
7
|
+
@invalid_emails = ['byby.head@heat']#, 'looptheloop@ireallyhopethisisntadomainpleasedontbeadomain.org'] # more!
|
8
|
+
#commented out the one with an invalid domain cos resolve timeout long
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown; end
|
12
|
+
|
13
|
+
def test_valid_emails
|
14
|
+
@valid_emails.each do |email|
|
15
|
+
email_addr = ShyCouch::Fields::Email_Addr.new(email)
|
16
|
+
assert_equal(true, email_addr.valid?)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_invalid_emails
|
21
|
+
@invalid_emails.each do |email|
|
22
|
+
email_addr = ShyCouch::Fields::Email_Addr.new(email)
|
23
|
+
assert_equal(false, email_addr.valid?)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
metadata
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ShyCouch
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Shy Inc.
|
9
|
+
- Daniel Bryan
|
10
|
+
- Cerales
|
11
|
+
autorequire:
|
12
|
+
bindir: bin
|
13
|
+
cert_chain: []
|
14
|
+
date: 2011-08-14 00:00:00.000000000Z
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: bundler
|
18
|
+
requirement: &70299706365800 !ruby/object:Gem::Requirement
|
19
|
+
none: false
|
20
|
+
requirements:
|
21
|
+
- - ~>
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.0.0
|
24
|
+
type: :development
|
25
|
+
prerelease: false
|
26
|
+
version_requirements: *70299706365800
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: jeweler
|
29
|
+
requirement: &70299706364960 !ruby/object:Gem::Requirement
|
30
|
+
none: false
|
31
|
+
requirements:
|
32
|
+
- - ~>
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 1.6.4
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: *70299706364960
|
38
|
+
- !ruby/object:Gem::Dependency
|
39
|
+
name: rcov
|
40
|
+
requirement: &70299706364040 !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
type: :development
|
47
|
+
prerelease: false
|
48
|
+
version_requirements: *70299706364040
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: sourcify
|
51
|
+
requirement: &70299706363060 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ~>
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: 0.5.0
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: *70299706363060
|
60
|
+
- !ruby/object:Gem::Dependency
|
61
|
+
name: ShyRubyJS
|
62
|
+
requirement: &70299706361900 !ruby/object:Gem::Requirement
|
63
|
+
none: false
|
64
|
+
requirements:
|
65
|
+
- - ! '>='
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: *70299706361900
|
71
|
+
- !ruby/object:Gem::Dependency
|
72
|
+
name: ShyRubyJS
|
73
|
+
requirement: &70299706360460 !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '0'
|
79
|
+
type: :runtime
|
80
|
+
prerelease: false
|
81
|
+
version_requirements: *70299706360460
|
82
|
+
- !ruby/object:Gem::Dependency
|
83
|
+
name: sourcify
|
84
|
+
requirement: &70299706359260 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ! '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: *70299706359260
|
93
|
+
description: Ruby API for CouchDB, designed to work with the Camping micro-framework.
|
94
|
+
email: danbryan@gmail.com
|
95
|
+
executables: []
|
96
|
+
extensions: []
|
97
|
+
extra_rdoc_files:
|
98
|
+
- LICENSE.txt
|
99
|
+
- README.rdoc
|
100
|
+
files:
|
101
|
+
- .document
|
102
|
+
- Gemfile
|
103
|
+
- Gemfile.lock
|
104
|
+
- LICENSE.txt
|
105
|
+
- README.rdoc
|
106
|
+
- Rakefile
|
107
|
+
- ShyCouch.gemspec
|
108
|
+
- VERSION
|
109
|
+
- lib/ShyCouch.rb
|
110
|
+
- test/helper.rb
|
111
|
+
- test/old-test.rb
|
112
|
+
- test/old-tests.rb
|
113
|
+
- test/test_ShyCouch.rb
|
114
|
+
- test/test_camping_integration.rb
|
115
|
+
- test/test_couch_document.rb
|
116
|
+
- test/test_couchdb_api.rb
|
117
|
+
- test/test_couchdb_factory.rb
|
118
|
+
- test/test_fields.rb
|
119
|
+
homepage: http://github.com/Cerales/ShyCouch
|
120
|
+
licenses:
|
121
|
+
- MIT
|
122
|
+
post_install_message:
|
123
|
+
rdoc_options: []
|
124
|
+
require_paths:
|
125
|
+
- lib
|
126
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
segments:
|
133
|
+
- 0
|
134
|
+
hash: 2260560036860812579
|
135
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
136
|
+
none: false
|
137
|
+
requirements:
|
138
|
+
- - ! '>='
|
139
|
+
- !ruby/object:Gem::Version
|
140
|
+
version: '0'
|
141
|
+
requirements: []
|
142
|
+
rubyforge_project:
|
143
|
+
rubygems_version: 1.8.6
|
144
|
+
signing_key:
|
145
|
+
specification_version: 3
|
146
|
+
summary: Ruby API for CouchDB, designed to work with the Camping micro-framework.
|
147
|
+
test_files: []
|