leanback 0.4.2 → 0.5.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.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +10 -0
  3. data/Gemfile +5 -6
  4. data/Gemfile.lock +65 -14
  5. data/README.md +465 -33
  6. data/Rakefile +8 -17
  7. data/VERSION +1 -1
  8. data/leanback.gemspec +26 -85
  9. data/lib/leanback.rb +129 -587
  10. data/spec/leanback_spec.rb +356 -0
  11. metadata +40 -117
  12. data/Changelog.rdoc +0 -146
  13. data/documentation/static/2011/11/20/i-moved-leanback-documentation/index.html +0 -180
  14. data/documentation/static/2011/11/20/index.html +0 -146
  15. data/documentation/static/2011/11/index.html +0 -146
  16. data/documentation/static/2011/index.html +0 -146
  17. data/documentation/static/2013/06/02/index.html +0 -146
  18. data/documentation/static/2013/06/02/released-leanback-v0-3-4/index.html +0 -180
  19. data/documentation/static/2013/06/09/index.html +0 -146
  20. data/documentation/static/2013/06/09/released-leanback-v0-4-0/index.html +0 -179
  21. data/documentation/static/2013/06/index.html +0 -158
  22. data/documentation/static/2013/index.html +0 -158
  23. data/documentation/static/author/admin/index.html +0 -175
  24. data/documentation/static/basic-couchdb-operations/index.html +0 -259
  25. data/documentation/static/category/uncategorized/index.html +0 -170
  26. data/documentation/static/couchdb-configuration/index.html +0 -189
  27. data/documentation/static/couchdb-security/index.html +0 -218
  28. data/documentation/static/count-by-multiple-documents/index.html +0 -221
  29. data/documentation/static/count-documents-by-key/index.html +0 -177
  30. data/documentation/static/css/2c-l-fixed.css +0 -1
  31. data/documentation/static/css/2c-l-fixed.dev.css +0 -62
  32. data/documentation/static/css/2c-r-fixed.css +0 -1
  33. data/documentation/static/css/2c-r-fixed.dev.css +0 -60
  34. data/documentation/static/css/3c-c-fixed.css +0 -1
  35. data/documentation/static/css/3c-c-fixed.dev.css +0 -84
  36. data/documentation/static/css/3c-l-fixed.css +0 -1
  37. data/documentation/static/css/3c-l-fixed.dev.css +0 -61
  38. data/documentation/static/css/3c-r-fixed.css +0 -1
  39. data/documentation/static/css/3c-r-fixed.dev.css +0 -62
  40. data/documentation/static/css/holy-grail-fluid.css +0 -5
  41. data/documentation/static/css/plugins.css +0 -5
  42. data/documentation/static/css/print.css +0 -5
  43. data/documentation/static/css/screen.css +0 -1
  44. data/documentation/static/design-documents-and-permanent-views/index.html +0 -454
  45. data/documentation/static/error-handling/index.html +0 -157
  46. data/documentation/static/find-document-by-multiple-keys/index.html +0 -269
  47. data/documentation/static/find-documents-by-key/index.html +0 -243
  48. data/documentation/static/index.html +0 -161
  49. data/documentation/static/leanback/index.html +0 -130
  50. data/documentation/static/leanback/installation/index.html +0 -119
  51. data/documentation/static/setting-the-bind_address-port/index.html +0 -151
  52. data/documentation/static/style.css +0 -16
  53. data/spec/admin_party/database_spec.rb +0 -400
  54. data/spec/no_admin_party/cloudant_spec.rb +0 -365
  55. data/spec/no_admin_party/database_spec.rb +0 -491
  56. data/spec/no_admin_party/non_admin_user_spec.rb +0 -67
  57. data/test/helper.rb +0 -18
  58. data/test/main.rb +0 -295
  59. data/test/my_view.json +0 -8
  60. data/test/my_views.json +0 -8
  61. data/test/start.json +0 -8
  62. data/test/test_leanback.rb +0 -319
  63. data/test/view_age.json +0 -8
data/Rakefile CHANGED
@@ -15,8 +15,8 @@ Jeweler::Tasks.new do |gem|
15
15
  gem.name = "leanback"
16
16
  gem.homepage = "http://github.com/obi-a/leanback"
17
17
  gem.license = "MIT"
