bcx 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/.rspec +1 -0
- data/Gemfile +1 -1
- data/README.md +64 -15
- data/Rakefile +5 -1
- data/bcx.gemspec +5 -0
- data/lib/bcx.rb +7 -2
- data/lib/bcx/client.rb +11 -4
- data/lib/bcx/configuration.rb +9 -0
- data/lib/bcx/resources/person.rb +13 -0
- data/lib/bcx/resources/project.rb +40 -2
- data/lib/bcx/resources/todo.rb +37 -0
- data/lib/bcx/resources/todolist.rb +40 -1
- data/lib/bcx/response_error.rb +17 -0
- data/lib/bcx/version.rb +1 -1
- data/spec/bcx/client_spec.rb +40 -0
- data/spec/bcx/project_spec.rb +65 -0
- data/spec/bcx/todolist_spec.rb +75 -0
- data/spec/cassettes/Bcx_Resources_Project/DELETE_/projects/2937644/should_delete_a_project.yml +105 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/2937644/should_have_the_correct_id.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/2937644/should_return_a_hash.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/archived/should_be_an_array.yml +58 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/archived/should_be_empty.yml +58 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/first_project_should_have_the_correct_id.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Project/GET_/projects/should_be_an_array.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Project/POST_/projects/should_create_a_new_project.yml +63 -0
- data/spec/cassettes/Bcx_Resources_Project/PUT_/projects/2937644/should_update_an_existing_project.yml +58 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/1/todolists/completed_json/first_todolist_should_have_the_correct_id.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/1/todolists/completed_json/should_be_an_array.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/123/todolists/456_json/should_have_the_correct_id.yml +67 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/123/todolists/456_json/should_return_a_hash.yml +67 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/2937644/todolists_json/first_todolist_should_have_the_correct_id.yml +114 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/2937644/todolists_json/should_be_an_array.yml +114 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/2956584/todolists/completed_json/first_todolist_should_have_the_correct_id.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/projects/2956584/todolists/completed_json/should_be_an_array.yml +59 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/todolists/completed_json/first_todolist_should_have_the_correct_id.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/todolists/completed_json/should_be_an_array.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/todolists_json/first_todolist_should_have_the_correct_id.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Todolist/GET_/todolists_json/should_be_an_array.yml +60 -0
- data/spec/cassettes/Bcx_Resources_Todolist/projects/123/todolists_json/should_create_a_new_todolist.yml +62 -0
- data/spec/spec_helper.rb +21 -0
- metadata +103 -8
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,29 +1,78 @@
|
|
1
|
-
|
1
|
+
## Bcx
|
2
2
|
|
3
|
-
|
3
|
+
> NB. This is still alpha software and may not work as expected. It's also missing a lot of the Basecamp endpoints. Please feel free to contribute!
|
4
4
|
|
5
|
-
|
5
|
+
Fully-fledged Ruby API wrapper for Basecamp Next
|
6
6
|
|
7
|
-
|
7
|
+
```
|
8
|
+
___________________ ____ ___
|
9
|
+
\______ \_ ___ \\ \/ /
|
10
|
+
| | _/ \ \/ \ /
|
11
|
+
| | \ \____/ \
|
12
|
+
|______ /\______ /___/\ \
|
13
|
+
\/ \/ \_/
|
14
|
+
```
|
8
15
|
|
9
|
-
|
16
|
+
### Installation
|
10
17
|
|
11
|
-
|
18
|
+
```shell
|
19
|
+
$ gem install bcx
|
20
|
+
```
|
12
21
|
|
13
|
-
|
22
|
+
Or if you are using Bundler
|
14
23
|
|
15
|
-
|
24
|
+
```ruby
|
25
|
+
gem 'bcx'
|
26
|
+
```
|
16
27
|
|
17
|
-
|
28
|
+
### Usage
|
18
29
|
|
19
|
-
|
30
|
+
You can connect to the Basecamp API using the Bcx client. The client provides authentication over HTTP or OAuth.
|
20
31
|
|
21
|
-
|
32
|
+
#### HTTP Basic Auth
|
22
33
|
|
23
|
-
|
34
|
+
```ruby
|
35
|
+
client = Bcx::Client.new(:http, login: 'username', password: 'secret')
|
36
|
+
```
|
37
|
+
|
38
|
+
#### OAuth
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
client = Bcx::Client.new(:oauth, client_id: '1234567890', client_secret: '831994c4170', access_token: 'b02ff9345c3')
|
42
|
+
```
|
43
|
+
|
44
|
+
You can get a `client_id` and `client_secret` from https://integrate.37signals.com/
|
45
|
+
|
46
|
+
### Resources
|
47
|
+
|
48
|
+
See the [full resource documentation](#todo) for all available API endpoints.
|
49
|
+
|
50
|
+
#### Bang operators
|
51
|
+
|
52
|
+
It's important to understand the use of bang methods when using Bcx. Each resource can be called with or without a `!`.
|
53
|
+
|
54
|
+
**Without the bang** you can chain and build endpoint calls:
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
client.projects(123).todolists
|
58
|
+
# => #<Bcx::Resources::Todolist ...>
|
59
|
+
|
60
|
+
client.projects(123).todolists.url
|
61
|
+
# => "projects/123/todolists"
|
62
|
+
```
|
63
|
+
|
64
|
+
**With the bang** you can hit the API endpoint over the network and fetch data:
|
65
|
+
|
66
|
+
```ruby
|
67
|
+
client.projects(123).todolists!
|
68
|
+
# => [#<Hashie::Mash id=456 ...>, #<Hashie::Mash id=789 ...>]
|
69
|
+
```
|
70
|
+
|
71
|
+
### Contributing
|
24
72
|
|
25
73
|
1. Fork it
|
26
74
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
-
3. Commit your changes (`git commit -am '
|
28
|
-
4.
|
29
|
-
5.
|
75
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
76
|
+
4. Write your tests and check everything passes
|
77
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
78
|
+
6. Create new Pull Request (into the development branch)
|
data/Rakefile
CHANGED
data/bcx.gemspec
CHANGED
@@ -16,4 +16,9 @@ Gem::Specification.new do |gem|
|
|
16
16
|
gem.version = Bcx::VERSION
|
17
17
|
|
18
18
|
gem.add_runtime_dependency 'rapidash', '~> 0.2.0'
|
19
|
+
|
20
|
+
gem.add_development_dependency 'rake'
|
21
|
+
gem.add_development_dependency 'rspec'
|
22
|
+
gem.add_development_dependency 'simplecov'
|
23
|
+
gem.add_development_dependency 'vcr'
|
19
24
|
end
|
data/lib/bcx.rb
CHANGED
@@ -3,13 +3,15 @@ require 'bcx/version'
|
|
3
3
|
|
4
4
|
module Bcx
|
5
5
|
autoload :Configuration, 'bcx/configuration'
|
6
|
-
autoload :Client, 'bcx/client'
|
7
6
|
|
8
7
|
module Resources
|
9
|
-
autoload :
|
8
|
+
autoload :Todo, 'bcx/resources/todo'
|
10
9
|
autoload :Todolist, 'bcx/resources/todolist'
|
10
|
+
autoload :Project, 'bcx/resources/project'
|
11
11
|
end
|
12
12
|
|
13
|
+
autoload :Client, 'bcx/client'
|
14
|
+
|
13
15
|
class << self
|
14
16
|
attr_accessor :configuration
|
15
17
|
end
|
@@ -19,3 +21,6 @@ module Bcx
|
|
19
21
|
yield(configuration)
|
20
22
|
end
|
21
23
|
end
|
24
|
+
|
25
|
+
require 'bcx/response_error'
|
26
|
+
Rapidash.response_exception_class = Bcx::ResponseError
|
data/lib/bcx/client.rb
CHANGED
@@ -1,15 +1,22 @@
|
|
1
1
|
module Bcx
|
2
2
|
class Client < Rapidash::Client
|
3
|
-
@account = Bcx.configuration.account
|
4
|
-
@api_version = Bcx.configuration.api_version
|
5
|
-
|
6
|
-
site "https://basecamp.com/#{@account}/api/#{@api_version}/"
|
7
3
|
extension :json
|
8
4
|
|
5
|
+
raise_errors
|
6
|
+
|
9
7
|
resource :projects, class_name: 'Bcx::Resources::Project'
|
8
|
+
resource :todolists, class_name: 'Bcx::Resources::Todolist'
|
10
9
|
|
11
10
|
def initialize(auth_method, options = {})
|
11
|
+
@account = Bcx.configuration.account
|
12
|
+
@api_version = Bcx.configuration.api_version
|
13
|
+
|
14
|
+
self.class.site("https://basecamp.com/#{@account}/api/#{@api_version}/")
|
12
15
|
self.class.method(auth_method)
|
16
|
+
|
17
|
+
options[:uid] ||= options[:client_id]
|
18
|
+
options[:secret] ||= options[:client_secret]
|
19
|
+
|
13
20
|
super(options)
|
14
21
|
end
|
15
22
|
|
data/lib/bcx/configuration.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
module Bcx
|
2
|
+
|
3
|
+
# Bcx::Configuration
|
4
|
+
# Provides a configuration block for setting up the Bcx client
|
5
|
+
# Example:
|
6
|
+
#
|
7
|
+
# Bcx.configure do |config|
|
8
|
+
# config.account = '1234567890'
|
9
|
+
# end
|
10
|
+
#
|
2
11
|
class Configuration
|
3
12
|
attr_accessor :account, :api_version
|
4
13
|
|
@@ -1,9 +1,47 @@
|
|
1
1
|
module Bcx
|
2
2
|
module Resources
|
3
|
+
|
4
|
+
# Bcx::Resources::Project
|
5
|
+
# Provides access to projects resoource and other nested resources
|
6
|
+
#
|
7
|
+
# Fetch all projects
|
8
|
+
# GET /projects.json
|
9
|
+
#
|
10
|
+
# client.projects!
|
11
|
+
#
|
12
|
+
# Fetch archived projects
|
13
|
+
# GET /projects/archived.json
|
14
|
+
#
|
15
|
+
# clients.projects.archived!
|
16
|
+
#
|
17
|
+
# Fetch single project with ID of 123
|
18
|
+
# GET /projects/123.json
|
19
|
+
#
|
20
|
+
# client.projects!(123)
|
21
|
+
#
|
22
|
+
# Create a project
|
23
|
+
# POST /projects.json
|
24
|
+
#
|
25
|
+
# client.projects.create!(name: 'Acme project', description: 'This is a new project')
|
26
|
+
#
|
27
|
+
# Update an existing project
|
28
|
+
# PUT /projects/123.json
|
29
|
+
#
|
30
|
+
# client.projects(123).update!(description: 'A new description')
|
31
|
+
#
|
32
|
+
# Delete a project
|
33
|
+
# DELETE /projects/123.json
|
34
|
+
#
|
35
|
+
# client.projects(123).delete!
|
36
|
+
#
|
3
37
|
class Project < Rapidash::Base
|
4
|
-
|
38
|
+
resource :todolists
|
39
|
+
resource :todos
|
5
40
|
|
6
|
-
|
41
|
+
def archived!
|
42
|
+
@url += '/archived'
|
43
|
+
call!
|
44
|
+
end
|
7
45
|
end
|
8
46
|
end
|
9
47
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Bcx
|
2
|
+
module Resources
|
3
|
+
|
4
|
+
# Bcx::Resources::Todo
|
5
|
+
# Provides access to todolist resoource both at the client level and per-project
|
6
|
+
#
|
7
|
+
# Get todos for a todolist
|
8
|
+
# GET /todolists/1.json
|
9
|
+
#
|
10
|
+
# todolist = client.todolists!(1)
|
11
|
+
# todolist.todos.remaining
|
12
|
+
# todolist.todos.completed
|
13
|
+
#
|
14
|
+
# Get a specific todo
|
15
|
+
# GET /projects/1/todos/2.json
|
16
|
+
#
|
17
|
+
# client.projects(1).todos!(2)
|
18
|
+
#
|
19
|
+
# Create a todo
|
20
|
+
# POST /projects/1/todolists/2/todos.json
|
21
|
+
#
|
22
|
+
# client.projects(1).todolists(2).todos.create!(content: 'Update copy text')
|
23
|
+
#
|
24
|
+
# Update a todo
|
25
|
+
# PUT /projects/1/todos/2.json
|
26
|
+
#
|
27
|
+
# client.projects(1).todos(2).update!(completed: true)
|
28
|
+
#
|
29
|
+
# Delete a todo
|
30
|
+
# DELETE /projects/1/todos/2.json
|
31
|
+
#
|
32
|
+
# client.projects(1).todos(2).delete!
|
33
|
+
#
|
34
|
+
class Todo < Rapidash::Base
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -1,7 +1,46 @@
|
|
1
1
|
module Bcx
|
2
2
|
module Resources
|
3
|
+
|
4
|
+
# Bcx::Resources::Todolist
|
5
|
+
# Provides access to todolist resoource both at the client level and per-project
|
6
|
+
#
|
7
|
+
# Get all todolists for a project
|
8
|
+
# GET /projects/123/todolists.json
|
9
|
+
#
|
10
|
+
# client.projects(123).todolists!
|
11
|
+
#
|
12
|
+
# Get all completed todolists for a project
|
13
|
+
# GET /projects/1/todolists/completed.json
|
14
|
+
#
|
15
|
+
# client.projects(123).todolists.completed!
|
16
|
+
#
|
17
|
+
# Get todolists for all projects
|
18
|
+
# GET /todolists.json
|
19
|
+
#
|
20
|
+
# client.todolists!
|
21
|
+
#
|
22
|
+
# Get completed todolists for all projects
|
23
|
+
# GET /todolists/completed.json
|
24
|
+
#
|
25
|
+
# client.todolists.completed!
|
26
|
+
#
|
27
|
+
# Get specific todolist including the todos
|
28
|
+
# GET /projects/123/todolists/456.json
|
29
|
+
#
|
30
|
+
# client.projects(123).todolists!(456)
|
31
|
+
#
|
32
|
+
# Create a new todolist
|
33
|
+
# POST /projects/1/todolists.json
|
34
|
+
#
|
35
|
+
# client.projects(123).todolists.create!(name: 'My todolist', description: 'This is a todolist')
|
36
|
+
#
|
3
37
|
class Todolist < Rapidash::Base
|
4
|
-
|
38
|
+
resource :todos, class_name: 'Bcx::Resources::Todo'
|
39
|
+
|
40
|
+
def completed!
|
41
|
+
@url += '/completed'
|
42
|
+
call!
|
43
|
+
end
|
5
44
|
end
|
6
45
|
end
|
7
46
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Bcx
|
2
|
+
class ResponseError < Rapidash::ResponseError
|
3
|
+
|
4
|
+
def errors
|
5
|
+
return body if body.kind_of?(String)
|
6
|
+
|
7
|
+
messages = []
|
8
|
+
|
9
|
+
body.each_pair do |attribute, msgs|
|
10
|
+
msgs.each { |msg| messages.push "#{attribute} #{msg}" }
|
11
|
+
end
|
12
|
+
|
13
|
+
messages.join(', ')
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
data/lib/bcx/version.rb
CHANGED
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bcx::Client do
|
4
|
+
|
5
|
+
let(:client) { Bcx::Client.new(:http, login: 'bcx-test-user', password: 'secret') }
|
6
|
+
|
7
|
+
describe "http auth" do
|
8
|
+
it "should assign login" do
|
9
|
+
expect(client.login).to eq 'bcx-test-user'
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should assign password" do
|
13
|
+
expect(client.password).to eq 'secret'
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should build a Faraday connection" do
|
17
|
+
expect(client.connection).not_to be_nil
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: test handling to reponse errors, with error codes
|
22
|
+
# it "should fail for invalid attributes" do
|
23
|
+
# expect { client.projects.create!(name: '') }.to raise_error { |error|
|
24
|
+
# expect(error).to be_a Bcx::ResponseError
|
25
|
+
# expect(error.status).to eq 422
|
26
|
+
# }
|
27
|
+
# end
|
28
|
+
|
29
|
+
# Rescue a response error example
|
30
|
+
# begin
|
31
|
+
# project = client.projects.create!(name: 'foo')
|
32
|
+
# rescue Bcx::ResponseError => response
|
33
|
+
# puts response.status
|
34
|
+
# => 422
|
35
|
+
# puts response.body
|
36
|
+
# => "Name cannot be blank"
|
37
|
+
# end
|
38
|
+
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Bcx::Resources::Project, :vcr do
|
4
|
+
let(:client) { Bcx::Client.new(:http, login: 'bcx-test-user', password: 'secret') }
|
5
|
+
|
6
|
+
describe "GET /projects" do
|
7
|
+
let(:projects) { client.projects! }
|
8
|
+
|
9
|
+
it "should be an array" do
|
10
|
+
expect(projects).to be_an Array
|
11
|
+
end
|
12
|
+
|
13
|
+
it "first project should have the correct id" do
|
14
|
+
expect(projects.first.id).to eq 2937644
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
describe "GET /projects/archived" do
|
19
|
+
let(:projects) { client.projects.archived! }
|
20
|
+
|
21
|
+
it "should be an array" do
|
22
|
+
expect(projects).to be_an Array
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should be empty" do
|
26
|
+
expect(projects).to be_empty
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe "GET /projects/2937644" do
|
31
|
+
let(:project) { client.projects!(2937644) }
|
32
|
+
|
33
|
+
it "should return a hash" do
|
34
|
+
expect(project).to be_a Hashie::Mash
|
35
|
+
end
|
36
|
+
|
37
|
+
it "should have the correct id" do
|
38
|
+
expect(project.id).to eq 2937644
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "POST /projects" do
|
43
|
+
it "should create a new project" do
|
44
|
+
project = client.projects.create!(name: 'New project', description: 'A new project created over the API')
|
45
|
+
expect(project.created_at).not_to be_blank
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "PUT /projects/2937644" do
|
50
|
+
it "should update an existing project" do
|
51
|
+
project = client.projects(2937644).update!(description: 'New description')
|
52
|
+
expect(project.description).to eq 'New description'
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
describe "DELETE /projects/2937644" do
|
57
|
+
it "should delete a project" do
|
58
|
+
client.projects(2937644).delete!
|
59
|
+
expect { client.projects!(2937644) }.to raise_error { |error|
|
60
|
+
expect(error).to be_a Bcx::ResponseError
|
61
|
+
expect(error.status).to eq 404
|
62
|
+
}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|