bugsnag-api 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/.yardopts +4 -0
  6. data/CHANGELOG.md +11 -0
  7. data/README.md +12 -4
  8. data/Rakefile +9 -0
  9. data/bugsnag-api.gemspec +5 -0
  10. data/lib/bugsnag/api.rb +20 -4
  11. data/lib/bugsnag/api/client.rb +47 -42
  12. data/lib/bugsnag/api/client/accounts.rb +8 -1
  13. data/lib/bugsnag/api/client/comments.rb +1 -1
  14. data/lib/bugsnag/api/client/errors.rb +1 -1
  15. data/lib/bugsnag/api/client/events.rb +3 -3
  16. data/lib/bugsnag/api/client/projects.rb +15 -4
  17. data/lib/bugsnag/api/client/users.rb +22 -4
  18. data/lib/bugsnag/api/configuration.rb +9 -6
  19. data/lib/bugsnag/api/error.rb +11 -1
  20. data/lib/bugsnag/api/version.rb +1 -1
  21. data/spec/bugsnag/api/client/accounts_spec.rb +45 -0
  22. data/spec/bugsnag/api/client/comments_spec.rb +58 -0
  23. data/spec/bugsnag/api/client/errors_spec.rb +69 -0
  24. data/spec/bugsnag/api/client/events_spec.rb +52 -0
  25. data/spec/bugsnag/api/client/projects_spec.rb +87 -0
  26. data/spec/bugsnag/api/client/users_spec.rb +105 -0
  27. data/spec/bugsnag/api/client_spec.rb +130 -0
  28. data/spec/bugsnag/api_spec.rb +44 -0
  29. data/spec/cassettes/Bugsnag_Api_Client/_get/handles_query_params.yml +56 -0
  30. data/spec/cassettes/Bugsnag_Api_Client/_last_response/caches_the_last_agent_response.yml +56 -0
  31. data/spec/cassettes/Bugsnag_Api_Client_Accounts/_account/returns_the_requested_account.yml +49 -0
  32. data/spec/cassettes/Bugsnag_Api_Client_Accounts/_account/when_using_account_credentials/returns_the_account.yml +51 -0
  33. data/spec/cassettes/Bugsnag_Api_Client_Accounts/_accounts/returns_all_accounts.yml +49 -0
  34. data/spec/cassettes/Bugsnag_Api_Client_Comments/_comments/returns_all_comments_on_an_error.yml +107 -0
  35. data/spec/cassettes/Bugsnag_Api_Client_Comments/_create_comment/created_a_comment.yml +51 -0
  36. data/spec/cassettes/Bugsnag_Api_Client_Comments/with_comment/_comment/returns_a_comment.yml +97 -0
  37. data/spec/cassettes/Bugsnag_Api_Client_Comments/with_comment/_delete_comment/deletes_an_existing_comment.yml +92 -0
  38. data/spec/cassettes/Bugsnag_Api_Client_Comments/with_comment/_update_comment/updates_an_existing_comment.yml +97 -0
  39. data/spec/cassettes/Bugsnag_Api_Client_Errors/_errors/returns_all_errors_on_an_project.yml +48 -0
  40. data/spec/cassettes/Bugsnag_Api_Client_Errors/with_error/_error/returns_an_error.yml +48 -0
  41. data/spec/cassettes/Bugsnag_Api_Client_Errors/with_error/_reopen_error/reopens_the_error.yml +48 -0
  42. data/spec/cassettes/Bugsnag_Api_Client_Errors/with_error/_resolve_error/resolves_the_error.yml +48 -0
  43. data/spec/cassettes/Bugsnag_Api_Client_Errors/with_error/_update_error/updates_the_error.yml +48 -0
  44. data/spec/cassettes/Bugsnag_Api_Client_Events/_error_events/returns_all_events_on_an_error.yml +64 -0
  45. data/spec/cassettes/Bugsnag_Api_Client_Events/_project_events/returns_all_events_on_a_project.yml +64 -0
  46. data/spec/cassettes/Bugsnag_Api_Client_Events/with_event/_event/returns_an_event.yml +56 -0
  47. data/spec/cassettes/Bugsnag_Api_Client_Projects/_account_projects/returns_all_projects_on_an_account.yml +61 -0
  48. data/spec/cassettes/Bugsnag_Api_Client_Projects/_account_projects/when_using_account_credentials/returns_all_projects.yml +63 -0
  49. data/spec/cassettes/Bugsnag_Api_Client_Projects/_create_project/creates_a_project_on_an_account.yml +50 -0
  50. data/spec/cassettes/Bugsnag_Api_Client_Projects/_user_projects/returns_all_projects_for_a_user.yml +61 -0
  51. data/spec/cassettes/Bugsnag_Api_Client_Projects/with_project/_delete_project/deletes_an_existing_project.yml +91 -0
  52. data/spec/cassettes/Bugsnag_Api_Client_Projects/with_project/_project/returns_a_project.yml +95 -0
  53. data/spec/cassettes/Bugsnag_Api_Client_Projects/with_project/_update_project/updates_an_existing_project.yml +95 -0
  54. data/spec/cassettes/Bugsnag_Api_Client_Users/_account_users/returns_all_users_on_an_account.yml +49 -0
  55. data/spec/cassettes/Bugsnag_Api_Client_Users/_account_users/when_using_account_credentials/returns_all_users.yml +51 -0
  56. data/spec/cassettes/Bugsnag_Api_Client_Users/_invite_user/invites_a_user_to_an_account.yml +48 -0
  57. data/spec/cassettes/Bugsnag_Api_Client_Users/_project_users/returns_all_users_for_a_project.yml +49 -0
  58. data/spec/cassettes/Bugsnag_Api_Client_Users/_user/returns_a_user.yml +48 -0
  59. data/spec/cassettes/Bugsnag_Api_Client_Users/_user/when_using_user_credentials/returns_the_authed_user.yml +48 -0
  60. data/spec/cassettes/Bugsnag_Api_Client_Users/with_user/_remove_user/removes_a_user_from_an_account.yml +89 -0
  61. data/spec/cassettes/Bugsnag_Api_Client_Users/with_user/_update_user_permissions/updates_a_users_permissions.yml +93 -0
  62. data/spec/spec_helper.rb +122 -0
  63. metadata +161 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 4f70dd5425512569c5778aa3a89d852326195967
