airbox 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2 @@
1
+ *.gem
2
+ Gemfile.lock
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fleetbit.gemspec
4
+ gemspec
5
+
data/LICENSE ADDED
@@ -0,0 +1,8 @@
1
+ ----------------------------------------------------------------------------
2
+ "THE BEER-WARE LICENSE" (Revision 42):
3
+ <anulman@gmail.com> wrote this file. As long as you retain this notice you
4
+ can do whatever you want with this stuff. If we meet some day, and you think
5
+ this stuff is worth it, you can buy me a beer in return. --Aidan Nulman
6
+ ----------------------------------------------------------------------------
7
+ [thanks to phk@FreeBSD.ORG for the license]
8
+
@@ -0,0 +1,83 @@
1
+ airbox
2
+ ======
3
+
4
+ ActiveResource extension to easily access and manipulate objects from Airbrake's reporting API.
5
+
6
+ ----
7
+ ## Usage
8
+
9
+ In your app, define Airbox.site & Airbox.auth_token to initialize the extension:
10
+
11
+ ```ruby
12
+ Airbox.site = "site_url"
13
+ Airbox.auth_token = "token"
14
+ ```
15
+
16
+ (Airbox will automatically scan for airbox.rb in the project's root directory; feel free to stash an initializer anywhere else).
17
+
18
+ ----
19
+ Most of the time, you'll want to start with a collection of resources:
20
+
21
+ ```ruby
22
+ @resources = Airbox::Group.find :all
23
+ @resources = @resources.first.notices(:page => 2)
24
+ @resources = Airbox::Error.all(show_resolved: true)
25
+ ```
26
+
27
+ Collections are paginated, with 30 objects per page. Airbox offers convenient ways to access other pages:
28
+
29
+ ```ruby
30
+ @p1 = @resources
31
+ @p2 = @p1.next_page
32
+ prest = @p2.next_pages
33
+ ```
34
+
35
+ While collecting _all_ pages can be done from any page, it's most efficient from the first:
36
+ ```ruby
37
+ p1all = @p1.all_pages
38
+ p2all = @p2.all_pages
39
+ p1all == p2all
40
+ ```
41
+
42
+ You can access most related resources through simple object methods:
43
+
44
+ ```ruby
45
+ project = Airbox::Project.first
46
+ errors = project.errors #Will return all errors associated to the project
47
+ group = errors.first.group #Will return the group object associated to the first error
48
+ notices = group.notices #Will return the notices associated to the group object
49
+ ```
50
+
51
+ Finally, some objects (looking at you, Error and Group::Notice) don't return with full information on collection calls. So sometimes, you need to request the full object:
52
+
53
+ ```ruby
54
+ project = Airbox::Project.first
55
+ errors = project.errors(show_resolved: true)
56
+ error = errors.first
57
+ error.request.url #Will error out, since the request object is not
58
+ available here
59
+ full_error = error.full_obj
60
+ full_error.request.url #Will return the URL for the requested error
61
+ ```
62
+
63
+ ## Resources
64
+
65
+ Resources are defined by [Airbrake's API](http://help.airbrake.io/kb/api-2/api-overview). Collections are paginated, with 30 objects per page.
66
+
67
+ Valid resources are Project, Error, Group, and Group::Notice.
68
+
69
+ ## To Do
70
+
71
+ This gem is brand new, so there's still work to be done. The current list includes:
72
+
73
+ * Write test suite
74
+ * Move nested resources (e.g. Group::Notice) to use prefix options vs. hard-coded from
75
+ * Split resource types into their own files
76
+ * Look for and patch holes in functionality between Airbrake's reporting API and Airbox
77
+ * Remove ActiveRecord dependency
78
+
79
+ All contributions appreciated; just issue a pull request!
80
+
81
+ ## License
82
+
83
+ This gem is distributed as Beerware. Full text in the LICENSE file, but it's yours to do with as you wish (so long as you keep the LICENSE file around). If you like it, and we meet one day, consider buying me a drink.
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "airbox/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "airbox"
7
+ s.version = Airbox::VERSION
8
+ s.authors = ["Aidan Nulman"]
9
+ s.email = ["anulman@gmail.com"]
10
+ s.homepage = "https://github.com/anulman/airbox"
11
+ s.summary = %q{Airbrake's missing "black box"}
12
+ s.description = %q{ActiveResource extension to easily access and manipulate objects from Airbrake's reporting API.}
13
+ s.license = "Beerware"
14
+ s.required_ruby_version = '>= 1.9.0'
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_dependency('activeresource', '< 4')
22
+ end
@@ -0,0 +1,200 @@
1
+ # *************************************************
2
+ #
3
+ # USAGE
4
+ #
5
+ # *************************************************
6
+ #
7
+ # Define Airbox.site & Airbox.auth_token
8
+ # (Automatically scans for init.rb in same dir)
9
+ #
10
+ # *************************************************
11
+ #
12
+ # Resources are paginated. You get 30 at a time.
13
+ #
14
+ # @resources = Airbox::Group.find :all
15
+ # @resources = @resources.first.notices(:page => 2)
16
+ # @resources = Airbox::Error.all(show_resolved: true)
17
+ #
18
+ # *************************************************
19
+
20
+ require "active_resource"
21
+
22
+ module Airbox
23
+ # Accessor methods for site/auth_token settings
24
+ # H/T to Instagram gem team for the inspiration
25
+ def self.site
26
+ Resource.site
27
+ end
28
+
29
+ def self.site=(site)
30
+ Resource.site = site
31
+ end
32
+
33
+ def self.auth_token
34
+ Resource.auth_token
35
+ end
36
+
37
+ def self.auth_token=(tok)
38
+ Resource.auth_token=(tok)
39
+ end
40
+
41
+ class Resource < ::ActiveResource::Base
42
+ # Airbrake's API responds with XML objects
43
+ self.format = ActiveResource::Formats::XmlFormat
44
+
45
+ class << self
46
+ # Store auth_token as class variable
47
+ def auth_token=(tok)
48
+ @@auth_token = tok
49
+ end
50
+
51
+ # Before standard ActiveResource::Base.find, prep params for request
52
+ def find(*arguments)
53
+ if !site
54
+ err = "No site defined. Please run Airbox.site = 'site_url'"
55
+ raise ConfigError, err
56
+ end
57
+ arguments = prepare_params(*arguments)
58
+ super(*arguments)
59
+ end
60
+
61
+ # Move opts (except for "from") into params hash
62
+ # Add auth_token to params hash
63
+ def prepare_params(*arguments)
64
+ if !class_variable_defined?(:@@auth_token)
65
+ err = "No auth token. Please run Airbox.auth_token = 'token'"
66
+ raise ConfigError, err
67
+ end
68
+
69
+ opts = arguments.last.is_a?(Hash) ? arguments.pop : {}
70
+
71
+ # Store pre-transformed opts in instance var
72
+ # Later accessed to ensure continuity on paged results
73
+ @opts = opts.dup
74
+
75
+ opts[:params] = add_relevant_opts_to_params(opts.except(:from))
76
+ opts[:params].merge!(auth_token: @@auth_token)
77
+ arguments << opts
78
+ arguments
79
+ end
80
+
81
+ # Method to move opts into params hash
82
+ def add_relevant_opts_to_params(opts)
83
+ params = opts[:params] || {}
84
+ opts.except(:params).each do |k,v|
85
+ params[k] = v
86
+ end
87
+ params
88
+ end
89
+
90
+ # After standard ActiveResource::Base.instantiate_collection,
91
+ # ensure collection is returned as Airbox::Array for easier use
92
+ #
93
+ # TODO - needs update to ActiveResource4 + backwards compatibility
94
+ # (Currently conforms to ActiveResource 3.2.13 spec)
95
+ def instantiate_collection(collection, original_params = {})
96
+ ary = super(collection, original_params)
97
+ ary = Array.new(ary)
98
+ ary.opts = @opts
99
+ ary
100
+ end
101
+
102
+ def ensure_collection(coll)
103
+ klass = self.class.to_s.split('::').last.downcase
104
+ if coll.has_key?(klass)
105
+ coll = coll[klass]
106
+ end
107
+ coll
108
+ end
109
+ end
110
+ end
111
+
112
+ # Airbrake project resources
113
+ class Project < Resource
114
+ # For some reason, these return as JSON?
115
+ self.format = ActiveResource::Formats::JsonFormat
116
+
117
+ # Return project's errors
118
+ def errors(opts={})
119
+ Error.all(opts.merge(project_id: id))
120
+ end
121
+ end
122
+
123
+ # Airbrake error resources
124
+ class Error < Resource
125
+
126
+ # Collect all associated data
127
+ def full_obj(opts={})
128
+ self.class.find(id, opts)
129
+ end
130
+
131
+ # Return related group
132
+ def group(opts={})
133
+ Group.find(id)
134
+ end
135
+ end
136
+
137
+ # Airbrake group resources
138
+ class Group < Resource
139
+
140
+ # Return group's notices
141
+ def notices(opts={})
142
+ Notice.all(opts.merge(from: "/groups/#{id}/notices"))
143
+ end
144
+
145
+ # Airbrake notice resources
146
+ class Notice < Resource
147
+
148
+ # Collect all associated data
149
+ def full_obj(opts={})
150
+ self.class.find :one, opts.merge(from: "/groups/#{group_id}/notices/#{id}")
151
+ end
152
+ end
153
+ end
154
+
155
+ # Extend Array class for module use
156
+ # When Airbox returns collections of resources, give them paging methods
157
+ class Array < ::Array
158
+ # Store/retrieve query in opts instance variable
159
+ attr_accessor :opts
160
+
161
+ # Return next page of results for current query
162
+ def next_page
163
+ @opts ||= {}
164
+ @opts[:page] ||= 1
165
+ return first.class.all(@opts.merge(page: @opts[:page] + 1).dup)
166
+ end
167
+
168
+ # Return all future pages of results for current query
169
+ def next_pages
170
+ collection = []
171
+ current = self
172
+ while(current.count == 30)
173
+ current = current.next_page
174
+ collection += current
175
+ end
176
+ collection
177
+ end
178
+
179
+ # Return all pages of results for current query
180
+ def all_pages
181
+ if !self.opts || self.opts[:page] == 1 || !self.opts[:page]
182
+ self + self.next_pages
183
+ else
184
+ collection = first.class.all(@opts.except(:page))
185
+ collection + collection.next_pages
186
+ end
187
+ end
188
+ end
189
+
190
+ class ConfigError < ::StandardError
191
+ end
192
+ end
193
+
194
+ # Load init file in same folder
195
+ # Rescue if no initialization found
196
+ begin
197
+ require "./airbox"
198
+ rescue LoadError
199
+ end
200
+
@@ -0,0 +1,3 @@
1
+ module Airbox
2
+ VERSION = '0.1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: airbox
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Aidan Nulman
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-07-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activeresource
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - <
20
+ - !ruby/object:Gem::Version
21
+ version: '4'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - <
28
+ - !ruby/object:Gem::Version
29
+ version: '4'
30
+ description: ActiveResource extension to easily access and manipulate objects from
31
+ Airbrake's reporting API.
32
+ email:
33
+ - anulman@gmail.com
34
+ executables: []
35
+ extensions: []
36
+ extra_rdoc_files: []
37
+ files:
38
+ - .gitignore
39
+ - Gemfile
40
+ - LICENSE
41
+ - README.md
42
+ - airbox.gemspec
43
+ - lib/airbox.rb
44
+ - lib/airbox/version.rb
45
+ homepage: https://github.com/anulman/airbox
46
+ licenses:
47
+ - Beerware
48
+ post_install_message:
49
+ rdoc_options: []
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ none: false
54
+ requirements:
55
+ - - ! '>='
56
+ - !ruby/object:Gem::Version
57
+ version: 1.9.0
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ none: false
60
+ requirements:
61
+ - - ! '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ requirements: []
65
+ rubyforge_project:
66
+ rubygems_version: 1.8.24
67
+ signing_key:
68
+ specification_version: 3
69
+ summary: Airbrake's missing "black box"
70
+ test_files: []
71
+ has_rdoc: