Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Response object now returned by all public module methods #13

Merged
merged 5 commits into from

2 participants

@stewartmatheson

An instance of response is now returned by all public methods. This instance contains debugging information as well as bound JSON from the response received from Urbanairship.

@joeyschoblaska

Thanks! This looks great; I'll merge it in.

It slipped my mind that json can parse to arrays as well as hashes, so I'll make a few modifications to allow the Response class to work equally well with both, then do a major version bump and release.

@joeyschoblaska joeyschoblaska merged commit 5fd4abc into urbanairship:master
@stewartmatheson

Hey Joey,

Thanks for doing this. I picked up a few ideas from your solution that I would like to use in the future.

@joeyschoblaska

Sure thing! Let me know if you ever want a second set of eyes on it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 16, 2012
  1. @stewartmatheson

    Added a response class that is returned by all public

    stewartmatheson authored
    methods of the Urbanairship module.
  2. @stewartmatheson

    Arrays and keys bind in the way expected

    stewartmatheson authored
    from the response.
  3. @stewartmatheson

    Added DOC

    stewartmatheson authored
  4. @stewartmatheson

    Formatting

    stewartmatheson authored
  5. @stewartmatheson

    Respect autoload.

    stewartmatheson authored
This page is out of date. Refresh to see the latest.
View
35 README.markdown
@@ -107,3 +107,38 @@ Urbanairship.delete_scheduled_push("123456789") # => true
Urbanairship.delete_scheduled_push(123456789) # => true
Urbanairship.delete_scheduled_push(:alias => "deadbeef") # => true
```
+
+Error checking with responses
+-----------------------------
+
+Each public method in Urbanairship returns an object with a base class of ```Urbanairship::Response```. This base class contains debugging information
+about the previous operation that was performed.
+
+To find out if an operation was successful use the ```success?``` method.
+
+```ruby
+response = Urbanairship.push(payload)
+if response.success?
+ # yay done!
+else
+ # give up
+end
+```
+
+To find the exact code of your last request use ```code```
+
+```ruby
+response = Urbanairship.push(payload)
+response.code # "200"
+```
+
+Expecting a JSON body back? We have you covered. It just so happens that ```Urbanairship::Response``` inherits ```Hash``` and binds the JSON body to its self.
+So if your working with the feedback you can iterate over each item returned.
+
+```ruby
+response = Urbanairship.feedback(Time.now)
+
+response.each do |device_token|
+ # do stuff
+end
+```
View
16 lib/urbanairship.rb
@@ -19,19 +19,15 @@ def register_device(device_token, options = {})
request.body = parse_register_options(options).to_json
request.add_field "Content-Type", "application/json" unless options.empty?
end
-
- response && %w(200 201).include?(response.code)
end
def unregister_device(device_token)
response = do_request(:delete, "/api/device_tokens/#{device_token}", :authenticate_with => :application_secret)
- response && response.code == "204"
end
def delete_scheduled_push(param)
path = (param.is_a? Hash) ? "/api/push/scheduled/alias/#{param[:alias].to_s}" : "/api/push/scheduled/#{param.to_s}"
response = do_request(:delete, path, :authenticate_with => :master_secret)
- response && response.code == "204"
end
def push(options = {})
@@ -39,8 +35,6 @@ def push(options = {})
request.body = parse_push_options(options).to_json
request.add_field "Content-Type", "application/json"
end
-
- response && response.code == "200"
end
def batch_push(notifications = [])
@@ -48,8 +42,6 @@ def batch_push(notifications = [])
request.body = notifications.map{|notification| parse_push_options(notification)}.to_json
request.add_field "Content-Type", "application/json"
end
-
- response && response.code == "200"
end
def broadcast_push(options = {})
@@ -57,13 +49,10 @@ def broadcast_push(options = {})
request.body = parse_push_options(options).to_json
request.add_field "Content-Type", "application/json"
end
-
- response && response.code == "200"
end
def feedback(time)
response = do_request(:get, "/api/device_tokens/feedback/?since=#{format_time(time)}", :authenticate_with => :master_secret)
- response && response.code == "200" ? JSON.parse(response.body) : false
end
private
@@ -82,11 +71,12 @@ def do_request(http_method, path, options = {})
start_time = Time.now
response = http_client.request(request)
log_request_and_response(request, response, Time.now - start_time)
- response
+ Response.new(response)
end
rescue Timeout::Error
logger.error "Urbanairship request timed out after #{request_timeout} seconds: [#{http_method} #{request.path} #{request.body}]"
- return false
+ timeout_response = Response.new(false)
+ timeout_response
end
def verify_configuration_values(*symbols)
View
42 lib/urbanairship/response.rb
@@ -0,0 +1,42 @@
+class Urbanairship::Response < Hash
+
+ def initialize(response)
+ @response = response
+ if @response
+ if success? && !body.empty?
+ parse_body(body)
+ end
+ else
+ @timeout = true
+ end
+ end
+
+ def code
+ @response.code
+ end
+
+ def body
+ @response.body
+ end
+
+ def success?
+ (code =~ /^2/) == 0 && !@timeout
+ end
+
+ def request_timeout?
+ @timeout
+ end
+
+ private
+
+ def parse_body(body)
+ json = JSON.parse(body)
+ if json.class == Array
+ json.each_with_index do |item, index|
+ self[index] = item
+ end
+ else
+ json.keys.each{|k| self[k] = json[k]}
+ end
+ end
+end
View
98 spec/response_spec.rb
@@ -0,0 +1,98 @@
+describe Urbanairship::Response do
+
+ before do
+ FakeWeb.allow_net_connect = false
+ end
+
+ context "::code" do
+ subject { Urbanairship.register_device("new_device_token") }
+
+ before do
+ FakeWeb.register_uri(:put, "https://my_app_key:my_app_secret@go.urbanairship.com/api/device_tokens/new_device_token", :status => ["201", "Created"])
+ FakeWeb.register_uri(:put, /bad_key\:my_app_secret\@go\.urbanairship\.com/, :status => ["401", "Unauthorized"])
+ Urbanairship.application_secret = "my_app_secret"
+ end
+
+ it "should be set correctly on new registraion token" do
+ Urbanairship.application_key = "my_app_key"
+ subject.code.should eql '201'
+ end
+
+ it "should set correctly on unauthhorized" do
+ Urbanairship.application_key = "bad_key"
+ subject.code.should eql '401'
+ end
+ end
+
+ context "::success?" do
+ subject { Urbanairship.register_device("new_device_token") }
+
+ before do
+ FakeWeb.register_uri(:put, "https://my_app_key:my_app_secret@go.urbanairship.com/api/device_tokens/new_device_token", :status => ["201", "Created"])
+ FakeWeb.register_uri(:put, /bad_key\:my_app_secret\@go\.urbanairship\.com/, :status => ["401", "Unauthorized"])
+ Urbanairship.application_secret = "my_app_secret"
+ end
+
+ it "should be true with good key" do
+ Urbanairship.application_key = "my_app_key"
+ subject.success?.should == true
+ end
+
+ it "should be false with bad key" do
+ Urbanairship.application_key = "bad_key"
+ subject.success?.should == false
+ end
+ end
+
+ context "::body" do
+ before do
+ FakeWeb.register_uri(:get, /my_app_key\:my_master_secret\@go\.urbanairship.com\/api\/device_tokens\/feedback/, :status => ["200", "OK"], :body => "[{\"device_token\":\"token\",\"marked_inactive_on\":\"2010-10-14T19:15:13Z\",\"alias\":\"my_alias\"}]")
+ Urbanairship.application_secret = "my_app_secret"
+ Urbanairship.application_key = "my_app_key"
+ Urbanairship.master_secret = "my_master_secret"
+ end
+
+ subject { Urbanairship.feedback(Time.now) }
+
+ it "should be set" do
+ subject.body.should eql "[{\"device_token\":\"token\",\"marked_inactive_on\":\"2010-10-14T19:15:13Z\",\"alias\":\"my_alias\"}]"
+ end
+ end
+
+ context "::request_timeout?" do
+ it "should report a timeout" do
+ # TODO : Test this...
+ end
+ end
+
+ context "body array accessor" do
+ subject { Urbanairship.feedback(Time.now) }
+
+ before do
+ FakeWeb.register_uri(:get, /my_app_key\:my_master_secret\@go\.urbanairship.com\/api\/device_tokens\/feedback/, :status => ["200", "OK"], :body => "[{\"device_token\":\"token\",\"marked_inactive_on\":\"2010-10-14T19:15:13Z\",\"alias\":\"my_alias\"},{\"device_token\":\"token2\",\"marked_inactive_on\":\"2010-10-14T19:15:13Z\",\"alias\":\"my_alias\"}]")
+ Urbanairship.application_secret = "my_app_secret"
+ Urbanairship.application_key = "my_app_key"
+ Urbanairship.master_secret = "my_master_secret"
+ end
+
+ it "should set up correct indexes" do
+ subject[0]['device_token'].should eql "token"
+ subject[1]['device_token'].should eql "token2"
+ end
+ end
+
+ context "non array response" do
+ subject { Urbanairship.feedback(Time.now) }
+
+ before do
+ FakeWeb.register_uri(:get, /my_app_key\:my_master_secret\@go\.urbanairship.com\/api\/device_tokens\/feedback/, :status => ["200", "OK"], :body => "{\"device_token\":\"token\",\"marked_inactive_on\":\"2010-10-14T19:15:13Z\",\"alias\":\"my_alias\"}")
+ Urbanairship.application_secret = "my_app_secret"
+ Urbanairship.application_key = "my_app_key"
+ Urbanairship.master_secret = "my_master_secret"
+ end
+
+ it "should set up correct keys" do
+ subject['device_token'].should eql "token"
+ end
+ end
+end
View
14 spec/spec_helper.rb
@@ -2,3 +2,17 @@
require 'fakeweb'
require File.expand_path(File.dirname(__FILE__) + '/../lib/urbanairship')
+require File.expand_path(File.dirname(__FILE__) + '/../lib/urbanairship/response')
+
+
+RSpec.configure do |config|
+ config.after(:each) do
+ # reset configuration
+ Urbanairship.application_key = nil
+ Urbanairship.application_secret = nil
+ Urbanairship.master_secret = nil
+ Urbanairship.logger = nil
+
+ FakeWeb.instance_variable_set("@last_request", nil)
+ end
+end
View
54 spec/urbanairship_spec.rb
@@ -35,16 +35,6 @@
FakeWeb.register_uri(:get, /my_app_key2\:my_master_secret2\@go\.urbanairship.com\/api\/device_tokens\/feedback/, :status => ["500", "Internal Server Error"])
end
- after(:each) do
- # reset configuration
- Urbanairship.application_key = nil
- Urbanairship.application_secret = nil
- Urbanairship.master_secret = nil
- Urbanairship.logger = nil
-
- FakeWeb.instance_variable_set("@last_request", nil)
- end
-
describe "configuration" do
it "enables you to configure the application key" do
Urbanairship.application_key.should be_nil
@@ -92,16 +82,16 @@
end
it "returns true when the device is registered for the first time" do
- Urbanairship.register_device("new_device_token").should == true
+ Urbanairship.register_device("new_device_token").success?.should == true
end
it "returns true when the device is registered again" do
- Urbanairship.register_device("existing_device_token").should == true
+ Urbanairship.register_device("existing_device_token").success?.should == true
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.register_device("new_device_token").should == false
+ Urbanairship.register_device("new_device_token").success?.should == false
end
it "doesn't set the content-type header to application/json if options are empty" do
@@ -110,7 +100,7 @@
end
it "accepts an alias" do
- Urbanairship.register_device("device_token_one", @valid_params).should == true
+ Urbanairship.register_device("device_token_one", @valid_params).success?.should == true
end
it "sets the content-type header to application/json when options are added" do
@@ -155,13 +145,13 @@
end
it "returns true when the device is successfully unregistered" do
- Urbanairship.unregister_device("key_to_delete").should == true
+ Urbanairship.unregister_device("key_to_delete").success?.should == true
FakeWeb.last_request.body.should be_nil
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.unregister_device("key_to_delete").should == false
+ Urbanairship.unregister_device("key_to_delete").success?.should == false
end
end
@@ -201,13 +191,13 @@
end
it "returns true when the push notification is successfully deleted" do
- Urbanairship.delete_scheduled_push("123456789").should == true
+ Urbanairship.delete_scheduled_push("123456789").success?.should == true
FakeWeb.last_request.body.should be_nil
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.delete_scheduled_push("123456789").should == false
+ Urbanairship.delete_scheduled_push("123456789").success?.should == false
end
end
@@ -233,12 +223,12 @@
end
it "returns true when it successfully pushes a notification" do
- Urbanairship.push(@valid_params).should == true
+ Urbanairship.push(@valid_params).success?.should == true
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.push(@valid_params).should == false
+ Urbanairship.push(@valid_params).success?.should == false
end
it "sets the content-type header to application/json" do
@@ -260,7 +250,7 @@
it "returns false if urbanairship responds with a non-200 response" do
Urbanairship.application_key = "my_app_key2"
Urbanairship.master_secret = "my_master_secret2"
- Urbanairship.push.should == false
+ Urbanairship.push.success?.should == false
end
end
@@ -289,12 +279,12 @@
end
it "returns true when it successfully pushes a notification" do
- Urbanairship.batch_push(@valid_params).should == true
+ Urbanairship.batch_push(@valid_params).success?.should == true
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.batch_push(@valid_params).should == false
+ Urbanairship.batch_push(@valid_params).success?.should == false
end
it "sets the content-type header to application/json" do
@@ -318,7 +308,7 @@
it "returns false if urbanairship responds with a non-200 response" do
Urbanairship.application_key = "my_app_key2"
Urbanairship.master_secret = "my_master_secret2"
- Urbanairship.batch_push.should == false
+ Urbanairship.batch_push.success?.should == false
end
end
@@ -344,12 +334,12 @@
end
it "returns true when it successfully pushes a notification" do
- Urbanairship.broadcast_push(@valid_params).should == true
+ Urbanairship.broadcast_push(@valid_params).success?.should == true
end
it "returns false when the authorization is invalid" do
Urbanairship.application_key = "bad_key"
- Urbanairship.broadcast_push(@valid_params).should == false
+ Urbanairship.broadcast_push(@valid_params).success?.should == false
end
it "sets the content-type header to application/json" do
@@ -373,7 +363,7 @@
it "returns false if urbanairship responds with a non-200 response" do
Urbanairship.application_key = "my_app_key2"
Urbanairship.master_secret = "my_master_secret2"
- Urbanairship.broadcast_push.should == false
+ Urbanairship.broadcast_push.success?.should == false
end
end
@@ -411,17 +401,17 @@
it "returns an array of responses from the feedback API" do
response = Urbanairship.feedback(Time.now)
- response.class.should == Array
- response[0].keys.should include("device_token")
- response[0].keys.should include("marked_inactive_on")
- response[0].keys.should include("alias")
+ response.class.should == Urbanairship::Response
+ response[0].should include("device_token")
+ response[0].should include("marked_inactive_on")
+ response[0].should include("alias")
end
it "returns false and doesn't parse JSON when the call doesn't return 200" do
Urbanairship.application_key = "my_app_key2"
Urbanairship.master_secret = "my_master_secret2"
JSON.should_not_receive(:parse)
- Urbanairship.feedback(Time.now).should == false
+ Urbanairship.feedback(Time.now).success?.should == false
end
end
Something went wrong with that request. Please try again.