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 ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ spec/fixtures
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in asana.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,8 @@
1
+ # More info at https://github.com/guard/guard#readme
2
+
3
+ guard 'rspec', :version => 2 do
4
+ watch(%r{^spec/.+_spec\.rb$})
5
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
6
+ watch('spec/spec_helper.rb') { "spec" }
7
+ end
8
+
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
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
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
@@ -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,2 @@
1
+ class Asana::Story < Asana::Resource
2
+ end
@@ -0,0 +1,3 @@
1
+ class Asana::Tag < Asana::Resource
2
+
3
+ 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,5 @@
1
+ class Asana::User < Asana::Resource
2
+ def self.me
3
+ self.new(get(:me))
4
+ end
5
+ 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,3 @@
1
+ module Asana
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ describe Asana do
4
+ it "should be a module" do
5
+ Asana.class.should == Module
6
+ end
7
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Asana::Config" do
4
+ it "should set configuration correctly" do
5
+ Asana.configure do |c|
6
+ c.api_key = "SOME API KEY"
7
+ end
8
+
9
+ Asana::Resource.user.should == "SOME API KEY"
10
+ end
11
+ 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,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Story do
5
+ pending
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Asana
4
+ describe Tag do
5
+
6
+ end
7
+ 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
@@ -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