parse-ruby-client 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +15 -0
- data/.travis.yml +2 -1
- data/Gemfile +4 -6
- data/Gemfile.lock +18 -18
- data/README.md +1 -1
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/example.rb +2 -1
- data/fixtures/vcr_cassettes/test_batch_update_nils_delete_keys.yml +57 -0
- data/fixtures/vcr_cassettes/test_empty_response.yml +72 -0
- data/fixtures/vcr_cassettes/test_get_missing.yml +95 -38
- data/fixtures/vcr_cassettes/test_image_file_associate_with_object.yml +2089 -0
- data/fixtures/vcr_cassettes/test_image_file_save.yml +1928 -0
- data/fixtures/vcr_cassettes/test_object_id.yml +56 -0
- data/fixtures/vcr_cassettes/test_reset_password.yml +109 -0
- data/fixtures/vcr_cassettes/test_retries.yml +357 -0
- data/fixtures/vcr_cassettes/test_retries_404.yml +72 -0
- data/fixtures/vcr_cassettes/test_retries_404_correct.yml +72 -0
- data/fixtures/vcr_cassettes/test_retries_json_error.yml +357 -0
- data/fixtures/vcr_cassettes/test_retries_server_error.yml +357 -0
- data/fixtures/vcr_cassettes/test_server_update.yml +248 -191
- data/fixtures/vcr_cassettes/test_user_login.yml +276 -0
- data/fixtures/vcr_cassettes/test_xget.yml +280 -0
- data/lib/faraday/better_retry.rb +94 -0
- data/lib/faraday/extended_parse_json.rb +39 -0
- data/lib/faraday/get_method_override.rb +32 -0
- data/lib/parse-ruby-client.rb +9 -9
- data/lib/parse/batch.rb +2 -3
- data/lib/parse/client.rb +72 -161
- data/lib/parse/cloud.rb +2 -1
- data/lib/parse/datatypes.rb +6 -1
- data/lib/parse/error.rb +7 -3
- data/lib/parse/installation.rb +18 -0
- data/lib/parse/model.rb +2 -1
- data/lib/parse/object.rb +7 -1
- data/lib/parse/protocol.rb +10 -0
- data/lib/parse/push.rb +3 -0
- data/lib/parse/query.rb +5 -2
- data/lib/parse/user.rb +1 -0
- data/lib/parse/util.rb +2 -0
- data/parse-ruby-client.gemspec +35 -15
- data/test/helper.rb +55 -1
- data/test/middleware/better_retry_test.rb +57 -0
- data/test/middleware/extend_parse_json_test.rb +55 -0
- data/test/test_client.rb +78 -28
- data/test/test_datatypes.rb +14 -0
- data/test/test_object.rb +16 -0
- metadata +39 -34
- data/lib/parse/http_client.rb +0 -84
@@ -0,0 +1,94 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
require 'ostruct'
|
3
|
+
module Faraday
|
4
|
+
# Catches exceptions and retries each request a limited number of times.
|
5
|
+
#
|
6
|
+
# By default, it retries 2 times and handles only timeout exceptions. It can
|
7
|
+
# be configured with an arbitrary number of retries, a list of exceptions to
|
8
|
+
# handle an a retry interval.
|
9
|
+
#
|
10
|
+
# Examples
|
11
|
+
#
|
12
|
+
# Faraday.new do |conn|
|
13
|
+
# conn.request :retry, max: 2, interval: 0.05,
|
14
|
+
# exceptions: [CustomException, 'Timeout::Error']
|
15
|
+
# conn.adapter ...
|
16
|
+
# end
|
17
|
+
class BetterRetry < Faraday::Middleware
|
18
|
+
class Options < OpenStruct
|
19
|
+
|
20
|
+
def max
|
21
|
+
(self[:max] ||= 2).to_i
|
22
|
+
end
|
23
|
+
|
24
|
+
def interval
|
25
|
+
(self[:interval] ||= 0).to_f
|
26
|
+
end
|
27
|
+
|
28
|
+
def exceptions
|
29
|
+
Array(self[:exceptions] ||= [Errno::ETIMEDOUT, 'Timeout::Error', Error::TimeoutError])
|
30
|
+
end
|
31
|
+
|
32
|
+
# define for ruby less than 2.0
|
33
|
+
def [](name)
|
34
|
+
@table[name.to_sym]
|
35
|
+
end
|
36
|
+
|
37
|
+
def []=(name, value)
|
38
|
+
modifiable[new_ostruct_member(name)] = value
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
# Public: Initialize middleware
|
44
|
+
#
|
45
|
+
# Options:
|
46
|
+
# max - Maximum number of retries (default: 2).
|
47
|
+
# interval - Pause in seconds between retries (default: 0).
|
48
|
+
# exceptions - The list of exceptions to handle. Exceptions can be
|
49
|
+
# given as Class, Module, or String. (default:
|
50
|
+
# [Errno::ETIMEDOUT, Timeout::Error, Error::TimeoutError])
|
51
|
+
def initialize(app, options = {})
|
52
|
+
super(app)
|
53
|
+
@options = Options.new(options)
|
54
|
+
@errmatch = build_exception_matcher(@options.exceptions)
|
55
|
+
@logger = options[:logger]
|
56
|
+
end
|
57
|
+
|
58
|
+
def call(env)
|
59
|
+
env[:retries] = retries = @options.max
|
60
|
+
begin
|
61
|
+
@app.call(env)
|
62
|
+
rescue @errmatch => e
|
63
|
+
if retries > 0
|
64
|
+
if @logger
|
65
|
+
@logger.warn("Retrying Parse Error #{e.inspect} on request #{env[:url].to_s} #{env[:body].inspect} response #{env[:response].inspect}")
|
66
|
+
end
|
67
|
+
retries -= 1
|
68
|
+
env[:retries] = retries
|
69
|
+
sleep @options.interval if @options.interval > 0
|
70
|
+
retry
|
71
|
+
end
|
72
|
+
raise
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
# Private: construct an exception matcher object.
|
77
|
+
#
|
78
|
+
# An exception matcher for the rescue clause can usually be any object that
|
79
|
+
# responds to `===`, but for Ruby 1.8 it has to be a Class or Module.
|
80
|
+
def build_exception_matcher(exceptions)
|
81
|
+
matcher = Module.new
|
82
|
+
(class << matcher; self; end).class_eval do
|
83
|
+
define_method(:===) do |error|
|
84
|
+
exceptions.any? do |ex|
|
85
|
+
if ex.is_a? Module then error.is_a? ex
|
86
|
+
else error.class.to_s == ex.to_s
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
matcher
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
module Faraday
|
3
|
+
|
4
|
+
class ExtendedParseJson < FaradayMiddleware::ParseJson
|
5
|
+
|
6
|
+
def process_response(env)
|
7
|
+
env[:raw_body] = env[:body] if preserve_raw?(env)
|
8
|
+
|
9
|
+
|
10
|
+
if env[:status] >= 400
|
11
|
+
data = parse(env[:body]) || {} rescue {}
|
12
|
+
|
13
|
+
array_codes = [
|
14
|
+
Parse::Protocol::ERROR_INTERNAL,
|
15
|
+
Parse::Protocol::ERROR_TIMEOUT,
|
16
|
+
Parse::Protocol::ERROR_EXCEEDED_BURST_LIMIT
|
17
|
+
]
|
18
|
+
error_hash = { "error" => "HTTP Status #{env[:status]} Body #{env[:body]}" }.merge(data)
|
19
|
+
if data['code'] && array_codes.include?(data['code'])
|
20
|
+
sleep 60 if data['code'] == Parse::Protocol::ERROR_EXCEEDED_BURST_LIMIT
|
21
|
+
raise exception(env).new(error_hash.merge(data))
|
22
|
+
elsif env[:status] >= 500
|
23
|
+
raise exception(env).new(error_hash.merge(data))
|
24
|
+
end
|
25
|
+
raise Parse::ParseProtocolError.new(error_hash)
|
26
|
+
else
|
27
|
+
data = parse(env[:body]) || {}
|
28
|
+
|
29
|
+
env[:body] = data
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def exception env
|
34
|
+
# decide to retry or not
|
35
|
+
(env[:retries].to_i.zero? ? Parse::ParseProtocolError : Parse::ParseProtocolRetry)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
2
|
+
|
3
|
+
require 'faraday'
|
4
|
+
|
5
|
+
module Faraday
|
6
|
+
# Public: Writes the original HTTP method to "X-Http-Method-Override" header
|
7
|
+
# and sends the request as POST for GET requests that are too long.
|
8
|
+
class GetMethodOverride < Faraday::Middleware
|
9
|
+
|
10
|
+
HEADER = "X-Http-Method-Override".freeze
|
11
|
+
|
12
|
+
# Public: Initialize the middleware.
|
13
|
+
#
|
14
|
+
# app - the Faraday app to wrap
|
15
|
+
def initialize(app, options = nil)
|
16
|
+
super(app)
|
17
|
+
end
|
18
|
+
|
19
|
+
def call(env)
|
20
|
+
if env[:method] == :get && env[:url].to_s.size > 2000
|
21
|
+
env[:request_headers][HEADER] = 'GET'
|
22
|
+
env[:request_headers]['Content-Type'] =
|
23
|
+
'application/x-www-form-urlencoded'
|
24
|
+
env[:body] = env[:url].query
|
25
|
+
env[:url].query = nil
|
26
|
+
env[:method] = :post
|
27
|
+
end
|
28
|
+
|
29
|
+
@app.call(env)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/parse-ruby-client.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
## ----------------------------------------------------------------------
|
2
3
|
##
|
3
4
|
## Ruby client for parse.com
|
@@ -5,18 +6,16 @@
|
|
5
6
|
## See https://parse.com/docs/rest for full documentation on the API.
|
6
7
|
##
|
7
8
|
## ----------------------------------------------------------------------
|
8
|
-
require
|
9
|
-
require
|
9
|
+
require 'rubygems'
|
10
|
+
require 'bundler/setup'
|
10
11
|
|
11
|
-
require '
|
12
|
+
require 'faraday'
|
13
|
+
require 'faraday_middleware'
|
14
|
+
require 'faraday/better_retry'
|
15
|
+
require 'faraday/extended_parse_json'
|
16
|
+
require 'faraday/get_method_override'
|
12
17
|
require 'date'
|
13
18
|
require 'cgi'
|
14
|
-
if defined?(JRUBY_VERSION)
|
15
|
-
require 'net/http'
|
16
|
-
require 'net/https'
|
17
|
-
else
|
18
|
-
require 'patron'
|
19
|
-
end
|
20
19
|
|
21
20
|
cwd = Pathname(__FILE__).dirname
|
22
21
|
$:.unshift(cwd.to_s) unless $:.include?(cwd.to_s) || $:.include?(cwd.expand_path.to_s)
|
@@ -27,6 +26,7 @@ require 'parse/datatypes'
|
|
27
26
|
require 'parse/util'
|
28
27
|
require 'parse/protocol'
|
29
28
|
require 'parse/user'
|
29
|
+
require "parse/installation"
|
30
30
|
require 'parse/push'
|
31
31
|
require 'parse/cloud'
|
32
32
|
require 'parse/model'
|
data/lib/parse/batch.rb
CHANGED
data/lib/parse/client.rb
CHANGED
@@ -1,12 +1,9 @@
|
|
1
|
+
# -*- encoding : utf-8 -*-
|
1
2
|
require 'parse/protocol'
|
2
3
|
require 'parse/error'
|
3
4
|
require 'parse/util'
|
4
|
-
require 'parse/http_client'
|
5
5
|
|
6
6
|
require 'logger'
|
7
|
-
|
8
|
-
require 'iron_mq'
|
9
|
-
|
10
7
|
module Parse
|
11
8
|
|
12
9
|
# A class which encapsulates the HTTPS communication with the Parse
|
@@ -21,7 +18,7 @@ module Parse
|
|
21
18
|
attr_accessor :max_retries
|
22
19
|
attr_accessor :logger
|
23
20
|
|
24
|
-
def initialize(data = {})
|
21
|
+
def initialize(data = {}, &blk)
|
25
22
|
@host = data[:host] || Protocol::HOST
|
26
23
|
@application_id = data[:application_id]
|
27
24
|
@api_key = data[:api_key]
|
@@ -29,27 +26,26 @@ module Parse
|
|
29
26
|
@session_token = data[:session_token]
|
30
27
|
@max_retries = data[:max_retries] || 3
|
31
28
|
@logger = data[:logger] || Logger.new(STDERR).tap{|l| l.level = Logger::INFO}
|
32
|
-
@session = data[:http_client] || Parse::DEFAULT_HTTP_CLIENT.new
|
33
29
|
|
34
|
-
|
30
|
+
options = {:request => {:timeout => 30, :open_timeout => 30}}
|
35
31
|
|
36
|
-
|
37
|
-
|
38
|
-
else
|
39
|
-
@max_concurrent_requests = 50
|
40
|
-
end
|
32
|
+
@session = Faraday.new("https://#{host}", options) do |c|
|
33
|
+
c.request :json
|
41
34
|
|
42
|
-
|
43
|
-
:project_id => data[:ironio_project_id],
|
44
|
-
:token => data[:ironio_token]
|
45
|
-
}).queue("concurrent_parse_requests")
|
35
|
+
c.use Faraday::GetMethodOverride
|
46
36
|
|
47
|
-
|
37
|
+
c.use Faraday::BetterRetry,
|
38
|
+
max: @max_retries,
|
39
|
+
logger: @logger,
|
40
|
+
interval: 0.5,
|
41
|
+
exceptions: ['Faraday::Error::TimeoutError', 'Faraday::Error::ParsingError', 'Parse::ParseProtocolRetry']
|
42
|
+
c.use Faraday::ExtendedParseJson
|
43
|
+
|
44
|
+
c.response :logger, @logger
|
45
|
+
c.adapter Faraday.default_adapter
|
48
46
|
|
49
|
-
|
50
|
-
|
51
|
-
@session.headers["Accept"] = "application/json"
|
52
|
-
@session.headers["User-Agent"] = "Parse for Ruby, 0.0"
|
47
|
+
yield(c) if block_given?
|
48
|
+
end
|
53
49
|
end
|
54
50
|
|
55
51
|
# Perform an HTTP request for the given uri and method
|
@@ -57,95 +53,20 @@ module Parse
|
|
57
53
|
# ParseProtocolError if the response has an error status code,
|
58
54
|
# and will return the parsed JSON body on success, if there is one.
|
59
55
|
def request(uri, method = :get, body = nil, query = nil, content_type = nil)
|
60
|
-
options = {}
|
61
56
|
headers = {}
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
options[:query] = @session.build_query(query)
|
73
|
-
|
74
|
-
# Avoid 502 or 414 when sending a large querystring. See https://parse.com/questions/502-error-when-query-with-huge-contains
|
75
|
-
if options[:query].size > 2000 && method == :get && !body && !content_type
|
76
|
-
options[:data] = options[:query]
|
77
|
-
options[:query] = nil
|
78
|
-
method = :post
|
79
|
-
headers['X-HTTP-Method-Override'] = 'GET'
|
80
|
-
content_type = 'application/x-www-form-urlencoded'
|
81
|
-
end
|
58
|
+
{
|
59
|
+
"Content-Type" => content_type || 'application/json',
|
60
|
+
"User-Agent" => 'Parse for Ruby, 0.0',
|
61
|
+
Protocol::HEADER_MASTER_KEY => @master_key,
|
62
|
+
Protocol::HEADER_APP_ID => @application_id,
|
63
|
+
Protocol::HEADER_API_KEY => @api_key,
|
64
|
+
Protocol::HEADER_SESSION_TOKEN => @session_token,
|
65
|
+
}.each do |key, value|
|
66
|
+
headers[key] = value if value
|
82
67
|
end
|
83
68
|
|
84
|
-
|
85
|
-
headers["Content-Type"] = content_type
|
86
|
-
end
|
87
|
-
|
88
|
-
num_tries = 0
|
89
|
-
begin
|
90
|
-
num_tries += 1
|
91
|
-
|
92
|
-
if @queue
|
93
|
-
|
94
|
-
#while true
|
95
|
-
# if @queue.reload.size >= @max_concurrent_requests
|
96
|
-
# sleep 1
|
97
|
-
# else
|
98
|
-
# add to queue before request
|
99
|
-
@queue.post("1")
|
100
|
-
response = @session.request(method, uri, headers, options)
|
101
|
-
# delete from queue after request
|
102
|
-
msg = @queue.get()
|
103
|
-
msg.delete
|
104
|
-
# end
|
105
|
-
#end
|
106
|
-
else
|
107
|
-
response = @session.request(method, uri, headers, options)
|
108
|
-
end
|
109
|
-
|
110
|
-
parsed = JSON.parse(response.body)
|
111
|
-
|
112
|
-
if response.status >= 400
|
113
|
-
parsed ||= {}
|
114
|
-
raise ParseProtocolError.new({"error" => "HTTP Status #{response.status} Body #{response.body}"}.merge(parsed))
|
115
|
-
end
|
116
|
-
|
117
|
-
if content_type
|
118
|
-
@session.headers["Content-Type"] = "application/json"
|
119
|
-
end
|
120
|
-
|
121
|
-
return parsed
|
122
|
-
rescue JSON::ParserError => e
|
123
|
-
if num_tries <= max_retries && response.status >= 500
|
124
|
-
log_retry(e, uri, query, body, response)
|
125
|
-
retry
|
126
|
-
end
|
127
|
-
raise
|
128
|
-
rescue HttpClient::TimeoutError => e
|
129
|
-
if num_tries <= max_retries
|
130
|
-
log_retry(e, uri, query, body, response)
|
131
|
-
retry
|
132
|
-
end
|
133
|
-
raise
|
134
|
-
rescue ParseProtocolError => e
|
135
|
-
if num_tries <= max_retries
|
136
|
-
if e.code
|
137
|
-
sleep 60 if e.code == Protocol::ERROR_EXCEEDED_BURST_LIMIT
|
138
|
-
if [Protocol::ERROR_INTERNAL, Protocol::ERROR_TIMEOUT, Protocol::ERROR_EXCEEDED_BURST_LIMIT].include?(e.code)
|
139
|
-
log_retry(e, uri, query, body, response)
|
140
|
-
retry
|
141
|
-
end
|
142
|
-
elsif response.status >= 500
|
143
|
-
log_retry(e, uri, query, body, response)
|
144
|
-
retry
|
145
|
-
end
|
146
|
-
end
|
147
|
-
raise
|
148
|
-
end
|
69
|
+
@session.send(method, uri, query || body || {}, headers).body
|
149
70
|
end
|
150
71
|
|
151
72
|
def get(uri)
|
@@ -164,72 +85,62 @@ module Parse
|
|
164
85
|
request(uri, :delete)
|
165
86
|
end
|
166
87
|
|
167
|
-
protected
|
168
|
-
|
169
|
-
def log_retry(e, uri, query, body, response)
|
170
|
-
logger.warn{"Retrying Parse Error #{e.inspect} on request #{uri} #{CGI.unescape(query.inspect)} #{body.inspect} response #{response.inspect}"}
|
171
|
-
end
|
172
88
|
end
|
173
89
|
|
174
90
|
|
175
91
|
# Module methods
|
176
92
|
# ------------------------------------------------------------
|
93
|
+
class << self
|
94
|
+
# A singleton client for use by methods in Object.
|
95
|
+
# Always use Parse.client to retrieve the client object.
|
96
|
+
@client = nil
|
97
|
+
|
98
|
+
# Initialize the singleton instance of Client which is used
|
99
|
+
# by all API methods. Parse.init must be called before saving
|
100
|
+
# or retrieving any objects.
|
101
|
+
def init(data = {}, &blk)
|
102
|
+
defaults = {:application_id => ENV["PARSE_APPLICATION_ID"], :api_key => ENV["PARSE_REST_API_KEY"]}
|
103
|
+
defaults.merge!(data)
|
104
|
+
|
105
|
+
# use less permissive key if both are specified
|
106
|
+
defaults[:master_key] = ENV["PARSE_MASTER_API_KEY"] unless data[:master_key] || defaults[:api_key]
|
107
|
+
@@client = Client.new(defaults, &blk)
|
108
|
+
end
|
177
109
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
:api_key => ENV["PARSE_REST_API_KEY"]}
|
188
|
-
defaulted.merge!(data)
|
189
|
-
|
190
|
-
# use less permissive key if both are specified
|
191
|
-
defaulted[:master_key] = ENV["PARSE_MASTER_API_KEY"] unless data[:master_key] || defaulted[:api_key]
|
192
|
-
|
193
|
-
|
194
|
-
@@client = Client.new(defaulted)
|
195
|
-
end
|
196
|
-
|
197
|
-
# A convenience method for using global.json
|
198
|
-
def Parse.init_from_cloud_code(path="../config/global.json")
|
199
|
-
global = JSON.parse(Object::File.open(path).read) # warning: toplevel constant File referenced by Parse::Object::File
|
200
|
-
application_name = global["applications"]["_default"]["link"]
|
201
|
-
application_id = global["applications"][application_name]["applicationId"]
|
202
|
-
master_key = global["applications"][application_name]["masterKey"]
|
203
|
-
Parse.init :application_id => application_id,
|
204
|
-
:master_key => master_key
|
205
|
-
end
|
206
|
-
|
207
|
-
# Used mostly for testing. Lets you delete the api key global vars.
|
208
|
-
def Parse.destroy
|
209
|
-
@@client = nil
|
210
|
-
self
|
211
|
-
end
|
110
|
+
# A convenience method for using global.json
|
111
|
+
def init_from_cloud_code(path = "../config/global.json")
|
112
|
+
# warning: toplevel constant File referenced by Parse::Object::File
|
113
|
+
global = JSON.parse(Object::File.open(path).read)
|
114
|
+
application_name = global["applications"]["_default"]["link"]
|
115
|
+
application_id = global["applications"][application_name]["applicationId"]
|
116
|
+
master_key = global["applications"][application_name]["masterKey"]
|
117
|
+
self.init(:application_id => application_id, :master_key => master_key)
|
118
|
+
end
|
212
119
|
|
213
|
-
|
214
|
-
|
215
|
-
|
120
|
+
# Used mostly for testing. Lets you delete the api key global vars.
|
121
|
+
def destroy
|
122
|
+
@@client = nil
|
123
|
+
self
|
216
124
|
end
|
217
|
-
@@client
|
218
|
-
end
|
219
125
|
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
# given class will be retrieved and returned in an Array.
|
224
|
-
def Parse.get(class_name, object_id = nil)
|
225
|
-
data = Parse.client.get( Protocol.class_uri(class_name, object_id) )
|
226
|
-
Parse.parse_json class_name, data
|
227
|
-
rescue ParseProtocolError => e
|
228
|
-
if e.code == Protocol::ERROR_OBJECT_NOT_FOUND_FOR_GET
|
229
|
-
e.message += ": #{class_name}:#{object_id}"
|
126
|
+
def client
|
127
|
+
raise ParseError, "API not initialized" if !@@client
|
128
|
+
@@client
|
230
129
|
end
|
231
130
|
|
232
|
-
|
131
|
+
# Perform a simple retrieval of a simple object, or all objects of a
|
132
|
+
# given class. If object_id is supplied, a single object will be
|
133
|
+
# retrieved. If object_id is not supplied, then all objects of the
|
134
|
+
# given class will be retrieved and returned in an Array.
|
135
|
+
def get(class_name, object_id = nil)
|
136
|
+
data = self.client.get( Protocol.class_uri(class_name, object_id) )
|
137
|
+
self.parse_json class_name, data
|
138
|
+
rescue ParseProtocolError => e
|
139
|
+
if e.code == Protocol::ERROR_OBJECT_NOT_FOUND_FOR_GET
|
140
|
+
e.message += ": #{class_name}:#{object_id}"
|
141
|
+
end
|
142
|
+
raise
|
143
|
+
end
|
233
144
|
end
|
234
145
|
|
235
146
|
end
|