Class: Basecamp

Inherits:
Object show all
Defined in:
lib/basecamp.rb,
lib/basecamper.rb

Overview

Basecamp wrapper extensions

Defined Under Namespace

Classes: FileUpload, Record

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(url, user_name, password, use_ssl = false) ⇒ Basecamp

Connects



96
97
98
99
100
# File 'lib/basecamp.rb', line 96

def initialize(url, user_name, password, use_ssl = false)
  @use_xml = false
  @user_name, @password = user_name, password
  connect!(url, use_ssl)
end

Instance Attribute Details

#use_xmlObject

Returns the value of attribute use_xml.



93
94
95
# File 'lib/basecamp.rb', line 93

def use_xml
  @use_xml
end

Instance Method Details

#all_peopleObject

Fetches all people from all companies and prunes for uniqueness



248
249
250
251
252
# File 'lib/basecamper.rb', line 248

def all_people
  companies.map do |company|
    records "person", "/contacts/people/#{company.id}"
  end.flatten
end

#comment(id) ⇒ Object

Retrieve a specific comment



204
205
206
# File 'lib/basecamp.rb', line 204

def comment(id)
  record "/msg/comment/#{id}"
end

#comments(post_id) ⇒ Object

Return a list of the comments for the specified message.



199
200
201
# File 'lib/basecamp.rb', line 199

def comments(post_id)
  records "comment", "/msg/comments/#{post_id}"
end

#companiesObject



243
244
245
# File 'lib/basecamper.rb', line 243

def companies
  records "company", "/contacts/companies"
end

#company(id) ⇒ Object

Return information for the company with the given id



118
119
120
# File 'lib/basecamp.rb', line 118

def company(id)
  record "/contacts/company/#{id}"
end

#complete_item(id) ⇒ Object

Marks the given item completed.



234
235
236
# File 'lib/basecamp.rb', line 234

def complete_item(id)
  record "/todos/complete_item/#{id}"
end

#complete_milestone(id) ⇒ Object

Complete the milestone with the given id



303
304
305
# File 'lib/basecamp.rb', line 303

def complete_milestone(id)
  record "/milestones/complete/#{id}"
end

#create_comment(post_id, comment, attachments = []) ⇒ Object

Add a new comment to a message. comment must be a hash describing the comment. You can add attachments to the comment, too, by giving them in an array. See the #post_message method for a description of how to do that.



211
212
213
214
215
# File 'lib/basecamp.rb', line 211

def create_comment(post_id, comment, attachments=[])
  prepare_attachments(attachments)
  record "/msg/create_comment", :comment => comment.merge(:post_id => post_id),
    :attachments => attachments
end

#create_item(list_id, content, responsible_party = nil, notify = true) ⇒ Object

Creates a new to-do item.



244
245
246
247
248
# File 'lib/basecamp.rb', line 244

def create_item(list_id, content, responsible_party=nil, notify=true)
  record "/todos/create_item/#{list_id}",
    :content => content, :responsible_party => responsible_party,
    :notify => notify
end

#create_list(project_id, list) ⇒ Object

Creates a new list using the given hash of list metadata.



251
252
253
# File 'lib/basecamp.rb', line 251

def create_list(project_id, list)
  record "/projects/#{project_id}/todos/create_list", list
end

#create_milestone(project_id, data) ⇒ Object

Create a new milestone for the given project. data must be hash of the values to set, including title, deadline, responsible_party, and notify.



310
311
312
# File 'lib/basecamp.rb', line 310

def create_milestone(project_id, data)
  create_milestones(project_id, [data]).first
end

#create_milestones(project_id, milestones) ⇒ Object

As #create_milestone, but can create multiple milestones in a single request. The milestones parameter must be an array of milestone values as descrbed in #create_milestone.



317
318
319
# File 'lib/basecamp.rb', line 317

def create_milestones(project_id, milestones)
  records "milestone", "/projects/#{project_id}/milestones/create", :milestone => milestones
end

#delete_comment(id) ⇒ Object

Deletes (and returns) the given comment.



225
226
227
# File 'lib/basecamp.rb', line 225

def delete_comment(id)
  record "/msg/delete_comment/#{id}"
end

#delete_item(id) ⇒ Object

Deletes the given item from it’s parent list.



256
257
258
# File 'lib/basecamp.rb', line 256

def delete_item(id)
  record "/todos/delete_item/#{id}"
end

#delete_list(id) ⇒ Object

Deletes the given list and all of its items.



261
262
263
# File 'lib/basecamp.rb', line 261

def delete_list(id)
  record "/todos/delete_list/#{id}"
end

#delete_message(id) ⇒ Object

Deletes the message with the given id, and returns it.



194
195
196
# File 'lib/basecamp.rb', line 194

def delete_message(id)
  record "/msg/delete/#{id}"
end

#delete_milestone(id) ⇒ Object

