asana 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,5 +1,7 @@
1
1
  *.gem
2
2
  *.rbc
3
+ *.un~
4
+ .DS_Store
3
5
  .bundle
4
6
  .config
5
7
  .yardoc
@@ -11,9 +13,8 @@ doc/
11
13
  lib/bundler/man
12
14
  pkg
13
15
  rdoc
16
+ spec/fixtures/cassettes
14
17
  spec/reports
15
18
  test/tmp
16
19
  test/version_tmp
17
20
  tmp
18
- .DS_Store
19
- *.un~
@@ -0,0 +1,5 @@
1
+ guard 'minitest' do
2
+ watch(%r|^lib/(.*/)?([^/]+)\.rb$|) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
3
+ watch(%r|^spec/spec_helper\.rb|) { "spec" }
4
+ watch(%r|^spec/(.*)\/?(.*)_spec\.rb|)
5
+ end
data/README.md CHANGED
@@ -1,6 +1,10 @@
1
1
  # Asana
2
2
 
3
- TODO: Write a gem description
3
+ This gem is a simple Ruby wrapper for the Asana REST API. It uses
4
+ [ActiveResource][] to provide a simple, familiar interface for accessing
5
+ your Asana account.
6
+
7
+ To learn more, check out the [Asana API Documentation][].
4
8
 
5
9
  ## Installation
6
10
 
@@ -18,7 +22,140 @@ Or install it yourself as:
18
22
 
19
23
  ## Usage
20
24
 
21
- TODO: Write usage instructions here
25
+ In order to access Asana, you need to provide your [API key][].
26
+
27
+
28
+ ```ruby
29
+ Asana.configure do |client|
30
+ client.api_key = 'your_asana_api_key'
31
+ end
32
+ ```
33
+
34
+ As a sanity check, you can fetch the object representing your user.
35
+
36
+ ```ruby
37
+ Asana::User.me
38
+ ```
39
+
40
+ ### [Users][]
41
+
42
+ > A user object represents an account in Asana that can be given access to
43
+ > various workspaces, projects, and tasks.
44
+ >
45
+ > Like other objects in the system, users are referred to by numerical IDs.
46
+ > However, the special string identifier me can be used anywhere a user ID is
47
+ > accepted, to refer to the current authenticated user.
48
+
49
+ **Note:** It is not possible to create, update, or delete a user from
50
+ the API.
51
+
52
+ ```ruby
53
+ # Get users from all of your workspaces
54
+ users = Asana::User.all
55
+
56
+ # Get a specific user
57
+ user = Asana::User.find(:id)
58
+
59
+ # Get the user associated with the API key being used
60
+ user = Asana::User.me
61
+
62
+ # Get all users in a given workspace
63
+ workspace = Asana::Workspace.find(:workspace_id)
64
+ users = workspace.users
65
+ ```
66
+
67
+ ### [Workspaces][]
68
+
69
+ > A workspace is the most basic organizational unit in Asana. All projects
70
+ > and tasks have an associated workspace.
71
+
72
+ **Note:** It is not possible to create or delete a workspace from the API.
73
+
74
+ ```ruby
75
+ # Get all workspaces
76
+ workspaces = Asana::Workspace.all
77
+
78
+ # Get a specific workspace
79
+ workspace = Asana::Workspace.find(:id)
80
+
81
+ # Get all projects in a given workspace
82
+ projects = workspace.projects
83
+
84
+ # Get all tasks in a given workspace and assigned to the given user
85
+ tasks = workspace.tasks(:user_id)
86
+
87
+ # Get all users with access to a given workspace
88
+ users = workspace.users
89
+
90
+ # Create a new task in a given workspace and assign it to the current user
91
+ workspace.create_task(task_settings)
92
+ ```
93
+
94
+ ### [Projects][]
95
+
96
+ > A project represents a prioritized list of tasks in Asana. It exists in a
97
+ > single workspace and is accessible to a subset of users in that workspace
98
+ > depending on its permissions.
99
+
100
+ **Note:** It is not possible to create a project from the API.
101
+
102
+ ```ruby
103
+ # Get all projects
104
+ projects = Asana::Project.all
105
+
106
+ # Get a specific project
107
+ project = Asana::Project.find(:id)
108
+
109
+ # Get all projects in a given workspace
110
+ workspace = Asana::Workspace.find(:workspace_id)
111
+ projects = workspace.projects
112
+ ```
113
+
114
+ ### [Tasks][]
115
+
116
+ > The task is the basic object around which many operations in Asana are
117
+ > centered. In the Asana application, multiple tasks populate the middle
118
+ > pane according to some view parameters, and the set of selected tasks
119
+ > determine the more detailed information presented in the details pane.
120
+
121
+ ```ruby
122
+ # Get all tasks in a given project
123
+ project = Asana::Project(:project_id)
124
+ tasks = project.tasks
125
+
126
+ # Get all tasks in a given workspace
127
+ workspace = Asana::Workspace(:workspace_id)
128
+ tasks = workspace.tasks
129
+
130
+ # Get all stories for a given task
131
+ task = tasks.first
132
+ stories = task.stories
133
+
134
+ # Create a new task in a given workspace and assign it to the current user
135
+ workspace.create_task(task_settings)
136
+
137
+ # Create a new story for the given task
138
+ task.create_story(story_settings)
139
+ ```
140
+
141
+ ### [Stories][]
142
+
143
+ > A story represents an activity associated with an object in the Asana
144
+ > system. Stories are generated by the system whenever users take actions
145
+ > such as creating or assigning tasks, or moving tasks between projects.
146
+ > Comments are also a form of user-generated story.
147
+
148
+ **Note:** It is not possible to update a story from the API.
149
+
150
+ ```ruby
151
+ # Get all stories for a given task
152
+ project = Asana::Project(:project_id)
153
+ task = project.tasks.first
154
+ stories = task.stories
155
+
156
+ # Create a new story for the given task
157
+ task.create_story(story_settings)
158
+ ```
22
159
 