18
- gem.summary = %Q{lightweight Ruby interface to CouchDB}
19
- gem.description = %Q{lightweight Ruby interface to CouchDB}
18
+ gem.summary = %Q{Simple Ruby interface to CouchDB}
19
+ gem.description = %Q{Simple Ruby interface to CouchDB}
20
20
  gem.email = "obioraakubue@yahoo.com"
21
21
  gem.authors = ["Obi Akubue"]
22
22
  # Include your dependencies below. Runtime dependencies are required when using your gem,
@@ -33,21 +33,12 @@ Rake::TestTask.new(:test) do |test|
33
33
  test.verbose = true
34
34
  end
35
35
 
36
- require 'rcov/rcovtask'
37
- Rcov::RcovTask.new do |test|
38
- test.libs << 'test'
39
- test.pattern = 'test/**/test_*.rb'
40
- test.verbose = true
36
+ task :repl do
37
+ leanback_file = File.expand_path(File.join(File.dirname(__FILE__), '..', 'leanback/lib/leanback'))
38
+ irb = "bundle exec pry -r #{leanback_file}"
39
+ sh irb
41
40
  end
42
41
 
43
- task :default => :test
44
-
45
- require 'rake/rdoctask'
46
- Rake::RDocTask.new do |rdoc|
47
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
42
+ task :r => :repl
48
43
 
49
- rdoc.rdoc_dir = 'rdoc'
50
- rdoc.title = "leanback #{version}"
51
- rdoc.rdoc_files.include('README*')
52
- rdoc.rdoc_files.include('lib/**/*.rb')
53
- end
44
+ task :default => :test
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.2
1
+ 0.5.0
data/leanback.gemspec CHANGED
@@ -2,15 +2,17 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
+ # stub: leanback 0.5.0 ruby lib
5
6
 
6
7
  Gem::Specification.new do |s|
7
8
  s.name = "leanback"
8
- s.version = "0.4.2"
9
+ s.version = "0.5.0"
9
10
 
10
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
11
13
  s.authors = ["Obi Akubue"]
12
- s.date = "2013-11-16"
13
- s.description = "lightweight Ruby interface to CouchDB"
14
+ s.date = "2014-06-14"
15
+ s.description = "Simple Ruby interface to CouchDB"
14
16
  s.email = "obioraakubue@yahoo.com"
15
17
  s.extra_rdoc_files = [
16
18
  "LICENSE.txt",
@@ -18,111 +20,50 @@ Gem::Specification.new do |s|
18
20
  ]
19
21
  s.files = [
20
22
  ".document",
21
- "Changelog.rdoc",
23
+ ".travis.yml",
22
24
  "Gemfile",
23
25
  "Gemfile.lock",
24
26
  "LICENSE.txt",
25
27
  "README.md",
26
28
  "Rakefile",
27
29
  "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",
68
30
  "leanback.gemspec",
69
31
  "lib/leanback.rb",
70
- "spec/admin_party/database_spec.rb",
71
- "spec/no_admin_party/cloudant_spec.rb",
72
- "spec/no_admin_party/database_spec.rb",
73
- "spec/no_admin_party/non_admin_user_spec.rb",
74
- "spec/spec_base.rb",
75
- "test/helper.rb",
76
- "test/main.rb",
77
- "test/my_view.json",
78
- "test/my_views.json",
79
- "test/start.json",
80
- "test/test_leanback.rb",
81
- "test/view_age.json"
32
+ "spec/leanback_spec.rb",
33
+ "spec/spec_base.rb"
82
34
  ]
83
35
  s.homepage = "http://github.com/obi-a/leanback"
84
36
  s.licenses = ["MIT"]
85
- s.require_paths = ["lib"]
86
- s.rubygems_version = "1.8.24"
87
- s.summary = "lightweight Ruby interface to CouchDB"
88
- s.test_files = [
89
- "spec/admin_party/database_spec.rb",
90
- "spec/no_admin_party/cloudant_spec.rb",
91
- "spec/no_admin_party/database_spec.rb",
92
- "spec/no_admin_party/non_admin_user_spec.rb",
93
- "spec/spec_base.rb",
94
- "test/helper.rb",
95
- "test/main.rb",
96
- "test/test_leanback.rb"
97
- ]
37
+ s.rubygems_version = "2.2.2"
38
+ s.summary = "Simple Ruby interface to CouchDB"
98
39
 