4
- data.tar.gz: 254567403bf2c32834d25a7b4c23696f33748467
3
+ metadata.gz: ae6a214efafc2a17097c3ce489c079d76205c098
4
+ data.tar.gz: 931212dfa15eeaedd848e7c7a4ef836690e7f777
5
5
  SHA512:
6
- metadata.gz: 67c60e4aae21b293ad5b75b2cb60d26ba2774c43d512c49d3a140fd82b6f43d10de5739eec93ac7edceb481939bd86b1bdb80c92a952b5030f01e111ec6b1f29
7
- data.tar.gz: 4b154b2bc908b61db969e19afc53a3f09f12a756d66292562d9d8a6a9fc9f2e7b60a0b1ac173404cb1d5099120dde7b41c5f0aadfa8641d771e247efefa4e357
6
+ metadata.gz: efbe6b07725c95659ac675856d9f59db7cdc851151c3606f1362aa36841d7924acf1403fb70061ea4c7fbe8a54732a574104456a736e01ca74be57d143d48ce9
7
+ data.tar.gz: 3a574921af5aaef6ca79cb04d0b646cc1f1f552c68ee5844d37d5d2fb0da874138fc21fcc9c3307d0b7d4e6c485a5717da0f813f0e3c41596c4f502949bfd5a2
data/.gitignore CHANGED
@@ -15,3 +15,4 @@ spec/reports
15
15
  test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
+ .env
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --order random
@@ -0,0 +1,8 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.1.0
4
+ - 2.0.0
5
+ - 1.9.3
6
+ - jruby-18mode
7
+ - jruby-19mode
8
+ - 1.8.7
@@ -0,0 +1,4 @@
1
+ --no-private
2
+ --title=""
3
+ --markup=markdown
4
+ --exclude lib/bugsnag/api/response
@@ -0,0 +1,11 @@
1
+ Changelog
2
+ =========
3
+
4
+ 1.0.1
5
+ -----
6
+ - Added test suite
7
+ - Fixed a few bugs
8
+
9
+ 1.0.0
10
+ -----
11
+ - Initial release
data/README.md CHANGED
@@ -1,7 +1,9 @@
1
- Bugsnag API Ruby Toolkit
2
- ========================
1
+ Bugsnag API Toolkit for Ruby
2
+ ============================
3
3
 
4
- The library allows for quick read-write access to the [Bugsnag API](https://bugsnag.com/docs/api) from Ruby applications. Use this library if you want to build your own applications which leverage data found in your Bugsnag dashboard. If you are looking to automatically detect crashes in your Ruby apps, you should take a look at the [Bugsnag Ruby Detection Library](https://bugsnag.com/docs/notifiers/ruby) instead.
4
+ The library allows for quick read/write access to the [Bugsnag API](https://bugsnag.com/docs/api) from your Ruby applications. You can use this library to build your own applications which leverage data found in your Bugsnag dashboard.
5
+
6
+ If you are looking to automatically detect crashes in your Ruby apps, you should take a look at the [Bugsnag Ruby Detection Library](https://bugsnag.com/docs/notifiers/ruby) instead.
5
7
 
6
8
  This library shares code and philosophies with the fantastic [Octokit](https://github.com/octokit/octokit.rb) library.
7
9
 
@@ -26,7 +28,7 @@ Or install it yourself as:
26
28
  ```ruby
27
29
  # Configure a Bugsnag API client
28
30
  Bugsnag::Api.configure do |config|
29
- config.api_token = "your-account-api-token"
31
+ config.auth_token = "your-account-api-token"
30
32
  end
31
33
 
32
34
  # Fetch information about the authenticated account
@@ -43,6 +45,12 @@ errors = Bugsnag::Api.errors(projects.first.id)
43
45
  ```
44
46
 
45
47
 
48
+ ## Documentation
49
+
50
+ Full documentation of available methods can be found here:
51
+ <http://rubydoc.info/github/bugsnag/bugsnag-api-ruby>
52
+
53
+
46
54
  ## Contributing
47
55
 
48
56
  1. Fork it
data/Rakefile CHANGED
@@ -1 +1,10 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ # RSpec tasks
4
+ require 'rspec/core'
5
+ require "rspec/core/rake_task"
6
+ RSpec::Core::RakeTask.new(:spec) do |spec|
7
+ spec.pattern = FileList['spec/**/*_spec.rb']
8
+ end
9
+
10
+ task :default => :spec
@@ -22,4 +22,9 @@ Gem::Specification.new do |spec|
22
22
 
23
23
  spec.add_development_dependency "bundler", "~> 1.3"
24
24
  spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec", "~> 3.0"
26
+ spec.add_development_dependency "webmock"
27
+ spec.add_development_dependency "faker"
28
+ spec.add_development_dependency "vcr"
29
+ spec.add_development_dependency "json"
25
30
  end
@@ -4,18 +4,34 @@ require "bugsnag/api/error"
4
4
  require "bugsnag/api/version"
5
5
 
6
6
  module Bugsnag
7
+
8
+ # Static access to a Bugsnag API Client
7
9
  module Api
8
10
  class << self
9
- def configure
10
- yield(configuration) if block_given?
11
+ # Set configuration options using a block
12
+ def configure(&block)
13
+ client.configure(&block) if block_given?
11
14
  end
12
15
 
16
+ # Get the static client's configuration options
17
+ #
18
+ # @return [Bugsnag::Api::Configuration] configuration wrapper
13
19
  def configuration
14
- @configuration ||= Bugsnag::Api::Configuration.new
20
+ client.configuration
15
21
  end
16
22
 
23
+ # Get the static API client
24
+ #
25
+ # @return [Bugsnag::Api::Client] API client
17
26
  def client
18
- @client ||= Bugsnag::Api::Client.new(configuration)
27
+ @client ||= Bugsnag::Api::Client.new
28
+ end
29
+
30
+ # Reset the static API client
31
+ #
32
+ # @return [Bugsnag::Api::Client] API client
33
+ def reset!
34
+ @client = nil
19
35
  end
20
36
 
21
37
 
@@ -24,14 +24,20 @@ module Bugsnag
24
24
  # Header keys that can be passed in options hash to {#get},{#head}
25
25
  CONVENIENCE_HEADERS = Set.new([:accept, :content_type])
26
26
 
27
- def initialize(options = {})
28
- if options.is_a?(Bugsnag::Api::Configuration)
29
- @configuration = options
30
- else
31
- configuration.load(options)
32
- end
27
+ def initialize(options = {}, &block)
28
+ configuration.load(options)
29
+ yield(configuration) if block_given?
30
+ end
31
+
32
+ # Set configuration options using a block
33
+ def configure
34
+ yield(configuration) if block_given?
35
+ reset_agent
33
36
  end
34
37
 
38
+ # Get client's configuration options
39
+ #
40
+ # @return [Bugsnag::Api::Configuration] configuration wrapper
35
41
  def configuration
36
42
  @configuration ||= Configuration.new
37
43
  end
@@ -54,15 +60,6 @@ module Bugsnag
54
60
  request :post, url, options
55
61
  end
56
62
 
57
- # Make a HTTP PUT request
58
- #
59
- # @param url [String] The path, relative to {#endpoint}
60
- # @param options [Hash] Body and header params for request
61
- # @return [Sawyer::Resource]
62
- def put(url, options = {})
63
- request :put, url, options
64
- end
65
-
66
63
  # Make a HTTP PATCH request
67
64
  #
68
65
  # @param url [String] The path, relative to {#endpoint}
@@ -81,15 +78,6 @@ module Bugsnag
81
78
  request :delete, url, options
82
79
  end
83
80
 
84
- # Make a HTTP HEAD request
85
- #
86
- # @param url [String] The path, relative to {#endpoint}
87
- # @param options [Hash] Query and header params for request
88
- # @return [Sawyer::Resource]
89
- def head(url, options = {})
90
- request :head, url, parse_query_and_convenience_headers(options)
91
- end
92
-
93
81
  # Make one or more HTTP GET requests, optionally fetching
94
82
  # the next page of results from URL in Link response header based
95
83
  # on value in {#auto_paginate}.
@@ -123,22 +111,6 @@ module Bugsnag
123
111
  data
124
112
  end
125
113
 
126
- # Hypermedia agent for the Bugsnag API
127
- #
128
- # @return [Sawyer::Agent]
129
- def agent
130
- @agent ||= Sawyer::Agent.new(configuration.endpoint, sawyer_options) do |http|
131
- http.headers[:content_type] = "application/json"
132
- http.headers[:user_agent] = configuration.user_agent
133
-
134
- if basic_authenticated?
135
- http.basic_auth configuration.email, configuration.password
136
- elsif token_authenticated?
137
- http.authorization "token", configuration.api_token
138
- end
139
- end
140
- end
141
-
142
114
  # Response for last HTTP request
143
115
  #
144
116
  # @return [Sawyer::Response]
@@ -146,16 +118,42 @@ module Bugsnag
146
118
  @last_response if defined? @last_response
147
119
  end
148
120
 
121
+ # Indicates if the client was supplied Basic Auth
122
+ # username and password
123
+ #
124
+ # @see https://bugsnag.com/docs/api#user-authentication
125
+ # @return [Boolean]
149
126
  def basic_authenticated?
150
127
  !!(configuration.email && configuration.password)
151
128
  end
152
129
 
130
+ # Indicates if the client was supplied an auth token
131
+ #
132
+ # @see https://bugsnag.com/docs/api#account-authentication
133
+ # @return [Boolean]
153
134
  def token_authenticated?
154
- !!configuration.api_token
135
+ !!configuration.auth_token
155
136
  end
156
137
 
157
138
 
158
139
  private
140
+ def agent
141
+ @agent ||= Sawyer::Agent.new(configuration.endpoint, sawyer_options) do |http|
142
+ http.headers[:content_type] = "application/json"
143
+ http.headers[:user_agent] = configuration.user_agent
144
+
145
+ if basic_authenticated?
146
+ http.basic_auth configuration.email, configuration.password
147
+ elsif token_authenticated?
148
+ http.authorization "token", configuration.auth_token
149
+ end
150
+ end
151
+ end
152
+
153
+ def reset_agent
154
+ @agent = nil
155
+ end
156
+
159
157
  def request(method, path, data, options = {})
160
158
  if data.is_a?(Hash)
161
159
  options[:query] = data.delete(:query) || {}
@@ -165,10 +163,17 @@ module Bugsnag
165
163
  end
166
164
  end
167
165
 
168
- @last_response = response = agent.call(method, URI::Parser.new.escape(path.to_s), data, options)
166
+ @last_response = response = agent.call(method, URI.escape(path.to_s), data, options)
169
167
  response.data
170
168
  end
171
169
 
170
+ def boolean_from_response(method, path, options = {})
171
+ request(method, path, options)
172
+ @last_response.status == 204
173
+ rescue Bugsnag::Api::NotFound
174
+ false
175
+ end
176
+
172
177
  def sawyer_options
173
178
  opts = {
174
179
  :links_parser => Sawyer::LinkParsers::Simple.new
@@ -25,7 +25,14 @@ module Bugsnag
25
25
  # @example
26
26
  # Bugsnag::Api.account("515fb9337c1074f6fd000009")
27
27
  def account(account=nil, options = {})
28
- if account.nil?
28
+ if account.nil? || account.is_a?(Hash)
29
+ options = account || {}
30
+
31
+ raise Bugsnag::Api::AccountCredentialsRequired.new(
32
+ "Fetching account without an id is only possible when using "\
33
+ "an account auth token."
34
+ ) unless token_authenticated?
35
+
29
36
  get "account", options
30
37
  else
31
38
  get "accounts/#{account}", options
@@ -56,7 +56,7 @@ module Bugsnag
56
56
  # @return [Boolean] `true` if comment was deleted
57
57
  # @see https://bugsnag.com/docs/api/comments#delete-a-comment
58
58
  def delete_comment(comment, options = {})
59
- delete "comments/#{comment}", options
59
+ boolean_from_response :delete, "comments/#{comment}", options
60
60
  end
61
61
  end
62
62
  end
@@ -67,7 +67,7 @@ module Bugsnag
67
67
  # @return [Boolean] `true` if error was deleted
68
68
  # @see https://bugsnag.com/docs/api/errors#delete-an-error
69
69
  def delete_error(error, options = {})
70
- delete "errors/#{error}", options
70
+ boolean_from_response :delete, "errors/#{error}", options
71
71
  end
72
72
  end
73
73
  end
@@ -26,7 +26,7 @@ module Bugsnag
26
26
  # @example
27
27
  # Bugsnag::Api.error_events("518031bcd775355c48a1cd4e")
28
28
  def error_events(error, options = {})
29
- paginate "error/#{error}/events", options
29
+ paginate "errors/#{error}/events", options
30
30
  end
31
31
 
32
32
  # Get a single event
@@ -36,7 +36,7 @@ module Bugsnag
36
36
  # @see https://bugsnag.com/docs/api/events#get-event-details
37
37
  # @example
38
38
  # Bugsnag::Api.event("51f5d152f002c6686d013a22")
39
- def event(error, options = {})
39
+ def event(event, options = {})
40
40
  get "events/#{event}", options
41
41
  end
42
42
 
@@ -46,7 +46,7 @@ module Bugsnag
46
46
  # @return [Boolean] `true` if event was deleted
47
47
  # @see https://bugsnag.com/docs/api/events#delete-an-event
48
48
  def delete_event(event, options = {})
49
- delete "events/#{event}", options
49
+ boolean_from_response :delete, "events/#{event}", options
50
50
  end
51
51
  end
52
52
  end
@@ -13,8 +13,19 @@ module Bugsnag
13
13
  # @see https://bugsnag.com/docs/api/projects#list-an-account-s-projects
14
14
  # @example
15
15
  # Bugsnag::Api.projects("515fb9337c1074f6fd000009")
16
- def projects(account, options = {})
17
- paginate "accounts/#{account}/projects", options
16
+ def projects(account=nil, options = {})
17
+ if account.nil? || account.is_a?(Hash)
18
+ options = account || {}
19
+
20
+ raise Bugsnag::Api::AccountCredentialsRequired.new(
21
+ "Fetching projects without an account id is only possible when "\
22
+ "using an account auth token."
23
+ ) unless token_authenticated?
24
+
25
+ paginate "account/projects", options
26
+ else
27
+ paginate "accounts/#{account}/projects", options
28
+ end
18
29
  end
19
30
  alias :account_projects :projects
20
31
 
@@ -26,7 +37,7 @@ module Bugsnag
26
37
  # @example
27
38
  # Bugsnag::Api.user_projects("515fb9337c1074f6fd000007")
28
39
  def user_projects(user, options = {})
29
- paginate "user/#{user}/projects", options
40
+ paginate "users/#{user}/projects", options
30
41
  end
31
42
 
32
43
  # Get a single project
@@ -69,7 +80,7 @@ module Bugsnag
69
80
  # @return [Boolean] `true` if project was deleted
70
81
  # @see https://bugsnag.com/docs/api/projects#delete-a-project
71
82
  def delete_project(project, options = {})
72
- delete "projects/#{project}", options
83
+ boolean_from_response :delete, "projects/#{project}", options
73
84
  end
74
85
  end
75
86
  end
@@ -11,8 +11,19 @@ module Bugsnag
11
11
  # @param account [String] Bugsnag account for which to list users
12
12
  # @return [Array<Sawyer::Resource>] List of users
13
13
  # @see https://bugsnag.com/docs/api/users#list-an-account-s-users
14
- def users(account, options = {})
15
- paginate "accounts/#{account}/users", options
14
+ def users(account=nil, options = {})
15
+ if account.nil? || account.is_a?(Hash)
16
+ options = account || {}
17
+
18
+ raise Bugsnag::Api::AccountCredentialsRequired.new(
19
+ "Fetching users without an account id is only possible when "\
20
+ "using an account auth token."
21
+ ) unless token_authenticated?
22
+
23
+ paginate "account/users", options
24
+ else
25
+ paginate "accounts/#{account}/users", options
26
+ end
16
27
  end
17
28
  alias :account_users :users
18
29
 
@@ -34,7 +45,14 @@ module Bugsnag
34
45
  # @example
35
46
  # Bugsnag::Api.user("515fb9337c1074f6fd000007")
36
47
  def user(user=nil, options = {})
37
- if user.nil?
48
+ if user.nil? || user.is_a?(Hash)
49
+ options = user || {}
50
+
51
+ raise Bugsnag::Api::UserCredentialsRequired.new(
52
+ "Fetching user without an id is only possible when using "\
53
+ "user auth credentials."
54
+ ) unless basic_authenticated?
55
+
38
56
  get "user", options
39
57
  else
40
58
  get "users/#{user}", options
@@ -73,7 +91,7 @@ module Bugsnag
73
91
  # @example
74
92
  # Bugsnag::Api.remove_user("515fb9337c1074f6fd000009", "515fb9337c1074f6fd000007")
75
93
  def remove_user(account, user, options = {})
76
- delete "accounts/#{account}/users/#{user}", options
94
+ boolean_from_response :delete, "accounts/#{account}/users/#{user}", options
77
95
  end
78
96
  end
79
97
  end
@@ -5,7 +5,6 @@ module Bugsnag
5
5
 
6
6
  # Configuration storage and defaults for {Client}
7
7
  class Configuration
8
-
9
8
  # Default API endpoint
10
9
  DEFAULT_ENDPOINT = "https://api.bugsnag.com"
11
10
 
@@ -22,12 +21,14 @@ module Bugsnag
22
21
  end
23
22
 
24
23
  # Configuration options
25
- attr_accessor :email, :password, :api_token, :endpoint, :user_agent,
26
- :proxy, :middleware, :connection_options, :auto_paginate,
27
- :per_page
24
+ KEYS = [:email, :password, :auth_token, :endpoint, :user_agent,
25
+ :proxy, :middleware, :connection_options, :auto_paginate,
26
+ :per_page]
27
+
28
+ attr_accessor *KEYS
28
29
 
29
30
  # Set up configuration defaults
30
- def initialize
31
+ def initialize(options = {})
31
32
  @endpoint = DEFAULT_ENDPOINT
32
33
  @user_agent = DEFAULT_USER_AGENT
33
34
  @middleware = DEFAULT_MIDDLEWARE
@@ -37,11 +38,13 @@ module Bugsnag
37
38
  :user_agent => DEFAULT_USER_AGENT
38
39
  }
39
40
  }
41
+
42
+ load(options)
40
43
  end
41
44
 
42
45
  # Load configuration from hash
43
46
  def load(options = {})
44
- options.each {|k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=")}
47
+ options.each {|k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") && !v.nil?}
45
48
  end
46
49
  end
47
50
  end