Destroys the milestone with the given id.



322
323
324
# File 'lib/basecamp.rb', line 322

def delete_milestone(id)
  record "/milestones/delete/#{id}"
end

#delete_time(id, project_id) ⇒ Object



230
231
232
# File 'lib/basecamper.rb', line 230

def delete_time(id, project_id)
  record "/projects/#{project_id}/time/delete_entry/#{id}"
end

#file_categories(project_id) ⇒ Object

Returns the list of file categories for the given project



113
114
115
# File 'lib/basecamp.rb', line 113

def file_categories(project_id)
  records "attachment-category", "/projects/#{project_id}/attachment_categories"
end

#get_list(id) ⇒ Object

Retrieves the specified list, and all of its items.



266
267
268
# File 'lib/basecamp.rb', line 266

def get_list(id)
  record "/todos/list/#{id}"
end

#lists(project_id, complete = nil) ⇒ Object

Return all lists for a project. If complete is true, only completed lists are returned. If complete is false, only uncompleted lists are returned.



272
273
274
# File 'lib/basecamp.rb', line 272

def lists(project_id, complete=nil)
  records "todo-list", "/projects/#{project_id}/todos/lists", :complete => complete
end

#log_time(project_id, person_id, date, hours, description = nil, todo_item_id = nil) ⇒ Object



223
224
225
226
227
228
# File 'lib/basecamper.rb', line 223

def log_time(project_id, person_id, date, hours, description = nil, todo_item_id = nil)
  entry = {"project_id" => project_id, "person_id" => person_id, "date" => date.to_s, "hours" => hours.to_s}
  entry["description"] = description if description
  entry["todo_item_id"] = todo_item_id if todo_item_id
  record "/time/save_entry", :entry => entry
end

#message(*ids) ⇒ Object

Return information about the message(s) with the given id(s). The API limits you to requesting 25 messages at a time, so if you need to get more than that, you’ll need to do it in multiple requests.



138
139
140
141
# File 'lib/basecamp.rb', line 138

def message(*ids)
  result = records("post", "/msg/get/#{ids.join(",")}")
  result.length == 1 ? result.first : result
end

#message_categories(project_id) ⇒ Object

Returns the list of message categories for the given project



108
109
110
# File 'lib/basecamp.rb', line 108

def message_categories(project_id)
  records "post-category", "/projects/#{project_id}/post_categories"
end

#message_list(project_id, category_id = nil) ⇒ Object

Returns a summary of all messages in the given project (and category, if specified). The summary is simply the title and category of the message, as well as the number of attachments (if any).



146
147
148
149
150
151
152
# File 'lib/basecamp.rb', line 146

def message_list(project_id, category_id=nil)
  url = "/projects/#{project_id}/msg"
  url << "/cat/#{category_id}" if category_id
  url << "/archive"
  
  records "post", url
end

#milestones(project_id, find = "all") ⇒ Object

Returns a list of all milestones for the given project, optionally filtered by whether they are completed, late, or upcoming.



328
329
330
# File 'lib/basecamp.rb', line 328

def milestones(project_id, find="all")
  records "milestone", "/projects/#{project_id}/milestones/list", :find => find
end

#move_item(id, to) ⇒ Object

Repositions an item to be at the given position in its list



277
278
279
# File 'lib/basecamp.rb', line 277

def move_item(id, to)
  record "/todos/move_item/#{id}", :to => to
end

#move_list(id, to) ⇒ Object

Repositions a list to be at the given position in its project



282
283
284
# File 'lib/basecamp.rb', line 282

def move_list(id, to)
  record "/todos/move_list/#{id}", :to => to
end

#people(company_id, project_id = nil) ⇒ Object

Return an array of the people in the given company. If the project-id is given, only people who have access to the given project will be returned.



124
125
126
127
128
# File 'lib/basecamp.rb', line 124

def people(company_id, project_id=nil)
  url = project_id ? "/projects/#{project_id}" : ""
  url << "/contacts/people/#{company_id}"
  records "person", url
end

#person(identifier) ⇒ Object

overrides existing #person to accept an ID or a user_name - IDs of 0 will be interpreted as a user_name



131
132
133
# File 'lib/basecamp.rb', line 131

def person(id)
  record "/contacts/person/#{id}"
end

#post_message(project_id, message, notify = [], attachments = []) ⇒ Object

Create a new message in the given project. The message parameter should be a hash. The email_to parameter must be an array of person-id’s that should be notified of the post.

If you want to add attachments to the message, the attachments parameter should be an array of hashes, where each has has a :name key (optional), and a :file key (required). The :file key must refer to a Basecamp::FileUpload instance.

