minmb-teambox-client 0.4.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/Gemfile +11 -0
- data/Gemfile.lock +54 -0
- data/History +6 -0
- data/License +20 -0
- data/README.rdoc +30 -0
- data/Rakefile +44 -0
- data/VERSION +1 -0
- data/examples/conversation.rb +12 -0
- data/examples/task.rb +17 -0
- data/examples/users.rb +19 -0
- data/lib/teambox-client/models/activity.rb +27 -0
- data/lib/teambox-client/models/comment.rb +55 -0
- data/lib/teambox-client/models/conversation.rb +26 -0
- data/lib/teambox-client/models/divider.rb +15 -0
- data/lib/teambox-client/models/invitation.rb +21 -0
- data/lib/teambox-client/models/membership.rb +15 -0
- data/lib/teambox-client/models/note.rb +15 -0
- data/lib/teambox-client/models/organization.rb +18 -0
- data/lib/teambox-client/models/page.rb +20 -0
- data/lib/teambox-client/models/page_slot.rb +16 -0
- data/lib/teambox-client/models/person.rb +19 -0
- data/lib/teambox-client/models/project.rb +52 -0
- data/lib/teambox-client/models/task.rb +66 -0
- data/lib/teambox-client/models/task_list.rb +26 -0
- data/lib/teambox-client/models/teambox_data.rb +16 -0
- data/lib/teambox-client/models/upload.rb +27 -0
- data/lib/teambox-client/models/user.rb +11 -0
- data/lib/teambox-client/reference_list.rb +49 -0
- data/lib/teambox-client/result_set.rb +72 -0
- data/lib/teambox-client/teambox.rb +288 -0
- data/lib/teambox-client/teambox_oauth.rb +37 -0
- data/lib/teambox-client.rb +8 -0
- data/minmb-teambox-client.gemspec +96 -0
- data/spec/client_spec.rb +17 -0
- data/spec/conversation_spec.rb +29 -0
- data/spec/project_spec.rb +11 -0
- data/spec/resource_spec.rb +77 -0
- data/spec/result_set_spec.rb +55 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/task_lists_spec.rb +17 -0
- data/spec/tasks_spec.rb +18 -0
- metadata +251 -0
@@ -0,0 +1,27 @@
|
|
1
|
+
module Teambox
|
2
|
+
class Upload < Teambox::Resource
|
3
|
+
def user
|
4
|
+
get_or_make_reference('User', @data, 'user_id')
|
5
|
+
end
|
6
|
+
|
7
|
+
def project
|
8
|
+
get_or_make_reference('Project', @data, 'project_id')
|
9
|
+
end
|
10
|
+
|
11
|
+
def page
|
12
|
+
get_or_make_reference('Project', @data, 'project_id')
|
13
|
+
end
|
14
|
+
|
15
|
+
def page_slot
|
16
|
+
get_or_make_reference('PageSlot', @data, 'page_slot_id')
|
17
|
+
end
|
18
|
+
|
19
|
+
def comment
|
20
|
+
get_or_make_reference('Comment', @data, 'comment_id')
|
21
|
+
end
|
22
|
+
|
23
|
+
def url #:nodoc:
|
24
|
+
"/projects/#{@data['project_id']}/#{@data['id']}"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Methods for handling references list
|
2
|
+
module ReferenceList
|
3
|
+
# Generate references hash from JSON data
|
4
|
+
def generate_references(data)
|
5
|
+
@references = {}
|
6
|
+
@references.tap { |h| data.each {|ref| h[ref['type'] + ref['id'].to_s] = Teambox.create_model(ref['type'], ref, self) } }
|
7
|
+
end
|
8
|
+
|
9
|
+
# References resource in the current Teambox::ResultSet
|
10
|
+
def set_reference(klass, resource)
|
11
|
+
real_resource = if resource.is_a? Teambox::Resource
|
12
|
+
resource
|
13
|
+
else
|
14
|
+
Teambox.const_get(klass).new(resource, self)
|
15
|
+
end
|
16
|
+
|
17
|
+
@references[klass.to_s + real_resource.id.to_s] = real_resource
|
18
|
+
real_resource
|
19
|
+
end
|
20
|
+
|
21
|
+
# Gets a referenced object. e.g:
|
22
|
+
# get_reference('User', 1)
|
23
|
+
def get_reference(klass, id)
|
24
|
+
@references[klass.to_s + (id||'').to_s]
|
25
|
+
end
|
26
|
+
|
27
|
+
# get reference based on data. Makes new resource if reference does not exist. e.g.
|
28
|
+
# get_or_make_reference('User', @data, 'user_id')
|
29
|
+
def get_or_make_reference(klass, data, field_id)
|
30
|
+
get_reference(klass, data[field_id]) || set_reference(klass, {}.merge({'id' => data[field_id]}))
|
31
|
+
end
|
32
|
+
|
33
|
+
# get a list of references based on data. Makes a new resource for each references which doesnot exist.
|
34
|
+
def get_or_make_references(klass, data, field_id, field_data=nil)
|
35
|
+
if data[field_data]
|
36
|
+
data[field_data].map do |object|
|
37
|
+
get_reference(klass, object['id']) ||
|
38
|
+
set_reference(klass, object)
|
39
|
+
end
|
40
|
+
elsif data[field_id]
|
41
|
+
data[field_id].map do |object_id|
|
42
|
+
get_reference(klass, object_id) ||
|
43
|
+
set_reference(klass, {'id' => object_id})
|
44
|
+
end
|
45
|
+
else
|
46
|
+
[]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Teambox
|
2
|
+
# This represents a list of objects along with referenced objects returned by the API.
|
3
|
+
#
|
4
|
+
# == Basic Usage
|
5
|
+
#
|
6
|
+
# A Teambox::ResultSet is usually returned from a get request from Teambox::Client. e.g.:
|
7
|
+
#
|
8
|
+
# list = client.get('/projects') # Teambox::ResultSet
|
9
|
+
# puts "Returned #{list.length} projects"
|
10
|
+
#
|
11
|
+
# The Teambox API only returns a limited amount of objects per request (currently 50),
|
12
|
+
# so the methods prev, next, and empty? are provided to navigate the list of objects.
|
13
|
+
# e.g. To get all projects, you can use something like:
|
14
|
+
#
|
15
|
+
# project_list = []
|
16
|
+
# list = client.get('/projects')
|
17
|
+
# while !list.empty?
|
18
|
+
# items += list.objects
|
19
|
+
# list = list.prev
|
20
|
+
# end
|
21
|
+
#
|
22
|
+
class ResultSet
|
23
|
+
include ReferenceList
|
24
|
+
attr_reader :first_id, :last_id, :client, :references, :objects
|
25
|
+
|
26
|
+
def initialize(client, request, objects, references) #:nodoc:
|
27
|
+
@client = client
|
28
|
+
@request = request
|
29
|
+
generate_references(references)
|
30
|
+
@objects = objects.map { |o| Teambox.create_model(o['type'], o, self) }
|
31
|
+
|
32
|
+
id_list = objects.map{|obj| obj['id']}.sort
|
33
|
+
@first_id = id_list[0]
|
34
|
+
@last_id = id_list[-1]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Yields for each object
|
38
|
+
def each(&block)
|
39
|
+
@objects.each(&block)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Yields for each object
|
43
|
+
def map(&block)
|
44
|
+
@objects.map(&block)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Length of object list
|
48
|
+
def length
|
49
|
+
@objects.length
|
50
|
+
end
|
51
|
+
|
52
|
+
# Is the object list empty?
|
53
|
+
def empty?
|
54
|
+
@objects.length == 0
|
55
|
+
end
|
56
|
+
|
57
|
+
# Gets older items as a Teambox::ResultSet
|
58
|
+
def prev
|
59
|
+
@client.get(@request[:url], {}, :query => (@request[:query]).merge(:max_id => @first_id))
|
60
|
+
end
|
61
|
+
|
62
|
+
# Gets newer items as a Teambox::ResultSet
|
63
|
+
def next
|
64
|
+
@client.get(@request[:url], {}, :query => (@request[:query]).merge(:since_id => @last_id))
|
65
|
+
end
|
66
|
+
|
67
|
+
# Indexes into object array
|
68
|
+
def [](idx)
|
69
|
+
@objects[idx]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
@@ -0,0 +1,288 @@
|
|
1
|
+
# Teambox API wrapper. See Teambox::Client for more details.
|
2
|
+
module Teambox
|
3
|
+
# This is the entrypoint to the Teambox API.
|
4
|
+
#
|
5
|
+
# == Basic Usage
|
6
|
+
#
|
7
|
+
# Create a Teambox::Client, passing in your authentication detials in :auth.
|
8
|
+
# Then use one of the helper methods to get data.
|
9
|
+
#
|
10
|
+
# client = Teambox::Client.new(:auth => {:user => 'frank', :password => 'papapa'})
|
11
|
+
# client.current_user # == frank
|
12
|
+
# client.project('earthworks')
|
13
|
+
#
|
14
|
+
# The methods get, post, put, delete, and safe_get are provided in case you want to
|
15
|
+
# access an API method not covered by a helper. e.g.:
|
16
|
+
#
|
17
|
+
# client.get('/account')
|
18
|
+
#
|
19
|
+
# The API will either return a Teambox::Resource, or a Teambox::ResultSet in the case of
|
20
|
+
# index methods.
|
21
|
+
#
|
22
|
+
# Errors returned by the api are thrown as a Teambox::APIError, so beware of this when writing
|
23
|
+
# your api code.
|
24
|
+
#
|
25
|
+
# begin
|
26
|
+
# client.project('earthworks').create_conversation(:name => 'Serious discussion', :body => 'We need a serious discussion')
|
27
|
+
# rescue Teambox::APIError => e
|
28
|
+
# puts "Something went wrong: #{e.inspect}"
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# == OAuth authentication
|
32
|
+
#
|
33
|
+
# To authenticate via OAuth (currently not supported on teambox.com), you will need
|
34
|
+
# to pass in your consumer key, secret, and redirect url in :auth. Then use authorize_url
|
35
|
+
# and authorize to complete authentication.
|
36
|
+
#
|
37
|
+
# client = Teambox::Client.new(:auth => {
|
38
|
+
# :oauth_app_id => 'h6K1Ru9sVFbPGEK5v9gQFPHTNZ5IRsVCGNeGENQ3',
|
39
|
+
# :oauth_app_secret => 'fec4x9P7atC666JzF6WEZIeY6pVv1lCp6aLfVJBw',
|
40
|
+
# :redirect_uri => 'http://www.myapp.com/auth/teambox'})
|
41
|
+
# client.authorize_url # Open this in your browser
|
42
|
+
# client.authenticate(:oauth_verifier => '1234') # Code returned from teambox
|
43
|
+
#
|
44
|
+
#
|
45
|
+
class Client
|
46
|
+
include HTTParty
|
47
|
+
include Teambox::OAuth
|
48
|
+
|
49
|
+
# Initializes the Teambox client
|
50
|
+
def initialize(opts = {})
|
51
|
+
opts[:base_uri] ||= 'https://teambox.com/api/1'
|
52
|
+
self.class.base_uri(opts[:base_uri])
|
53
|
+
|
54
|
+
@base_uri = opts[:base_uri]
|
55
|
+
@auth = opts[:auth] || {}
|
56
|
+
@consumer = consumer if oauth?
|
57
|
+
|
58
|
+
authenticate(opts[:auth])
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns true if oauth is being used for authentication
|
62
|
+
def oauth?
|
63
|
+
!@auth[:oauth_app_id].nil?
|
64
|
+
end
|
65
|
+
|
66
|
+
# Returns the URL required to authenticate access if using OAuth
|
67
|
+
def authorize_url(opts={})
|
68
|
+
if oauth?
|
69
|
+
@consumer.web_server.authorize_url({:redirect_uri => @auth[:redirect_uri]}.merge(opts))
|
70
|
+
else
|
71
|
+
nil
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Authenticates the client with teambox
|
76
|
+
def authenticate(opts={})
|
77
|
+
@current_user = nil
|
78
|
+
if oauth?
|
79
|
+
if opts[:oauth_verifier]
|
80
|
+
authorize_from_request(opts[:oauth_verifier])
|
81
|
+
elsif opts[:oauth_token]
|
82
|
+
@auth.merge!({:oauth_token => opts[:oauth_token]})
|
83
|
+
authorize_from_access
|
84
|
+
end
|
85
|
+
else
|
86
|
+
if opts[:user]
|
87
|
+
@auth.merge!({:user => opts[:user], :password => opts[:password]})
|
88
|
+
self.class.basic_auth(@auth[:user], @auth[:password])
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
!current_user.nil?
|
93
|
+
end
|
94
|
+
|
95
|
+
# Is the client is authenticated?
|
96
|
+
def authenticated?
|
97
|
+
!current_user.nil?
|
98
|
+
end
|
99
|
+
|
100
|
+
# Current user the client is logged in as
|
101
|
+
def current_user
|
102
|
+
@current_user ||= safe_get('/account')
|
103
|
+
end
|
104
|
+
|
105
|
+
# Performs a GET on path
|
106
|
+
def get(path, query={}, options={})
|
107
|
+
api_unwrap perform_request(:get, path, {:query => query}.merge(options)), {:url => path, :query => query}
|
108
|
+
end
|
109
|
+
|
110
|
+
# Performs a POST on path
|
111
|
+
def post(path, query={}, options={})
|
112
|
+
api_unwrap perform_request(:post, path, {:body => query}.merge(options)), {:url => path, :body => query}
|
113
|
+
end
|
114
|
+
|
115
|
+
# Performs a PUT on path
|
116
|
+
def put(path, query={}, options={})
|
117
|
+
api_unwrap perform_request(:put, path, {:body => query}.merge(options)), {:url => path, :body => query}
|
118
|
+
end
|
119
|
+
|
120
|
+
# Performs a DELETE on path
|
121
|
+
def delete(path, query={}, options={})
|
122
|
+
api_unwrap perform_request(:delete, path, {:body => query}.merge(options)), {:url => path, :body => query}
|
123
|
+
end
|
124
|
+
|
125
|
+
# Performs a GET on path, catching any exceptions
|
126
|
+
def safe_get(path, query={}, options={})
|
127
|
+
api_unwrap(perform_request(:get, path, {:query => query}.merge(options)), {:url => path, :query => query}) rescue nil
|
128
|
+
end
|
129
|
+
|
130
|
+
# urls
|
131
|
+
|
132
|
+
# Gets a list Teambox::Project corresponding to the current users project list
|
133
|
+
def projects(query={})
|
134
|
+
get('/projects', query)
|
135
|
+
end
|
136
|
+
|
137
|
+
# Gets a Teambox::Project by id or permalink
|
138
|
+
def project(id)
|
139
|
+
get("/projects/#{id}")
|
140
|
+
end
|
141
|
+
|
142
|
+
protected
|
143
|
+
|
144
|
+
# Internal request handler
|
145
|
+
def perform_request(method, path, options)
|
146
|
+
options[:headers] ||= {}
|
147
|
+
headers = options[:headers]
|
148
|
+
|
149
|
+
options[:query] ||= {}
|
150
|
+
options[:query][:access_token] = @access_token.token if @access_token
|
151
|
+
self.class.send(method, path, options)
|
152
|
+
end
|
153
|
+
|
154
|
+
# Decodes response and returns appropriate API object
|
155
|
+
def api_unwrap(response, request={})
|
156
|
+
data = JSON.parse(response.body) rescue nil
|
157
|
+
if [200, 201, 202].include? response.response.code.to_i
|
158
|
+
raise StandardError.new('Please update your Teambox') unless response.has_key?('type')
|
159
|
+
if data['type'] == 'List'
|
160
|
+
ResultSet.new(self, request, data['objects'], data['references'])
|
161
|
+
else
|
162
|
+
Teambox.create_model(data['type'], data, ResultSet.new(self, request, [], []))
|
163
|
+
end
|
164
|
+
else
|
165
|
+
error_list = data ? data['errors'] : {'type' => 'UnknownError', 'message' => data}
|
166
|
+
error_list['type'] = error_list['type'][0] if error_list['type'].is_a? Array
|
167
|
+
error_list['message'] = error_list['message'][0] if error_list['message'].is_a? Array
|
168
|
+
raise APIError.new(response.response.code, error_list)
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
|
174
|
+
# Exception handling for API Errors
|
175
|
+
class APIError < StandardError
|
176
|
+
attr_reader :error_type # Type of error. See the API Docs for a list of error types
|
177
|
+
attr_reader :status_code # HTTP status code returned
|
178
|
+
def initialize(status_code, details)
|
179
|
+
@error_type = details['type'].to_sym
|
180
|
+
@status_code = status_code
|
181
|
+
super(details['message'] || details['type'])
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
# Exception handling unknown Teambox::Resource types
|
186
|
+
class UnknownResourceError < APIError
|
187
|
+
def initialize(type)
|
188
|
+
super(200, {'type' => 'UnknownResource', :message => "Unknown Resource #{type}"})
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
def self.create_model(type, data, list=nil) #:nodoc:
|
193
|
+
klass = const_get(type.to_sym) rescue nil
|
194
|
+
if klass
|
195
|
+
klass.new data, list
|
196
|
+
else
|
197
|
+
throw UnknownResourceError.new(type)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
# Represents an object located on Teambox.
|
202
|
+
#
|
203
|
+
# Most resources belonging to a Teambox::Project can be modified, in which case you can use
|
204
|
+
# the save, destroy, and reload methods.
|
205
|
+
#
|
206
|
+
# All attributes are exposed by the method_missing handler.
|
207
|
+
class Resource
|
208
|
+
include ReferenceList
|
209
|
+
|
210
|
+
attr_accessor :list, :data
|
211
|
+
attr_reader :references
|
212
|
+
|
213
|
+
def initialize(data, result_list=nil)
|
214
|
+
@data = data
|
215
|
+
@list = result_list || ResultSet.new(nil, nil, [], [])
|
216
|
+
if @data['references']
|
217
|
+
generate_references(@data['references'])
|
218
|
+
else
|
219
|
+
@references = result_list ? result_list.references : {}
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def id
|
224
|
+
@data['id']
|
225
|
+
end
|
226
|
+
|
227
|
+
# The time this object was created
|
228
|
+
def created_at
|
229
|
+
@data.has_key?('created_at') ? Time.parse(data['created_at']) : nil
|
230
|
+
end
|
231
|
+
|
232
|
+
# The last time this object was updated
|
233
|
+
def updated_at
|
234
|
+
@data.has_key?('updated_at') ? Time.parse(data['updated_at']) : nil
|
235
|
+
end
|
236
|
+
|
237
|
+
def next #:nodoc:
|
238
|
+
nil
|
239
|
+
end
|
240
|
+
|
241
|
+
def prev #:nodoc:
|
242
|
+
nil
|
243
|
+
end
|
244
|
+
|
245
|
+
# Location of this object on teambox, used for updating
|
246
|
+
def url
|
247
|
+
nil
|
248
|
+
end
|
249
|
+
|
250
|
+
# Reloads the resource from source data
|
251
|
+
# @returns self
|
252
|
+
def reload
|
253
|
+
if @list.client && url
|
254
|
+
updated = @list.client.get(url) rescue nil
|
255
|
+
unless updated.nil?
|
256
|
+
@data = updated.data
|
257
|
+
end
|
258
|
+
end
|
259
|
+
self
|
260
|
+
end
|
261
|
+
|
262
|
+
# Saves the resource to teambox
|
263
|
+
# @returns true if saved
|
264
|
+
def save
|
265
|
+
if @list.client && url
|
266
|
+
updated = @list.client.put(url, @data) rescue nil
|
267
|
+
return true unless updated.nil?
|
268
|
+
end
|
269
|
+
false
|
270
|
+
end
|
271
|
+
|
272
|
+
# Destroys the resource on teambox
|
273
|
+
def destroy
|
274
|
+
@list.client.delete(url) if @list.client && url
|
275
|
+
true
|
276
|
+
end
|
277
|
+
|
278
|
+
def method_missing(method, *args, &block) #:nodoc:
|
279
|
+
@data.include?(method.to_s) ? @data[method.to_s] : super
|
280
|
+
end
|
281
|
+
|
282
|
+
def inspect
|
283
|
+
"#<#{self.class} @data=#{@data.inspect} list=#{@list.object_id}>"
|
284
|
+
end
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
Dir[File.expand_path('models/*.rb', File.dirname(__FILE__))].each { |f| require f }
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Teambox
|
2
|
+
# Methods used to authenticate with OAuth on teambox.com. Normally you won't have to call these.
|
3
|
+
module OAuth
|
4
|
+
attr_accessor :access_token
|
5
|
+
|
6
|
+
# OAuth consumer required for authentication
|
7
|
+
def consumer
|
8
|
+
return nil if @auth[:oauth_app_id].nil?
|
9
|
+
@consumer ||= OAuth2::Client.new(@auth[:oauth_app_id], @auth[:oauth_app_secret],
|
10
|
+
:site => consumer_url,
|
11
|
+
:access_token_path => consumer_url+'oauth/token',
|
12
|
+
:authorize_path => consumer_url+'oauth/authorize?response_type=code')
|
13
|
+
end
|
14
|
+
|
15
|
+
def consumer_url
|
16
|
+
uri = URI.parse(self.class.base_uri)
|
17
|
+
uri.path = '/'
|
18
|
+
uri.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
# Is the client authorized via OAuth?
|
22
|
+
def authorized?
|
23
|
+
!@access_token.nil?
|
24
|
+
end
|
25
|
+
|
26
|
+
def authorize_from_request(verifier)
|
27
|
+
@access_token = consumer.web_server.get_access_token(verifier, :redirect_uri => @auth[:redirect_uri], :grant_type => 'authorization_code')
|
28
|
+
@auth[:oauth_token] = @access_token.token
|
29
|
+
@access_token
|
30
|
+
end
|
31
|
+
|
32
|
+
# Authorizes the client from an existing OAuth token
|
33
|
+
def authorize_from_access
|
34
|
+
@access_token = ::OAuth2::AccessToken.new(nil, @auth[:oauth_token])
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = "minmb-teambox-client"
|
8
|
+
s.version = "0.4.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Pablo Villalba", "James Urquhart", "Martin H\u{e4}ger"]
|
12
|
+
s.date = "2012-08-28"
|
13
|
+
s.description = "Provides methods to read and write to Teambox for ruby apps"
|
14
|
+
s.email = "martin.hager@minmb.se"
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"README.rdoc"
|
17
|
+
]
|
18
|
+
s.files = [
|
19
|
+
"Gemfile",
|
20
|
+
"Gemfile.lock",
|
21
|
+
"History",
|
22
|
+
"License",
|
23
|
+
"README.rdoc",
|
24
|
+
"Rakefile",
|
25
|
+
"VERSION",
|
26
|
+
"examples/conversation.rb",
|
27
|
+
"examples/task.rb",
|
28
|
+
"examples/users.rb",
|
29
|
+
"lib/teambox-client.rb",
|
30
|
+
"lib/teambox-client/models/activity.rb",
|
31
|
+
"lib/teambox-client/models/comment.rb",
|
32
|
+
"lib/teambox-client/models/conversation.rb",
|
33
|
+
"lib/teambox-client/models/divider.rb",
|
34
|
+
"lib/teambox-client/models/invitation.rb",
|
35
|
+
"lib/teambox-client/models/membership.rb",
|
36
|
+
"lib/teambox-client/models/note.rb",
|
37
|
+
"lib/teambox-client/models/organization.rb",
|
38
|
+
"lib/teambox-client/models/page.rb",
|
39
|
+
"lib/teambox-client/models/page_slot.rb",
|
40
|
+
"lib/teambox-client/models/person.rb",
|
41
|
+
"lib/teambox-client/models/project.rb",
|
42
|
+
"lib/teambox-client/models/task.rb",
|
43
|
+
"lib/teambox-client/models/task_list.rb",
|
44
|
+
"lib/teambox-client/models/teambox_data.rb",
|
45
|
+
"lib/teambox-client/models/upload.rb",
|
46
|
+
"lib/teambox-client/models/user.rb",
|
47
|
+
"lib/teambox-client/reference_list.rb",
|
48
|
+
"lib/teambox-client/result_set.rb",
|
49
|
+
"lib/teambox-client/teambox.rb",
|
50
|
+
"lib/teambox-client/teambox_oauth.rb",
|
51
|
+
"minmb-teambox-client.gemspec",
|
52
|
+
"spec/client_spec.rb",
|
53
|
+
"spec/conversation_spec.rb",
|
54
|
+
"spec/project_spec.rb",
|
55
|
+
"spec/resource_spec.rb",
|
56
|
+
"spec/result_set_spec.rb",
|
57
|
+
"spec/spec_helper.rb",
|
58
|
+
"spec/task_lists_spec.rb",
|
59
|
+
"spec/tasks_spec.rb"
|
60
|
+
]
|
61
|
+
s.homepage = "http://github.com/minmb/teambox-ruby-client"
|
62
|
+
s.require_paths = ["lib"]
|
63
|
+
s.rubygems_version = "1.8.24"
|
64
|
+
s.summary = "A ruby gem wrapper for Teambox API"
|
65
|
+
|
66
|
+
if s.respond_to? :specification_version then
|
67
|
+
s.specification_version = 3
|
68
|
+
|
69
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
70
|
+
s.add_runtime_dependency(%q<minmb-teambox-client>, [">= 0"])
|
71
|
+
s.add_development_dependency(%q<rake>, [">= 0"])
|
72
|
+
s.add_development_dependency(%q<jeweler>, [">= 0"])
|
73
|
+
s.add_development_dependency(%q<rspec>, [">= 0"])
|
74
|
+
s.add_runtime_dependency(%q<httparty>, ["~> 0.7.4"])
|
75
|
+
s.add_runtime_dependency(%q<oauth2>, ["~> 0.1.1"])
|
76
|
+
s.add_runtime_dependency(%q<json>, ["~> 1.5.1"])
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<minmb-teambox-client>, [">= 0"])
|
79
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
80
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
81
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
82
|
+
s.add_dependency(%q<httparty>, ["~> 0.7.4"])
|
83
|
+
s.add_dependency(%q<oauth2>, ["~> 0.1.1"])
|
84
|
+
s.add_dependency(%q<json>, ["~> 1.5.1"])
|
85
|
+
end
|
86
|
+
else
|
87
|
+
s.add_dependency(%q<minmb-teambox-client>, [">= 0"])
|
88
|
+
s.add_dependency(%q<rake>, [">= 0"])
|
89
|
+
s.add_dependency(%q<jeweler>, [">= 0"])
|
90
|
+
s.add_dependency(%q<rspec>, [">= 0"])
|
91
|
+
s.add_dependency(%q<httparty>, ["~> 0.7.4"])
|
92
|
+
s.add_dependency(%q<oauth2>, ["~> 0.1.1"])
|
93
|
+
s.add_dependency(%q<json>, ["~> 1.5.1"])
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
data/spec/client_spec.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Teambox::Client do
|
4
|
+
before do
|
5
|
+
@client = make_teambox_client
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should authenticate" do
|
9
|
+
@client.authenticated?.should == true
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should return the current user" do
|
13
|
+
user = @client.current_user
|
14
|
+
user.class.should == Teambox::User
|
15
|
+
user.username.should == 'frank'
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Teambox::Conversation do
|
4
|
+
before do
|
5
|
+
@client = make_teambox_client
|
6
|
+
@project = @client.project('earthworks')
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should query conversations" do
|
10
|
+
@project.conversations.length.should_not == 0
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should make a conversation" do
|
14
|
+
conversation = @project.create_conversation({:name => 'Hello', :body => 'World'})
|
15
|
+
conversation.name.should == 'Hello'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should list recent comments in a conversation" do
|
19
|
+
recent_comments = @project.conversations[0].recent_comments
|
20
|
+
recent_comments.length.should > 0
|
21
|
+
recent_comments.each {|c| c.class.should == Teambox::Comment}
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should list the first comment in a conversation" do
|
25
|
+
comment = @project.conversations[0].first_comment
|
26
|
+
comment.should_not == nil
|
27
|
+
comment.class.should == Teambox::Comment
|
28
|
+
end
|
29
|
+
end
|