leanback 0.4.0 → 0.4.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.
- data/Changelog.rdoc +6 -0
- data/README.md +1 -1
- data/VERSION +1 -1
- data/documentation/static/2011/11/20/i-moved-leanback-documentation/index.html +180 -0
- data/documentation/static/2011/11/20/index.html +146 -0
- data/documentation/static/2011/11/index.html +146 -0
- data/documentation/static/2011/index.html +146 -0
- data/documentation/static/2013/06/02/index.html +146 -0
- data/documentation/static/2013/06/02/released-leanback-v0-3-4/index.html +180 -0
- data/documentation/static/2013/06/09/index.html +146 -0
- data/documentation/static/2013/06/09/released-leanback-v0-4-0/index.html +179 -0
- data/documentation/static/2013/06/index.html +158 -0
- data/documentation/static/2013/index.html +158 -0
- data/documentation/static/author/admin/index.html +175 -0
- data/documentation/static/basic-couchdb-operations/index.html +259 -0
- data/documentation/static/category/uncategorized/index.html +170 -0
- data/documentation/static/couchdb-configuration/index.html +189 -0
- data/documentation/static/couchdb-security/index.html +218 -0
- data/documentation/static/count-by-multiple-documents/index.html +221 -0
- data/documentation/static/count-documents-by-key/index.html +177 -0
- data/documentation/static/css/2c-l-fixed.css +1 -0
- data/documentation/static/css/2c-l-fixed.dev.css +62 -0
- data/documentation/static/css/2c-r-fixed.css +1 -0
- data/documentation/static/css/2c-r-fixed.dev.css +60 -0
- data/documentation/static/css/3c-c-fixed.css +1 -0
- data/documentation/static/css/3c-c-fixed.dev.css +84 -0
- data/documentation/static/css/3c-l-fixed.css +1 -0
- data/documentation/static/css/3c-l-fixed.dev.css +61 -0
- data/documentation/static/css/3c-r-fixed.css +1 -0
- data/documentation/static/css/3c-r-fixed.dev.css +62 -0
- data/documentation/static/css/holy-grail-fluid.css +5 -0
- data/documentation/static/css/plugins.css +5 -0
- data/documentation/static/css/print.css +5 -0
- data/documentation/static/css/screen.css +1 -0
- data/documentation/static/design-documents-and-permanent-views/index.html +454 -0
- data/documentation/static/error-handling/index.html +157 -0
- data/documentation/static/find-document-by-multiple-keys/index.html +269 -0
- data/documentation/static/find-documents-by-key/index.html +243 -0
- data/documentation/static/index.html +161 -0
- data/documentation/static/leanback/index.html +130 -0
- data/documentation/static/leanback/installation/index.html +119 -0
- data/documentation/static/setting-the-bind_address-port/index.html +151 -0
- data/documentation/static/style.css +16 -0
- data/leanback.gemspec +44 -2
- data/lib/leanback.rb +518 -535
- data/spec/no_admin_party/cloudant_spec.rb +365 -0
- metadata +45 -3
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Name: Hybrid
|
|
3
|
+
* Theme URI: http://themehybrid.com/themes/hybrid
|
|
4
|
+
* Description: A user-friendly, search-engine optimized parent theme, featuring 15 custom page templates and multiple widget-ready areas, allowing you to create any type of site you want.
|
|
5
|
+
* Version: 1.0
|
|
6
|
+
* Author: Justin Tadlock
|
|
7
|
+
* Author URI: http://justintadlock.com
|
|
8
|
+
* Tags: theme-options, threaded-comments, sticky-post, microformats, translation-ready, rtl-language-support, one-column, two-columns, three-columns, fixed-width
|
|
9
|
+
* License: GNU General Public License v2.0
|
|
10
|
+
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
|
|
11
|
+
*
|
|
12
|
+
* Copyright (c) 2008 - 2011 Justin Tadlock. All rights reserved.
|
|
13
|
+
* http://justintadlock.com
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
html,body,div,span,object,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,img,ins,kbd,q,samp,small,strong,sub,sup,tt,var,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,canvas,details,figcaption,figure,footer,header,hgroup,menu,nav,section,summary,time,mark,audio,video{margin:0;padding:0;vertical-align:baseline;outline:none;font-size:100%;background:transparent;border:none;text-decoration:none}article,aside,details,figcaption,figure,footer,header,hgroup,menu,nav,section{display:block}b,i,hr,u,center,menu,layer,s,strike,font,xmp{margin:0;padding:0;vertical-align:baseline;outline:none;font-size:100%;font-weight:normal;font-style:normal;background:transparent;border:none;text-decoration:none}body{line-height:24px;font-family:Georgia,Times,"Times New Roman",serif;color:#333;background:#fff}h1,h2,h3,h4,h5,h6{font-style:normal;font-weight:normal;margin:0 0 21px 0}h1{font-size:1.8em}h2{font-size:1.7em}h3{font-size:1.55em}h4{font-size:1.4em}h5{font-size:1.25em}h6{font-size:1.1em}p{margin:0 0 21px 0}ol,ul{list-style:none}ul{list-style:disc;margin:0 0 21px 2.5em}ol{list-style-type:decimal;margin:0 0 21px 3em}ol ol{list-style:upper-roman}ol ol ol{list-style:lower-roman}ol ol ol ol{list-style:upper-alpha}ol ol ol ol ol{list-style:lower-alpha}ul ul,ol ol,ul ol,ol ul{margin-bottom:0}dl{margin:0 0 18px 3px}dl dt{font-weight:bold;margin:12px 0 0 0}dl dd{margin:6px 0 0 1.5em}strong{font-weight:bold}strong strong{font-weight:normal}em,cite{font-style:italic}em em,cite cite{font-style:normal}abbr{cursor:help}acronym{text-transform:uppercase;border-bottom:1px dashed #666;cursor:help}big{font-size:120%}small,sup,sub{font-size:80%}sup{vertical-align:baseline;position:relative;bottom:0.3em}sub{vertical-align:baseline;position:relative;top:0.3em}address{font-style:italic;margin:0 0 21px 0}li address,dd address{margin:0}blockquote{margin:0 2.5em;font-style:normal}blockquote em,blockquote cite{font-style:italic}blockquote,q{quotes:none}blockquote:before,blockquote:after,q:before,q:after{content:'';content:none}a{cursor:pointer}a img{border:none}pre{overflow:auto;font:.9em Monaco,monospace,Courier,"Courier New";line-height:21px;margin-bottom:21px;padding:9px}code{font:.9em Monaco,monospace,Courier,"Courier New"}pre code{font-size:1em}ins,dfn{font-style:italic;text-decoration:none;border-bottom:1px solid #666}del,s,strike{text-decoration:line-through}object{margin-bottom:21px}input,textarea{font-size:1em;padding:3px}input[type="submit"]{cursor:pointer}:focus{outline:none}form label{cursor:pointer}option{padding:1px 3px}table{border-collapse:collapse;border-spacing:0;margin-bottom:21px}th,td{text-align:left}hr{height:1px;margin-bottom:21px;background:#333}img.wp-smiley{max-height:12px;margin:0;padding:0;border:none}.gallery{display:block;text-align:center;margin-bottom:21px}.alignleft,.left{float:left;margin-right:15px}.alignright,.right{float:right;margin-left:15px}.aligncenter,.center{display:block;margin:0 auto 21px auto}.alignnone,.block{clear:both;margin:0 0 21px 0}.clear{clear:both}img.alignleft,img.alignright{display:inline}blockquote.alignleft,blockquote.alignright{width:33%}#body-container{overflow:hidden;width:960px;margin:0 auto}#container{overflow:hidden;float:left;width:960px}.content{overflow:hidden;float:left;width:620px}.no-widgets .content,.no-default-widgets .content{width:960px}#primary{position:relative;float:right;width:300px}#secondary{position:relative;clear:right;float:right;width:300px}#subsidiary{overflow:hidden}#subsidiary .widget{overflow:hidden;float:left;width:300px;margin:0 20px 0 0}#footer-container{clear:both;overflow:hidden}#footer{clear:both;overflow:hidden}div.menu ul{margin:0;padding:0;list-style:none;line-height:1.0}div.menu ul ul{position:absolute;top:-999em;width:10em}div.menu ul ul li{width:100%}div.menu li:hover{visibility:inherit}div.menu li{float:left;position:relative}div.menu a{display:block;position:relative}div.menu li:hover ul,li.sfHover ul{left:0;top:2em;z-index:99}div.menu li:hover li ul,li.sfHover li ul{top:-999em}div.menu li li:hover ul,li li.sfHover ul{left:10em;top:0}div.menu li li:hover li ul,li li.sfHover li ul{top:-999em}div.menu li li li:hover ul,li li li.sfHover ul{left:10em;top:0}.gallery{display:block;clear:both;overflow:hidden;margin:0 auto}.gallery .gallery-row{display:block;clear:both;overflow:hidden;margin:0}.gallery .gallery-item{overflow:hidden;float:left;margin:0;text-align:center;list-style:none;padding:0}.gallery .gallery-item .gallery-icon img{width:auto;max-width:89%;height:auto;padding:1%;margin:0 auto}.gallery-caption{margin-left:0}.gallery .col-0{width:100%}.gallery .col-1{width:100%}.gallery .col-2{width:50%}.gallery .col-3{width:33.33%}.gallery .col-4{width:25%}.gallery .col-5{width:20%}.gallery .col-6{width:16.66%}.gallery .col-7{width:14.28%}.gallery .col-8{width:12.5%}.gallery .col-9{width:11.11%}.gallery .col-10{width:10%}.gallery .col-11{width:9.09%}.gallery .col-12{width:8.33%}.gallery .col-13{width:7.69%}.gallery .col-14{width:7.14%}.gallery .col-15{width:6.66%}.gallery .col-16{width:6.25%}.gallery .col-17{width:5.88%}.gallery .col-18{width:5.55%}.gallery .col-19{width:5.26%}.gallery .col-20{width:5%}.gallery .col-21{width:4.76%}.gallery .col-22{width:4.54%}.gallery .col-23{width:4.34%}.gallery .col-24{width:4.16%}.gallery .col-25{width:4%}.gallery .col-26{width:3.84%}.gallery .col-27{width:3.7%}.gallery .col-28{width:3.57%}.gallery .col-29{width:3.44%}.gallery .col-30{width:3.33%}.sticky,.bypostauthor{}body{font:normal normal normal 15px/21px Georgia,Times,"Times New Roman",serif;color:#000}#body-container{margin:90px auto 21px auto}a{color:#21759b;text-decoration:none}a:visited{color:#551a8b}a:hover,a:active{color:#d54e21;text-decoration:underline}h1,h2,h3,h4,h5,h6{font-family:Arial,Verdana,sans-serif;color:#000;font-weight:bold}h1{font-size:24px}h2{font-size:21px}h3{font-size:19px}h4{font-size:17px}h5{font-size:15px}h6{font-size:13px}ul{list-style:square}blockquote{font-style:italic;color:#555}blockquote blockquote{color:#777}blockquote em{font-style:normal}pre{padding:9px;background:#f9f9f9;border:1px solid #ccc}code{padding:0 3px;background:#eee}pre code{background:transparent}table{width:100%;border-collapse:separate;border-top:1px solid #ccc;border-left:1px solid #ccc}caption{font-size:.9em;font-style:italic;text-align:right}td,th{padding:3px 6px;border-bottom:1px solid #ccc;border-right:1px solid #ccc}th{background:#eee}.drop-cap{float:left;margin:3px 3px 0 0;font:normal normal normal 47px/35px "Warnock Pro","Goudy Old Style",Palatino,"Book Antiqua",Georgia,serif;color:#333}.note{padding:6px 9px;background:#eee;border:1px solid #ccc}.warning,.alert{padding:6px 9px;background:#fffbbc;border:1px solid #E6DB55}.error{padding:6px 9px;background:#ffebe8;border:1px solid #C00}.download{padding:6px 9px;background:#e7f7d3;border:1px solid #6c3}.breadcrumb{margin:0 0 30px 0;font-size:.9em;font-style:italic;color:#666}.breadcrumb a{color:#111;text-decoration:none}.breadcrumb a:hover{color:#d54e21;text-decoration:underline}.hentry img{max-width:610px;height:auto;padding:4px;border:1px solid #ccc}.no-widgets .hentry img{max-width:950px}img.alignleft,img.alignright{margin-bottom:10px}.thumbnail{float:left;width:100px;height:100px;margin:5px 15px 10px 0}img.wp-smiley{max-width:12px;padding:0;background:transparent;border:none}.wp-caption{max-width:616px;margin-top:6px;padding:6px 1px 3px 1px;border:1px solid #ccc;text-align:center}.wp-caption .wp-caption-text{margin:0;padding:0 5px;text-align:right;font-size:.9em;font-style:italic;color:#666}.wp-caption img{max-width:604px;margin:0 auto;padding:0;border:1px solid #666}.no-widgets .wp-caption{max-width:956px}.no-widgets .wp-caption img{max-width:946px}.gallery img{border:1px solid #ccc}.avatar{float:left;width:100px;height:100px;margin:5px 15px 0 0;padding:4px;border:1px solid #ccc}#header{margin:0 0 40px 0}#site-title{font:normal normal bold 35px/35px Arial,Verdana,sans-serif;margin:0 0 10px 0}#site-title a{color:#000}#site-description{font:normal normal normal 16px/20px Georgia,Times,"Times New Roman",serif;margin:0;color:#666}#primary-menu,#navigation{overflow:visible;height:34px;margin:0 0 60px 0;z-index:100}#primary-menu li,#page-nav li{margin-right:15px}#primary-menu li li,#page-nav li li{margin-right:0}#primary-menu li a,#page-nav li a{padding:8px 15px 8px 15px;color:#111;background:#fff;border:1px solid #ccc}#primary-menu li:hover ul,#primary-menu li.sfHover ul,#page-nav li:hover ul,#page-nav li.sfHover ul{top:32px}#primary-menu li li a,#page-nav li li a{border-top:none;margin-right:0}#primary-menu li ul,#page-nav li ul{background:#fff;border-top:1px solid #ccc}#primary-menu li li:hover ul,#primary-menu li li.sfHover ul,#primary-menu li li li:hover ul,#primary-menu li li li.sfHover ul,#page-nav li li:hover ul,#page-nav li li.sfHover ul,#page-nav li li li:hover ul,#page-nav li li li.sfHover ul {top:-1px}#primary-menu li li li,#page-nav li li li{margin-left:-1px}#container{margin-bottom:21px}.content{margin:0 0 21px 0}.no-widgets .content,.page-template-no-widgets .content{width:960px}.hentry{overflow:hidden;margin:0 0 40px 0}.singular .hentry{margin:0}.loop-meta{overflow:hidden;margin:0 0 40px 0}.loop-title{font:normal normal bold 24px/24px Arial,Verdana,sans-serif}.entry-title{font:normal normal bold 24px/24px Arial,Verdana,sans-serif;margin:0 0 12px 0}.archive .entry-title,.search .entry-title{font-size:21px;margin:0 0 5px 0}.singular-page .entry-title,.singular-attachment .entry-title{margin:0 0 21px 0}.entry-title a{color:#000}.byline{margin:0 0 30px 0;font-style:italic;color:#666}.archive .byline,.search .byline{margin:0 0 5px 0}.entry-content{margin:0 0 10px 0}.entry-meta{clear:both;font-style:italic;color:#666}p.page-links,.comment-pagination{clear:both}.comment-pagination{margin-bottom:21px}p.page-links a,.comment-pagination .page-numbers{margin:0 3px;padding:3px 9px 3px 9px;border:1px solid #ccc}.navigation-links{margin-bottom:21px;font-style:italic}.navigation-links .previous{float:left;max-width:50%}.navigation-links .next{float:right;max-width:50%;text-align:right}.navigation-attachment{overflow:hidden}.widget{overflow:hidden;margin:0 0 15px 0;color:#464646}.widget a{color:#464646;text-decoration:underline}.widget a:hover{color:#d54e21;text-decoration:none}.widget-title{font-size:18px;color:#111}#utility-before-content,#utility-after-content,#utility-after-page,#utility-after-single{margin:0 0 21px 0;padding:20px 20px 0 20px;border:1px solid #ccc}#comments-template{clear:both}.comments-header{font-size:1.2em}.comments-closed{font-style:italic}ol.comment-list,ol.comment-list ol.children{list-style:none;margin:0 0 21px 0}li.comment,li li li.comment,li li li li li.comment,li li li li li li li.comment,li li li li li li li li li.comment,li.pingback,li.trackback{overflow:hidden;margin:0 0 21px 0;padding:21px 21px 0 21px;background:#fff;border:1px solid #ccc}li li.comment,li li li li.comment,li li li li li li.comment,li li li li li li li li.comment,li li li li li li li li li li.comment{background:#f9f9f9}#comments-template .avatar{width:40px;height:40px;float:left;margin-right:15px;padding:0;border:1px solid #666}.comment-meta{margin:10px 0 21px 0;font-size:13px;color:#666}.comment-author{font-size:15px;color:#000}.comment-reply-link,.permalink,.comment-edit-link{font-style:italic;color:#666}.comment-text{clear:left;margin:0 15px}.text-input{display:block;padding:3px 6px;width:97%}#comments-template label{font-size:.9em}textarea{width:98%}#submit{display:inline-block;margin-right:15px;padding:7px 15px 8px 15px;background:#fff;border:1px solid #ccc}#submit:hover{cursor:pointer;background:#f9f9f9}#footer-container{clear:both;margin:0 0 21px 0}#subsidiary{margin:0 0 21px 0}#footer{font-style:italic;color:#444}#footer .copyright{display:inline;float:left;margin-right:9px}.content{float:left;width:620px}#primary{float:right;width:300px}#secondary{clear:right;float:right;width:300px}
|
data/leanback.gemspec
CHANGED
|
@@ -5,11 +5,11 @@
|
|
|
5
5
|
|
|
6
6
|
Gem::Specification.new do |s|
|
|
7
7
|
s.name = "leanback"
|
|
8
|
-
s.version = "0.4.
|
|
8
|
+
s.version = "0.4.1"
|
|
9
9
|
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
|
11
11
|
s.authors = ["Obi Akubue"]
|
|
12
|
-
s.date = "2013-
|
|
12
|
+
s.date = "2013-08-24"
|
|
13
13
|
s.description = "lightweight Ruby interface to CouchDB"
|
|
14
14
|
s.email = "obioraakubue@yahoo.com"
|
|
15
15
|
s.extra_rdoc_files = [
|
|
@@ -25,9 +25,50 @@ Gem::Specification.new do |s|
|
|
|
25
25
|
"README.md",
|
|
26
26
|
"Rakefile",
|
|
27
27
|
"VERSION",
|
|
28
|
+
"documentation/static/2011/11/20/i-moved-leanback-documentation/index.html",
|
|
29
|
+
"documentation/static/2011/11/20/index.html",
|
|
30
|
+
"documentation/static/2011/11/index.html",
|
|
31
|
+
"documentation/static/2011/index.html",
|
|
32
|
+
"documentation/static/2013/06/02/index.html",
|
|
33
|
+
"documentation/static/2013/06/02/released-leanback-v0-3-4/index.html",
|
|
34
|
+
"documentation/static/2013/06/09/index.html",
|
|
35
|
+
"documentation/static/2013/06/09/released-leanback-v0-4-0/index.html",
|
|
36
|
+
"documentation/static/2013/06/index.html",
|
|
37
|
+
"documentation/static/2013/index.html",
|
|
38
|
+
"documentation/static/author/admin/index.html",
|
|
39
|
+
"documentation/static/basic-couchdb-operations/index.html",
|
|
40
|
+
"documentation/static/category/uncategorized/index.html",
|
|
41
|
+
"documentation/static/couchdb-configuration/index.html",
|
|
42
|
+
"documentation/static/couchdb-security/index.html",
|
|
43
|
+
"documentation/static/count-by-multiple-documents/index.html",
|
|
44
|
+
"documentation/static/count-documents-by-key/index.html",
|
|
45
|
+
"documentation/static/css/2c-l-fixed.css",
|
|
46
|
+
"documentation/static/css/2c-l-fixed.dev.css",
|
|
47
|
+
"documentation/static/css/2c-r-fixed.css",
|
|
48
|
+
"documentation/static/css/2c-r-fixed.dev.css",
|
|
49
|
+
"documentation/static/css/3c-c-fixed.css",
|
|
50
|
+
"documentation/static/css/3c-c-fixed.dev.css",
|
|
51
|
+
"documentation/static/css/3c-l-fixed.css",
|
|
52
|
+
"documentation/static/css/3c-l-fixed.dev.css",
|
|
53
|
+
"documentation/static/css/3c-r-fixed.css",
|
|
54
|
+
"documentation/static/css/3c-r-fixed.dev.css",
|
|
55
|
+
"documentation/static/css/holy-grail-fluid.css",
|
|
56
|
+
"documentation/static/css/plugins.css",
|
|
57
|
+
"documentation/static/css/print.css",
|
|
58
|
+
"documentation/static/css/screen.css",
|
|
59
|
+
"documentation/static/design-documents-and-permanent-views/index.html",
|
|
60
|
+
"documentation/static/error-handling/index.html",
|
|
61
|
+
"documentation/static/find-document-by-multiple-keys/index.html",
|
|
62
|
+
"documentation/static/find-documents-by-key/index.html",
|
|
63
|
+
"documentation/static/index.html",
|
|
64
|
+
"documentation/static/leanback/index.html",
|
|
65
|
+
"documentation/static/leanback/installation/index.html",
|
|
66
|
+
"documentation/static/setting-the-bind_address-port/index.html",
|
|
67
|
+
"documentation/static/style.css",
|
|
28
68
|
"leanback.gemspec",
|
|
29
69
|
"lib/leanback.rb",
|
|
30
70
|
"spec/admin_party/database_spec.rb",
|
|
71
|
+
"spec/no_admin_party/cloudant_spec.rb",
|
|
31
72
|
"spec/no_admin_party/database_spec.rb",
|
|
32
73
|
"spec/no_admin_party/non_admin_user_spec.rb",
|
|
33
74
|
"spec/spec_base.rb",
|
|
@@ -46,6 +87,7 @@ Gem::Specification.new do |s|
|
|
|
46
87
|
s.summary = "lightweight Ruby interface to CouchDB"
|
|
47
88
|
s.test_files = [
|
|
48
89
|
"spec/admin_party/database_spec.rb",
|
|
90
|
+
"spec/no_admin_party/cloudant_spec.rb",
|
|
49
91
|
"spec/no_admin_party/database_spec.rb",
|
|
50
92
|
"spec/no_admin_party/non_admin_user_spec.rb",
|
|
51
93
|
"spec/spec_base.rb",
|
data/lib/leanback.rb
CHANGED
|
@@ -3,621 +3,604 @@ require 'yajl'
|
|
|
3
3
|
require 'erb'
|
|
4
4
|
|
|
5
5
|
class CouchdbException < RuntimeError
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
attr :error
|
|
7
|
+
def initialize(error)
|
|
8
8
|
@error = error.values[0]
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
module Couchdb
|
|
13
|
+
def self.couch_error(e)
|
|
14
|
+
raise e if e.is_a? OpenSSL::SSL::SSLError
|
|
15
|
+
hash = Yajl::Parser.parse(e.response.to_s)
|
|
16
|
+
raise CouchdbException.new(hash), "CouchDB: Error - #{hash.values[0]}. Reason - #{hash.values[1]}"
|
|
17
|
+
end
|
|
13
18
|
|
|
14
|
-
def self.salt
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
19
|
+
def self.salt
|
|
20
|
+
o = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten;
|
|
21
|
+
salt = (0..50).map{ o[rand(o.length)] }.join;
|
|
22
|
+
end
|
|
18
23
|
|
|
19
|
-
#change non-admin user password
|
|
20
|
-
def self.change_password(username, new_password,auth_session = "")
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
24
|
+
#change non-admin user password
|
|
25
|
+
def self.change_password(username, new_password,auth_session = "")
|
|
26
|
+
salty = salt()
|
|
27
|
+
password_sha = Digest::SHA1.hexdigest(new_password + salty)
|
|
28
|
+
user_id = 'org.couchdb.user:' + username
|
|
29
|
+
data = {"salt" => salty,"password_sha" => password_sha}
|
|
30
|
+
doc = { :database => '_users', :doc_id => user_id, :data => data}
|
|
31
|
+
update_doc doc,auth_session
|
|
32
|
+
end
|
|
28
33
|
|
|
29
|
-
#add a new user
|
|
30
|
-
def self.add_user(user, auth_session="")
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
end
|
|
34
|
+
#add a new user
|
|
35
|
+
def self.add_user(user, auth_session="")
|
|
36
|
+
o = [('a'..'z'),('A'..'Z')].map{|i| i.to_a}.flatten;
|
|
37
|
+
salt = (0..50).map{ o[rand(o.length)] }.join;
|
|
38
|
+
new_user = {:username => user[:username], :password => user[:password], :roles => user[:roles], :salt => salt}
|
|
39
|
+
create_user(new_user,auth_session)
|
|
40
|
+
end
|
|
36
41
|
|
|
37
|
-
#create a new user
|
|
38
|
-
def self.create_user(user,auth_session= "")
|
|
39
|
-
|
|
42
|
+
#create a new user
|
|
43
|
+
def self.create_user(user,auth_session= "")
|
|
44
|
+
password_sha = Digest::SHA1.hexdigest(user[:password] + user[:salt])
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
46
|
+
user_hash = { :type => "user",
|
|
47
|
+
:name => user[:username],
|
|
48
|
+
:password_sha => password_sha,
|
|
49
|
+
:salt => user[:salt],
|
|
50
|
+
:roles => user[:roles]
|
|
51
|
+
}
|
|
47
52
|
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
end
|
|
57
|
-
|
|
58
|
-
end
|
|
53
|
+
str = Yajl::Encoder.encode(user_hash)
|
|
54
|
+
set_address
|
|
55
|
+
begin
|
|
56
|
+
response = RestClient.put "#{@address}:#{@port}/_users/org.couchdb.user:#{URI.escape(user[:username])}", str,{:cookies => {"AuthSession" => auth_session}}
|
|
57
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
58
|
+
rescue => e
|
|
59
|
+
couch_error(e)
|
|
60
|
+
end
|
|
59
61
|
|
|
60
|
-
|
|
61
|
-
def self.set_security(db_name, data,auth_session="")
|
|
62
|
-
security_data = Yajl::Encoder.encode(data)
|
|
63
|
-
set_address
|
|
64
|
-
begin
|
|
65
|
-
response = RestClient.put 'http://' + @address + ':' + @port + '/' + URI.escape(db_name) + '/_security/',security_data, {:cookies => {"AuthSession" => auth_session}}
|
|
66
|
-
hash = Yajl::Parser.parse(response.to_str)
|
|
67
|
-
rescue => e
|
|
68
|
-
hash = Yajl::Parser.parse(e.response.to_s)
|
|
69
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
70
|
-
end
|
|
71
|
-
end
|
|
72
|
-
#get security object
|
|
73
|
-
def self.get_security(db_name, auth_session="")
|
|
74
|
-
set_address
|
|
75
|
-
begin
|
|
76
|
-
response = RestClient.get 'http://' + @address + ':' + @port + '/' + URI.escape(db_name) + '/_security/', {:cookies => {"AuthSession" => auth_session}}
|
|
77
|
-
hash = Yajl::Parser.parse(response.to_str)
|
|
78
|
-
rescue => e
|
|
79
|
-
hash = Yajl::Parser.parse(e.response.to_s)
|
|
80
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
81
|
-
end
|
|
82
|
-
end
|
|
62
|
+
end
|
|
83
63
|
|
|
64
|
+
#add security object
|
|
65
|
+
def self.set_security(db_name, data,auth_session="")
|
|
66
|
+
security_data = Yajl::Encoder.encode(data)
|
|
67
|
+
set_address
|
|
68
|
+
begin
|
|
69
|
+
response = RestClient.put "#{@address}:#{@port}/#{URI.escape(db_name)}/_security/",security_data, {:cookies => {"AuthSession" => auth_session}}
|
|
70
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
71
|
+
rescue => e
|
|
72
|
+
couch_error(e)
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
#get security object
|
|
77
|
+
def self.get_security(db_name, auth_session="")
|
|
78
|
+
set_address
|
|
79
|
+
begin
|
|
80
|
+
response = RestClient.get "#{@address}:#{@port}/#{URI.escape(db_name)}/_security/", {:cookies => {"AuthSession" => auth_session}}
|
|
81
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
82
|
+
rescue => e
|
|
83
|
+
couch_error(e)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
84
86
|
|
|
85
|
-
#login to couchdb
|
|
86
|
-
def self.login(username, password)
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
87
|
+
#login to couchdb
|
|
88
|
+
def self.login(username, password)
|
|
89
|
+
set_address
|
|
90
|
+
data = "name=#{username}&password=#{password}"
|
|
91
|
+
begin
|
|
92
|
+
response = RestClient.post "#{@address}:#{@port}/_session/", data, {:content_type => 'application/x-www-form-urlencoded'}
|
|
93
|
+
response.cookies
|
|
94
|
+
rescue => e
|
|
95
|
+
couch_error(e)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
97
98
|
|
|
98
|
-
#couchdb configuration api
|
|
99
|
-
def self.set_config(data,auth_session = "")
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
end
|
|
99
|
+
#couchdb configuration api
|
|
100
|
+
def self.set_config(data,auth_session = "")
|
|
101
|
+
section = data[:section]
|
|
102
|
+
key = data[:key]
|
|
103
|
+
value = data[:value]
|
|
104
|
+
json_data = Yajl::Encoder.encode(value)
|
|
105
|
+
set_address
|
|
106
|
+
begin
|
|
107
|
+
response = RestClient.put "#{@address}:#{@port}/_config/#{URI.escape(section)}/#{URI.escape(key)}",json_data, {:cookies => {"AuthSession" => auth_session}}
|
|
108
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
109
|
+
rescue => e
|
|
110
|
+
couch_error(e)
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
113
|
|
|
114
|
-
def self.delete_config(data,auth_session = "")
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
end
|
|
114
|
+
def self.delete_config(data,auth_session = "")
|
|
115
|
+
section = data[:section]
|
|
116
|
+
key = data[:key]
|
|
117
|
+
set_address
|
|
118
|
+
begin
|
|
119
|
+
response = RestClient.delete "#{@address}:#{@port}/_config/#{URI.escape(section)}/#{URI.escape(key)}", {:cookies => {"AuthSession" => auth_session}}
|
|
120
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
121
|
+
rescue => e
|
|
122
|
+
couch_error(e)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
126
125
|
|
|
127
126
|
|
|
128
|
-
def self.get_config(data,auth_session = "")
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
end
|
|
127
|
+
def self.get_config(data,auth_session = "")
|
|
128
|
+
section = data[:section]
|
|
129
|
+
key = data[:key]
|
|
130
|
+
set_address
|
|
131
|
+
begin
|
|
132
|
+
response = RestClient.get "#{@address}:#{@port}/_config/#{URI.escape(section)}/#{URI.escape(key)}", {:cookies => {"AuthSession" => auth_session}}
|
|
133
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
134
|
+
rescue => e
|
|
135
|
+
couch_error(e)
|
|
136
|
+
end
|
|
137
|
+
end
|
|
140
138
|
|
|
141
|
-
#create a document
|
|
139
|
+
#create a document
|
|
142
140
|
def self.create_doc( doc,auth_session = "")
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
end
|
|
141
|
+
db_name = doc[:database]
|
|
142
|
+
doc_id = doc[:doc_id]
|
|
143
|
+
data = doc[:data]
|
|
144
|
+
json_data = Yajl::Encoder.encode(data)
|
|
145
|
+
set_address
|
|
146
|
+
begin
|
|
147
|
+
response = RestClient.put "#{@address}:#{@port}/#{URI.escape(db_name)}/#{URI.escape(doc_id)}",json_data, {:cookies => {"AuthSession" => auth_session}}
|
|
148
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
149
|
+
rescue => e
|
|
150
|
+
couch_error(e)
|
|
151
|
+
end
|
|
155
152
|
end
|
|
156
153
|
|
|
157
154
|
#edit a document
|
|
158
155
|
def self.edit_doc(doc,auth_session = "")
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
end
|
|
156
|
+
db_name = doc[:database]
|
|
157
|
+
doc_id = doc[:doc_id]
|
|
158
|
+
data = doc[:data]
|
|
159
|
+
json_data = Yajl::Encoder.encode(data)
|
|
160
|
+
set_address
|
|
161
|
+
begin
|
|
162
|
+
response = RestClient.put "#{@address}:#{@port}/#{URI.escape(db_name)}/#{URI.escape(doc_id)}", json_data, {:cookies => {"AuthSession" => auth_session}}
|
|
163
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
164
|
+
rescue => e
|
|
165
|
+
couch_error(e)
|
|
166
|
+
end
|
|
171
167
|
end
|
|
172
168
|
|
|
173
169
|
#update a doc
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
#delete document
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
170
|
+
def self.update_doc(doc,auth_session = "")
|
|
171
|
+
db_name = doc[:database]
|
|
172
|
+
doc_id = doc[:doc_id]
|
|
173
|
+
data = doc[:data]
|
|
174
|
+
doc = {:database => db_name, :doc_id => doc_id}
|
|
175
|
+
options = Couchdb.view doc,auth_session
|
|
176
|
+
options = options.merge(data)
|
|
177
|
+
doc = {:database => db_name, :doc_id => doc_id, :data => options}
|
|
178
|
+
edit_doc doc,auth_session
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
#delete document
|
|
182
|
+
def self.delete_doc(doc,auth_session = "")
|
|
183
|
+
db_name = doc[:database]
|
|
184
|
+
doc_id = doc[:doc_id]
|
|
185
|
+
doc = {:database => db_name, :doc_id => doc_id}
|
|
186
|
+
hash = Couchdb.view doc,auth_session
|
|
187
|
+
doc = {:database => db_name, :doc_id => doc_id, :rev => hash["_rev"]}
|
|
188
|
+
delete_rev(doc,auth_session)
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
#delete a doc by rev#
|
|
193
|
+
def self.delete_rev(doc,auth_session = "")
|
|
194
|
+
db_name = doc[:database]
|
|
195
|
+
doc_id = doc[:doc_id]
|
|
196
|
+
rev = doc[:rev]
|
|
197
|
+
set_address
|
|
198
|
+
begin
|
|
199
|
+
response = RestClient.delete "#{@address}:#{@port}/#{URI.escape(db_name)}/#{URI.escape(doc_id)}?rev=#{rev}", {:cookies => {"AuthSession" => auth_session}}
|
|
204
200
|
hash = Yajl::Parser.parse(response.to_str)
|
|
205
201
|
rescue => e
|
|
206
|
-
|
|
207
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
202
|
+
couch_error(e)
|
|
208
203
|
end
|
|
209
|
-
|
|
204
|
+
end
|
|
210
205
|
|
|
211
206
|
|
|
212
207
|
#create a database if one with the same name doesn't already exist
|
|
213
208
|
def self.create(database_name,auth_session = "")
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
#delete a database
|
|
225
|
-
def self.delete(database_name,auth_session = "")
|
|
226
|
-
set_address
|
|
227
|
-
begin
|
|
228
|
-
response = RestClient.delete 'http://' + @address + ':' + @port + '/' + URI.escape(database_name), {:cookies => {"AuthSession" => auth_session}}
|
|
229
|
-
hash = Yajl::Parser.parse(response.to_str)
|
|
230
|
-
rescue => e
|
|
231
|
-
hash = Yajl::Parser.parse(e.response.to_s)
|
|
232
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
233
|
-
end
|
|
234
|
-
end
|
|
235
|
-
|
|
236
|
-
#return a list of all databases
|
|
237
|
-
def self.all(auth_session = "")
|
|
238
|
-
set_address
|
|
239
|
-
begin
|
|
240
|
-
response = RestClient.get 'http://' + @address + ':' + @port + '/_all_dbs', {:cookies => {"AuthSession" => auth_session}}
|
|
241
|
-
hash = Yajl::Parser.parse(response.to_str)
|
|
242
|
-
rescue => e
|
|
243
|
-
raise e
|
|
244
|
-
end
|
|
245
|
-
end
|
|
246
|
-
|
|
247
|
-
##view a document
|
|
248
|
-
def self.view(doc,auth_session = "")
|
|
249
|
-
set_address
|
|
250
|
-
db_name = doc[:database]
|
|
251
|
-
doc_id = doc[:doc_id]
|
|
252
|
-
begin
|
|
253
|
-
response = RestClient.get 'http://' + @address + ':' + @port + '/' + db_name + '/' + doc_id,{:cookies => {"AuthSession" => auth_session}}
|
|
254
|
-
hash = Yajl::Parser.parse(response.to_str)
|
|
255
|
-
rescue => e
|
|
256
|
-
hash = Yajl::Parser.parse(e.response.to_s)
|
|
257
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
258
|
-
end
|
|
259
|
-
end
|
|
209
|
+
set_address
|
|
210
|
+
begin
|
|
211
|
+
response = RestClient.put "#{@address}:#{@port}/#{URI.escape(database_name)}", {:content_type => :json},{:cookies => {"AuthSession" => auth_session}}
|
|
212
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
213
|
+
rescue => e
|
|
214
|
+
couch_error(e)
|
|
215
|
+
end
|
|
216
|
+
end
|
|
260
217
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
218
|
+
#delete a database
|
|
219
|
+
def self.delete(database_name,auth_session = "")
|
|
220
|
+
set_address
|
|
221
|
+
begin
|
|
222
|
+
response = RestClient.delete "#{@address}:#{@port}/#{URI.escape(database_name)}", {:cookies => {"AuthSession" => auth_session}}
|
|
223
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
224
|
+
rescue => e
|
|
225
|
+
couch_error(e)
|
|
226
|
+
end
|
|
268
227
|
end
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
228
|
+
|
|
229
|
+
#return a list of all databases
|
|
230
|
+
def self.all(auth_session = "")
|
|
231
|
+
set_address
|
|
232
|
+
begin
|
|
233
|
+
response = RestClient.get "#{@address}:#{@port}/_all_dbs", {:cookies => {"AuthSession" => auth_session}}
|
|
234
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
235
|
+
rescue => e
|
|
236
|
+
raise e
|
|
237
|
+
end
|
|
275
238
|
end
|
|
276
|
-
end
|
|
277
239
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
240
|
+
##view a document
|
|
241
|
+
def self.view(doc,auth_session = "")
|
|
242
|
+
set_address
|
|
243
|
+
db_name = doc[:database]
|
|
244
|
+
doc_id = doc[:doc_id]
|
|
245
|
+
begin
|
|
246
|
+
response = RestClient.get "#{@address}:#{@port}/#{db_name}/#{doc_id}",{:cookies => {"AuthSession" => auth_session}}
|
|
247
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
248
|
+
rescue => e
|
|
249
|
+
couch_error(e)
|
|
250
|
+
end
|
|
251
|
+
end
|
|
281
252
|
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
253
|
+
def self.get_params(options)
|
|
254
|
+
params = ""
|
|
255
|
+
if options.has_key?(:startkey)
|
|
256
|
+
if options[:startkey].is_a? String
|
|
257
|
+
params = 'startkey="' + options[:startkey] + '"'
|
|
258
|
+
else
|
|
259
|
+
params = 'startkey=' + options[:startkey].to_s # for complex keys
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
if options.has_key?(:endkey)
|
|
263
|
+
if options[:endkey].is_a? String
|
|
264
|
+
params = params + '&endkey="' + options[:endkey] + '"'
|
|
265
|
+
else
|
|
266
|
+
params = params + '&endkey=' + options[:endkey].to_s #for complex keys
|
|
267
|
+
end
|
|
268
|
+
end
|
|
285
269
|
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
270
|
+
if options.has_key?(:limit)
|
|
271
|
+
params = params + "&" + "limit=" + options[:limit].to_s
|
|
272
|
+
end
|
|
289
273
|
|
|
290
|
-
|
|
291
|
-
|
|
274
|
+
if options.has_key?(:skip)
|
|
275
|
+
params = params + "&" + "skip=" + options[:skip].to_s
|
|
276
|
+
end
|
|
277
|
+
|
|
278
|
+
if options.has_key?(:descending)
|
|
279
|
+
params = params + "&" + "descending=true"
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
return params
|
|
283
|
+
end
|
|
292
284
|
|
|
293
285
|
|
|
294
|
-
#query a permanent view
|
|
295
|
-
def self.find(doc,auth_session = "", key=nil, options = {})
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
286
|
+
#query a permanent view
|
|
287
|
+
def self.find(doc,auth_session = "", key=nil, options = {})
|
|
288
|
+
set_address
|
|
289
|
+
db_name = doc[:database]
|
|
290
|
+
design_doc_name = doc[:design_doc]
|
|
291
|
+
view_name = doc[:view]
|
|
292
|
+
params = get_params(options)
|
|
301
293
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
294
|
+
begin
|
|
295
|
+
if key == nil
|
|
296
|
+
response = RestClient.get "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}/_view/#{view_name}?#{URI.escape(params)}",{:cookies => {"AuthSession" => auth_session}}
|
|
297
|
+
else
|
|
298
|
+
key = URI.escape('?key="' + key + '"')
|
|
299
|
+
response = RestClient.get "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}/_view/#{view_name}#{key}&#{URI.escape(params)}" ,{:cookies => {"AuthSession" => auth_session}}
|
|
300
|
+
end
|
|
301
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
302
|
+
rows = hash["rows"]
|
|
303
|
+
count = 0
|
|
304
|
+
rows.each do |row|
|
|
305
|
+
rows[count] = row["value"]
|
|
306
|
+
count += 1
|
|
307
|
+
end
|
|
308
|
+
return rows
|
|
309
|
+
rescue => e
|
|
310
|
+
couch_error(e)
|
|
315
311
|
end
|
|
316
|
-
|
|
317
|
-
rescue => e
|
|
318
|
-
hash = Yajl::Parser.parse(e.response.to_s)
|
|
319
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
320
|
-
end
|
|
321
|
-
end
|
|
312
|
+
end
|
|
322
313
|
|
|
323
|
-
#create a design document with views
|
|
324
|
-
def self.create_design(doc,auth_session = "")
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
raise CouchdbException.new(hash), "CouchDB: Error - " + hash.values[0] + ". Reason - " + hash.values[1]
|
|
314
|
+
#create a design document with views
|
|
315
|
+
def self.create_design(doc,auth_session = "")
|
|
316
|
+
set_address
|
|
317
|
+
db_name = doc[:database]
|
|
318
|
+
design_doc_name = doc[:design_doc]
|
|
319
|
+
json_doc_name = doc[:json_doc]
|
|
320
|
+
|
|
321
|
+
begin
|
|
322
|
+
#bind json doc to string
|
|
323
|
+
message_template = ERB.new File.new(json_doc_name).read
|
|
324
|
+
str = message_template.result(binding)
|
|
325
|
+
rescue => e
|
|
326
|
+
raise e
|
|
327
|
+
end
|
|
328
|
+
|
|
329
|
+
begin
|
|
330
|
+
response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", str, {:cookies => {"AuthSession" => auth_session}}
|
|
331
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
332
|
+
rescue => e
|
|
333
|
+
couch_error(e)
|
|
334
|
+
end
|
|
345
335
|
end
|
|
346
|
-
end
|
|
347
336
|
|
|
348
|
-
#Query view, create view on fly if it dosen't already exist
|
|
349
|
-
def self.find_on_fly(doc,auth_session = "",key = nil, options = {})
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
337
|
+
#Query view, create view on fly if it dosen't already exist
|
|
338
|
+
def self.find_on_fly(doc,auth_session = "",key = nil, options = {})
|
|
339
|
+
db_name = doc[:database]
|
|
340
|
+
design_doc = doc[:design_doc]
|
|
341
|
+
view = doc[:view]
|
|
342
|
+
json_doc = doc[:json_doc]
|
|
354
343
|
|
|
355
|
-
|
|
344
|
+
begin
|
|
356
345
|
if( key == nil)
|
|
357
|
-
|
|
346
|
+
docs = find({:database => db_name, :design_doc => design_doc, :view => view},auth_session,key=nil,options)
|
|
358
347
|
else
|
|
359
|
-
|
|
348
|
+
docs = find({:database => db_name, :design_doc => design_doc, :view => view},auth_session,key,options)
|
|
360
349
|
end
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
end
|
|
350
|
+
rescue CouchdbException => e
|
|
351
|
+
document = { :database => db_name, :design_doc => design_doc, :json_doc => json_doc}
|
|
352
|
+
create_design document,auth_session
|
|
353
|
+
if( key == nil)
|
|
354
|
+
docs = find({:database => db_name, :design_doc => design_doc, :view => view},auth_session,key=nil,options)
|
|
355
|
+
else
|
|
356
|
+
docs = find({:database => db_name, :design_doc => design_doc, :view => view},auth_session,key,options)
|
|
369
357
|
end
|
|
370
|
-
|
|
371
|
-
|
|
358
|
+
end
|
|
359
|
+
return docs
|
|
360
|
+
end
|
|
372
361
|
|
|
373
362
|
|
|
374
|
-
#add a finder method to the database
|
|
375
|
-
#this creates a find by key method
|
|
376
|
-
def self.add_finder(options,auth_session = "")
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
363
|
+
#add a finder method to the database
|
|
364
|
+
#this creates a find by key method
|
|
365
|
+
def self.add_finder(options,auth_session = "")
|
|
366
|
+
set_address
|
|
367
|
+
db_name = options[:database]
|
|
368
|
+
key = options[:key]
|
|
369
|
+
design_doc_name = key + '_finder'
|
|
381
370
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
371
|
+
view ='{
|
|
372
|
+
"language" : "javascript",
|
|
373
|
+
"views" :{
|
|
374
|
+
"find_by_'+key+'" : {
|
|
375
|
+
"map" : "function(doc){ if(doc.'+key+') emit(doc.'+key+',doc);}"
|
|
376
|
+
}
|
|
387
377
|
}
|
|
388
|
-
|
|
389
|
-
}'
|
|
378
|
+
}'
|
|
390
379
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
end
|
|
398
|
-
|
|
399
|
-
#add a multiple finder method to the database
|
|
400
|
-
#this creates a find by keys method
|
|
401
|
-
def self.add_multiple_finder(options,auth_session = "")
|
|
402
|
-
set_address
|
|
403
|
-
db_name = options[:database]
|
|
404
|
-
keys = options[:keys]
|
|
405
|
-
view_name = keys.join("_")
|
|
406
|
-
key = keys.join(",doc.")
|
|
407
|
-
condition = keys.join(" && doc.")
|
|
408
|
-
design_doc_name = view_name + '_keys_finder'
|
|
409
|
-
|
|
410
|
-
view = '{
|
|
411
|
-
"language" : "javascript",
|
|
412
|
-
"views" :{
|
|
413
|
-
"find_by_keys_'+view_name+'" : {
|
|
414
|
-
"map" : "function(doc){ if(doc.'+condition+') emit([doc.'+key+'],doc);}"
|
|
415
|
-
}
|
|
416
|
-
}
|
|
417
|
-
}'
|
|
380
|
+
begin
|
|
381
|
+
response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
|
|
382
|
+
rescue => e
|
|
383
|
+
couch_error(e)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
418
386
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
387
|
+
#add a multiple finder method to the database
|
|
388
|
+
#this creates a find by keys method
|
|
389
|
+
def self.add_multiple_finder(options,auth_session = "")
|
|
390
|
+
set_address
|
|
391
|
+
db_name = options[:database]
|
|
392
|
+
keys = options[:keys]
|
|
393
|
+
view_name = keys.join("_")
|
|
394
|
+
key = keys.join(",doc.")
|
|
395
|
+
condition = keys.join(" && doc.")
|
|
396
|
+
design_doc_name = "#{view_name}_keys_finder"
|
|
397
|
+
|
|
398
|
+
view = '{
|
|
399
|
+
"language" : "javascript",
|
|
400
|
+
"views" :{
|
|
401
|
+
"find_by_keys_'+view_name+'" : {
|
|
402
|
+
"map" : "function(doc){ if(doc.'+condition+') emit([doc.'+key+'],doc);}"
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
}'
|
|
406
|
+
|
|
407
|
+
begin
|
|
408
|
+
response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
|
|
409
|
+
rescue => e
|
|
410
|
+
couch_error(e)
|
|
411
|
+
end
|
|
412
|
+
end
|
|
426
413
|
|
|
427
|
-
#add a multiple counter method to the database
|
|
428
|
-
#this creates a count by keys method
|
|
429
|
-
def self.add_multiple_counter(options,auth_session = "")
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
"views" :{
|
|
414
|
+
#add a multiple counter method to the database
|
|
415
|
+
#this creates a count by keys method
|
|
416
|
+
def self.add_multiple_counter(options,auth_session = "")
|
|
417
|
+
set_address
|
|
418
|
+
db_name = options[:database]
|
|
419
|
+
keys = options[:keys]
|
|
420
|
+
view_name = keys.join("_")
|
|
421
|
+
key = keys.join(",doc.")
|
|
422
|
+
condition = keys.join(" && doc.")
|
|
423
|
+
design_doc_name = "#{view_name}_keys_counter"
|
|
424
|
+
view = '{
|
|
425
|
+
"language" : "javascript",
|
|
426
|
+
"views" :{
|
|
441
427
|
"count_by_keys_'+view_name+'" : {
|
|
442
428
|
"map" : "function(doc){ if(doc.'+condition+') emit([doc.'+key+'],null);}", "reduce": "_count"
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
}'
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}'
|
|
446
432
|
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
end
|
|
433
|
+
begin
|
|
434
|
+
response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
|
|
435
|
+
rescue => e
|
|
436
|
+
couch_error(e)
|
|
437
|
+
end
|
|
438
|
+
end
|
|
454
439
|
|
|
455
|
-
#add a counter method to the database
|
|
456
|
-
#this creates a count method that counts documents by key
|
|
457
|
-
def self.add_counter(options,auth_session = "")
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
440
|
+
#add a counter method to the database
|
|
441
|
+
#this creates a count method that counts documents by key
|
|
442
|
+
def self.add_counter(options,auth_session = "")
|
|
443
|
+
set_address
|
|
444
|
+
db_name = options[:database]
|
|
445
|
+
key = options[:key]
|
|
446
|
+
design_doc_name = key + '_counter'
|
|
462
447
|
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
}'
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
end
|
|
448
|
+
view ='{
|
|
449
|
+
"language" : "javascript",
|
|
450
|
+
"views" :{
|
|
451
|
+
"count_'+key+'" : {
|
|
452
|
+
"map" : "function(doc){ if(doc.'+key+') emit(doc.'+key+',null);}", "reduce": "_count"
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
}'
|
|
456
|
+
|
|
457
|
+
begin
|
|
458
|
+
response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
|
|
459
|
+
rescue => e
|
|
460
|
+
couch_error(e)
|
|
461
|
+
end
|
|
462
|
+
end
|
|
479
463
|
|
|
480
|
-
#count by key
|
|
481
|
-
def self.count(options,auth_session = "")
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
464
|
+
#count by key
|
|
465
|
+
def self.count(options,auth_session = "")
|
|
466
|
+
set_address
|
|
467
|
+
db_name = options[:database]
|
|
468
|
+
index = options.keys[1].to_s
|
|
469
|
+
search_term = options.values[1]
|
|
470
|
+
design_doc_name = "#{index}_counter"
|
|
471
|
+
view_name = "count_#{index}"
|
|
488
472
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
end
|
|
473
|
+
begin
|
|
474
|
+
view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
|
|
475
|
+
docs = find view,auth_session,search_term
|
|
476
|
+
rescue CouchdbException => e
|
|
477
|
+
#add a counter index if one doesn't already exist in the database
|
|
478
|
+
#then count_by_key
|
|
479
|
+
add_counter({:database => db_name, :key => index},auth_session)
|
|
480
|
+
docs = find view,auth_session,search_term
|
|
481
|
+
end
|
|
482
|
+
count = docs[0]
|
|
483
|
+
return count.to_i
|
|
484
|
+
end
|
|
501
485
|
|
|
502
|
-
#count by keys
|
|
503
|
-
#example:
|
|
504
|
-
#hash = {:firstname =>'john', :gender => 'male' }
|
|
505
|
-
#Couchdb.count_by_keys({:database => 'contacts', :keys => hash},auth_session)
|
|
506
|
-
def self.count_by_keys(options,auth_session = "", params = {})
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
486
|
+
#count by keys
|
|
487
|
+
#example:
|
|
488
|
+
#hash = {:firstname =>'john', :gender => 'male' }
|
|
489
|
+
#Couchdb.count_by_keys({:database => 'contacts', :keys => hash},auth_session)
|
|
490
|
+
def self.count_by_keys(options,auth_session = "", params = {})
|
|
491
|
+
set_address
|
|
492
|
+
db_name = options[:database]
|
|
493
|
+
keys = []
|
|
494
|
+
search_term = []
|
|
495
|
+
hash = options[:keys]
|
|
496
|
+
|
|
497
|
+
hash.each do |k,v|
|
|
498
|
+
keys << k
|
|
499
|
+
search_term << v
|
|
500
|
+
end
|
|
501
|
+
index = keys.join("_")
|
|
502
|
+
design_doc_name = "#{index}_keys_counter"
|
|
503
|
+
view_name = "count_by_keys_#{index}"
|
|
504
|
+
params[:startkey] = search_term
|
|
505
|
+
params[:endkey] = search_term
|
|
522
506
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
end
|
|
507
|
+
begin
|
|
508
|
+
view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
|
|
509
|
+
docs = find view,auth_session,key=nil,params
|
|
510
|
+
rescue CouchdbException => e
|
|
511
|
+
#add a finder/index if one doesn't already exist in the database
|
|
512
|
+
#then find_by_keys
|
|
513
|
+
add_multiple_counter({:database => db_name, :keys => keys},auth_session)
|
|
514
|
+
docs = find view,auth_session,key=nil,params
|
|
515
|
+
end
|
|
516
|
+
count = docs[0]
|
|
517
|
+
return count.to_i
|
|
518
|
+
end
|
|
535
519
|
|
|
536
|
-
#find by key
|
|
537
|
-
def self.find_by(options,auth_session = "", params = {})
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
520
|
+
#find by key
|
|
521
|
+
def self.find_by(options,auth_session = "", params = {})
|
|
522
|
+
set_address
|
|
523
|
+
db_name = options[:database]
|
|
524
|
+
index = options.keys[1].to_s
|
|
525
|
+
search_term = options.values[1]
|
|
526
|
+
design_doc_name = "#{index}_finder"
|
|
527
|
+
view_name = "find_by_#{index}"
|
|
544
528
|
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
end
|
|
529
|
+
begin
|
|
530
|
+
view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
|
|
531
|
+
docs = find view,auth_session,search_term,params
|
|
532
|
+
rescue CouchdbException => e
|
|
533
|
+
#add a finder/index if one doesn't already exist in the database
|
|
534
|
+
#then find_by_key
|
|
535
|
+
add_finder({:database => db_name, :key => index},auth_session)
|
|
536
|
+
docs = find view,auth_session,search_term,params
|
|
537
|
+
end
|
|
538
|
+
return docs
|
|
539
|
+
end
|
|
556
540
|
|
|
557
|
-
#find by keys
|
|
558
|
-
#example:
|
|
559
|
-
#hash = {:firstname =>'john', :gender => 'male' }
|
|
560
|
-
#Couchdb.find_by_keys({:database => 'contacts', :keys => hash},auth_session)
|
|
561
|
-
def self.find_by_keys(options,auth_session = "", params = {})
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
541
|
+
#find by keys
|
|
542
|
+
#example:
|
|
543
|
+
#hash = {:firstname =>'john', :gender => 'male' }
|
|
544
|
+
#Couchdb.find_by_keys({:database => 'contacts', :keys => hash},auth_session)
|
|
545
|
+
def self.find_by_keys(options,auth_session = "", params = {})
|
|
546
|
+
set_address
|
|
547
|
+
db_name = options[:database]
|
|
548
|
+
keys = []
|
|
549
|
+
search_term = []
|
|
550
|
+
hash = options[:keys]
|
|
551
|
+
|
|
552
|
+
hash.each do |k,v|
|
|
553
|
+
keys << k
|
|
554
|
+
search_term << v
|
|
555
|
+
end
|
|
556
|
+
index = keys.join("_")
|
|
557
|
+
design_doc_name = "#{index}_keys_finder"
|
|
558
|
+
view_name = "find_by_keys_#{index}"
|
|
559
|
+
params[:startkey] = search_term
|
|
560
|
+
params[:endkey] = search_term
|
|
577
561
|
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
end
|
|
562
|
+
begin
|
|
563
|
+
view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
|
|
564
|
+
docs = find view,auth_session,key=nil,params
|
|
565
|
+
rescue CouchdbException => e
|
|
566
|
+
#add a finder/index if one doesn't already exist in the database
|
|
567
|
+
#then find_by_keys
|
|
568
|
+
add_multiple_finder({:database => db_name, :keys => keys},auth_session)
|
|
569
|
+
docs = find view,auth_session,key=nil,params
|
|
570
|
+
end
|
|
571
|
+
return docs
|
|
572
|
+
end
|
|
589
573
|
|
|
590
|
-
|
|
591
|
-
def self.docs_from(database_name,auth_session = "")
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
end
|
|
607
|
-
end
|
|
574
|
+
#return a list of all docs in the database
|
|
575
|
+
def self.docs_from(database_name,auth_session = "")
|
|
576
|
+
set_address
|
|
577
|
+
begin
|
|
578
|
+
response = RestClient.get "#{@address}:#{@port}/#{URI.escape(database_name)}/_all_docs?include_docs=true",{:cookies => {"AuthSession" => auth_session}}
|
|
579
|
+
hash = Yajl::Parser.parse(response.to_str)
|
|
580
|
+
rows = hash["rows"]
|
|
581
|
+
count = 0
|
|
582
|
+
rows.each do |row|
|
|
583
|
+
rows[count] = row["doc"]
|
|
584
|
+
count += 1
|
|
585
|
+
end
|
|
586
|
+
return rows
|
|
587
|
+
rescue => e
|
|
588
|
+
couch_error(e)
|
|
589
|
+
end
|
|
590
|
+
end
|
|
608
591
|
|
|
609
592
|
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
593
|
+
class << self
|
|
594
|
+
attr_accessor :address
|
|
595
|
+
attr_accessor :port
|
|
613
596
|
|
|
614
|
-
|
|
597
|
+
def set_address()
|
|
615
598
|
if @address == nil
|
|
616
|
-
|
|
599
|
+
@address = 'http://127.0.0.1'
|
|
617
600
|
end
|
|
618
601
|
if @port == nil
|
|
619
|
-
|
|
602
|
+
@port = '5984'
|
|
620
603
|
end
|
|
621
|
-
|
|
604
|
+
end
|
|
622
605
|
end
|
|
623
606
|
end
|