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 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
@@ -0,0 +1,4 @@
1
+ module Reflect
2
+ class RequestError < StandardError
3
+ end
4
+ end
@@ -0,0 +1,3 @@
1
+ module Reflect
2
+ VERSION = "0.1.4"
3
+ 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: []