turingstudio-basecamp-rb 0.0.1 → 0.0.2
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/Rakefile +21 -0
- data/lib/basecamp/attachment.rb +23 -23
- data/lib/basecamp/attachment_category.rb +10 -0
- data/lib/basecamp/base.rb +5 -109
- data/lib/basecamp/company.rb +10 -0
- data/lib/basecamp/message.rb +24 -22
- data/lib/basecamp/milestone.rb +50 -0
- data/lib/basecamp/person.rb +18 -0
- data/lib/basecamp/post_category.rb +10 -0
- data/lib/basecamp/project.rb +22 -0
- data/lib/basecamp/record.rb +42 -13
- data/lib/basecamp/resource.rb +9 -9
- data/lib/basecamp/time_entry.rb +11 -9
- data/lib/basecamp/todoitem.rb +6 -6
- data/lib/basecamp/todolist.rb +16 -14
- data/lib/basecamp/version.rb +1 -1
- data/lib/basecamp.rb +7 -1
- data/spec/lib/basecamp/attachment_category_spec.rb +12 -0
- data/spec/lib/basecamp/attachment_spec.rb +26 -0
- data/spec/lib/basecamp/base_spec.rb +44 -0
- data/spec/lib/basecamp/company_spec.rb +13 -0
- data/spec/lib/basecamp/message_spec.rb +45 -0
- data/spec/lib/basecamp/milestone_spec.rb +44 -0
- data/spec/lib/basecamp/person_spec.rb +18 -0
- data/spec/lib/basecamp/post_category_spec.rb +13 -0
- data/spec/lib/basecamp/project_spec.rb +12 -0
- data/spec/lib/basecamp/record_spec.rb +57 -0
- data/spec/lib/basecamp/time_entry_spec.rb +23 -0
- data/spec/lib/basecamp/todo_item_spec.rb +38 -0
- data/spec/lib/basecamp/todo_list_spec.rb +36 -0
- data/spec/spec_helper.rb +68 -1
- metadata +44 -18
- data/spec/basecamp_spec.rb +0 -61
- data/spec/lib/basecamp_base.rb +0 -75
- data/spec/lib/basecamp_message_spec.rb +0 -42
- data/spec/lib/basecamp_todo_item_spec.rb +0 -40
- data/spec/lib/basecamp_todo_list_spec.rb +0 -32
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
%w[rubygems rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
2
|
+
require File.dirname(__FILE__) + '/lib/basecamp/version'
|
3
|
+
|
4
|
+
# Generate all the Rake tasks
|
5
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
6
|
+
$hoe = Hoe.new('basecamp-rb', Basecamp::VERSION) do |p|
|
7
|
+
p.developer('The Turing Studio, Inc.', 'support@turingstudio.com')
|
8
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
9
|
+
p.extra_deps = [
|
10
|
+
['xml-simple','>= 1.0.11'],
|
11
|
+
['activesupport','>= 2.2.2'],
|
12
|
+
['activeresource','>= 2.2.2']
|
13
|
+
]
|
14
|
+
p.extra_dev_deps = [
|
15
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
16
|
+
]
|
17
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
18
|
+
end
|
19
|
+
|
20
|
+
require 'newgem/tasks'
|
21
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
data/lib/basecamp/attachment.rb
CHANGED
@@ -1,28 +1,20 @@
|
|
1
|
+
# === Attaching Files to a Resource
|
2
|
+
#
|
3
|
+
# If the resource accepts file attachments, the +attachments+ parameter should
|
4
|
+
# be an array of Basecamp::Attachment objects. Example:
|
5
|
+
#
|
6
|
+
# a1 = Basecamp::Atachment.create('primary', File.read('primary.doc'))
|
7
|
+
# a2 = Basecamp::Atachment.create('another', File.read('another.doc'))
|
8
|
+
#
|
9
|
+
# m = Basecamp::Message.new(:project_id => 1037)
|
10
|
+
# ...
|
11
|
+
# m.attachments = [a1, a2]
|
12
|
+
# m.save # => true
|
13
|
+
#
|
1
14
|
module Basecamp
|
2
|
-
class Attachment
|
3
|
-
|
4
|
-
# === Attaching Files to a Resource
|
5
|
-
#
|
6
|
-
# If the resource accepts file attachments, the +attachments+ parameter should
|
7
|
-
# be an array of Basecamp::Attachment objects. Example:
|
8
|
-
#
|
9
|
-
# a1 = Basecamp::Atachment.create('primary', File.read('primary.doc'))
|
10
|
-
# a2 = Basecamp::Atachment.create('another', File.read('another.doc'))
|
11
|
-
#
|
12
|
-
# m = Basecamp::Message.new(:project_id => 1037)
|
13
|
-
# ...
|
14
|
-
# m.attachments = [a1, a2]
|
15
|
-
# m.save # => true
|
16
|
-
#
|
17
|
-
|
15
|
+
class Attachment
|
18
16
|
attr_accessor :id, :filename, :content, :content_type
|
19
|
-
|
20
|
-
def self.create(filename, content)
|
21
|
-
returning new(filename, content) do |attachment|
|
22
|
-
attachment.save
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
17
|
+
|
26
18
|
def initialize(filename, content, content_type = 'application/octet-stream')
|
27
19
|
@filename, @content, @content_type = filename, content, content_type
|
28
20
|
end
|
@@ -49,5 +41,13 @@ module Basecamp
|
|
49
41
|
raise "Could not save attachment: #{response.message} (#{response.code})"
|
50
42
|
end
|
51
43
|
end
|
44
|
+
|
45
|
+
class << self
|
46
|
+
def create(filename, content)
|
47
|
+
returning new(filename, content) do |attachment|
|
48
|
+
attachment.save
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
52
|
end
|
53
53
|
end
|
data/lib/basecamp/base.rb
CHANGED
@@ -26,128 +26,24 @@ module Basecamp
|
|
26
26
|
@use_xml = false
|
27
27
|
end
|
28
28
|
|
29
|
-
# ==========================================================================
|
30
|
-
# GENERAL
|
31
|
-
# ==========================================================================
|
32
|
-
|
33
|
-
# Return the list of all accessible projects
|
34
|
-
def projects
|
35
|
-
records "project", "/project/list"
|
36
|
-
end
|
37
|
-
|
38
|
-
# Returns the list of message categories for the given project
|
39
|
-
def message_categories(project_id)
|
40
|
-
records "post-category", "/projects/#{project_id}/post_categories"
|
41
|
-
end
|
42
|
-
|
43
|
-
# Returns the list of file categories for the given project
|
44
|
-
def file_categories(project_id)
|
45
|
-
records "attachment-category", "/projects/#{project_id}/attachment_categories"
|
46
|
-
end
|
47
|
-
|
48
|
-
# ==========================================================================
|
49
|
-
# CONTACT MANAGEMENT
|
50
|
-
# ==========================================================================
|
51
|
-
|
52
|
-
# Return information for the company with the given id
|
53
|
-
def company(id)
|
54
|
-
record "/contacts/company/#{id}"
|
55
|
-
end
|
56
|
-
|
57
|
-
# Return an array of the people in the given company. If the project-id is
|
58
|
-
# given, only people who have access to the given project will be returned.
|
59
|
-
def people(company_id, project_id=nil)
|
60
|
-
url = project_id ? "/projects/#{project_id}" : ""
|
61
|
-
url << "/contacts/people/#{company_id}"
|
62
|
-
records "person", url
|
63
|
-
end
|
64
|
-
|
65
|
-
# Return information about the person with the given id
|
66
|
-
def person(id)
|
67
|
-
record "/contacts/person/#{id}"
|
68
|
-
end
|
69
|
-
|
70
|
-
# ==========================================================================
|
71
|
-
# MILESTONES
|
72
|
-
# ==========================================================================
|
73
|
-
|
74
|
-
# Complete the milestone with the given id
|
75
|
-
def complete_milestone(id)
|
76
|
-
record "/milestones/complete/#{id}"
|
77
|
-
end
|
78
|
-
|
79
|
-
# Create a new milestone for the given project. +data+ must be hash of the
|
80
|
-
# values to set, including +title+, +deadline+, +responsible_party+, and
|
81
|
-
# +notify+.
|
82
|
-
def create_milestone(project_id, data)
|
83
|
-
create_milestones(project_id, [data]).first
|
84
|
-
end
|
85
|
-
|
86
|
-
# As #create_milestone, but can create multiple milestones in a single
|
87
|
-
# request. The +milestones+ parameter must be an array of milestone values as
|
88
|
-
# descrbed in #create_milestone.
|
89
|
-
def create_milestones(project_id, milestones)
|
90
|
-
records "milestone", "/projects/#{project_id}/milestones/create", :milestone => milestones
|
91
|
-
end
|
92
|
-
|
93
|
-
# Destroys the milestone with the given id.
|
94
|
-
def delete_milestone(id)
|
95
|
-
record "/milestones/delete/#{id}"
|
96
|
-
end
|
97
|
-
|
98
|
-
# Returns a list of all milestones for the given project, optionally filtered
|
99
|
-
# by whether they are completed, late, or upcoming.
|
100
|
-
def milestones(project_id, find="all")
|
101
|
-
records "milestone", "/projects/#{project_id}/milestones/list", :find => find
|
102
|
-
end
|
103
|
-
|
104
|
-
# Uncomplete the milestone with the given id
|
105
|
-
def uncomplete_milestone(id)
|
106
|
-
record "/milestones/uncomplete/#{id}"
|
107
|
-
end
|
108
|
-
|
109
|
-
# Updates an existing milestone.
|
110
|
-
def update_milestone(id, data, move=false, move_off_weekends=false)
|
111
|
-
record "/milestones/update/#{id}", :milestone => data,
|
112
|
-
:move_upcoming_milestones => move,
|
113
|
-
:move_upcoming_milestones_off_weekends => move_off_weekends
|
114
|
-
end
|
115
|
-
|
116
|
-
private
|
117
|
-
|
118
29
|
# Make a raw web-service request to Basecamp. This will return a Hash of
|
119
30
|
# Arrays of the response, and may seem a little odd to the uninitiated.
|
120
31
|
def request(path, parameters = {})
|
121
32
|
response = Base.connection.post(path, convert_body(parameters), "Content-Type" => content_type)
|
122
|
-
|
33
|
+
|
123
34
|
if response.code.to_i / 100 == 2
|
124
35
|
result = XmlSimple.xml_in(response.body, 'keeproot' => true, 'contentkey' => '__content__', 'forcecontent' => true)
|
125
|
-
typecast_value(result)
|
36
|
+
typecast_value(result)
|
126
37
|
else
|
127
38
|
raise "#{response.message} (#{response.code})"
|
128
39
|
end
|
129
40
|
end
|
130
41
|
|
131
|
-
|
132
|
-
|
133
|
-
def record(path, parameters={})
|
134
|
-
result = request(path, parameters)
|
135
|
-
(result && !result.empty?) ? Record.new(result.keys.first, result.values.first) : nil
|
136
|
-
end
|
137
|
-
|
138
|
-
# A convenience method for wrapping the result of a query in Record
|
139
|
-
# objects. This assumes that the result is a collection--any singleton
|
140
|
-
# result will be wrapped in an array.
|
141
|
-
def records(node, path, parameters={})
|
142
|
-
result = request(path, parameters).values.first or return []
|
143
|
-
result = result[node] or return []
|
144
|
-
result = [result] unless Array === result
|
145
|
-
result.map { |row| Record.new(node, row) }
|
146
|
-
end
|
147
|
-
|
42
|
+
private
|
43
|
+
|
148
44
|
def convert_body(body)
|
149
45
|
body = use_xml ? body.to_legacy_xml : body.to_yaml
|
150
|
-
end
|
46
|
+
end
|
151
47
|
|
152
48
|
def content_type
|
153
49
|
use_xml ? "application/xml" : "application/x-yaml"
|
data/lib/basecamp/message.rb
CHANGED
@@ -3,30 +3,32 @@ module Basecamp
|
|
3
3
|
parent_resources :project
|
4
4
|
self.element_name = 'post'
|
5
5
|
|
6
|
-
# Returns the most recent 25 messages in the given project (and category,
|
7
|
-
# if specified). If you need to retrieve older messages, use the archive
|
8
|
-
# method instead. Example:
|
9
|
-
#
|
10
|
-
# Basecamp::Message.list(1037)
|
11
|
-
# Basecamp::Message.list(1037, :category_id => 7301)
|
12
|
-
#
|
13
|
-
def self.list(project_id, options = {})
|
14
|
-
find(:all, :params => options.merge(:project_id => project_id))
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns a summary of all messages in the given project (and category, if
|
18
|
-
# specified). The summary is simply the title and category of the message,
|
19
|
-
# as well as the number of attachments (if any). Example:
|
20
|
-
#
|
21
|
-
# Basecamp::Message.archive(1037)
|
22
|
-
# Basecamp::Message.archive(1037, :category_id => 7301)
|
23
|
-
#
|
24
|
-
def self.archive(project_id, options = {})
|
25
|
-
find(:all, :params => options.merge(:project_id => project_id), :from => :archive)
|
26
|
-
end
|
27
|
-
|
28
6
|
def comments(options = {})
|
29
7
|
@comments ||= Comment.find(:all, :params => options.merge(:post_id => id))
|
30
8
|
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
# Returns the most recent 25 messages in the given project (and category,
|
12
|
+
# if specified). If you need to retrieve older messages, use the archive
|
13
|
+
# method instead. Example:
|
14
|
+
#
|
15
|
+
# Basecamp::Message.list(1037)
|
16
|
+
# Basecamp::Message.list(1037, :category_id => 7301)
|
17
|
+
#
|
18
|
+
def list(project_id, options = {})
|
19
|
+
find(:all, :params => options.merge(:project_id => project_id))
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns a summary of all messages in the given project (and category, if
|
23
|
+
# specified). The summary is simply the title and category of the message,
|
24
|
+
# as well as the number of attachments (if any). Example:
|
25
|
+
#
|
26
|
+
# Basecamp::Message.archive(1037)
|
27
|
+
# Basecamp::Message.archive(1037, :category_id => 7301)
|
28
|
+
#
|
29
|
+
def archive(project_id, options = {})
|
30
|
+
find(:all, :params => options.merge(:project_id => project_id), :from => :archive)
|
31
|
+
end
|
32
|
+
end
|
31
33
|
end
|
32
34
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
module Basecamp
|
2
|
+
class Milestone < Record
|
3
|
+
# Updates an existing milestone.
|
4
|
+
def update_attributes(params = {})
|
5
|
+
data = params.dup
|
6
|
+
move = data.delete :move
|
7
|
+
move_off_weekends = data.delete :move_off_weekends
|
8
|
+
record "/milestones/update/#{id}",
|
9
|
+
:milestone => data,
|
10
|
+
:move_upcoming_milestones => move,
|
11
|
+
:move_upcoming_milestones_off_weekends => move_off_weekends
|
12
|
+
end
|
13
|
+
|
14
|
+
# Destroys the milestone
|
15
|
+
def destroy
|
16
|
+
record "/milestones/delete/#{id}"
|
17
|
+
end
|
18
|
+
|
19
|
+
# Complete the milestone
|
20
|
+
def complete!
|
21
|
+
record "/milestones/complete/#{id}"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Uncomplete the milestone
|
25
|
+
def uncomplete!
|
26
|
+
record "/milestones/uncomplete/#{id}"
|
27
|
+
end
|
28
|
+
|
29
|
+
class << self
|
30
|
+
def list(project_id, find = "all")
|
31
|
+
records "/projects/#{project_id}/milestones/list", :find => find
|
32
|
+
end
|
33
|
+
|
34
|
+
# Create a new milestone for the given project. +data+ must be hash of the
|
35
|
+
# values to set, including +title+, +deadline+, +responsible_party+, and
|
36
|
+
# +notify+.
|
37
|
+
def create(project_id, data = {})
|
38
|
+
create_milestones(project_id, [data]).first
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
# As #create_milestone, but can create multiple milestones in a single
|
43
|
+
# request. The +milestones+ parameter must be an array of milestone values as
|
44
|
+
# descrbed in #create_milestone.
|
45
|
+
def create_milestones(project_id, milestones)
|
46
|
+
records "/projects/#{project_id}/milestones/create", :milestone => milestones
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Basecamp
|
2
|
+
class Person < Record
|
3
|
+
class << self
|
4
|
+
# Return an array of the people in the given company. If the project-id is
|
5
|
+
# given, only people who have access to the given project will be returned.
|
6
|
+
def list(company_id, project_id = nil)
|
7
|
+
url = project_id ? "/projects/#{project_id}" : ""
|
8
|
+
url << "/contacts/people/#{company_id}"
|
9
|
+
records url
|
10
|
+
end
|
11
|
+
|
12
|
+
# Return information about the person with the given id
|
13
|
+
def find(id)
|
14
|
+
record "/contacts/person/#{id}"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Basecamp
|
2
|
+
class Project < Record
|
3
|
+
class << self
|
4
|
+
# Return the list of all accessible projects
|
5
|
+
def list
|
6
|
+
records "/project/list"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
# def messages(options = {})
|
11
|
+
# Message.list(id, options)
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# def message_archive(options = {})
|
15
|
+
# @message_archive ||= Message.archive(id, options)
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# def milestones(find="all")
|
19
|
+
# Milestone.list(id, find)
|
20
|
+
# end
|
21
|
+
end
|
22
|
+
end
|
data/lib/basecamp/record.rb
CHANGED
@@ -1,20 +1,22 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class Record #:nodoc:
|
3
3
|
attr_reader :type
|
4
|
-
|
5
|
-
def initialize(
|
6
|
-
|
4
|
+
|
5
|
+
def initialize(hash)
|
6
|
+
# type = self.class.to_s
|
7
|
+
@hash = hash
|
7
8
|
end
|
8
9
|
|
9
10
|
def [](name)
|
10
|
-
name =
|
11
|
+
name = name.to_s.dasherize
|
11
12
|
|
12
13
|
case @hash[name]
|
13
14
|
when Hash then
|
15
|
+
puts @hash[name].inspect
|
14
16
|
@hash[name] = if (@hash[name].keys.length == 1 && @hash[name].values.first.is_a?(Array))
|
15
|
-
@hash[name].values.first.map { |v|
|
17
|
+
@hash[name].values.first.map { |v| self.class.new_with_type(@hash[name].keys.first, v) }
|
16
18
|
else
|
17
|
-
|
19
|
+
self.class.new_with_type(name, @hash[name])
|
18
20
|
end
|
19
21
|
else
|
20
22
|
@hash[name]
|
@@ -30,7 +32,7 @@ module Basecamp
|
|
30
32
|
end
|
31
33
|
|
32
34
|
def respond_to?(sym)
|
33
|
-
super || @hash.has_key?(
|
35
|
+
super || @hash.has_key?(sym.to_s.dasherize)
|
34
36
|
end
|
35
37
|
|
36
38
|
def method_missing(sym, *args)
|
@@ -42,17 +44,44 @@ module Basecamp
|
|
42
44
|
end
|
43
45
|
|
44
46
|
def to_s
|
45
|
-
"\#<Record(#{
|
47
|
+
"\#<Record(#{self.class}) #{@hash.inspect[1..-2]}>"
|
46
48
|
end
|
47
49
|
|
48
50
|
def inspect
|
49
51
|
to_s
|
50
52
|
end
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
def
|
55
|
-
|
54
|
+
# A convenience method for wrapping the result of a query in a Record
|
55
|
+
# object. This assumes that the result is a singleton, not a collection.
|
56
|
+
def record(path, parameters = {})
|
57
|
+
self.class.record(path, parameters)
|
56
58
|
end
|
57
|
-
|
59
|
+
|
60
|
+
class << self
|
61
|
+
def new_with_type(type, hash)
|
62
|
+
"Basecamp::#{type.classify}".constantize.new(hash)
|
63
|
+
end
|
64
|
+
|
65
|
+
def record(path, parameters = {})
|
66
|
+
result = Basecamp::Base.new.request(path, parameters)
|
67
|
+
(result && !result.empty?) ? new(result.values.first) : nil
|
68
|
+
end
|
69
|
+
|
70
|
+
# A convenience method for wrapping the result of a query in Record
|
71
|
+
# objects. This assumes that the result is a collection--any singleton
|
72
|
+
# result will be wrapped in an array.
|
73
|
+
def records(path, parameters = {})
|
74
|
+
result = Basecamp::Base.new.request(path, parameters)
|
75
|
+
node_singular = name.demodulize.underscore.dasherize
|
76
|
+
node_plural = node_singular.pluralize
|
77
|
+
|
78
|
+
# FIX: rename FileCategory class to AttachmentCategory
|
79
|
+
# node_plural = 'attachment-categories' if node_plural == 'file-categories'
|
80
|
+
|
81
|
+
result = result[node_plural][node_singular] or return []
|
82
|
+
result = [result] unless Array === result
|
83
|
+
result.map { |row| new(row) }
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
58
87
|
end
|
data/lib/basecamp/resource.rb
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class Resource < ActiveResource::Base #:nodoc:
|
3
|
+
def prefix_options
|
4
|
+
id ? {} : super
|
5
|
+
end
|
6
|
+
|
3
7
|
class << self
|
4
8
|
def parent_resources(*parents)
|
5
9
|
@parent_resources = parents
|
6
10
|
end
|
7
|
-
|
11
|
+
|
8
12
|
def element_name
|
9
13
|
name.split(/::/).last.underscore
|
10
14
|
end
|
11
|
-
|
15
|
+
|
12
16
|
def prefix_source
|
13
17
|
@parent_resources.map { |resource| "/#{resource.to_s.pluralize}/:#{resource}_id/" }.join
|
14
18
|
end
|
15
|
-
|
19
|
+
|
16
20
|
def prefix(options={})
|
17
21
|
if options.any?
|
18
22
|
options.map { |name, value| "/#{name.to_s.chomp('_id').pluralize}/#{value}/" }.join
|
19
23
|
else
|
20
|
-
|
24
|
+
'/'
|
21
25
|
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def prefix_options
|
26
|
-
id ? {} : super
|
26
|
+
end
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
data/lib/basecamp/time_entry.rb
CHANGED
@@ -1,17 +1,19 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class TimeEntry < Resource
|
3
3
|
parent_resources :project, :todo_item
|
4
|
-
|
5
|
-
def
|
6
|
-
|
4
|
+
|
5
|
+
def todo_item(options={})
|
6
|
+
@todo_item ||= todo_item_id && TodoItem.find(todo_item_id, options)
|
7
7
|
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
def all(project_id, page=0)
|
11
|
+
find(:all, :params => { :project_id => project_id, :page => page })
|
12
|
+
end
|
8
13
|
|
9
|
-
|
10
|
-
|
14
|
+
def report(options={})
|
15
|
+
find(:all, :from => :report, :params => options)
|
16
|
+
end
|
11
17
|
end
|
12
|
-
|
13
|
-
def todo_item(options={})
|
14
|
-
@todo_item ||= todo_item_id && TodoItem.find(todo_item_id, options)
|
15
|
-
end
|
16
18
|
end
|
17
19
|
end
|
data/lib/basecamp/todoitem.rb
CHANGED
@@ -1,23 +1,23 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class TodoItem < Resource
|
3
3
|
parent_resources :todo_list
|
4
|
-
|
4
|
+
|
5
5
|
def todo_list(options={})
|
6
|
-
@todo_list ||= TodoList.find(todo_list_id, options)
|
6
|
+
@todo_list ||= TodoList.find(self.todo_list_id, options)
|
7
7
|
end
|
8
|
-
|
8
|
+
|
9
9
|
def time_entries(options={})
|
10
10
|
@time_entries ||= TimeEntry.find(:all, :params => options.merge(:todo_item_id => id))
|
11
11
|
end
|
12
|
-
|
12
|
+
|
13
13
|
def comments(options = {})
|
14
14
|
@comments ||= Comment.find(:all, :params => options.merge(:todo_item_id => id))
|
15
15
|
end
|
16
|
-
|
16
|
+
|
17
17
|
def complete!
|
18
18
|
put(:complete)
|
19
19
|
end
|
20
|
-
|
20
|
+
|
21
21
|
def uncomplete!
|
22
22
|
put(:uncomplete)
|
23
23
|
end
|
data/lib/basecamp/todolist.rb
CHANGED
@@ -1,22 +1,24 @@
|
|
1
1
|
module Basecamp
|
2
2
|
class TodoList < Resource
|
3
3
|
parent_resources :project
|
4
|
-
|
5
|
-
# Returns all lists for a project. If complete is true, only completed lists
|
6
|
-
# are returned. If complete is false, only uncompleted lists are returned.
|
7
|
-
def self.all(project_id, complete=nil)
|
8
|
-
filter = case complete
|
9
|
-
when nil then "all"
|
10
|
-
when true then "finished"
|
11
|
-
when false then "pending"
|
12
|
-
else raise ArgumentError, "invalid value for `complete'"
|
13
|
-
end
|
14
|
-
|
15
|
-
find(:all, :params => { :project_id => project_id, :filter => filter })
|
16
|
-
end
|
17
|
-
|
4
|
+
|
18
5
|
def todo_items(options={})
|
19
6
|
@todo_items ||= TodoItem.find(:all, :params => options.merge(:todo_list_id => id))
|
20
7
|
end
|
8
|
+
|
9
|
+
class << self
|
10
|
+
# Returns all lists for a project. If complete is true, only completed lists
|
11
|
+
# are returned. If complete is false, only uncompleted lists are returned.
|
12
|
+
def all(project_id, complete=nil)
|
13
|
+
filter = case complete
|
14
|
+
when nil then "all"
|
15
|
+
when true then "finished"
|
16
|
+
when false then "pending"
|
17
|
+
else raise ArgumentError, "invalid value for `complete'"
|
18
|
+
end
|
19
|
+
|
20
|
+
find(:all, :params => { :project_id => project_id, :filter => filter })
|
21
|
+
end
|
22
|
+
end
|
21
23
|
end
|
22
24
|
end
|
data/lib/basecamp/version.rb
CHANGED
data/lib/basecamp.rb
CHANGED
@@ -8,11 +8,17 @@ require 'activeresource'
|
|
8
8
|
|
9
9
|
require 'basecamp/base'
|
10
10
|
require 'basecamp/resource'
|
11
|
+
require 'basecamp/record'
|
11
12
|
require 'basecamp/attachment'
|
12
13
|
require 'basecamp/comment'
|
14
|
+
require 'basecamp/company'
|
13
15
|
require 'basecamp/connection'
|
16
|
+
require 'basecamp/file_category'
|
14
17
|
require 'basecamp/message'
|
15
|
-
require 'basecamp/
|
18
|
+
require 'basecamp/milestone'
|
19
|
+
require 'basecamp/project'
|
20
|
+
require 'basecamp/person'
|
21
|
+
require 'basecamp/post_category'
|
16
22
|
require 'basecamp/time_entry'
|
17
23
|
require 'basecamp/todoitem'
|
18
24
|
require 'basecamp/todolist'
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../../spec_helper.rb'
|
2
|
+
|
3
|
+
describe Basecamp::AttachmentCategory do
|
4
|
+
before(:each) do
|
5
|
+
establish_connection
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return the list of file categories for the given project" do
|
9
|
+
list = Basecamp::AttachmentCategory.list(TEST_PROJECT_ID)
|
10
|
+
list.should be_kind_of(Array)
|
11
|
+
end
|
12
|
+
end
|