msg = session.post_message(158141,
   { :title => "Requirements",
     :body => "Here are the requirements documents you asked for.",
     :category_id => 2301121 },
   [john.id, martha.id],
   [ { :name => "Primary Requirements",
       :file => Basecamp::FileUpload.new('primary.doc", File.read('primary.doc')) },
     { :file => Basecamp::FileUpload.new('other.doc', File.read('other.doc')) } ])


171
172
173
174
175
176
177
# File 'lib/basecamp.rb', line 171

def post_message(project_id, message, notify=[], attachments=[])
  prepare_attachments(attachments)
  record "/projects/#{project_id}/msg/create",
    :post => message,
    :notify => notify,
    :attachments => attachments
end

#projectsObject

Return the list of all accessible projects.



103
104
105
# File 'lib/basecamp.rb', line 103

def projects
  records "project", "/project/list"
end

#record(path, parameters = {}) ⇒ Object

A convenience method for wrapping the result of a query in a Record object. This assumes that the result is a singleton, not a collection.



368
369
370
371
# File 'lib/basecamp.rb', line 368

def record(path, parameters={})
  result = request(path, parameters)
  (result && !result.empty?) ? Record.new(result.keys.first, result.values.first) : nil
end

#records(node, path, parameters = {}) ⇒ Object

A convenience method for wrapping the result of a query in Record objects. This assumes that the result is a collection–any singleton result will be wrapped in an array.



376
377
378
379
380
381
# File 'lib/basecamp.rb', line 376

def records(node, path, parameters={})
  result = request(path, parameters).values.first or return []
  result = result[node] or return []
  result = [result] unless Array === result
  result.map { |row| Record.new(node, row) }
end

#request(path, parameters = {}, second_try = false) ⇒ Object

Make a raw web-service request to Basecamp. This will return a Hash of Arrays of the response, and may seem a little odd to the uninitiated.



346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
# File 'lib/basecamp.rb', line 346

def request(path, parameters = {}, second_try = false)
  response = post(path, convert_body(parameters), "Content-Type" => content_type)
  
  if DEBUG
    puts "Reponse:"
    puts response.body
  end
  
  if response.code.to_i / 100 == 2
    result = XmlSimple.xml_in(response.body, 'keeproot' => true,
      'contentkey' => '__content__', 'forcecontent' => true)
    typecast_value(result)
  elsif response.code == "302" && !second_try
    connect!(@url, !@use_ssl)
    request(path, parameters, true)
  else
    raise "#{response.message} (#{response.code})"
  end
end

#test_authObject

tests credentials



255
256
257
258
259
260
261
262
# File 'lib/basecamper.rb', line 255

def test_auth
  begin
    projects
    true
  rescue
    false
  end
end

#uncomplete_item(id) ⇒ Object

Marks the given item uncompleted.



239
240
241
# File 'lib/basecamp.rb', line 239

def uncomplete_item(id)
  record "/todos/uncomplete_item/#{id}"
end

#uncomplete_milestone(id) ⇒ Object

Uncomplete the milestone with the given id



333
334
335
# File 'lib/basecamp.rb', line 333

def uncomplete_milestone(id)
  record "/milestones/uncomplete/#{id}"
end

#update_comment(id, comment, attachments = []) ⇒ Object

Update the given comment. Attachments follow the same format as #post_message.



218
219
220
221
222
# File 'lib/basecamp.rb', line 218

def update_comment(id, comment, attachments=[])
  prepare_attachments(attachments)
  record "/msg/update_comment", :comment_id => id,
    :comment => comment, :attachments => attachments
end

#update_item(id, content, responsible_party = nil, notify = true) ⇒ Object

Updates the given item



287
288
289
290
291
# File 'lib/basecamp.rb', line 287

def update_item(id, content, responsible_party=nil, notify=true)
  record "/todos/update_item/#{id}",
    :item => { :content => content }, :responsible_party => responsible_party,
    :notify => notify
end

#update_list(id, list) ⇒ Object

Updates the given list’s metadata



294
295
296
# File 'lib/basecamp.rb', line 294

def update_list(id, list)
  record "/todos/update_list/#{id}", :list => list
end

#update_message(id, message, notify = [], attachments = []) ⇒ Object

Edit the message with the given id. The message parameter should be a hash. The email_to parameter must be an array of person-id’s that should be notified of the post.

The attachments parameter, if used, should be the same as described for #post_message.



185
186
187
188
189
190
191
# File 'lib/basecamp.rb', line 185

def update_message(id, message, notify=[], attachments=[])
  prepare_attachments(attachments)
  record "/msg/update/#{id}",
    :post => message,
    :notify => notify,
    :attachments => attachments
end

#update_milestone(id, data, move = false, move_off_weekends = false) ⇒ Object

Updates an existing milestone.



338
339
340
341
342
# File 'lib/basecamp.rb', line 338

def update_milestone(id, data, move=false, move_off_weekends=false)
  record "/milestones/update/#{id}", :milestone => data,
    :move_upcoming_milestones => move,
    :move_upcoming_milestones_off_weekends => move_off_weekends
end