99
40
  if s.respond_to? :specification_version then
100
- s.specification_version = 3
41
+ s.specification_version = 4
101
42
 
102
43
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
44
+ s.add_runtime_dependency(%q<activesupport>, [">= 0"])
103
45
  s.add_runtime_dependency(%q<rest-client>, [">= 0"])
104
- s.add_runtime_dependency(%q<yajl-ruby>, [">= 0"])
105
- s.add_development_dependency(%q<shoulda>, [">= 0"])
106
- s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
107
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
108
- s.add_development_dependency(%q<rcov>, [">= 0"])
46
+ s.add_runtime_dependency(%q<json_pure>, [">= 0"])
47
+ s.add_development_dependency(%q<pry>, [">= 0"])
48
+ s.add_development_dependency(%q<bundler>, [">= 0"])
49
+ s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
109
50
  s.add_development_dependency(%q<rspec>, [">= 0"])
110
51
  else
52
+ s.add_dependency(%q<activesupport>, [">= 0"])
111
53
  s.add_dependency(%q<rest-client>, [">= 0"])
112
- s.add_dependency(%q<yajl-ruby>, [">= 0"])
113
- s.add_dependency(%q<shoulda>, [">= 0"])
114
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
115
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
116
- s.add_dependency(%q<rcov>, [">= 0"])
54
+ s.add_dependency(%q<json_pure>, [">= 0"])
55
+ s.add_dependency(%q<pry>, [">= 0"])
56
+ s.add_dependency(%q<bundler>, [">= 0"])
57
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
117
58
  s.add_dependency(%q<rspec>, [">= 0"])
118
59
  end
119
60
  else
61
+ s.add_dependency(%q<activesupport>, [">= 0"])
120
62
  s.add_dependency(%q<rest-client>, [">= 0"])
121
- s.add_dependency(%q<yajl-ruby>, [">= 0"])
122
- s.add_dependency(%q<shoulda>, [">= 0"])
123
- s.add_dependency(%q<bundler>, ["~> 1.0.0"])
124
- s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
125
- s.add_dependency(%q<rcov>, [">= 0"])
63
+ s.add_dependency(%q<json_pure>, [">= 0"])
64
+ s.add_dependency(%q<pry>, [">= 0"])
65
+ s.add_dependency(%q<bundler>, [">= 0"])
66
+ s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
126
67
  s.add_dependency(%q<rspec>, [">= 0"])
127
68
  end
128
69
  end
data/lib/leanback.rb CHANGED
@@ -1,614 +1,156 @@
1
1
  require 'rest_client'
