asana-ruby 0.0.1
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/.gitignore +18 -0
- data/Gemfile +4 -0
- data/Guardfile +8 -0
- data/LICENSE +22 -0
- data/README.md +180 -0
- data/Rakefile +2 -0
- data/asana.gemspec +28 -0
- data/lib/asana.rb +20 -0
- data/lib/asana/config.rb +19 -0
- data/lib/asana/resource.rb +53 -0
- data/lib/asana/resources/project.rb +18 -0
- data/lib/asana/resources/story.rb +2 -0
- data/lib/asana/resources/tag.rb +3 -0
- data/lib/asana/resources/task.rb +28 -0
- data/lib/asana/resources/user.rb +5 -0
- data/lib/asana/resources/workspace.rb +32 -0
- data/lib/asana/version.rb +3 -0
- data/spec/asana/asana_spec.rb +7 -0
- data/spec/asana/config_spec.rb +11 -0
- data/spec/asana/resources/project_spec.rb +47 -0
- data/spec/asana/resources/story_spec.rb +7 -0
- data/spec/asana/resources/tag_spec.rb +7 -0
- data/spec/asana/resources/task_spec.rb +36 -0
- data/spec/asana/resources/user_spec.rb +25 -0
- data/spec/asana/resources/workspace_spec.rb +53 -0
- data/spec/spec_helper.rb +29 -0
- metadata +186 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Harley Trung
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,180 @@
|
|
1
|
+
# Asana
|
2
|
+
|
3
|
+
This gem is a simple Ruby wrapper for the Asana REST API. It's based on Ryan Bright's [asana gem](https://github.com/rbright/asana) but it handles a few things differently and it supports more API calls, such as tag handling.
|
4
|
+
|
5
|
+
It uses
|
6
|
+
[ActiveResource][] to provide a simple, familiar interface for accessing
|
7
|
+
your Asana account.
|
8
|
+
|
9
|
+
To learn more, check out the [Asana API Documentation][].
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add this line to your application's Gemfile:
|
14
|
+
|
15
|
+
gem 'asana-ruby'
|
16
|
+
|
17
|
+
And then execute:
|
18
|
+
|
19
|
+
$ bundle
|
20
|
+
|
21
|
+
Or install it yourself as:
|
22
|
+
|
23
|
+
$ gem install asana-ruby
|
24
|
+
|
25
|
+
## Usage
|
26
|
+
|
27
|
+
In order to access Asana, you need to provide your [API key][].
|
28
|
+
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
Asana.configure do |client|
|
32
|
+
client.api_key = 'your_asana_api_key'
|
33
|
+
end
|
34
|
+
```
|
35
|
+
|
36
|
+
As a sanity check, you can fetch the object representing your user.
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
Asana::User.me
|
40
|
+
```
|
41
|
+
|
42
|
+
### [Users][]
|
43
|
+
|
44
|
+
> A user object represents an account in Asana that can be given access to
|
45
|
+
> various workspaces, projects, and tasks.
|
46
|
+
>
|
47
|
+
> Like other objects in the system, users are referred to by numerical IDs.
|
48
|
+
> However, the special string identifier me can be used anywhere a user ID is
|
49
|
+
> accepted, to refer to the current authenticated user.
|
50
|
+
|
51
|
+
**Note:** It is not possible to create, update, or delete a user from
|
52
|
+
the API.
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
# Get users from all of your workspaces
|
56
|
+
users = Asana::User.all
|
57
|
+
|
58
|
+
# Get a specific user
|
59
|
+
user = Asana::User.find(:user_id)
|
60
|
+
|
61
|
+
# Get the user associated with the API key being used
|
62
|
+
user = Asana::User.me
|
63
|
+
|
64
|
+
# Get all users in a given workspace
|
65
|
+
workspace = Asana::Workspace.find(:workspace_id)
|
66
|
+
users = workspace.users
|
67
|
+
```
|
68
|
+
|
69
|
+
### [Workspaces][]
|
70
|
+
|
71
|
+
> A workspace is the most basic organizational unit in Asana. All projects
|
72
|
+
> and tasks have an associated workspace.
|
73
|
+
|
74
|
+
**Note:** It is not possible to create or delete a workspace from the API.
|
75
|
+
|
76
|
+
```ruby
|
77
|
+
# Get all workspaces
|
78
|
+
workspaces = Asana::Workspace.all
|
79
|
+
|
80
|
+
# Get a specific workspace
|
81
|
+
workspace = Asana::Workspace.find(:workspace_id)
|
82
|
+
|
83
|
+
# Get all projects in a given workspace
|
84
|
+
projects = workspace.projects
|
85
|
+
|
86
|
+
# Get all tasks in a given workspace that are assigned to the given user
|
87
|
+
tasks = workspace.tasks(:user_id)
|
88
|
+
|
89
|
+
# Get all users with access to a given workspace
|
90
|
+
users = workspace.users
|
91
|
+
|
92
|
+
# Create a new task in a given workspace and assign it to the current user
|
93
|
+
workspace.create_task(:name => 'Get milk from the grocery store')
|
94
|
+
```
|
95
|
+
|
96
|
+
### [Projects][]
|
97
|
+
|
98
|
+
> A project represents a prioritized list of tasks in Asana. It exists in a
|
99
|
+
> single workspace and is accessible to a subset of users in that workspace
|
100
|
+
> depending on its permissions.
|
101
|
+
|
102
|
+
**Note:** It is not possible to create or delete a project from the API.
|
103
|
+
|
104
|
+
```ruby
|
105
|
+
# Get all projects
|
106
|
+
projects = Asana::Project.all
|
107
|
+
|
108
|
+
# Get a specific project
|
109
|
+
project = Asana::Project.find(:project_id)
|
110
|
+
|
111
|
+
# Get all projects in a given workspace
|
112
|
+
workspace = Asana::Workspace.find(:workspace_id)
|
113
|
+
projects = workspace.projects
|
114
|
+
```
|
115
|
+
|
116
|
+
### [Tasks][]
|
117
|
+
|
118
|
+
> The task is the basic object around which many operations in Asana are
|
119
|
+
> centered. In the Asana application, multiple tasks populate the middle
|
120
|
+
> pane according to some view parameters, and the set of selected tasks
|
121
|
+
> determine the more detailed information presented in the details pane.
|
122
|
+
|
123
|
+
```ruby
|
124
|
+
# Get all tasks in a given project
|
125
|
+
project = Asana::Project.find(:project_id)
|
126
|
+
tasks = project.tasks
|
127
|
+
|
128
|
+
# Get all tasks in a given workspace
|
129
|
+
workspace = Asana::Workspace.find(:workspace_id)
|
130
|
+
tasks = workspace.tasks
|
131
|
+
|
132
|
+
# Get all stories for a given task
|
133
|
+
task = tasks.first
|
134
|
+
stories = task.stories
|
135
|
+
|
136
|
+
# Create a new task in a given workspace and assign it to the current user
|
137
|
+
workspace.create_task(:name => 'Get milk from the grocery store')
|
138
|
+
|
139
|
+
# Create a new story for the given task
|
140
|
+
task.create_story(story_settings)
|
141
|
+
```
|
142
|
+
|
143
|
+
### [Stories][]
|
144
|
+
|
145
|
+
> A story represents an activity associated with an object in the Asana
|
146
|
+
> system. Stories are generated by the system whenever users take actions
|
147
|
+
> such as creating or assigning tasks, or moving tasks between projects.
|
148
|
+
> Comments are also a form of user-generated story.
|
149
|
+
|
150
|
+
**Note:** It is not possible to update or delete a story from the API.
|
151
|
+
|
152
|
+
```ruby
|
153
|
+
# Get all stories for a given task
|
154
|
+
project = Asana::Project.find(:project_id)
|
155
|
+
task = project.tasks.first
|
156
|
+
stories = task.stories
|
157
|
+
|
158
|
+
# Get a specific story
|
159
|
+
story = Story.find(:story_id)
|
160
|
+
|
161
|
+
# Create a new story for the given task
|
162
|
+
task.create_story(story_settings)
|
163
|
+
```
|
164
|
+
|
165
|
+
## Contributing
|
166
|
+
|
167
|
+
1. Fork it
|
168
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
169
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
170
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
171
|
+
5. Create new Pull Request
|
172
|
+
|
173
|
+
[API key]: http://app.asana.com/-/account_api
|
174
|
+
[ActiveResource]: http://api.rubyonrails.org/classes/ActiveResource/Base.html
|
175
|
+
[Asana API Documentation]: http://developer.asana.com/documentation/
|
176
|
+
[Users]: http://developer.asana.com/documentation/#users
|
177
|
+
[Workspaces]: http://developer.asana.com/documentation/#workspaces
|
178
|
+
[Projects]: http://developer.asana.com/documentation/#projects
|
179
|
+
[Tasks]: http://developer.asana.com/documentation/#tasks
|
180
|
+
[Stories]: http://developer.asana.com/documentation/#stories
|
data/Rakefile
ADDED
data/asana.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/asana/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Harley Trung"]
|
6
|
+
gem.email = ["harley@socialsci.com"]
|
7
|
+
gem.description = %q{Ruby API wrapper for Asana, supporting workspaces, projects, tasks, tags, users and stories}
|
8
|
+
gem.summary = %q{Ruby wrapper for Asana}
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "asana-ruby"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = Asana::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency 'activeresource', '>= 3.0'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec', '~> 2.11'
|
22
|
+
gem.add_development_dependency 'guard'
|
23
|
+
gem.add_development_dependency 'guard-rspec'
|
24
|
+
gem.add_development_dependency 'vcr', '~> 2.2.4'
|
25
|
+
gem.add_development_dependency 'webmock', '~> 1.8.8'
|
26
|
+
gem.add_development_dependency 'pry'
|
27
|
+
gem.add_development_dependency 'pry-debugger'
|
28
|
+
end
|
data/lib/asana.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
|
3
|
+
require 'asana/version'
|
4
|
+
require 'asana/config'
|
5
|
+
|
6
|
+
require 'asana/resource'
|
7
|
+
require 'asana/resources/user'
|
8
|
+
require 'asana/resources/workspace'
|
9
|
+
require 'asana/resources/task'
|
10
|
+
require 'asana/resources/project'
|
11
|
+
require 'asana/resources/tag'
|
12
|
+
require 'asana/resources/story'
|
13
|
+
|
14
|
+
module Asana
|
15
|
+
# Your code goes here...
|
16
|
+
extend Config
|
17
|
+
def self.default_workspace
|
18
|
+
Asana::Workspace.first
|
19
|
+
end
|
20
|
+
end
|
data/lib/asana/config.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'asana/resource'
|
2
|
+
require 'asana/version'
|
3
|
+
|
4
|
+
module Asana
|
5
|
+
module Config
|
6
|
+
API_VERSION = '1.0'
|
7
|
+
DEFAULT_ENDPOINT = "https://app.asana.com/api/#{API_VERSION}/"
|
8
|
+
USER_AGENT = "Asana Ruby Gem #{Asana::VERSION}"
|
9
|
+
|
10
|
+
attr_accessor :api_key
|
11
|
+
def configure
|
12
|
+
yield self
|
13
|
+
Resource.user = self.api_key
|
14
|
+
Resource.password = ''
|
15
|
+
Resource.format = :json
|
16
|
+
Resource.site = DEFAULT_ENDPOINT
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module Asana
|
2
|
+
class Resource < ActiveResource::Base
|
3
|
+
def method_not_allowed
|
4
|
+
raise ActiveResource::MethodNotAllowed.new(__method__)
|
5
|
+
end
|
6
|
+
|
7
|
+
# OVERRIDING
|
8
|
+
class << self
|
9
|
+
def remove_json_extension(url)
|
10
|
+
url.gsub(/\.json/,'')
|
11
|
+
end
|
12
|
+
|
13
|
+
# override to remove .json extension in the URL
|
14
|
+
def custom_method_collection_url(method_name, options = {})
|
15
|
+
remove_json_extension super
|
16
|
+
end
|
17
|
+
|
18
|
+
def element_path(id, prefix_options = {}, query_options = nil)
|
19
|
+
remove_json_extension super
|
20
|
+
end
|
21
|
+
|
22
|
+
def new_element_path(prefix_options = {})
|
23
|
+
remove_json_extension super
|
24
|
+
end
|
25
|
+
|
26
|
+
def collection_path(prefix_options = {}, query_options = nil)
|
27
|
+
remove_json_extension super
|
28
|
+
end
|
29
|
+
|
30
|
+
def singleton_path(prefix_options = {}, query_options = nil)
|
31
|
+
remove_json_extension super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Asana wants it to be nested under data
|
36
|
+
def to_json(options={})
|
37
|
+
ret = super({ :root => 'data' }.merge(options))
|
38
|
+
puts "CONVERTING: #{options} TO: #{ret}"
|
39
|
+
ret
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
# override to remove .json extension in the URL
|
44
|
+
def custom_method_element_url(method_name, options = {})
|
45
|
+
self.class.remove_json_extension super
|
46
|
+
end
|
47
|
+
|
48
|
+
# override to remove .json extension in the URL
|
49
|
+
def custom_method_new_element_url(method_name, options = {})
|
50
|
+
self.class.remove_json_extension super
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class Asana::Project < Asana::Resource
|
2
|
+
alias :create :method_not_allowed
|
3
|
+
alias :destroy :method_not_allowed
|
4
|
+
|
5
|
+
def self.all_by_task(*args)
|
6
|
+
parent_resources :task
|
7
|
+
all(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.all_by_workspace(*args)
|
11
|
+
parent_resources :workspace
|
12
|
+
all(*args)
|
13
|
+
end
|
14
|
+
|
15
|
+
def tasks
|
16
|
+
get(:tasks).map{|h| Asana::Task.find h["id"]}
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Asana
|
2
|
+
class Task < Asana::Resource
|
3
|
+
# don't want update_attribute because it posts all data to asana instead of just changed attributes
|
4
|
+
alias :update_attribute :method_not_allowed
|
5
|
+
# create a task via a project or workspace instead
|
6
|
+
alias :create :method_not_allowed
|
7
|
+
|
8
|
+
def add_project(project)
|
9
|
+
project = project.id if project.is_a?(Project)
|
10
|
+
post('addProject', nil, {data: {project: project}}.to_json)
|
11
|
+
end
|
12
|
+
|
13
|
+
def remove_project(project)
|
14
|
+
project = project.id if project.is_a?(Project)
|
15
|
+
post('removeProject', nil, {data: {project: project}}.to_json)
|
16
|
+
end
|
17
|
+
|
18
|
+
def add_tag(tag)
|
19
|
+
tag = tag.id if tag.is_a?(Tag)
|
20
|
+
post('addTag', nil, {data: {tag: tag}}.to_json)
|
21
|
+
end
|
22
|
+
|
23
|
+
def remove_tag(tag)
|
24
|
+
tag = tag.id if tag.is_a?(Tag)
|
25
|
+
post('removeTag', nil, {data: {tag: tag}}.to_json)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'pry'
|
2
|
+
class Asana::Workspace < Asana::Resource
|
3
|
+
def create_task(options = {})
|
4
|
+
options.merge!(assignee: 'me') unless options[:assignee] or options['assignee']
|
5
|
+
|
6
|
+
post_body = { data: options }
|
7
|
+
response = post("tasks", nil, post_body.to_json)
|
8
|
+
Asana::Task.new(connection.format.decode(response.body))
|
9
|
+
rescue Exception => e
|
10
|
+
$stderr.puts "ERROR: #{e.message}"
|
11
|
+
$stderr.puts "RESPONSE: #{e.response.body}" if e.respond_to?(:response)
|
12
|
+
end
|
13
|
+
|
14
|
+
# From API docs: If you specify a workspace you must also specify an assignee to filter on.
|
15
|
+
def tasks(options = {})
|
16
|
+
options.merge!(assignee: 'me') unless options[:assignee] or options['assignee']
|
17
|
+
|
18
|
+
get("tasks?assignee=#{options[:assignee]}").map{|h| Asana::Task.find h["id"]}
|
19
|
+
rescue Exception => e
|
20
|
+
$stderr.puts "ERROR: #{e.message}"
|
21
|
+
$stderr.puts "RESPONSE: #{e.response.body}" if e.respond_to?(:response)
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_tag(options = {})
|
25
|
+
response = post("tags", nil, {data: options}.to_json)
|
26
|
+
Asana::Tag.new(connection.format.decode(response.body))
|
27
|
+
end
|
28
|
+
|
29
|
+
def tags
|
30
|
+
get(:tags).map{|h| Asana::Tag.find h["id"]}
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Asana
|
4
|
+
describe Project do
|
5
|
+
use_vcr_cassette
|
6
|
+
before do
|
7
|
+
authorize_with_asana
|
8
|
+
end
|
9
|
+
|
10
|
+
describe '.all' do
|
11
|
+
it 'should return all of the user\'s projects' do
|
12
|
+
projects = Project.all
|
13
|
+
projects.should be_instance_of Array
|
14
|
+
projects.first.should be_instance_of Project
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe '.create' do
|
19
|
+
it 'should raise an ActiveResource::MethodNotAllowed exception' do
|
20
|
+
project = Project.new
|
21
|
+
lambda { project.save }.should raise_error(ActiveResource::MethodNotAllowed)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe '.find' do
|
26
|
+
it 'should return a single project' do
|
27
|
+
project = Project.find(Project.all.first.id)
|
28
|
+
project.should be_instance_of Project
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe '#destroy' do
|
33
|
+
it 'should raise an ActiveResource::MethodNotAllowed exception' do
|
34
|
+
project = Project.all.first
|
35
|
+
lambda { project.destroy}.should raise_error ActiveResource::MethodNotAllowed
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe '#tasks' do
|
40
|
+
it 'should return all tasks for the given project' do
|
41
|
+
projects = Project.all.first
|
42
|
+
tasks = projects.tasks
|
43
|
+
tasks.should be_instance_of Array
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Asana::Task do
|
4
|
+
use_vcr_cassette
|
5
|
+
before do
|
6
|
+
authorize_with_asana
|
7
|
+
end
|
8
|
+
|
9
|
+
context "API" do
|
10
|
+
context "creating a new task" do
|
11
|
+
describe "POST /tasks" do
|
12
|
+
it "should raise exception with incomplete data" do
|
13
|
+
expect {Asana::Task.post('/', nil, "name='first time'")}.to raise_exception
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".remove_project and .add_project" do
|
20
|
+
let(:project) { Asana::Project.first }
|
21
|
+
let(:task) { project.tasks.first }
|
22
|
+
|
23
|
+
it "should work" do
|
24
|
+
task.remove_project(project)
|
25
|
+
project.tasks.should_not include task
|
26
|
+
|
27
|
+
task.add_project(project)
|
28
|
+
project.tasks.should include task
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe ".add_tag and .remove_tag" do
|
33
|
+
let(:tag)
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Asana
|
4
|
+
describe User do
|
5
|
+
use_vcr_cassette
|
6
|
+
before do
|
7
|
+
authorize_with_asana
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "showing a single user" do
|
11
|
+
describe '.me' do
|
12
|
+
specify do
|
13
|
+
user = User.me
|
14
|
+
user.should_not be_nil
|
15
|
+
user.should be_instance_of User
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
pending "GET /users/user-id"
|
20
|
+
end
|
21
|
+
|
22
|
+
pending "showing all users in all workspaces"
|
23
|
+
pending "showing all users in a single workspace"
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Asana
|
4
|
+
describe Workspace do
|
5
|
+
use_vcr_cassette
|
6
|
+
before do
|
7
|
+
authorize_with_asana
|
8
|
+
end
|
9
|
+
|
10
|
+
let(:workspace) { Asana::Workspace.first }
|
11
|
+
|
12
|
+
describe "Showing available workspaces" do
|
13
|
+
specify do
|
14
|
+
#binding.pry
|
15
|
+
Asana::Workspace.all.first.should be_instance_of Asana::Workspace
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
pending "Updating an existing workspace (name only)"
|
20
|
+
|
21
|
+
describe ".create_task" do
|
22
|
+
specify do
|
23
|
+
task = workspace.create_task(name: "test .create_task")
|
24
|
+
task.should be_instance_of Asana::Task
|
25
|
+
task.name.should == "test .create_task"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe ".create_tag" do
|
30
|
+
let(:tag_name) { "tag #{Date.today}" }
|
31
|
+
subject { workspace.create_tag(name: tag_name)}
|
32
|
+
|
33
|
+
it { should be_instance_of Asana::Tag}
|
34
|
+
its(:name) { should == tag_name }
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".tasks" do
|
38
|
+
subject { workspace }
|
39
|
+
its(:tasks) { should be_instance_of Array }
|
40
|
+
it "should return task instances" do
|
41
|
+
workspace.tasks.first.should be_instance_of Task
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "tags" do
|
46
|
+
subject { workspace }
|
47
|
+
its(:tags) { should be_instance_of Array }
|
48
|
+
it "should return task instances" do
|
49
|
+
workspace.tags.first.should be_instance_of Tag
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'asana'
|
2
|
+
require 'vcr'
|
3
|
+
require 'active_resource'
|
4
|
+
|
5
|
+
VCR.configure do |c|
|
6
|
+
c.cassette_library_dir = 'spec/fixtures/cassettes'
|
7
|
+
c.hook_into :webmock
|
8
|
+
c.default_cassette_options = { :record => :new_episodes }
|
9
|
+
end
|
10
|
+
|
11
|
+
RSpec.configure do |c|
|
12
|
+
c.extend VCR::RSpec::Macros
|
13
|
+
end
|
14
|
+
|
15
|
+
def authorize_with_asana
|
16
|
+
Asana.configure do |c|
|
17
|
+
c.api_key = 'nSZfywi.U8aR4lxeTJBkYgK84Ton0UNp'
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
TEST_WORKSPACE_ID = '1356785960235'
|
22
|
+
|
23
|
+
class ActiveResource::Connection
|
24
|
+
def http
|
25
|
+
ret = configure_http(new_http)
|
26
|
+
ret.set_debug_output $stderr
|
27
|
+
ret
|
28
|
+
end
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,186 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: asana-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Harley Trung
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-07-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activeresource
|
16
|
+
requirement: &2164303060 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '3.0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2164303060
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: rake
|
27
|
+
requirement: &2164301940 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2164301940
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rspec
|
38
|
+
requirement: &2164300960 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '2.11'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2164300960
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: guard
|
49
|
+
requirement: &2164300320 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2164300320
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: guard-rspec
|
60
|
+
requirement: &2164299280 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *2164299280
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: vcr
|
71
|
+
requirement: &2164297400 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 2.2.4
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: *2164297400
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: webmock
|
82
|
+
requirement: &2164328280 !ruby/object:Gem::Requirement
|
83
|
+
none: false
|
84
|
+
requirements:
|
85
|
+
- - ~>
|
86
|
+
- !ruby/object:Gem::Version
|
87
|
+
version: 1.8.8
|
88
|
+
type: :development
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *2164328280
|
91
|
+
- !ruby/object:Gem::Dependency
|
92
|
+
name: pry
|
93
|
+
requirement: &2164326420 !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ! '>='
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
version: '0'
|
99
|
+
type: :development
|
100
|
+
prerelease: false
|
101
|
+
version_requirements: *2164326420
|
102
|
+
- !ruby/object:Gem::Dependency
|
103
|
+
name: pry-debugger
|
104
|
+
requirement: &2164324800 !ruby/object:Gem::Requirement
|
105
|
+
none: false
|
106
|
+
requirements:
|
107
|
+
- - ! '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: *2164324800
|
113
|
+
description: Ruby API wrapper for Asana, supporting workspaces, projects, tasks, tags,
|
114
|
+
users and stories
|
115
|
+
email:
|
116
|
+
- harley@socialsci.com
|
117
|
+
executables: []
|
118
|
+
extensions: []
|
119
|
+
extra_rdoc_files: []
|
120
|
+
files:
|
121
|
+
- .gitignore
|
122
|
+
- Gemfile
|
123
|
+
- Guardfile
|
124
|
+
- LICENSE
|
125
|
+
- README.md
|
126
|
+
- Rakefile
|
127
|
+
- asana.gemspec
|
128
|
+
- lib/asana.rb
|
129
|
+
- lib/asana/config.rb
|
130
|
+
- lib/asana/resource.rb
|
131
|
+
- lib/asana/resources/project.rb
|
132
|
+
- lib/asana/resources/story.rb
|
133
|
+
- lib/asana/resources/tag.rb
|
134
|
+
- lib/asana/resources/task.rb
|
135
|
+
- lib/asana/resources/user.rb
|
136
|
+
- lib/asana/resources/workspace.rb
|
137
|
+
- lib/asana/version.rb
|
138
|
+
- spec/asana/asana_spec.rb
|
139
|
+
- spec/asana/config_spec.rb
|
140
|
+
- spec/asana/resources/project_spec.rb
|
141
|
+
- spec/asana/resources/story_spec.rb
|
142
|
+
- spec/asana/resources/tag_spec.rb
|
143
|
+
- spec/asana/resources/task_spec.rb
|
144
|
+
- spec/asana/resources/user_spec.rb
|
145
|
+
- spec/asana/resources/workspace_spec.rb
|
146
|
+
- spec/spec_helper.rb
|
147
|
+
homepage: ''
|
148
|
+
licenses: []
|
149
|
+
post_install_message:
|
150
|
+
rdoc_options: []
|
151
|
+
require_paths:
|
152
|
+
- lib
|
153
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
154
|
+
none: false
|
155
|
+
requirements:
|
156
|
+
- - ! '>='
|
157
|
+
- !ruby/object:Gem::Version
|
158
|
+
version: '0'
|
159
|
+
segments:
|
160
|
+
- 0
|
161
|
+
hash: 4402489200243794366
|
162
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
163
|
+
none: false
|
164
|
+
requirements:
|
165
|
+
- - ! '>='
|
166
|
+
- !ruby/object:Gem::Version
|
167
|
+
version: '0'
|
168
|
+
segments:
|
169
|
+
- 0
|
170
|
+
hash: 4402489200243794366
|
171
|
+
requirements: []
|
172
|
+
rubyforge_project:
|
173
|
+
rubygems_version: 1.8.17
|
174
|
+
signing_key:
|
175
|
+
specification_version: 3
|
176
|
+
summary: Ruby wrapper for Asana
|
177
|
+
test_files:
|
178
|
+
- spec/asana/asana_spec.rb
|
179
|
+
- spec/asana/config_spec.rb
|
180
|
+
- spec/asana/resources/project_spec.rb
|
181
|
+
- spec/asana/resources/story_spec.rb
|
182
|
+
- spec/asana/resources/tag_spec.rb
|
183
|
+
- spec/asana/resources/task_spec.rb
|
184
|
+
- spec/asana/resources/user_spec.rb
|
185
|
+
- spec/asana/resources/workspace_spec.rb
|
186
|
+
- spec/spec_helper.rb
|