zeppelin 0.5.0 → 0.6.0
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.
- data/.gitignore +2 -3
- data/.travis.yml +2 -1
- data/.yardopts +4 -1
- data/Changelog.md +28 -0
- data/Gemfile +9 -1
- data/Guardfile +10 -0
- data/Rakefile +7 -7
- data/lib/zeppelin.rb +97 -47
- data/lib/zeppelin/middleware.rb +7 -0
- data/lib/zeppelin/middleware/json_parser.rb +37 -0
- data/lib/zeppelin/middleware/response_raise_error.rb +22 -0
- data/lib/zeppelin/version.rb +1 -1
- data/spec/middleware/json_parser_spec.rb +34 -0
- data/spec/middleware/response_raise_error_spec.rb +32 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/zeppelin_spec.rb +470 -0
- data/zeppelin.gemspec +4 -7
- metadata +30 -62
- data/.autotest +0 -15
- data/lib/zeppelin/json_parser_middleware.rb +0 -35
- data/test/json_parser_middleware_test.rb +0 -35
- data/test/test_helper.rb +0 -13
- data/test/zeppelin_test.rb +0 -453
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/.yardopts
CHANGED
data/Changelog.md
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# 0.6.0
|
2
|
+
|
3
|
+
## Enhancements
|
4
|
+
|
5
|
+
* [MultiJson](https://github.com/intridea/multi_json) used to handle JSON
|
6
|
+
encoding/decoding. Using the JSON engine of your choice is as simple
|
7
|
+
as: `MultiJson.engine = :your_choice`
|
8
|
+
|
9
|
+
## Breaking Changes
|
10
|
+
|
11
|
+
* Instead of having an invalid request return false, exceptions will be raised
|
12
|
+
with messages containing details about the fail. This allows for
|
13
|
+
better error handling. Should the desired resource not be found,
|
14
|
+
`Zeppelin::ResourceNotFound` will be raised, for other errors,
|
15
|
+
`Zeppelin::ClientError` will be raised. Successful responses will still
|
16
|
+
return `true`.
|
17
|
+
|
18
|
+
## Changes
|
19
|
+
|
20
|
+
* Now using RSpec as the test harness
|
21
|
+
* CI covers Ruby 1.9.3
|
22
|
+
* [James Herdman](https://github.com/jherdman) added as a contributor
|
23
|
+
|
24
|
+
# 0.5.0
|
25
|
+
|
26
|
+
## Changes
|
27
|
+
|
28
|
+
* Refactored handling of responses
|
data/Gemfile
CHANGED
@@ -1,2 +1,10 @@
|
|
1
1
|
source :rubygems
|
2
|
-
gemspec
|
2
|
+
gemspec
|
3
|
+
|
4
|
+
group :development do
|
5
|
+
gem 'rb-fsevent', :require => RUBY_PLATFORM.include?('darwin') && 'rb-fsevent'
|
6
|
+
gem 'growl', :require => RUBY_PLATFORM.include?('darwin') && 'growl'
|
7
|
+
gem 'guard'
|
8
|
+
gem 'guard-bundler'
|
9
|
+
gem 'guard-rspec'
|
10
|
+
end
|
data/Guardfile
ADDED
data/Rakefile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
3
|
|
4
|
-
|
4
|
+
require 'rspec/core/rake_task'
|
5
5
|
|
6
|
-
|
7
|
-
|
8
|
-
t.
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
7
|
+
t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
|
8
|
+
t.pattern = 'spec/**/*_spec.rb'
|
9
|
+
end
|
10
|
+
|
11
|
+
task :default => :spec
|
data/lib/zeppelin.rb
CHANGED
@@ -13,6 +13,8 @@ class Zeppelin
|
|
13
13
|
BROADCAST_URI = '/api/push/broadcast/'
|
14
14
|
JSON_HEADERS = { 'Content-Type' => 'application/json' }
|
15
15
|
|
16
|
+
attr_reader :application_key, :application_master_secret, :options
|
17
|
+
|
16
18
|
# @param [String] application_key your Urban Airship Application Key
|
17
19
|
#
|
18
20
|
# @param [String] application_master_secret your Urban Airship Application
|
@@ -33,97 +35,107 @@ class Zeppelin
|
|
33
35
|
#
|
34
36
|
# @param [String] device_token
|
35
37
|
# @param [Hash] payload the payload to send during registration
|
38
|
+
#
|
36
39
|
# @return [Boolean] whether or not the registration was successful
|
40
|
+
#
|
41
|
+
# @raise [Zeppelin::ClientError] malformed request
|
37
42
|
def register_device_token(device_token, payload = {})
|
38
43
|
uri = device_token_uri(device_token)
|
39
|
-
|
40
|
-
if payload.empty?
|
41
|
-
response = connection.put(uri)
|
42
|
-
else
|
43
|
-
response = connection.put(uri, payload, JSON_HEADERS)
|
44
|
-
end
|
45
|
-
|
46
|
-
response.success?
|
44
|
+
put_request(uri, payload)
|
47
45
|
end
|
48
46
|
|
49
47
|
# Retrieves information on a device token.
|
50
48
|
#
|
51
49
|
# @param [String] device_token
|
52
50
|
# @return [Hash, nil]
|
51
|
+
#
|
52
|
+
# @raise [Zeppelin::ResourceNotFound] invalid device token provided
|
53
53
|
def device_token(device_token)
|
54
|
-
|
55
|
-
|
54
|
+
uri = device_token_uri(device_token)
|
55
|
+
get_request(uri)
|
56
56
|
end
|
57
57
|
|
58
58
|
# Deletes a device token.
|
59
59
|
#
|
60
60
|
# @param [String] device_token
|
61
|
+
#
|
61
62
|
# @return [Boolean] whether or not the deletion was successful
|
63
|
+
#
|
64
|
+
# @raise [Zeppelin::ResourceNotFound] invalid device token provided
|
62
65
|
def delete_device_token(device_token)
|
63
|
-
|
64
|
-
|
66
|
+
uri = device_token_uri(device_token)
|
67
|
+
delete_request(uri)
|
65
68
|
end
|
66
69
|
|
67
70
|
# Registers an APID.
|
68
71
|
#
|
69
72
|
# @param [String] apid
|
73
|
+
#
|
70
74
|
# @param [Hash] payload the payload to send during registration
|
75
|
+
#
|
71
76
|
# @return [Boolean] whether or not the registration was successful
|
77
|
+
#
|
78
|
+
# @raise [Zeppelin::ClientError] invalid payload format
|
72
79
|
def register_apid(apid, payload = {})
|
73
80
|
uri = apid_uri(apid)
|
74
|
-
|
75
|
-
if payload.empty?
|
76
|
-
response = connection.put(uri)
|
77
|
-
else
|
78
|
-
response = connection.put(uri, payload, JSON_HEADERS)
|
79
|
-
end
|
80
|
-
|
81
|
-
response.success?
|
81
|
+
put_request(uri, payload)
|
82
82
|
end
|
83
83
|
|
84
84
|
# Retrieves information on an APID.
|
85
85
|
#
|
86
86
|
# @param [String] apid
|
87
|
+
#
|
87
88
|
# @return [Hash, nil]
|
89
|
+
#
|
90
|
+
# @raise [Zeppelin::ResourceNotFound] invalid APID provided
|
88
91
|
def apid(apid)
|
89
|
-
|
90
|
-
|
92
|
+
uri = apid_uri(apid)
|
93
|
+
get_request(uri)
|
91
94
|
end
|
92
95
|
|
93
96
|
# Deletes an APID.
|
94
97
|
#
|
95
98
|
# @param [String] apid
|
99
|
+
#
|
96
100
|
# @return [Boolean] whether or not the deletion was successful
|
101
|
+
#
|
102
|
+
# @raise [Zeppelin::ResourceNotFound] invalid APID provided
|
97
103
|
def delete_apid(apid)
|
98
|
-
|
99
|
-
|
104
|
+
uri = apid_uri(apid)
|
105
|
+
delete_request(uri)
|
100
106
|
end
|
101
107
|
|
102
108
|
# Pushes a message.
|
103
109
|
#
|
104
110
|
# @param [Hash] payload the payload of the message
|
111
|
+
#
|
105
112
|
# @return [Boolean] whether or not pushing the message was successful
|
113
|
+
#
|
114
|
+
# @raise [Zeppelin::ClientError] invalid payload format
|
106
115
|
def push(payload)
|
107
|
-
|
108
|
-
response.success?
|
116
|
+
post_request(PUSH_URI, payload)
|
109
117
|
end
|
110
118
|
|
111
119
|
# Batch pushes multiple messages.
|
112
120
|
#
|
113
121
|
# @param [<Hash>] payload the payloads of each message
|
122
|
+
#
|
114
123
|
# @return [Boolean] whether or not pushing the messages was successful
|
124
|
+
#
|
125
|
+
# @raise [Zeppelin::ClientError] invalid payload format
|
115
126
|
def batch_push(*payload)
|
116
|
-
|
117
|
-
response.success?
|
127
|
+
post_request(BATCH_PUSH_URI, payload)
|
118
128
|
end
|
119
129
|
|
120
130
|
# Broadcasts a message.
|
121
131
|
#
|
122
132
|
# @param [Hash] payload the payload of the message
|
133
|
+
#
|
123
134
|
# @return [Boolean] whether or not broadcasting the message was successful
|
135
|
+
#
|
136
|
+
# @raise [Zeppelin::ClientError] invalid payload format
|
124
137
|
def broadcast(payload)
|
125
|
-
|
126
|
-
response.success?
|
138
|
+
post_request(BROADCAST_URI, payload)
|
127
139
|
end
|
128
140
|
|
129
141
|
# Retrieves feedback on device tokens.
|
@@ -131,18 +143,21 @@ class Zeppelin
|
|
131
143
|
# This is useful for removing inactive device tokens for the database.
|
132
144
|
#
|
133
145
|
# @param [Time] since the time to retrieve inactive tokens from
|
146
|
+
#
|
134
147
|
# @return [Hash, nil]
|
148
|
+
#
|
149
|
+
# @raise [Zeppelin::ClientError] invalid time param
|
135
150
|
def feedback(since)
|
136
|
-
|
137
|
-
|
151
|
+
uri = feedback_uri(since)
|
152
|
+
get_request(uri)
|
138
153
|
end
|
139
154
|
|
140
155
|
# Retrieve all tags on the service
|
141
156
|
#
|
142
157
|
# @return [Hash, nil]
|
143
158
|
def tags
|
144
|
-
|
145
|
-
|
159
|
+
uri = tag_uri(nil)
|
160
|
+
get_request(uri)
|
146
161
|
end
|
147
162
|
|
148
163
|
# Modifies device tokens associated with a tag.
|
@@ -153,7 +168,8 @@ class Zeppelin
|
|
153
168
|
#
|
154
169
|
# @see http://urbanairship.com/docs/tags.html#modifying-device-tokens-on-a-tag
|
155
170
|
def modify_device_tokens_on_tag(tag_name, payload = {})
|
156
|
-
|
171
|
+
uri = tag_uri(tag_name)
|
172
|
+
post_request(uri, payload)
|
157
173
|
end
|
158
174
|
|
159
175
|
# Creates a tag that is not associated with any device
|
@@ -162,8 +178,8 @@ class Zeppelin
|
|
162
178
|
#
|
163
179
|
# @return [Boolean] whether or not the request was successful
|
164
180
|
def add_tag(name)
|
165
|
-
|
166
|
-
|
181
|
+
uri = tag_uri(name)
|
182
|
+
put_request(uri)
|
167
183
|
end
|
168
184
|
|
169
185
|
# Removes a tag from the service
|
@@ -172,17 +188,21 @@ class Zeppelin
|
|
172
188
|
#
|
173
189
|
# @return [Boolean] true when the request was successful. Note that this
|
174
190
|
# method will return false if the tag has already been removed.
|
191
|
+
#
|
192
|
+
# @raise [Zeppelin::ResourceNotFound] tag already removed
|
175
193
|
def remove_tag(name)
|
176
|
-
|
177
|
-
|
194
|
+
uri = tag_uri(name)
|
195
|
+
delete_request(uri)
|
178
196
|
end
|
179
197
|
|
180
198
|
# @param [String] device_token
|
181
199
|
#
|
182
200
|
# @return [Hash, nil]
|
201
|
+
#
|
202
|
+
# @raise [Zeppelin::ResourceNotFound] device does not exist
|
183
203
|
def device_tags(device_token)
|
184
|
-
|
185
|
-
|
204
|
+
uri = device_tag_uri(device_token, nil)
|
205
|
+
get_request(uri)
|
186
206
|
end
|
187
207
|
|
188
208
|
# @param [String] device_token
|
@@ -191,9 +211,11 @@ class Zeppelin
|
|
191
211
|
#
|
192
212
|
# @return [Boolean] whether or not a tag was successfully associated with
|
193
213
|
# a device
|
214
|
+
#
|
215
|
+
# @raise [Zeppelin::ResourceNotFound] device does not exist
|
194
216
|
def add_tag_to_device(device_token, tag_name)
|
195
|
-
|
196
|
-
|
217
|
+
uri = device_tag_uri(device_token, tag_name)
|
218
|
+
put_request(uri)
|
197
219
|
end
|
198
220
|
|
199
221
|
# @param [String] device_token
|
@@ -202,18 +224,23 @@ class Zeppelin
|
|
202
224
|
#
|
203
225
|
# @return [Boolean] whether or not a tag was successfully dissociated from
|
204
226
|
# a device
|
227
|
+
#
|
228
|
+
# @raise [Zeppelin::ResourceNotFound] device does not exist
|
205
229
|
def remove_tag_from_device(device_token, tag_name)
|
206
|
-
|
207
|
-
|
230
|
+
uri = device_tag_uri(device_token, tag_name)
|
231
|
+
delete_request(uri)
|
208
232
|
end
|
209
233
|
|
210
234
|
private
|
211
235
|
|
212
236
|
def initialize_connection
|
237
|
+
Faraday::Request::JSON.adapter = MultiJson
|
238
|
+
|
213
239
|
conn = Faraday::Connection.new(BASE_URI, @options) do |builder|
|
214
240
|
builder.request :json
|
215
241
|
|
216
|
-
builder.use Zeppelin::
|
242
|
+
builder.use Zeppelin::Middleware::JsonParser
|
243
|
+
builder.use Zeppelin::Middleware::ResponseRaiseError
|
217
244
|
|
218
245
|
builder.adapter :net_http
|
219
246
|
end
|
@@ -223,6 +250,29 @@ class Zeppelin
|
|
223
250
|
conn
|
224
251
|
end
|
225
252
|
|
253
|
+
def put_request(uri, payload={})
|
254
|
+
if !(payload.nil? || payload.empty?)
|
255
|
+
response =connection.put(uri, payload, JSON_HEADERS)
|
256
|
+
else
|
257
|
+
response = connection.put(uri)
|
258
|
+
end
|
259
|
+
|
260
|
+
response.success?
|
261
|
+
end
|
262
|
+
|
263
|
+
def delete_request(uri)
|
264
|
+
connection.delete(uri).success?
|
265
|
+
end
|
266
|
+
|
267
|
+
def get_request(uri)
|
268
|
+
response = connection.get(uri)
|
269
|
+
response.body if response.success?
|
270
|
+
end
|
271
|
+
|
272
|
+
def post_request(uri, payload)
|
273
|
+
connection.post(uri, payload, JSON_HEADERS).success?
|
274
|
+
end
|
275
|
+
|
226
276
|
def device_token_uri(device_token)
|
227
277
|
"/api/device_tokens/#{device_token}"
|
228
278
|
end
|
@@ -244,5 +294,5 @@ class Zeppelin
|
|
244
294
|
end
|
245
295
|
end
|
246
296
|
|
247
|
-
require 'zeppelin/
|
297
|
+
require 'zeppelin/middleware'
|
248
298
|
require 'zeppelin/version'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
class Zeppelin
|
4
|
+
module Middleware
|
5
|
+
# Middleware for Faraday that parses JSON response bodies. Based on code in
|
6
|
+
# the FaradayMiddleware project.
|
7
|
+
#
|
8
|
+
# @private
|
9
|
+
class JsonParser < Faraday::Middleware
|
10
|
+
CONTENT_TYPE = 'Content-Type'
|
11
|
+
|
12
|
+
def initialize(app=nil)
|
13
|
+
@app = app
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(env)
|
17
|
+
@app.call(env).on_complete do
|
18
|
+
parse_response(env) if process_content_type?(env) && parse_response?(env)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def parse_response(env)
|
25
|
+
env[:body] = MultiJson.decode(env[:body])
|
26
|
+
end
|
27
|
+
|
28
|
+
def process_content_type?(env)
|
29
|
+
env[:response_headers][CONTENT_TYPE].to_s =~ /\bjson$/
|
30
|
+
end
|
31
|
+
|
32
|
+
def parse_response?(env)
|
33
|
+
env[:body].respond_to? :to_str
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|