2
- require 'yajl'
3
- require 'erb'
4
-
5
- class CouchdbException < RuntimeError
6
- attr :error
7
- def initialize(error)
8
- @error = error.values[0]
9
- end
10
- end
11
-
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
18
-
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
23
-
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
33
-
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
41
-
42
- #create a new user
43
- def self.create_user(user,auth_session= "")
44
- password_sha = Digest::SHA1.hexdigest(user[:password] + user[:salt])
45
-
46
- user_hash = { :type => "user",
47
- :name => user[:username],
48
- :password_sha => password_sha,
49
- :salt => user[:salt],
50
- :roles => user[:roles]
51
- }
52
-
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
61
-
62
- end
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
86
-
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)
2
+ require 'json/pure'
3
+ require 'active_support/all'
4
+
5
+ module Leanback
6
+ class InvalidDatabaseName < StandardError; end
7
+ class InvalidDocumentID < StandardError; end
8
+ class CouchdbException < StandardError
9
+ attr_reader :response
10
+ def initialize(response)
11
+ @response = response
12
+ end
13
+ end
14
+ class Couchdb
15
+ attr_reader :address
16
+ attr_reader :port
17
+ attr_reader :username
18
+ attr_reader :password
19
+ attr_reader :database
20
+ def initialize(args = {})
21
+ @database = args.fetch(:database, nil)
22
+ @address = args.fetch(:address, 'http://127.0.0.1')
23
+ @port = args.fetch(:port, '5984')
24
+ @username = args.fetch(:username, nil)
25
+ @password = args.fetch(:password, nil)
26
+ end
27
+ def create
28
+ api_request { RestClient.put "#{address_port}/#{db_uri}", content_type, cookies }
29
+ end
30
+ def delete
31
+ api_request { RestClient.delete "#{address_port}/#{db_uri}", cookies }
32
+ end
33
+ def create_doc(doc_id, doc)
34
+ api_request { RestClient.put "#{address_port}/#{db_uri}/#{doc_uri(doc_id)}", generate_json(doc), cookies }
35
+ end
36
+ def delete_doc(doc_id, rev)
37
+ api_request { RestClient.delete "#{address_port}/#{db_uri}/#{doc_uri(doc_id)}?rev=#{rev}", cookies }
38
+ end
39
+ def delete_doc!(doc_id)
40
+ document = get_doc(doc_id)
41
+ delete_doc(document[:_id], document[:_rev])
42
+ end
43
+ def get_doc(doc_id)
44
+ api_request { RestClient.get "#{address_port}/#{@database}/#{doc_id}", cookies }
45
+ end
46
+ def update_doc(doc_id, data)
47
+ api_request { RestClient.put "#{address_port}/#{db_uri}/#{doc_uri(doc_id)}", generate_json(data), cookies }
48
+ end
49
+ def edit_doc!(doc_id, data)
50
+ document = get_doc(doc_id)
51
+ document_with_rev = document.merge(data)
52
+ update_doc(doc_id, document_with_rev)
53
+ end
54
+ def view(design_doc_name, view_name, options = {})
55
+ api_request { RestClient.get "#{address_port}/#{db_uri}/#{URI.escape(design_doc_name)}/_view/#{URI.escape(view_name)}?#{options.to_query}", cookies }
56
+ end
57
+ def where(hash, options = {})
58
+ search_term = hash.values
59
+ index = hash.keys.join("_")
60
+ new_options = options.merge({startkey: search_term.to_s, endkey: search_term.to_s})
61
+ view!("_design/#{index}_keys_finder", "find_by_keys_#{index}", new_options)
62
+ rescue CouchdbException => e
63
+ add_multiple_finder(hash.keys)
64
+ view!("_design/#{index}_keys_finder", "find_by_keys_#{index}", new_options)
96
65
  end
97
- end
98
-
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)
66
+ def security_object=(security_settings)
67
+ api_request { RestClient.put "#{address_port}/#{db_uri}/_security/", generate_json(security_settings), cookies }
111
68
  end
112
- end
113
-
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)
69
+ def security_object
70
+ api_request { RestClient.get "#{address_port}/#{db_uri}/_security/", cookies }
123
71
  end
124
- end
125
-
126
-
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)
72
+ def set_config(section, key, value)
73
+ !!(RestClient.put "#{address_port}/_config/#{URI.escape(section)}/#{URI.escape(key)}", value, cookies)
136
74
  end
137
- end
138
-
139
- #create a document
140
- def self.create_doc( doc,auth_session = "")
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)
75
+ def get_config(section, key)
76
+ RestClient.get "#{address_port}/_config/#{URI.escape(section)}/#{URI.escape(key)}", cookies
149
77
  rescue => e
150
- couch_error(e)
78
+ raise_error(e)
151
79
  end
152
- end
153
-
154
- #edit a document
155
- def self.edit_doc(doc,auth_session = "")
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)
80
+ def delete_config(section, key)
81
+ !!(RestClient.delete "#{address_port}/_config/#{URI.escape(section)}/#{URI.escape(key)}", cookies)
164
82
  rescue => e
165
- couch_error(e)
83
+ raise_error(e)
166
84
  end
167
- end
168
-
169
- #update a doc
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}}
200
- hash = Yajl::Parser.parse(response.to_str)
201
- rescue => e
202
- couch_error(e)
85
+ private
86
+ def view!(design_doc_name, view_name, options = {})
87
+ new_options = options.merge({include_docs: true})
88
+ result = view(design_doc_name, view_name, new_options)
89
+ rows = result[:rows]
90
+ rows.map { |row| row[:doc] }
203
91
  end
204
- end
205
-
206
-
207
- #create a database if one with the same name doesn't already exist
208
- def self.create(database_name,auth_session = "")
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)
92
+ def add_multiple_finder(keys)
93
+ view_name = keys.join("_")
94
+ condition = keys.join(" && doc.")
95
+ key = keys.join(",doc.")
96
+ design_doc_name = "#{view_name}_keys_finder"
97
+ design_doc = {
98
+ language: "javascript",
99
+ views: {
100
+ "find_by_keys_#{view_name}" => {
101
+ map: "function(doc){ if(doc.#{condition}) emit([doc.#{key}]);}"
102
+ }
103
+ }
104
+ }
105
+ create_doc "_design/#{design_doc_name}", design_doc
215
106
  end
216
- end
217
-
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
227
- end
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)
107
+ def api_request
108
+ response = yield
109
+ parse_json(response)
235
110
  rescue => e
236
- raise e
111
+ raise_error(e)
237
112
  end
238
- end
239
-
240
- ##view a document
241
- def self.view(doc,auth_session = "", options = {})
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, symbolize_keys(options))
248
- rescue => e
249
- couch_error(e)
250
- end
251
- end
252
-
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
113
+ def doc_uri(doc_id)
114
+ error_message = "Invalid Document ID: #{doc_id}"
115
+ raise(Leanback::InvalidDocumentID.new(error_message), error_message) unless doc_id.is_a?(String)
116
+ URI.escape(doc_id)
261
117
  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
118
+ def db_uri
119
+ error_message = "Invalid database name: #{@database}"
120
+ raise(Leanback::InvalidDatabaseName.new(error_message), error_message) unless @database.is_a?(String)
121
+ URI.escape(@database)
268
122
  end
269
-
270
- if options.has_key?(:limit)
271
- params = params + "&" + "limit=" + options[:limit].to_s
123
+ def content_type
124
+ {content_type: :json}
272
125
  end
273
-
274
- if options.has_key?(:skip)
275
- params = params + "&" + "skip=" + options[:skip].to_s
126
+ def cookies
127
+ {cookies: {"AuthSession" => auth_session}}
276
128
  end
277
-
278
- if options.has_key?(:descending)
279
- params = params + "&" + "descending=true"
129
+ def address_port
130
+ "#{@address}:#{@port}"
280
131
  end
281
-
282
- return params
283
- end
284
-
285
-
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)
293
-
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, symbolize_keys(options))
302
- data = []
303
- rows = hash["rows"] unless hash["rows"].nil?
304
- rows = hash[:rows] unless hash[:rows].nil?
305
- rows.each do |row|
306
- value = row["value"] unless row["value"].nil?
307
- value = row[:value] unless row[:value].nil?
308
- data << value
309
- end
310
- return data
311
- rescue => e
312
- couch_error(e)
313
- end
314
- end
315
-
316
- #create a design document with views
317
- def self.create_design(doc,auth_session = "")
318
- set_address
319
- db_name = doc[:database]
320
- design_doc_name = doc[:design_doc]
321
- json_doc_name = doc[:json_doc]
322
-
323
- begin
324
- #bind json doc to string
325
- message_template = ERB.new File.new(json_doc_name).read
326
- str = message_template.result(binding)
327
- rescue => e
328
- raise e
132
+ def parse_json(json_doc)
133
+ JSON.parse(json_doc, symbolize_names: true)
329
134
  end
330
-
331
- begin
332
- response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", str, {:cookies => {"AuthSession" => auth_session}}
333
- hash = Yajl::Parser.parse(response.to_str)
334
- rescue => e
335
- couch_error(e)
135
+ def generate_json(data)
136
+ JSON.generate(data)
336
137
  end
337
- end
338
-
339
- #Query view, create view on fly if it dosen't already exist
340
- def self.find_on_fly(doc,auth_session = "",key = nil, options = {})
341
- db_name = doc[:database]
342
- design_doc = doc[:design_doc]
343
- view = doc[:view]
344
- json_doc = doc[:json_doc]
345
- query_info = {:database => db_name, :design_doc => design_doc, :view => view}
346
- begin
347
- if( key == nil)
348
- docs = find(query_info,auth_session,key=nil,options)
138
+ def raise_error(exeception)
139
+ if exeception.respond_to?('response')
140
+ response = parse_json(exeception.response)
141
+ raise(CouchdbException.new(response), response)
349
142
  else
350
- docs = find(query_info,auth_session,key,options)
143
+ raise(exeception)
351
144
  end
352
- rescue CouchdbException => e
353
- document = { :database => db_name, :design_doc => design_doc, :json_doc => json_doc}
354
- create_design document,auth_session
355
- if( key == nil)
356
- docs = find(query_info,auth_session,key=nil,options)
357
- else
358
- docs = find(query_info,auth_session,key,options)
359
- end
360
- end
361
- return docs
362
- end
363
-
364
-
365
- #add a finder method to the database
366
- #this creates a find by key method
367
- def self.add_finder(options,auth_session = "")
368
- set_address
369
- db_name = options[:database]
370
- key = options[:key]
371
- design_doc_name = key + '_finder'
372
-
373
- view ='{
374
- "language" : "javascript",
375
- "views" :{
376
- "find_by_'+key+'" : {
377
- "map" : "function(doc){ if(doc.'+key+') emit(doc.'+key+',doc);}"
378
- }
379
- }
380
- }'
381
-
382
- begin
383
- response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
384
- rescue => e
385
- couch_error(e)
386
- end
387
- end
388
-
389
- #add a multiple finder method to the database
390
- #this creates a find by keys method
391
- def self.add_multiple_finder(options,auth_session = "")
392
- set_address
393
- db_name = options[:database]
394
- keys = options[:keys]
395
- view_name = keys.join("_")
396
- key = keys.join(",doc.")
397
- condition = keys.join(" && doc.")
398
- design_doc_name = "#{view_name}_keys_finder"
399
-
400
- view = '{
401
- "language" : "javascript",
402
- "views" :{
403
- "find_by_keys_'+view_name+'" : {
404
- "map" : "function(doc){ if(doc.'+condition+') emit([doc.'+key+'],doc);}"
405
- }
406
- }
407
- }'
408
-
409
- begin
410
- response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
411
- rescue => e
412
- couch_error(e)
413
- end
414
- end
415
-
416
- #add a multiple counter method to the database
417
- #this creates a count by keys method
418
- def self.add_multiple_counter(options,auth_session = "")
419
- set_address
420
- db_name = options[:database]
421
- keys = options[:keys]
422
- view_name = keys.join("_")
423
- key = keys.join(",doc.")
424
- condition = keys.join(" && doc.")
425
- design_doc_name = "#{view_name}_keys_counter"
426
- view = '{
427
- "language" : "javascript",
428
- "views" :{
429
- "count_by_keys_'+view_name+'" : {
430
- "map" : "function(doc){ if(doc.'+condition+') emit([doc.'+key+'],null);}", "reduce": "_count"
431
- }
432
- }
433
- }'
434
-
435
- begin
436
- response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
437
- rescue => e
438
- couch_error(e)
439
145
  end
440
- end
441
-
442
- #add a counter method to the database
443
- #this creates a count method that counts documents by key
444
- def self.add_counter(options,auth_session = "")
445
- set_address
446
- db_name = options[:database]
447
- key = options[:key]
448
- design_doc_name = key + '_counter'
449
-
450
- view ='{
451
- "language" : "javascript",
452
- "views" :{
453
- "count_'+key+'" : {
454
- "map" : "function(doc){ if(doc.'+key+') emit(doc.'+key+',null);}", "reduce": "_count"
455
- }
456
- }
457
- }'
458
-
459
- begin
460
- response = RestClient.put "#{@address}:#{@port}/#{db_name}/_design/#{design_doc_name}", view, {:cookies => {"AuthSession" => auth_session}}
146
+ def auth_session
147
+ return "" if @username.nil? && @password.nil?
148
+ data = "name=#{@username}&password=#{@password}"
149
+ response = RestClient.post "#{@address}:#{@port}/_session/", data, {content_type: 'application/x-www-form-urlencoded'}
150
+ hash = response.cookies
151
+ hash["AuthSession"]
461
152
  rescue => e
462
- couch_error(e)
463
- end
464
- end
465
-
466
- #count by key
467
- def self.count(options,auth_session = "")
468
- set_address
469
- db_name = options[:database]
470
- index = options.keys[1].to_s
471
- search_term = options.values[1]
472
- design_doc_name = "#{index}_counter"
473
- view_name = "count_#{index}"
474
-
475
- begin
476
- view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
477
- docs = find view,auth_session,search_term
478
- rescue CouchdbException => e
479
- #add a counter index if one doesn't already exist in the database
480
- #then count_by_key
481
- add_counter({:database => db_name, :key => index},auth_session)
482
- docs = find view,auth_session,search_term
483
- end
484
- count = docs[0]
485
- return count.to_i
486
- end
487
-
488
- #count by keys
489
- #example:
490
- #hash = {:firstname =>'john', :gender => 'male' }
491
- #Couchdb.count_by_keys({:database => 'contacts', :keys => hash},auth_session)
492
- def self.count_by_keys(options,auth_session = "", params = {})
493
- set_address
494
- db_name = options[:database]
495
- keys = []
496
- search_term = []
497
- hash = options[:keys]
498
-
499
- hash.each do |k,v|
500
- keys << k
501
- search_term << v
502
- end
503
- index = keys.join("_")
504
- design_doc_name = "#{index}_keys_counter"
505
- view_name = "count_by_keys_#{index}"
506
- params[:startkey] = search_term
507
- params[:endkey] = search_term
508
-
509
- begin
510
- view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
511
- docs = find view,auth_session,key=nil,params
512
- rescue CouchdbException => e
513
- #add a finder/index if one doesn't already exist in the database
514
- #then find_by_keys
515
- add_multiple_counter({:database => db_name, :keys => keys},auth_session)
516
- docs = find view,auth_session,key=nil,params
517
- end
518
- count = docs[0]
519
- return count.to_i
520
- end
521
-
522
- #find by key
523
- def self.find_by(options,auth_session = "", params = {})
524
- set_address
525
- db_name = options[:database]
526
- index = options.keys[1].to_s
527
- search_term = options.values[1]
528
- design_doc_name = "#{index}_finder"
529
- view_name = "find_by_#{index}"
530
-
531
- begin
532
- view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
533
- docs = find view,auth_session,search_term,params
534
- rescue CouchdbException => e
535
- #add a finder/index if one doesn't already exist in the database
536
- #then find_by_key
537
- add_finder({:database => db_name, :key => index},auth_session)
538
- docs = find view,auth_session,search_term,params
539
- end
540
- return docs
541
- end
542
-
543
- #find by keys
544
- #example:
545
- #hash = {:firstname =>'john', :gender => 'male' }
546
- #Couchdb.find_by_keys({:database => 'contacts', :keys => hash},auth_session)
547
- def self.find_by_keys(options,auth_session = "", params = {})
548
- set_address
549
- db_name = options[:database]
550
- keys = []
551
- search_term = []
552
- hash = options[:keys]
553
-
554
- hash.each do |k,v|
555
- keys << k
556
- search_term << v
557
- end
558
- index = keys.join("_")
559
- design_doc_name = "#{index}_keys_finder"
560
- view_name = "find_by_keys_#{index}"
561
- params[:startkey] = search_term
562
- params[:endkey] = search_term
563
-
564
- begin
565
- view = { :database => db_name, :design_doc => design_doc_name, :view => view_name}
566
- docs = find view,auth_session,key=nil,params
567
- rescue CouchdbException => e
568
- #add a finder/index if one doesn't already exist in the database
569
- #then find_by_keys
570
- add_multiple_finder({:database => db_name, :keys => keys},auth_session)
571
- docs = find view,auth_session,key=nil,params
572
- end
573
- return docs
574
- end
575
-
576
- #return a list of all docs in the database
577
- def self.docs_from(database_name,auth_session = "")
578
- set_address
579
- begin
580
- response = RestClient.get "#{@address}:#{@port}/#{URI.escape(database_name)}/_all_docs?include_docs=true",{:cookies => {"AuthSession" => auth_session}}
581
- hash = Yajl::Parser.parse(response.to_str)
582
- rows = hash["rows"]
583
- count = 0
584
- rows.each do |row|
585
- rows[count] = row["doc"]
586
- count += 1
587
- end
588
- return rows
589
- rescue => e
590
- couch_error(e)
591
- end
592
- end
593
-
594
- def self.symbolize_keys(options)
595
- return {symbolize_keys: true} if options[:symbolize_keys]
596
- return {}
597
- end
598
-
599
- private_class_method :symbolize_keys
600
-
601
- class << self
602
- attr_accessor :address
603
- attr_accessor :port
604
-
605
- def set_address()
606
- if @address == nil
607
- @address = 'http://127.0.0.1'
608
- end
609
- if @port == nil
610
- @port = '5984'
611
- end
153
+ raise_error(e)
612
154
  end
613
155
  end
614
156
  end