basecamp 0.0.9 → 0.0.10
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.rdoc +56 -0
- data/lib/basecamp.rb +1 -0
- data/lib/basecamp/active_resource.rb +23 -0
- data/lib/basecamp/base.rb +29 -7
- data/lib/basecamp/connection.rb +4 -2
- data/lib/basecamp/resources/time_entry.rb +1 -1
- data/lib/basecamp/resources/todo_item.rb +0 -2
- metadata +96 -125
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6a4aed33709e1c506d03f74ea93caa37b20e28f6
|
4
|
+
data.tar.gz: 724ac3904f5e834266ab001891f7bc270fe358f4
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 38d4ff046a943c7e16ca6852cd14ba098505b7ef5a7c1d6a1924433c98dc116b2d9811a398ee3e3b9106220e023251e1d10284864ccb06d82ebbab394440295e
|
7
|
+
data.tar.gz: c795d56445d90fadb6937d3f102ecae247fa4dc0e841f94515070fd64f6ed47d002c027ccd9512a204ae944c4afcf63b0e74e90545234b947f69c162ba8497ea
|
data/README.rdoc
CHANGED
@@ -43,10 +43,16 @@ requires your Basecamp site address and your login credentials or API token.
|
|
43
43
|
|
44
44
|
Basecamp.establish_connection!('yoururl.basecamphq.com', 'APITOKEN', 'X')
|
45
45
|
|
46
|
+
=== Using OAuth access token
|
47
|
+
|
48
|
+
Basecamp.establish_oauth_connection!('yoururl.basecamphq.com', 'oauth_access_token')
|
49
|
+
|
46
50
|
=== With a Basecamp account that use SSL (https://yoururl.basecamphq.com)
|
47
51
|
|
48
52
|
Basecamp.establish_connection!('yoururl.basecamphq.com', 'APITOKEN', 'X', true)
|
49
53
|
|
54
|
+
Basecamp.establish_oauth_connection!('yoururl.basecamphq.com', 'oauth_access_token', true)
|
55
|
+
|
50
56
|
This is the same whether you're accessing using the ActiveResource interface,
|
51
57
|
or the legacy interface.
|
52
58
|
|
@@ -59,6 +65,22 @@ information on working with ActiveResource, see:
|
|
59
65
|
* http://api.rubyonrails.org/files/activeresource/README.html
|
60
66
|
* http://api.rubyonrails.org/classes/ActiveResource/Base.html
|
61
67
|
|
68
|
+
== Basecamp API rate limit and app identification
|
69
|
+
|
70
|
+
If your app creates a lot of requests, you may hit the (new) basecamp rate limit. ({read more here about rate limiting}[https://github.com/basecamp/basecamp-classic-api#rate-limiting]).
|
71
|
+
|
72
|
+
To raise your limit you can send a custom user-agent to basecamp with your identifying information ({read more here}[https://github.com/basecamp/basecamp-classic-api#rate-limiting]).
|
73
|
+
|
74
|
+
For this you need to create an initializer in your rails application, for example: +config/inititalizer/basecamp_user_agent.rb+ with the following line:
|
75
|
+
|
76
|
+
ActiveResource::Base.headers["User-Agent"] = "Fabian's Ingenious Integration (fabian@example.com)"
|
77
|
+
|
78
|
+
This initializer ensures that all requests made through ActiveResource (which this gem uses) are identifiable with your information.
|
79
|
+
|
80
|
+
**NOTE**: If you are using ActiveResource for accessing multiple APIs at once and not only basecamp's, you will need the following initializer instead:
|
81
|
+
|
82
|
+
Basecamp::Resource.headers["User-Agent"] = "Fabian's Ingenious Integration (fabian@example.com)"
|
83
|
+
|
62
84
|
=== Finding a Resource
|
63
85
|
|
64
86
|
Find a specific resource using the +find+ method. Attributes of the resource
|
@@ -196,6 +218,40 @@ By default the wrapper will use :xml for the active record connection but you ca
|
|
196
218
|
|
197
219
|
Note: We recommend using xml. There are some API calls that don't behave well with json.
|
198
220
|
|
221
|
+
= Access active resource response object
|
222
|
+
|
223
|
+
You can acces the last response object:
|
224
|
+
|
225
|
+
Basecamp::Message.find(:all, params => { :project_id => 1037 })
|
226
|
+
Basecamp::Message.connection.response["status"] # => "200 OK"
|
227
|
+
|
228
|
+
= Using the raw response body
|
229
|
+
|
230
|
+
This is useful for example to get pagination data to access all comments in a commentable resource: https://github.com/37signals/basecamp-classic-api/blob/master/sections/comments.md#get-recent-comments-for-a-commentable-resource
|
231
|
+
|
232
|
+
def get_threshold
|
233
|
+
# Get the last response object
|
234
|
+
response = Basecamp::Comment.connection.response
|
235
|
+
# Parse the xml
|
236
|
+
xml = XmlSimple.xml_in(response.body)
|
237
|
+
# continued-at is an attribute specifying the path where the next oldest 75 comments can be retrieved
|
238
|
+
if continued_at = xml["continued-at"]
|
239
|
+
# There are more comments
|
240
|
+
# We need to extract the threshold parameter from the continued-at url
|
241
|
+
hash = CGI::parse(URI.parse(continued_at).query)
|
242
|
+
hash["threshold"].first
|
243
|
+
else
|
244
|
+
# We're done
|
245
|
+
nil
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
comments = Basecamp::Comment.find(:all, :params => { :post_id => 1037 })
|
250
|
+
if threshold = get_threshold
|
251
|
+
# Get the next set of comments using the threshold
|
252
|
+
Basecamp::Comment.find(:all, :params => { :post_id => 1037, :threshold => threshold })
|
253
|
+
end
|
254
|
+
|
199
255
|
== Contributors
|
200
256
|
|
201
257
|
* jamesarosen
|
data/lib/basecamp.rb
CHANGED
@@ -0,0 +1,23 @@
|
|
1
|
+
# ActiveResource connection patch to let users access the last response object and the headers.
|
2
|
+
#
|
3
|
+
# Example:
|
4
|
+
# >> Basecamp::Message.find(:all, params => { :project_id => 1037 })
|
5
|
+
# >> Basecamp::Message.connection.response["status"]
|
6
|
+
# => "200 OK"
|
7
|
+
class ActiveResource::Connection
|
8
|
+
alias_method :original_handle_response, :handle_response
|
9
|
+
alias :static_default_header :default_header
|
10
|
+
|
11
|
+
def handle_response(response)
|
12
|
+
Thread.current[:active_resource_connection_headers] = response
|
13
|
+
original_handle_response(response)
|
14
|
+
end
|
15
|
+
|
16
|
+
def response
|
17
|
+
Thread.current[:active_resource_connection_headers]
|
18
|
+
end
|
19
|
+
|
20
|
+
def set_header(key, value)
|
21
|
+
default_header.update(key => value)
|
22
|
+
end
|
23
|
+
end
|
data/lib/basecamp/base.rb
CHANGED
@@ -1,14 +1,15 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class << self
|
3
3
|
attr_accessor :use_xml
|
4
|
-
attr_reader :site, :user, :password, :use_ssl
|
4
|
+
attr_reader :site, :user, :password, :use_ssl, :use_oauth, :access_token
|
5
5
|
|
6
6
|
def establish_connection!(site, user, password, use_ssl = false, use_xml = true)
|
7
|
-
@site
|
8
|
-
@user
|
9
|
-
@password
|
10
|
-
@use_ssl
|
11
|
-
@use_xml
|
7
|
+
@site = site
|
8
|
+
@user = user
|
9
|
+
@password = password
|
10
|
+
@use_ssl = use_ssl
|
11
|
+
@use_xml = use_xml
|
12
|
+
@use_oauth = false
|
12
13
|
|
13
14
|
Resource.user = user
|
14
15
|
Resource.password = password
|
@@ -18,6 +19,20 @@ module Basecamp
|
|
18
19
|
@connection = Connection.new(self)
|
19
20
|
end
|
20
21
|
|
22
|
+
def establish_oauth_connection!(site, access_token, use_ssl = false, use_xml = true)
|
23
|
+
@site = site
|
24
|
+
@use_ssl = use_ssl
|
25
|
+
@use_xml = use_xml
|
26
|
+
@use_oauth = true
|
27
|
+
@access_token = access_token
|
28
|
+
|
29
|
+
Resource.site = (use_ssl ? "https" : "http") + "://" + site
|
30
|
+
Resource.format = (use_xml ? :xml : :json)
|
31
|
+
Resource.connection.set_header('Authorization', "Bearer #{access_token}")
|
32
|
+
|
33
|
+
@connection = Connection.new(self)
|
34
|
+
end
|
35
|
+
|
21
36
|
def connection
|
22
37
|
@connection || raise('No connection established')
|
23
38
|
end
|
@@ -25,9 +40,16 @@ module Basecamp
|
|
25
40
|
# Make a raw web-service request to Basecamp. This will return a Hash of
|
26
41
|
# Arrays of the response, and may seem a little odd to the uninitiated.
|
27
42
|
def request(path, parameters = {})
|
28
|
-
|
43
|
+
headers = { "Content-Type" => content_type }
|
44
|
+
headers.merge!('Authorization' => "Bearer #{@access_token}") if @use_oauth
|
45
|
+
if parameters.empty?
|
46
|
+
response = Basecamp.connection.get(path, headers)
|
47
|
+
else
|
48
|
+
response = Basecamp.connection.post(path, StringIO.new(convert_body(parameters)), headers)
|
49
|
+
end
|
29
50
|
|
30
51
|
if response.code.to_i / 100 == 2
|
52
|
+
return {} if response.body.blank?
|
31
53
|
result = XmlSimple.xml_in(response.body, 'keeproot' => true, 'contentkey' => '__content__', 'forcecontent' => true)
|
32
54
|
typecast_value(result)
|
33
55
|
else
|
data/lib/basecamp/connection.rb
CHANGED
@@ -8,7 +8,8 @@ module Basecamp; class Connection
|
|
8
8
|
|
9
9
|
def post(path, iostream, headers = {})
|
10
10
|
request = Net::HTTP::Post.new(path, headers.merge('Accept' => 'application/xml'))
|
11
|
-
request.basic_auth(@master.user, @master.password)
|
11
|
+
request.basic_auth(@master.user, @master.password) unless @master.use_oauth
|
12
|
+
request.initialize_http_header(@master.class.headers)
|
12
13
|
request.body_stream = iostream
|
13
14
|
request.content_length = iostream.size
|
14
15
|
@connection.request(request)
|
@@ -16,7 +17,8 @@ module Basecamp; class Connection
|
|
16
17
|
|
17
18
|
def get(path, headers = {})
|
18
19
|
request = Net::HTTP::Get.new(path, headers.merge('Accept' => 'application/xml'))
|
19
|
-
request.
|
20
|
+
request.initialize_http_header(@master.class.headers)
|
21
|
+
request.basic_auth(@master.user, @master.password) unless @master.use_oauth
|
20
22
|
@connection.request(request)
|
21
23
|
end
|
22
24
|
end; end
|
metadata
CHANGED
@@ -1,139 +1,123 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: basecamp
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
prerelease:
|
6
|
-
segments:
|
7
|
-
- 0
|
8
|
-
- 0
|
9
|
-
- 9
|
10
|
-
version: 0.0.9
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.10
|
11
5
|
platform: ruby
|
12
|
-
authors:
|
6
|
+
authors:
|
13
7
|
- Anibal Cucco
|
14
8
|
- James A. Rosen
|
15
9
|
autorequire:
|
16
10
|
bindir: bin
|
17
11
|
cert_chain: []
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
dependencies:
|
22
|
-
- !ruby/object:Gem::Dependency
|
12
|
+
date: 2014-11-03 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
23
15
|
name: oauth2
|
24
|
-
|
25
|
-
|
26
|
-
none: false
|
27
|
-
requirements:
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
28
18
|
- - ">="
|
29
|
-
- !ruby/object:Gem::Version
|
30
|
-
|
31
|
-
segments:
|
32
|
-
- 0
|
33
|
-
version: "0"
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: '0'
|
34
21
|
type: :runtime
|
35
|
-
version_requirements: *id001
|
36
|
-
- !ruby/object:Gem::Dependency
|
37
|
-
name: xml-simple
|
38
22
|
prerelease: false
|
39
|
-
|
40
|
-
|
41
|
-
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: '0'
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: xml-simple
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
42
32
|
- - ">="
|
43
|
-
- !ruby/object:Gem::Version
|
44
|
-
|
45
|
-
segments:
|
46
|
-
- 0
|
47
|
-
version: "0"
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
48
35
|
type: :runtime
|
49
|
-
version_requirements: *id002
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
|
-
name: activeresource
|
52
36
|
prerelease: false
|
53
|
-
|
54
|
-
|
55
|
-
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: activeresource
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
56
46
|
- - ">="
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
hash: 3
|
59
|
-
segments:
|
60
|
-
- 2
|
61
|
-
- 3
|
62
|
-
- 0
|
47
|
+
- !ruby/object:Gem::Version
|
63
48
|
version: 2.3.0
|
64
49
|
type: :runtime
|
65
|
-
version_requirements: *id003
|
66
|
-
- !ruby/object:Gem::Dependency
|
67
|
-
name: rake
|
68
50
|
prerelease: false
|
69
|
-
|
70
|
-
|
71
|
-
requirements:
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
72
53
|
- - ">="
|
73
|
-
- !ruby/object:Gem::Version
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 2.3.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rake
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - ">="
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
78
63
|
type: :development
|
79
|
-
version_requirements: *id004
|
80
|
-
- !ruby/object:Gem::Dependency
|
81
|
-
name: mg
|
82
64
|
prerelease: false
|
83
|
-
|
84
|
-
|
85
|
-
requirements:
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
86
67
|
- - ">="
|
87
|
-
- !ruby/object:Gem::Version
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: '0'
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: mg
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
93
76
|
version: 0.0.8
|
94
77
|
type: :development
|
95
|
-
version_requirements: *id005
|
96
|
-
- !ruby/object:Gem::Dependency
|
97
|
-
name: rspec
|
98
78
|
prerelease: false
|
99
|
-
|
100
|
-
|
101
|
-
requirements:
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
102
81
|
- - ">="
|
103
|
-
- !ruby/object:Gem::Version
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.0.8
|
84
|
+
- !ruby/object:Gem::Dependency
|
85
|
+
name: rspec
|
86
|
+
requirement: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
109
90
|
version: 1.3.0
|
110
91
|
type: :development
|
111
|
-
version_requirements: *id006
|
112
|
-
- !ruby/object:Gem::Dependency
|
113
|
-
name: webmock
|
114
92
|
prerelease: false
|
115
|
-
|
116
|
-
|
117
|
-
|
93
|
+
version_requirements: !ruby/object:Gem::Requirement
|
94
|
+
requirements:
|
95
|
+
- - ">="
|
96
|
+
- !ruby/object:Gem::Version
|
97
|
+
version: 1.3.0
|
98
|
+
- !ruby/object:Gem::Dependency
|
99
|
+
name: webmock
|
100
|
+
requirement: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
118
102
|
- - ">="
|
119
|
-
- !ruby/object:Gem::Version
|
120
|
-
hash: 27
|
121
|
-
segments:
|
122
|
-
- 1
|
123
|
-
- 2
|
124
|
-
- 2
|
103
|
+
- !ruby/object:Gem::Version
|
125
104
|
version: 1.2.2
|
126
105
|
type: :development
|
127
|
-
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: 1.2.2
|
128
112
|
description: Basecamp API wrapper.
|
129
113
|
email: nobody@gmail.com
|
130
114
|
executables: []
|
131
|
-
|
132
115
|
extensions: []
|
133
|
-
|
134
116
|
extra_rdoc_files: []
|
135
|
-
|
136
|
-
|
117
|
+
files:
|
118
|
+
- README.rdoc
|
119
|
+
- lib/basecamp.rb
|
120
|
+
- lib/basecamp/active_resource.rb
|
137
121
|
- lib/basecamp/base.rb
|
138
122
|
- lib/basecamp/connection.rb
|
139
123
|
- lib/basecamp/hash.rb
|
@@ -151,41 +135,28 @@ files:
|
|
151
135
|
- lib/basecamp/resources/todo_item.rb
|
152
136
|
- lib/basecamp/resources/todo_list.rb
|
153
137
|
- lib/basecamp/symbol.rb
|
154
|
-
- lib/basecamp.rb
|
155
|
-
- README.rdoc
|
156
|
-
has_rdoc: true
|
157
138
|
homepage: http://github.com/anibalcucco/basecamp-wrapper
|
158
139
|
licenses: []
|
159
|
-
|
140
|
+
metadata: {}
|
160
141
|
post_install_message:
|
161
142
|
rdoc_options: []
|
162
|
-
|
163
|
-
require_paths:
|
143
|
+
require_paths:
|
164
144
|
- lib
|
165
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
166
|
-
|
167
|
-
requirements:
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
168
147
|
- - ">="
|
169
|
-
- !ruby/object:Gem::Version
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
version: "0"
|
174
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
175
|
-
none: false
|
176
|
-
requirements:
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
177
152
|
- - ">="
|
178
|
-
- !ruby/object:Gem::Version
|
179
|
-
|
180
|
-
segments:
|
181
|
-
- 0
|
182
|
-
version: "0"
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
183
155
|
requirements: []
|
184
|
-
|
185
156
|
rubyforge_project:
|
186
|
-
rubygems_version:
|
157
|
+
rubygems_version: 2.4.2
|
187
158
|
signing_key:
|
188
|
-
specification_version:
|
159
|
+
specification_version: 4
|
189
160
|
summary: Basecamp API wrapper.
|
190
161
|
test_files: []
|
191
|
-
|
162
|
+
has_rdoc:
|