23
160
  ## Contributing
24
161
 
@@ -27,3 +164,12 @@ TODO: Write usage instructions here
27
164
  3. Commit your changes (`git commit -am 'Added some feature'`)
28
165
  4. Push to the branch (`git push origin my-new-feature`)
29
166
  5. Create new Pull Request
167
+
168
+ [API key]: http://app.asana.com/-/account_api
169
+ [ActiveResource]: http://api.rubyonrails.org/classes/ActiveResource/Base.html
170
+ [Asana API Documentation]: http://developer.asana.com/documentation/
171
+ [Users]: http://developer.asana.com/documentation/#users
172
+ [Workspaces]: http://developer.asana.com/documentation/#workspaces
173
+ [Projects]: http://developer.asana.com/documentation/#projects
174
+ [Tasks]: http://developer.asana.com/documentation/#tasks
175
+ [Stories]: http://developer.asana.com/documentation/#stories
@@ -10,6 +10,12 @@ Gem::Specification.new do |gem|
10
10
 
11
11
  gem.add_dependency 'activeresource', '~> 3.2.3'
12
12
 
13
+ gem.add_development_dependency 'growl', '~> 1.0.3'
14
+ gem.add_development_dependency 'guard-minitest', '~> 0.5.0'
15
+ gem.add_development_dependency 'minitest', '~> 2.12.1'
16
+ gem.add_development_dependency 'vcr', '~> 2.1.0'
17
+ gem.add_development_dependency 'webmock', '~> 1.8.6'
18
+
13
19
  gem.files = `git ls-files`.split($\)
14
20
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
21
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
@@ -5,6 +5,15 @@ module Asana
5
5
  def check_prefix_options(options)
6
6
  end
7
7
 
8
+ def custom_method_collection_url(method_name, options = {})
9
+ prefix_options, query_options = split_options(options)
10
+ if method_name
11
+ "#{prefix(prefix_options)}#{collection_name}/#{method_name}.#{format.extension}#{query_string(query_options)}"
12
+ else
13
+ "#{prefix(prefix_options)}#{collection_name}.#{format.extension}#{query_string(query_options)}"
14
+ end
15
+ end
16
+
8
17
  def parent_resources(*resources)
9
18
  @parent_resources = resources
10
19
  end
@@ -6,5 +6,9 @@ module Asana
6
6
  parent_resources :workspace
7
7
  all(*args)
8
8
  end
9
+
10
+ def tasks
11
+ Task.all_by_project(:params => { :project_id => self.id })
12
+ end
9
13
  end
10
14
  end
@@ -13,5 +13,11 @@ module Asana
13
13
  def stories
14
14
  Story.all_by_task(:params => { :task_id => self.id })
15
15
  end
16
+
17
+ def create_story(*args)
18
+ story = Story.new
19
+ query_options = { :task => self.id }
20
+ Task.post("#{self.id}/stories", query_options.merge(args.first), story.to_json)
21
+ end
16
22
  end
17
23
  end
@@ -3,13 +3,13 @@ module Asana
3
3
  alias :save :method_not_allowed
4
4
  alias :destroy :method_not_allowed
5
5
 
6
- def self.me
7
- get(:me)
8
- end
9
-
10
6
  def self.all_by_workspace(*args)
11
7
  parent_resources :workspace
12
8
  all(*args)
13
9
  end
10
+
11
+ def self.me
12
+ User.new(get(:me))
13
+ end
14
14
  end
15
15
  end
@@ -7,8 +7,15 @@ module Asana
7
7
  Project.all_by_workspace(:params => { :workspace_id => self.id })
8
8
  end
9
9
 
10
- def tasks
11
- Task.all_by_workspace(:params => { :workspace_id => self.id })
10
+ def tasks(assignee)
11
+ query_options = { :workspace => self.id, :assignee => assignee }
12
+ Task.all_by_workspace(:params => query_options)
13
+ end
14
+
15
+ def create_task(*args)
16
+ task = Task.new
17
+ query_options = { :workspace => self.id, :assignee => 'me' }
18
+ Task.post(nil, query_options.merge(args.first), task.to_json)
12
19
  end
13
20
 
14
21
  def users
@@ -1,3 +1,3 @@
1
1
  module Asana
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,51 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Project do
5
+
6
+ before do
7
+ VCR.insert_cassette('projects', :record => :new_episodes)
8
+ Asana.configure do |c|
9
+ c.api_key = ENV['ASANA_API_KEY']
10
+ end
11
+ end
12
+
13
+ after do
14
+ VCR.eject_cassette
15
+ end
16
+
17
+ describe '.all' do
18
+ it 'should return all of the user\'s projects' do
19
+ projects = Project.all
20
+ projects.must_be_instance_of Array
21
+ projects.first.must_be_instance_of Project
22
+ end
23
+ end
24
+
25
+ describe '.all_by_workspace' do
26
+ it 'should return all projects for the given workspace' do
27
+ workspace = Workspace.all.first
28
+ projects = workspace.projects
29
+ projects.must_be_instance_of Array
30
+ projects.first.must_be_instance_of Project
31
+ end
32
+ end
33
+
34
+ describe '.create' do
35
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
36
+ project = Project.new
37
+ lambda { project.save }.must_raise ActiveResource::MethodNotAllowed
38
+ end
39
+ end
40
+
41
+ describe '#tasks' do
42
+ it 'should return all tasks for the given project' do
43
+ projects = Project.all.first
44
+ tasks = projects.tasks
45
+ tasks.must_be_instance_of Array
46
+ tasks.first.must_be_instance_of Task
47
+ end
48
+ end
49
+
50
+ end
51
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Story do
5
+
6
+ before do
7
+ VCR.insert_cassette('stories', :record => :new_episodes)
8
+ Asana.configure do |c|
9
+ c.api_key = ENV['ASANA_API_KEY']
10
+ end
11
+ end
12
+
13
+ after do
14
+ VCR.eject_cassette
15
+ end
16
+
17
+ describe '#create_story' do
18
+ it 'should create a new story for the given task' do
19
+ task = Project.all.first.tasks.first
20
+ story = task.create_story(:text => 'foo')
21
+ story.must_be_instance_of Net::HTTPCreated
22
+ end
23
+ end
24
+
25
+ describe '#update' do
26
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
27
+ story = Project.all.first.tasks.first.stories.first
28
+ lambda { story.save }.must_raise ActiveResource::MethodNotAllowed
29
+ end
30
+ end
31
+
32
+ end
33
+ end
@@ -0,0 +1,27 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Task do
5
+
6
+ before do
7
+ VCR.insert_cassette('tasks', :record => :new_episodes)
8
+ Asana.configure do |c|
9
+ c.api_key = ENV['ASANA_API_KEY']
10
+ end
11
+ end
12
+
13
+ after do
14
+ VCR.eject_cassette
15
+ end
16
+
17
+ describe '#stories' do
18
+ it 'should return all stories for the given task' do
19
+ task = Project.all.first.tasks.first
20
+ stories = task.stories
21
+ stories.must_be_instance_of Array
22
+ stories.first.must_be_instance_of Story
23
+ end
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,74 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe User do
5
+
6
+ before do
7
+ VCR.insert_cassette('users', :record => :new_episodes)
8
+ Asana.configure do |c|
9
+ c.api_key = ENV['ASANA_API_KEY']
10
+ end
11
+ end
12
+
13
+ after do
14
+ VCR.eject_cassette
15
+ end
16
+
17
+ describe '.all' do
18
+ it 'should return all users for all of the user\'s workspaces' do
19
+ users = User.all
20
+ users.must_be_instance_of Array
21
+ users.first.must_be_instance_of User
22
+ end
23
+ end
24
+
25
+ describe '.all_by_workspace' do
26
+ it 'should return all users for the given workspace' do
27
+ user = User.me
28
+ workspace = user.workspaces.first
29
+ users = workspace.users
30
+ users.must_be_instance_of Array
31
+ users.first.must_be_instance_of User
32
+ end
33
+ end
34
+
35
+ describe '.find' do
36
+ it 'should return the user with the given ID' do
37
+ user = User.me
38
+ user = User.find(user.id)
39
+ user.wont_be_nil
40
+ user.must_be_instance_of User
41
+ end
42
+ end
43
+
44
+ describe '.me' do
45
+ it 'should return the user associated with the given API key' do
46
+ user = User.me
47
+ user.wont_be_nil
48
+ user.must_be_instance_of User
49
+ end
50
+ end
51
+
52
+ describe '#save' do
53
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
54
+ user = User.me
55
+ lambda { user.save }.must_raise ActiveResource::MethodNotAllowed
56
+ end
57
+ end
58
+
59
+ describe '#update' do
60
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
61
+ user = User.me
62
+ lambda { user.update_attribute(:name, 'foo') }.must_raise ActiveResource::MethodNotAllowed
63
+ end
64
+ end
65
+
66
+ describe '#destroy' do
67
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
68
+ user = User.me
69
+ lambda { user.destroy }.must_raise ActiveResource::MethodNotAllowed
70
+ end
71
+ end
72
+
73
+ end
74
+ end
@@ -0,0 +1,76 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Workspace do
5
+
6
+ before do
7
+ VCR.insert_cassette('workspaces', :record => :new_episodes)
8
+ Asana.configure do |c|
9
+ c.api_key = ENV['ASANA_API_KEY']
10
+ end
11
+ end
12
+
13
+ after do
14
+ VCR.eject_cassette
15
+ end
16
+
17
+ describe '.all' do
18
+ it 'should return all of the user\'s workspaces' do
19
+ workspaces = Workspace.all
20
+ workspaces.must_be_instance_of Array
21
+ workspaces.first.must_be_instance_of Workspace
22
+ end
23
+ end
24
+
25
+ describe '#create_task' do
26
+ it 'should create a new task for the given workspace' do
27
+ workspace = Workspace.all.first
28
+ task = workspace.create_task(:name => 'foo')
29
+ task.must_be_instance_of Net::HTTPCreated
30
+ end
31
+ end
32
+
33
+ describe '#projects' do
34
+ it 'should return all projects for the given workspace' do
35
+ workspace = Workspace.all.first
36
+ projects = workspace.projects
37
+ projects.must_be_instance_of Array
38
+ projects.first.must_be_instance_of Project
39
+ end
40
+ end
41
+
42
+ describe '#tasks' do
43
+ it 'should return all tasks for the given workspace' do
44
+ workspace = Workspace.all.first
45
+ user = User.all.first
46
+ tasks = workspace.tasks(user.id)
47
+ tasks.must_be_instance_of Array
48
+ tasks.first.must_be_instance_of Task
49
+ end
50
+ end
51
+
52
+ describe '#users' do
53
+ it 'should return all users for the given workspace' do
54
+ workspace = Workspace.all.first
55
+ users = workspace.users
56
+ users.must_be_instance_of Array
57
+ users.first.must_be_instance_of User
58
+ end
59
+ end
60
+
61
+ describe '#create' do
62
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
63
+ workspace = Workspace.new
64
+ lambda { workspace.save }.must_raise ActiveResource::MethodNotAllowed
65
+ end
66
+ end
67
+
68
+ describe '#destroy' do
69
+ it 'should raise an ActiveResource::MethodNotAllowed exception' do
70
+ workspace = Workspace.all.first
71
+ lambda { workspace.destroy }.must_raise ActiveResource::MethodNotAllowed
72
+ end
73
+ end
74
+
75
+ end
76
+ end
@@ -0,0 +1,9 @@
1
+ require 'minitest/autorun'
2
+ require 'vcr'
3
+ require 'asana'
4
+
5
+ VCR.configure do |c|
6
+ c.cassette_library_dir = 'spec/fixtures/cassettes'
7
+ c.hook_into :webmock
8
+ c.filter_sensitive_data('<API_KEY>') { ENV['ASANA_API_KEY'] }
9
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: asana
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-19 00:00:00.000000000 Z
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activeresource
@@ -27,6 +27,86 @@ dependencies:
27
27
  - - ~>
