riak_json 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,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