riak_json 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,25 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ module RiakJson
22
+ # Generic RiakJson exception class
23
+ class RiakJsonError < StandardError
24
+ end
25
+ end
@@ -0,0 +1,34 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ module RiakJson
22
+ # Query helper object
23
+ # Provides a DSL for building json queries to collections
24
+ class Query
25
+ attr_accessor :body
26
+
27
+ # Create a Query object instance with a custom-built query
28
+ def self.from_json(json)
29
+ query = RiakJson::Query.new
30
+ query.body = json
31
+ query
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,50 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ module RiakJson
22
+ # QueryResult is a helper object that
23
+ # holds the results of a collection.find_all query
24
+ class QueryResult
25
+ attr_reader :documents
26
+ attr_reader :num_pages
27
+ attr_reader :page
28
+ attr_reader :per_page
29
+ attr_reader :total
30
+
31
+ def initialize(response)
32
+ if response.nil? or response.empty?
33
+ result_hash = {}
34
+ else
35
+ result_hash = JSON.parse(response)
36
+ if result_hash.kind_of? Array and result_hash.empty?
37
+ result_hash = {}
38
+ end
39
+ end
40
+
41
+ @num_pages = result_hash.fetch('num_pages', 0)
42
+ @page = result_hash.fetch('page', 0)
43
+ @total = result_hash.fetch('total', 0)
44
+ @per_page = result_hash.fetch('per_page', 0)
45
+
46
+ documents = result_hash.fetch('data', [])
47
+ @documents = documents.map { | body | RiakJson::Document.new(body['_id'], body) }
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,23 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ module RiakJson
22
+ VERSION = "0.0.2"
23
+ end
data/lib/riak_json.rb ADDED
@@ -0,0 +1,34 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ require 'riak_json/client'
22
+ require 'riak_json/client_transport'
23
+ require 'riak_json/collection'
24
+ require 'riak_json/collection_schema'
25
+ require 'riak_json/document'
26
+ require 'riak_json/errors'
27
+ require 'riak_json/query'
28
+ require 'riak_json/query_result'
29
+ require 'riak_json/version'
30
+
31
+ # RiakJson is a client library for reading and writing
32
+ # documents to the RiakJson document store.
33
+ module RiakJson
34
+ end
data/riak_json.gemspec ADDED
@@ -0,0 +1,51 @@
1
+ # coding: utf-8
2
+ ## -------------------------------------------------------------------
3
+ ##
4
+ ## Copyright (c) "2013" Basho Technologies, Inc.
5
+ ##
6
+ ## This file is provided to you under the Apache License,
7
+ ## Version 2.0 (the "License"); you may not use this file
8
+ ## except in compliance with the License. You may obtain
9
+ ## a copy of the License at
10
+ ##
11
+ ## http://www.apache.org/licenses/LICENSE-2.0
12
+ ##
13
+ ## Unless required by applicable law or agreed to in writing,
14
+ ## software distributed under the License is distributed on an
15
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16
+ ## KIND, either express or implied. See the License for the
17
+ ## specific language governing permissions and limitations
18
+ ## under the License.
19
+ ##
20
+ ## -------------------------------------------------------------------
21
+ lib = File.expand_path('../lib', __FILE__)
22
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
23
+ require 'riak_json/version'
24
+
25
+ Gem::Specification.new do |spec|
26
+ spec.name = "riak_json"
27
+ spec.version = RiakJson::VERSION
28
+ spec.authors = ["Dmitri Zagidulin", "Drew Kerrigan"]
29
+ spec.email = ["dzagidulin@basho.com", "dkerrigan@basho.com"]
30
+ spec.description = %q{A Ruby client for Riak Json}
31
+ spec.summary = %q{riak_json is a client library for RiakJson, a set of JSON document based endpoints for the Riak database}
32
+ spec.homepage = "http://github.com/basho-labs/riak_json_ruby_client"
33
+ spec.license = "Apache 2.0"
34
+
35
+ spec.files = `git ls-files`.split($/)
36
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
37
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
38
+ spec.require_paths = ["lib"]
39
+
40
+ spec.add_dependency 'json'
41
+ spec.add_dependency 'rest-client'
42
+
43
+ spec.add_development_dependency "bundler"
44
+ spec.add_development_dependency "rake"
45
+ spec.add_development_dependency "minitest"
46
+ spec.add_development_dependency "minitest-spec-context"
47
+
48
+ spec.add_development_dependency "ruby-prof"
49
+ spec.add_development_dependency "debugger", "1.6.5"
50
+ spec.add_development_dependency "pry"
51
+ end
@@ -0,0 +1,13 @@
1
+ # Configure Riak Json connections for the client, by environment
2
+ development:
3
+ http_port: 8098
4
+ host: 127.0.0.1
5
+
6
+ # You can spin up another RiakJson instance to use as a test server
7
+ test:
8
+ http_port: 8098
9
+ host: 127.0.0.1
10
+
11
+ production:
12
+ http_port: 8098
13
+ host: 127.0.0.1
data/test/helper.rb ADDED
@@ -0,0 +1,31 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ require 'minitest/autorun'
22
+ require 'minitest-spec-context'
23
+ require 'riak_json'
24
+
25
+ class Minitest::Test
26
+ def rj_test_client
27
+ host = ENV['RIAK_HOST'] ? ENV['RIAK_HOST'] : RiakJson::RIAK_TEST_HOST
28
+ port = ENV['RIAK_PORT'] ? ENV['RIAK_PORT'] : RiakJson::RIAK_TEST_PORT
29
+ @rj_client ||= RiakJson::Client.new(host, port)
30
+ end
31
+ end
@@ -0,0 +1,51 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ require 'helper'
22
+
23
+ describe "RiakJson Ruby Client" do
24
+ it "can load configuration from a file" do
25
+ test_config_path = 'test/examples/riak.yml'
26
+ config_hash = RiakJson::Client.load_config_file(test_config_path)
27
+ assert config_hash.include?('development'), "Sample config file should have a 'development' environment section"
28
+ dev_config = config_hash['development']
29
+ dev_config['http_port'].wont_be_nil
30
+ dev_config['host'].wont_be_nil
31
+ # The loaded config hash can then be used to set up the client
32
+ client = RiakJson::Client.new(dev_config['host'], dev_config['http_port'])
33
+ end
34
+
35
+ context "connects to RiakJson" do
36
+ it "can perform an HTTP /ping to the RiakJson cluster" do
37
+ response = rj_test_client.ping
38
+ response.must_equal 'OK'
39
+ response.code.must_equal 200
40
+ end
41
+ end
42
+
43
+ context "performs document Schema administration" do
44
+ it "receives a 404 Exception when reading a non-existing schema" do
45
+ # Note: A default schema is auto-created whenever a document is written to a collection
46
+ # For a schema to not exist, no schemas could have been stored for that collection, and no documents inserted
47
+ collection_name = 'non-existing-collection'
48
+ lambda { rj_test_client.get_schema(collection_name) }.must_raise RestClient::ResourceNotFound # 404
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,227 @@
1
+ ## -------------------------------------------------------------------
2
+ ##
3
+ ## Copyright (c) "2013" Basho Technologies, Inc.
4
+ ##
5
+ ## This file is provided to you under the Apache License,
6
+ ## Version 2.0 (the "License"); you may not use this file
7
+ ## except in compliance with the License. You may obtain
8
+ ## a copy of the License at
9
+ ##
10
+ ## http://www.apache.org/licenses/LICENSE-2.0
11
+ ##
12
+ ## Unless required by applicable law or agreed to in writing,
13
+ ## software distributed under the License is distributed on an
14
+ ## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15
+ ## KIND, either express or implied. See the License for the
16
+ ## specific language governing permissions and limitations
17
+ ## under the License.
18
+ ##
19
+ ## -------------------------------------------------------------------
20
+
21
+ require 'helper'
22
+
23
+ describe "a RiakJson Collection" do
24
+ context "uses a RiakJson client to perform CRUD on raw JSON objects" do
25
+ it "inserts a raw json object with a key" do
26
+ client = rj_test_client
27
+ collection_name = 'ruby_test_collection'
28
+ collection = client.collection(collection_name) # create a new collection object
29
+ test_key = 'document-key-123'
30
+ json_obj = { 'field_one' => '123', 'field_two' => 'abc' }.to_json
31
+ key = collection.insert_raw_json(test_key, json_obj)
32
+ key.must_equal test_key
33
+ end
34
+
35
+ it "updates a raw json object" do
36
+ client = rj_test_client
37
+ collection_name = 'ruby_test_collection'
38
+ collection = client.collection(collection_name) # create a new collection object
39
+ test_key = 'document-key-update'
40
+ # Insert an object first
41
+ json_obj_initial = { 'field_one' => '123', 'field_two' => 'abc' }.to_json
42
+ collection.insert_raw_json(test_key, json_obj_initial)
43
+
44
+ # Now update the object
45
+ json_obj_modified = { 'field_one' => '345', 'field_two' => 'efg' }.to_json
46
+ collection.update_raw_json(test_key, json_obj_modified)
47
+ end
48
+
49
+ it "deletes a raw json object" do
50
+ client = rj_test_client
51
+ collection_name = 'ruby_test_collection'
52
+ collection = client.collection(collection_name) # create a new collection object
53
+ test_key = 'document-key-delete'
54
+ # Insert an object first
55
+ json_obj = { 'field_one' => '123', 'field_two' => 'abc' }.to_json
56
+ collection.insert_raw_json(test_key, json_obj)
57
+
58
+ # Now delete that object
59
+ collection.delete_raw_json(test_key)
60
+
61
+ # Issue a get to make sure it now returns a 404 / Resource not found exception
62
+ lambda { collection.get_raw_json(test_key) }.must_raise RestClient::ResourceNotFound
63
+ end
64
+ end
65
+
66
+ context "uses a RiakJson client to perform CRUD on RiakJson Documents" do
67
+ it "inserts a new document with a key" do
68
+ client = rj_test_client
69
+ collection_name = 'ruby_test_collection'
70
+ collection = client.collection(collection_name)
71
+
72
+ test_key = 'key-123'
73
+ test_body = { 'field_one' => 'abc' }
74
+ doc = RiakJson::Document.new(test_key, test_body)
75
+ key = collection.insert(doc)
76
+ key.must_equal test_key
77
+ end
78
+
79
+ it "inserts a new document with no key, receives key from RiakJson" do
80
+ client = rj_test_client
81
+ collection_name = 'ruby_test_collection'
82
+ collection = client.collection(collection_name)
83
+
84
+ test_body = { 'field_one' => 'abc' }
85
+ doc = RiakJson::Document.new
86
+ doc.body = test_body
87
+ doc.key.must_be_nil
88
+
89
+ # Insert the document, get key back from db
90
+ generated_key = collection.insert(doc)
91
+ # The insert() operation should initialize the document's key field
92
+ doc.key.must_equal generated_key
93
+ end
94
+
95
+ it "updates an existing document" do
96
+ client = rj_test_client
97
+ collection_name = 'ruby_test_collection'
98
+ collection = client.collection(collection_name)
99
+
100
+ test_key = 'key-123'
101
+ test_body = { 'field_one' => 'abc' }
102
+ doc = RiakJson::Document.new(test_key, test_body)
103
+ collection.update(doc)
104
+ end
105
+
106
+ it "reads an existing document (loads it by key)" do
107
+ client = rj_test_client
108
+ collection_name = 'ruby_test_collection'
109
+ collection = client.collection(collection_name)
110
+
111
+ # First, insert the document that's to be read
112
+ test_key = 'key-123'
113
+ test_body = { 'field_one' => 'abc' }
114
+ doc = RiakJson::Document.new(test_key, test_body)
115
+ collection.update(doc)
116
+
117
+ loaded_doc = collection.find_by_key(test_key)
118
+ loaded_doc.must_be_kind_of RiakJson::Document
119
+ loaded_doc['field_one'].must_equal 'abc'
120
+ end
121
+ end
122
+
123
+ context "can set, read and delete schemas" do
124
+ it "can use a raw JSON object to set schema" do
125
+ client = rj_test_client
126
+ collection = client.collection('cities')
127
+
128
+ schema = [{
129
+ :name => "city",
130
+ :type => "text",
131
+ :require => true
132
+ }, {
133
+ :name => "state",
134
+ :type => "string",
135
+ :require => true
136
+ }, {
137
+ :name => "zip_codes",
138
+ :type => "multi_string",
139
+ :require => false
140
+ }, {
141
+ :name => "population",
142
+ :type => "integer",
143
+ :require => false
144
+ }, {
145
+ :name => "country",
146
+ :type => "string",
147
+ :require => true
148
+ }].to_json
149
+ response = collection.set_schema(schema)
150
+ collection.has_schema?.must_equal true
151
+ response.code.must_equal 204
152
+ end
153
+
154
+ it "uses a CollectionSchema object to set schemas" do
155
+ client = rj_test_client
156
+ collection = client.collection('cities')
157
+
158
+ schema = RiakJson::CollectionSchema.new
159
+ schema.add_text_field(name='city', required=true)
160
+ schema.add_string_field('state', true)
161
+ schema.add_multi_string_field('zip_codes') # required: false
162
+ schema.add_integer_field('population', false)
163
+ schema.add_string_field('country', true)
164
+
165
+ response = collection.set_schema(schema)
166
+ response.code.must_equal 204
167
+ end
168
+
169
+ it "can delete (unset) a schema for a collection" do
170
+ client = rj_test_client
171
+ collection = client.collection('cities-delete-schema')
172
+
173
+ # Ensure a collection has an existing schema
174
+ schema = RiakJson::CollectionSchema.new
175
+ schema.add_text_field(name='city', required=true)
176
+ response = collection.set_schema(schema)
177
+ response.code.must_equal 204
178
+
179
+ # Delete the schema
180
+ response = collection.delete_schema
181
+ response.code.must_equal 204
182
+
183
+ end
184
+ end
185
+
186
+ context "performs queries" do
187
+ it "retrieves a single document with find_one()" do
188
+ client = rj_test_client
189
+ collection = client.collection('cities')
190
+ key = "nyc"
191
+ body = { 'city' => "New York", 'state' => "NY", 'country' => "USA" }
192
+ doc = RiakJson::Document.new(key, body)
193
+ collection.insert(doc)
194
+
195
+ result_doc = collection.find_one({"city" => "New York"}.to_json)
196
+ result_doc.key.must_equal "nyc"
197
+ end
198
+
199
+ it "retrieves many documents with find_all()" do
200
+ client = rj_test_client
201
+ collection = client.collection('cities')
202
+
203
+ # Populate the cities collection with data
204
+ doc = RiakJson::Document.new(
205
+ key="nyc",
206
+ body={ 'city'=>"New York", 'state'=>"NY", 'country'=>"USA" })
207
+ collection.insert(doc)
208
+ doc = RiakJson::Document.new(
209
+ key="boston",
210
+ body={ 'city'=>"Boston", 'state'=>"MA", 'country'=>"USA" })
211
+ collection.insert(doc)
212
+ doc = RiakJson::Document.new(
213
+ key="sf",
214
+ body={ 'city'=>"San Francisco", 'state'=>"CA", 'country'=>"USA" })
215
+ collection.insert(doc)
216
+
217
+ results = collection.find_all({'country'=>'USA'}.to_json)
218
+ results.num_pages.must_equal 1 # Total number of pages in result set
219
+ results.page.must_equal 0 # Current page, zero-indexed
220
+ results.total.must_equal 3 # Total number of documents in result set
221
+ results.per_page.must_be :>, 0 # defaults to 100
222
+
223
+ results.documents.count.must_equal 3
224
+ results.documents[0].must_be_kind_of RiakJson::Document
225
+ end
226
+ end
227
+ end