28
28
  - !ruby/object:Gem::Version
29
29
  version: 3.2.3
30
+ - !ruby/object:Gem::Dependency
31
+ name: growl
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 1.0.3
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 1.0.3
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard-minitest
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ version: 0.5.0
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.5.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: minitest
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 2.12.1
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 2.12.1
78
+ - !ruby/object:Gem::Dependency
79
+ name: vcr
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ~>
84
+ - !ruby/object:Gem::Version
85
+ version: 2.1.0
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ~>
92
+ - !ruby/object:Gem::Version
93
+ version: 2.1.0
94
+ - !ruby/object:Gem::Dependency
95
+ name: webmock
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ~>
100
+ - !ruby/object:Gem::Version
101
+ version: 1.8.6
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ~>
108
+ - !ruby/object:Gem::Version
109
+ version: 1.8.6
30
110
  description: Ruby wrapper for the Asana REST API
31
111
  email:
32
112
  - ryan@rbright.net
@@ -36,6 +116,7 @@ extra_rdoc_files: []
36
116
  files:
37
117
  - .gitignore
38
118
  - Gemfile
119
+ - Guardfile
39
120
  - LICENSE
40
121
  - README.md
41
122
  - Rakefile
@@ -49,6 +130,12 @@ files:
49
130
  - lib/asana/resources/user.rb
50
131
  - lib/asana/resources/workspace.rb
51
132
  - lib/asana/version.rb
133
+ - spec/asana/resources/project_spec.rb
134
+ - spec/asana/resources/story_spec.rb
135
+ - spec/asana/resources/task_spec.rb
136
+ - spec/asana/resources/user_spec.rb
137
+ - spec/asana/resources/workspace_spec.rb
138
+ - spec/spec_helper.rb
52
139
  homepage: http://github.com/rbright/asana
53
140
  licenses: []
54
141
  post_install_message:
@@ -73,5 +160,11 @@ rubygems_version: 1.8.21
73
160
  signing_key:
74
161
  specification_version: 3
75
162
  summary: Ruby wrapper for the Asana REST API
76
- test_files: []
163
+ test_files:
164
+ - spec/asana/resources/project_spec.rb
165
+ - spec/asana/resources/story_spec.rb
166
+ - spec/asana/resources/task_spec.rb
167
+ - spec/asana/resources/user_spec.rb
168
+ - spec/asana/resources/workspace_spec.rb
169
+ - spec/spec_helper.rb
77
170
  has_rdoc: