reflect 0.1.4
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.
- checksums.yaml +7 -0
- data/lib/reflect.rb +31 -0
- data/lib/reflect/client.rb +72 -0
- data/lib/reflect/field.rb +19 -0
- data/lib/reflect/key_list.rb +21 -0
- data/lib/reflect/keyspace.rb +144 -0
- data/lib/reflect/request_error.rb +4 -0
- data/lib/reflect/version.rb +3 -0
- data/reflect.gemspec +41 -0
- metadata +92 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 928aa43cbfd50fdfcd1843a1233bbf704a45e509
|
4
|
+
data.tar.gz: d5afdd92cf542be18c98a47b02096ef6be285695
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c044b1a3ec63e1110f16af6b69a78569d84d573e39d2e5e3be1907441a8feca2dca3c5715a73f44aac91bd39fb9123e4995be2f2bdfd25cb72d00b34787f5e62
|
7
|
+
data.tar.gz: 322204507bcdbe50df45c8b028a2e31c54303b0d643d8a766fcfb4bd7da6dec045d9dce8f350464a231d489fe3db6b07ad5cbbbbf27e31af60882b26a39a5a7a
|
data/lib/reflect.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift(File.expand_path("../", __FILE__))
|
2
|
+
|
3
|
+
require 'reflect/key_list'
|
4
|
+
require 'reflect/request_error'
|
5
|
+
require 'reflect/keyspace'
|
6
|
+
require 'reflect/field'
|
7
|
+
require 'reflect/client'
|
8
|
+
|
9
|
+
module Reflect
|
10
|
+
def self._format_error_message(resp)
|
11
|
+
"An error occured with the request. Status: #{resp.response.code} Error: #{_extract_error_message(resp)}"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self._extract_error_message(resp)
|
15
|
+
begin
|
16
|
+
json = JSON.parse(resp.body)
|
17
|
+
json["error"]
|
18
|
+
rescue JSON::ParserError
|
19
|
+
# TODO: Report this?
|
20
|
+
""
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.logger=(logger)
|
25
|
+
@logger = logger
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.logger
|
29
|
+
@logger ||= Logger.new("/dev/null")
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'uri'
|
2
|
+
require 'json'
|
3
|
+
require 'httparty'
|
4
|
+
require 'reflect/version'
|
5
|
+
|
6
|
+
module Reflect
|
7
|
+
class Client
|
8
|
+
include HTTParty
|
9
|
+
|
10
|
+
base_uri 'https://api.reflect.io'
|
11
|
+
|
12
|
+
def initialize(token)
|
13
|
+
@token = token
|
14
|
+
end
|
15
|
+
|
16
|
+
def keyspace(slug)
|
17
|
+
res = get("/v1/keyspaces/#{slug}")
|
18
|
+
|
19
|
+
if res.response.code == "200"
|
20
|
+
Keyspace.new(self, JSON.parse(res.body))
|
21
|
+
else
|
22
|
+
# TODO: What happens if we failed to look this up or whatever?
|
23
|
+
raise Reflect::RequestError, Reflect._format_error_message(res)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def get(path)
|
28
|
+
self.class.get(URI.encode(path), options)
|
29
|
+
end
|
30
|
+
|
31
|
+
def post(path, content)
|
32
|
+
self.class.post(URI.encode(path), options(body: dump(content)))
|
33
|
+
end
|
34
|
+
|
35
|
+
def put(path, content)
|
36
|
+
self.class.put(URI.encode(path), options(body: dump(content)))
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete(path)
|
40
|
+
logger.debug { "[reflect] Sending DELETE #{URI.encode(path)}" }
|
41
|
+
self.class.delete(URI.encode(path), options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def patch(path, content, headers={})
|
45
|
+
opts = options(body: dump(content))
|
46
|
+
opts[:headers].merge!(headers) unless headers.empty?
|
47
|
+
self.class.patch(path, opts)
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def options(opts={})
|
53
|
+
defaults = {
|
54
|
+
basic_auth: { username: '', password: @token },
|
55
|
+
headers: {
|
56
|
+
"User-Agent" => "Reflect Ruby API client v#{Reflect::VERSION}",
|
57
|
+
"Content-Type" => "application/json"
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
opts.merge(defaults)
|
62
|
+
end
|
63
|
+
|
64
|
+
def dump(obj)
|
65
|
+
JSON.dump(obj)
|
66
|
+
end
|
67
|
+
|
68
|
+
def logger
|
69
|
+
Reflect.logger
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Reflect
|
2
|
+
class Field
|
3
|
+
attr_accessor :name
|
4
|
+
attr_accessor :column_type
|
5
|
+
attr_accessor :type
|
6
|
+
attr_accessor :description
|
7
|
+
attr_accessor :fields
|
8
|
+
attr_accessor :created_at
|
9
|
+
attr_accessor :updated_at
|
10
|
+
|
11
|
+
def initialize(client, attrs={})
|
12
|
+
@client = client
|
13
|
+
|
14
|
+
attrs.each do |k, v|
|
15
|
+
self.send("#{k}=".to_s, v)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Reflect
|
2
|
+
class KeyList
|
3
|
+
include Enumerable
|
4
|
+
|
5
|
+
attr_reader :keys
|
6
|
+
attr_reader :next
|
7
|
+
|
8
|
+
def initialize(keys, continuation)
|
9
|
+
@keys = keys || []
|
10
|
+
@next = continuation
|
11
|
+
end
|
12
|
+
|
13
|
+
def each(&blk)
|
14
|
+
keys.each(&blk)
|
15
|
+
end
|
16
|
+
|
17
|
+
def empty?
|
18
|
+
keys.count < 1
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,144 @@
|
|
1
|
+
require 'time'
|
2
|
+
require 'reflect/field'
|
3
|
+
|
4
|
+
module Reflect
|
5
|
+
class Keyspace
|
6
|
+
attr_reader :client
|
7
|
+
|
8
|
+
attr_accessor :name
|
9
|
+
attr_accessor :slug
|
10
|
+
attr_accessor :statistics_key
|
11
|
+
attr_accessor :description
|
12
|
+
attr_accessor :fields
|
13
|
+
attr_accessor :status
|
14
|
+
attr_accessor :created_at
|
15
|
+
attr_accessor :updated_at
|
16
|
+
|
17
|
+
def initialize(client, attrs={})
|
18
|
+
@client = client
|
19
|
+
|
20
|
+
# If we have fields, we'll need to populate them individually.
|
21
|
+
fields = attrs.delete("fields")
|
22
|
+
|
23
|
+
attrs['updated_at'] = Time.parse(attrs['updated_at']) if attrs['updated_at']
|
24
|
+
attrs['created_at'] = Time.parse(attrs['created_at']) if attrs['created_at']
|
25
|
+
|
26
|
+
attrs.each do |k, v|
|
27
|
+
self.send("#{k}=".to_s, v)
|
28
|
+
end
|
29
|
+
|
30
|
+
if fields
|
31
|
+
self.fields = fields.map { |f| Field.new(f) }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def keys(continuation=nil)
|
36
|
+
resp = client.get(keys_path(slug, continuation))
|
37
|
+
|
38
|
+
if resp.response.code != "200"
|
39
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
40
|
+
end
|
41
|
+
|
42
|
+
json = JSON.parse(resp.body)
|
43
|
+
|
44
|
+
if json["keys"].nil? || json["keys"].empty?
|
45
|
+
nil
|
46
|
+
else
|
47
|
+
KeyList.new(json["keys"], json["next"])
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Appends records to a tablet. If the tablet doesn't exist it will be
|
52
|
+
# created. records can be either a single object or an array of objects. A
|
53
|
+
# single object represents a single row.
|
54
|
+
#
|
55
|
+
# @param String key the key to create
|
56
|
+
# @param Array|Hash records the records to create
|
57
|
+
#
|
58
|
+
def append(key, records)
|
59
|
+
resp = client.put(path(slug, key), records)
|
60
|
+
|
61
|
+
if resp.response.code != "202"
|
62
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
# Replaces the existing records in a tablet with a net set of records.
|
67
|
+
# records can be either a single object or an array of objects. A single
|
68
|
+
# object represents a single row.
|
69
|
+
#
|
70
|
+
# @param String key the key to create
|
71
|
+
# @param Array|Hash records the records to create
|
72
|
+
#
|
73
|
+
def replace(key, records)
|
74
|
+
resp = client.post(path(slug, key), records)
|
75
|
+
|
76
|
+
if resp.response.code != "202"
|
77
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Patches the existing records in a tablet with a net set of records. The
|
82
|
+
# criteria parameter indicates which records to match existing records on.
|
83
|
+
# In the Reflect API, if no existing records match the supplied records
|
84
|
+
# then those records are dropped.
|
85
|
+
#
|
86
|
+
# @param String key the key to create
|
87
|
+
# @param Array|Hash records the records to create
|
88
|
+
# @param Array criteria an array of field names within a record to match
|
89
|
+
#
|
90
|
+
def patch(key, records, criteria)
|
91
|
+
resp = client.patch(path(slug, key), records, "X-Criteria" => criteria.join(", "))
|
92
|
+
|
93
|
+
if resp.response.code != "202"
|
94
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
# Patch the existing records in a tablet with a new set of records and
|
99
|
+
# insert any that aren't matched. The criteria parameter indicates which
|
100
|
+
# records to match existing records on.
|
101
|
+
#
|
102
|
+
# @param String key the key to create
|
103
|
+
# @param Array|Hash records the records to create
|
104
|
+
# @param Array criteria an array of field names within a record to match
|
105
|
+
#
|
106
|
+
def upsert(key, records, criteria)
|
107
|
+
headers = {
|
108
|
+
"X-Criteria" => criteria.join(", "),
|
109
|
+
"X-Insert-Missing" => true
|
110
|
+
}
|
111
|
+
|
112
|
+
resp = client.patch(path(slug, key), records, headers)
|
113
|
+
|
114
|
+
if resp.response.code != "202"
|
115
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
|
120
|
+
# Deletes a key within a keyspace.
|
121
|
+
#
|
122
|
+
# @param String key the key to delete
|
123
|
+
#
|
124
|
+
def delete(key)
|
125
|
+
resp = client.delete(path(slug, key))
|
126
|
+
|
127
|
+
if resp.response.code != "202"
|
128
|
+
raise Reflect::RequestError, Reflect._format_error_message(resp)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
private
|
133
|
+
|
134
|
+
def path(slug, key)
|
135
|
+
"/v1/keyspaces/#{slug}/tablets/#{key}"
|
136
|
+
end
|
137
|
+
|
138
|
+
def keys_path(slug, continuation=nil)
|
139
|
+
base = "/v1/keyspaces/#{slug}/keys"
|
140
|
+
base += "?next=#{continuation}" if continuation
|
141
|
+
base
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
data/reflect.gemspec
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "reflect/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
FILES = Dir[File.expand_path('../lib/**/*.rb', __FILE__)].map { |fi| fi.gsub(File.expand_path('../', __FILE__) +"/", "") } + ['reflect.gemspec']
|
7
|
+
|
8
|
+
s.name = "reflect"
|
9
|
+
s.version = Reflect::VERSION
|
10
|
+
|
11
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
|
+
s.authors = ["Brad Heller"]
|
13
|
+
s.date = "2015-08-30"
|
14
|
+
s.description = "Ruby client for Reflect.io"
|
15
|
+
s.email = "brad@reflect.io"
|
16
|
+
s.files = FILES
|
17
|
+
s.homepage = "http://github.com/reflect/reflect-rb"
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
s.rubygems_version = "1.8.24"
|
20
|
+
s.summary = "Reflect.io API Ruby client"
|
21
|
+
|
22
|
+
if s.respond_to? :specification_version then
|
23
|
+
s.specification_version = 3
|
24
|
+
|
25
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
26
|
+
s.add_runtime_dependency(%q<httparty>, [">= 0"])
|
27
|
+
s.add_development_dependency('rake', '~> 10.1.0')
|
28
|
+
s.add_development_dependency('minitest', '~> 5.3')
|
29
|
+
else
|
30
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
31
|
+
s.add_development_dependency('rake', '~> 10.1.0')
|
32
|
+
s.add_development_dependency('minitest', '~> 5.3')
|
33
|
+
end
|
34
|
+
else
|
35
|
+
s.add_dependency(%q<httparty>, [">= 0"])
|
36
|
+
s.add_development_dependency('rake', '~> 10.1.0')
|
37
|
+
s.add_development_dependency('minitest', '~> 5.3')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reflect
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.4
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Brad Heller
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-08-30 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 10.1.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 10.1.0
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '5.3'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '5.3'
|
55
|
+
description: Ruby client for Reflect.io
|
56
|
+
email: brad@reflect.io
|
57
|
+
executables: []
|
58
|
+
extensions: []
|
59
|
+
extra_rdoc_files: []
|
60
|
+
files:
|
61
|
+
- lib/reflect.rb
|
62
|
+
- lib/reflect/client.rb
|
63
|
+
- lib/reflect/field.rb
|
64
|
+
- lib/reflect/key_list.rb
|
65
|
+
- lib/reflect/keyspace.rb
|
66
|
+
- lib/reflect/request_error.rb
|
67
|
+
- lib/reflect/version.rb
|
68
|
+
- reflect.gemspec
|
69
|
+
homepage: http://github.com/reflect/reflect-rb
|
70
|
+
licenses: []
|
71
|
+
metadata: {}
|
72
|
+
post_install_message:
|
73
|
+
rdoc_options: []
|
74
|
+
require_paths:
|
75
|
+
- lib
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
77
|
+
requirements:
|
78
|
+
- - ">="
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
82
|
+
requirements:
|
83
|
+
- - ">="
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 2.4.8
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: Reflect.io API Ruby client
|
92
|
+
test_files: []
|