letsfreckle-client 0.1.2 → 0.2.0
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/bin/run-examples +41 -0
- data/letsfreckle-client.gemspec +7 -4
- data/lib/faraday/request/xml.rb +20 -0
- data/lib/faraday/response/flatten_body.rb +19 -0
- data/lib/faraday/response/verify_status.rb +17 -0
- data/lib/letsfreckle.rb +7 -2
- data/lib/letsfreckle/client_resource.rb +25 -22
- data/lib/letsfreckle/entry.rb +7 -5
- data/lib/letsfreckle/error.rb +4 -5
- data/lib/letsfreckle/project.rb +1 -1
- data/lib/letsfreckle/tag.rb +1 -1
- data/lib/letsfreckle/user.rb +1 -1
- data/lib/letsfreckle/version.rb +1 -1
- data/spec/letsfreckle/entry_spec.rb +1 -1
- data/spec/letsfreckle/project_spec.rb +1 -1
- data/spec/letsfreckle/tag_spec.rb +1 -1
- data/spec/letsfreckle/user_spec.rb +1 -1
- data/spec/support/webmock_helper.rb +13 -1
- metadata +91 -85
data/bin/run-examples
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
4
|
+
require 'letsfreckle'
|
5
|
+
|
6
|
+
# Configure the API credentials.
|
7
|
+
LetsFreckle.configure do
|
8
|
+
account_host "apitest"
|
9
|
+
username "apitest@letsfreckle.com"
|
10
|
+
token "lx3gi6pxdjtjn57afp8c2bv1me7g89j"
|
11
|
+
end
|
12
|
+
|
13
|
+
puts "Fetch all entries:"
|
14
|
+
LetsFreckle::Entry.all.each do |entry|
|
15
|
+
puts "Entry #{entry.description} - #{entry.minutes} minutes"
|
16
|
+
end
|
17
|
+
|
18
|
+
puts "Search for entries from a specific start date and tags:"
|
19
|
+
LetsFreckle::Entry.find(:from => '2010-07-10', :tags => ['development', 'design']).each do |entry|
|
20
|
+
puts entry.description
|
21
|
+
end
|
22
|
+
|
23
|
+
puts "Fetch all projects and associated entries:"
|
24
|
+
LetsFreckle::Project.all.each do |project|
|
25
|
+
puts "Project #{project.name} has #{project.entries.size} entries"
|
26
|
+
end
|
27
|
+
|
28
|
+
puts "Fetch all tags and associated entries:"
|
29
|
+
LetsFreckle::Tag.all.each do |tag|
|
30
|
+
puts "Tag #{tag.name} has #{tag.entries.size} entries"
|
31
|
+
end
|
32
|
+
|
33
|
+
puts "Fetch all users and associated permissions:"
|
34
|
+
LetsFreckle::User.all.each do |user|
|
35
|
+
puts "User #{user.email} has following permissions: #{user.permissions}"
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
|
data/letsfreckle-client.gemspec
CHANGED
@@ -19,8 +19,11 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
20
20
|
s.require_paths = ["lib"]
|
21
21
|
|
22
|
-
s.add_dependency
|
23
|
-
s.add_dependency
|
24
|
-
s.
|
25
|
-
s.
|
22
|
+
s.add_dependency 'hashie', '~> 1.1.0'
|
23
|
+
s.add_dependency 'faraday', '~> 0.7.4'
|
24
|
+
s.add_dependency 'faraday_middleware', '~> 0.7.0'
|
25
|
+
s.add_dependency 'multi_xml', '~> 0.2.0'
|
26
|
+
s.add_development_dependency "activesupport", "~> 2.3"
|
27
|
+
s.add_development_dependency 'rspec', '~> 2.5.0'
|
28
|
+
s.add_development_dependency 'webmock', '~> 1.6.2'
|
26
29
|
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Request
|
3
|
+
class XML < Faraday::Middleware
|
4
|
+
dependency 'active_support/all'
|
5
|
+
|
6
|
+
def initialize(app, options={})
|
7
|
+
@app = app
|
8
|
+
@options = options
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(env)
|
12
|
+
if env[:method] == :post
|
13
|
+
env[:body] = env[:body].to_xml(:root => env[:body].delete(:root))
|
14
|
+
puts env[:body]
|
15
|
+
end
|
16
|
+
@app.call(env)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Response
|
3
|
+
# FlattenBody is a middleware that flattens the response body, and also extends
|
4
|
+
# Hashie::Mash instances with a module that allows them to work properly with DelegateClass.
|
5
|
+
class FlattenBody < Response::Middleware
|
6
|
+
dependency 'hashie/mash'
|
7
|
+
|
8
|
+
def parse(body)
|
9
|
+
return body unless body.respond_to?(:to_a)
|
10
|
+
flattened_response = body.to_a.flatten
|
11
|
+
flattened_response.keep_if { |item| ::Hashie::Mash === item }
|
12
|
+
flattened_response.map do |mash|
|
13
|
+
# extend so that #respond_to? works nicely with DelegateClass
|
14
|
+
mash.extend(LetsFreckle::Extensions::Mash)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Faraday
|
2
|
+
class Response
|
3
|
+
class VerifyStatus < Response::Middleware
|
4
|
+
def on_complete(env)
|
5
|
+
status = env[:status].to_i
|
6
|
+
case env[:method]
|
7
|
+
when :get
|
8
|
+
raise LetsFreckle::FetchError, "Fetch failed, HTTP error: #{status}" unless status == 200
|
9
|
+
when :post
|
10
|
+
raise LetsFreckle::CreateError, "Create failed, HTTP error: #{status}" unless status == 201
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
data/lib/letsfreckle.rb
CHANGED
@@ -1,7 +1,12 @@
|
|
1
|
-
require 'hashie'
|
2
|
-
require 'httparty'
|
3
1
|
require 'delegate'
|
4
2
|
|
3
|
+
require 'hashie'
|
4
|
+
require 'faraday'
|
5
|
+
require 'faraday_middleware'
|
6
|
+
require 'faraday/request/xml'
|
7
|
+
require 'faraday/response/flatten_body'
|
8
|
+
require 'faraday/response/verify_status'
|
9
|
+
|
5
10
|
require 'letsfreckle/version'
|
6
11
|
require 'letsfreckle/extensions/mash'
|
7
12
|
require 'letsfreckle/configuration'
|
@@ -2,38 +2,41 @@ module LetsFreckle
|
|
2
2
|
# ClientResource should be extended by resource classes in order to gain
|
3
3
|
# access to HTTP methods.
|
4
4
|
module ClientResource
|
5
|
-
API_URL = "https://%s.letsfreckle.com/api/%s.xml?token=%s"
|
6
5
|
|
7
|
-
def
|
8
|
-
response =
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
def get(resource, options = {})
|
7
|
+
response = client.get do |request|
|
8
|
+
request.url relative_path_for(resource), options
|
9
|
+
end
|
10
|
+
response.body.map { |mash| new(mash) }
|
12
11
|
end
|
13
12
|
|
14
13
|
def post(resource, options = {})
|
15
|
-
|
16
|
-
|
14
|
+
client.post do |request|
|
15
|
+
request.url relative_path_for(resource)
|
16
|
+
request.headers['Content-Type'] = 'application/xml'
|
17
|
+
request.body = options
|
18
|
+
end
|
17
19
|
end
|
18
20
|
|
19
|
-
def
|
20
|
-
|
21
|
+
def base_api_url
|
22
|
+
"https://#{LetsFreckle.config.account_host}.letsfreckle.com"
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
|
-
|
25
|
-
def verify!(response, code, &block)
|
26
|
-
block.call unless response.code == code
|
25
|
+
def relative_path_for(resource)
|
26
|
+
"/api/#{resource}.xml?token=#{LetsFreckle.config.token}"
|
27
27
|
end
|
28
28
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def client
|
32
|
+
Faraday.new(:url => base_api_url) do |builder|
|
33
|
+
builder.use Faraday::Request::UrlEncoded
|
34
|
+
builder.use Faraday::Request::XML
|
35
|
+
builder.use Faraday::Response::FlattenBody
|
36
|
+
builder.use Faraday::Response::Mashify
|
37
|
+
builder.use Faraday::Response::ParseXml
|
38
|
+
builder.use Faraday::Response::VerifyStatus
|
39
|
+
builder.use Faraday::Adapter::NetHttp
|
37
40
|
end
|
38
41
|
end
|
39
42
|
end
|
data/lib/letsfreckle/entry.rb
CHANGED
@@ -3,7 +3,7 @@ module LetsFreckle
|
|
3
3
|
extend ClientResource
|
4
4
|
|
5
5
|
def self.all
|
6
|
-
|
6
|
+
get('entries')
|
7
7
|
end
|
8
8
|
|
9
9
|
# Fetches all entries. Supported options are:
|
@@ -14,7 +14,7 @@ module LetsFreckle
|
|
14
14
|
# :to => '2012-01-01'
|
15
15
|
# :billable => true/false
|
16
16
|
def self.find(options = {})
|
17
|
-
|
17
|
+
get('entries', searchable_options_from(options))
|
18
18
|
end
|
19
19
|
|
20
20
|
# Creates a new entry. Supported options are:
|
@@ -25,14 +25,16 @@ module LetsFreckle
|
|
25
25
|
def self.create(options = {})
|
26
26
|
raise ArgumentError, ':username config missing' unless LetsFreckle.config.username
|
27
27
|
raise ArgumentError, ':minutes missing' unless options.has_key?(:minutes)
|
28
|
-
post('entries',
|
28
|
+
post('entries', options.merge(:root => :entry, :user => LetsFreckle.config.username))
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.searchable_options_from(options = {})
|
32
32
|
options.each_with_object({}) do |(key, value), result|
|
33
33
|
case value
|
34
|
-
when Array then
|
35
|
-
|
34
|
+
when Array then
|
35
|
+
result["search[#{key}]"] = value.join(',')
|
36
|
+
else
|
37
|
+
result["search[#{key}]"] = value.to_s
|
36
38
|
end
|
37
39
|
end
|
38
40
|
end
|
data/lib/letsfreckle/error.rb
CHANGED
data/lib/letsfreckle/project.rb
CHANGED
data/lib/letsfreckle/tag.rb
CHANGED
data/lib/letsfreckle/user.rb
CHANGED
data/lib/letsfreckle/version.rb
CHANGED
@@ -9,7 +9,7 @@ describe LetsFreckle::Project do
|
|
9
9
|
token "secret"
|
10
10
|
end
|
11
11
|
|
12
|
-
|
12
|
+
stub_api_request('projects')
|
13
13
|
projects = LetsFreckle::Project.all
|
14
14
|
projects.size.should == 2
|
15
15
|
|
@@ -2,4 +2,16 @@ module WebMockHelper
|
|
2
2
|
def load_response(resource)
|
3
3
|
File.read(File.join(File.dirname(__FILE__), '/../responses', "#{resource}.xml.response"))
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
|
+
def url_for_resource(resource)
|
7
|
+
"#{LetsFreckle::Entry.base_api_url}#{LetsFreckle::Entry.relative_path_for(resource)}"
|
8
|
+
end
|
9
|
+
|
10
|
+
def stub_api_request(resource)
|
11
|
+
stub_http_request(:get, url_for_resource(resource)).
|
12
|
+
with(:headers => { 'Accept' =>'*/*',
|
13
|
+
'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3',
|
14
|
+
'User-Agent' =>'Ruby' }).
|
15
|
+
to_return(:body => load_response(resource))
|
16
|
+
end
|
17
|
+
end
|
metadata
CHANGED
@@ -1,98 +1,112 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: letsfreckle-client
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
5
|
-
|
6
|
-
- 0
|
7
|
-
- 1
|
8
|
-
- 2
|
9
|
-
version: 0.1.2
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
10
6
|
platform: ruby
|
11
|
-
authors:
|
7
|
+
authors:
|
12
8
|
- Ryan LeCompte
|
13
9
|
autorequire:
|
14
10
|
bindir: bin
|
15
11
|
cert_chain: []
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
12
|
+
date: 2011-08-25 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: hashie
|
16
|
+
requirement: &70346356154000 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 1.1.0
|
22
|
+
type: :runtime
|
22
23
|
prerelease: false
|
23
|
-
|
24
|
+
version_requirements: *70346356154000
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: faraday
|
27
|
+
requirement: &70346356153180 !ruby/object:Gem::Requirement
|
24
28
|
none: false
|
25
|
-
requirements:
|
26
|
-
- -
|
27
|
-
- !ruby/object:Gem::Version
|
28
|
-
|
29
|
-
- 0
|
30
|
-
- 7
|
31
|
-
- 8
|
32
|
-
version: 0.7.8
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.7.4
|
33
33
|
type: :runtime
|
34
|
-
version_requirements: *id001
|
35
|
-
- !ruby/object:Gem::Dependency
|
36
|
-
name: hashie
|
37
34
|
prerelease: false
|
38
|
-
|
35
|
+
version_requirements: *70346356153180
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: faraday_middleware
|
38
|
+
requirement: &70346356152680 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
|
-
requirements:
|
41
|
-
- -
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
|
44
|
-
- 1
|
45
|
-
- 0
|
46
|
-
- 0
|
47
|
-
version: 1.0.0
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 0.7.0
|
48
44
|
type: :runtime
|
49
|
-
version_requirements: *id002
|
50
|
-
- !ruby/object:Gem::Dependency
|
51
|
-
name: rspec
|
52
45
|
prerelease: false
|
53
|
-
|
46
|
+
version_requirements: *70346356152680
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: multi_xml
|
49
|
+
requirement: &70346356152220 !ruby/object:Gem::Requirement
|
54
50
|
none: false
|
55
|
-
requirements:
|
51
|
+
requirements:
|
56
52
|
- - ~>
|
57
|
-
- !ruby/object:Gem::Version
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 0.2.0
|
55
|
+
type: :runtime
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *70346356152220
|
58
|
+
- !ruby/object:Gem::Dependency
|
59
|
+
name: activesupport
|
60
|
+
requirement: &70346356151760 !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ~>
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '2.3'
|
66
|
+
type: :development
|
67
|
+
prerelease: false
|
68
|
+
version_requirements: *70346356151760
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: &70346356151260 !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
73
|
+
requirements:
|
74
|
+
- - ~>
|
75
|
+
- !ruby/object:Gem::Version
|
62
76
|
version: 2.5.0
|
63
77
|
type: :development
|
64
|
-
version_requirements: *id003
|
65
|
-
- !ruby/object:Gem::Dependency
|
66
|
-
name: webmock
|
67
78
|
prerelease: false
|
68
|
-
|
79
|
+
version_requirements: *70346356151260
|
80
|
+
- !ruby/object:Gem::Dependency
|
81
|
+
name: webmock
|
82
|
+
requirement: &70346356150740 !ruby/object:Gem::Requirement
|
69
83
|
none: false
|
70
|
-
requirements:
|
84
|
+
requirements:
|
71
85
|
- - ~>
|
72
|
-
- !ruby/object:Gem::Version
|
73
|
-
segments:
|
74
|
-
- 1
|
75
|
-
- 6
|
76
|
-
- 2
|
86
|
+
- !ruby/object:Gem::Version
|
77
87
|
version: 1.6.2
|
78
88
|
type: :development
|
79
|
-
|
80
|
-
|
81
|
-
|
89
|
+
prerelease: false
|
90
|
+
version_requirements: *70346356150740
|
91
|
+
description: Ruby client for letsfreckle.com API that supports entries, projects,
|
92
|
+
tags, and users
|
93
|
+
email:
|
82
94
|
- lecompte@gmail.com
|
83
|
-
executables:
|
84
|
-
|
95
|
+
executables:
|
96
|
+
- run-examples
|
85
97
|
extensions: []
|
86
|
-
|
87
98
|
extra_rdoc_files: []
|
88
|
-
|
89
|
-
files:
|
99
|
+
files:
|
90
100
|
- .gitignore
|
91
101
|
- Gemfile
|
92
102
|
- LICENSE
|
93
103
|
- README.rdoc
|
94
104
|
- Rakefile
|
105
|
+
- bin/run-examples
|
95
106
|
- letsfreckle-client.gemspec
|
107
|
+
- lib/faraday/request/xml.rb
|
108
|
+
- lib/faraday/response/flatten_body.rb
|
109
|
+
- lib/faraday/response/verify_status.rb
|
96
110
|
- lib/letsfreckle.rb
|
97
111
|
- lib/letsfreckle/client_resource.rb
|
98
112
|
- lib/letsfreckle/configuration.rb
|
@@ -114,39 +128,31 @@ files:
|
|
114
128
|
- spec/responses/users.xml.response
|
115
129
|
- spec/spec_helper.rb
|
116
130
|
- spec/support/webmock_helper.rb
|
117
|
-
has_rdoc: true
|
118
131
|
homepage: http://github.com/ryanlecompte/letsfreckle-client
|
119
132
|
licenses: []
|
120
|
-
|
121
133
|
post_install_message:
|
122
134
|
rdoc_options: []
|
123
|
-
|
124
|
-
require_paths:
|
135
|
+
require_paths:
|
125
136
|
- lib
|
126
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
137
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
|
-
requirements:
|
129
|
-
- -
|
130
|
-
- !ruby/object:Gem::Version
|
131
|
-
|
132
|
-
|
133
|
-
version: "0"
|
134
|
-
required_rubygems_version: !ruby/object:Gem::Requirement
|
139
|
+
requirements:
|
140
|
+
- - ! '>='
|
141
|
+
- !ruby/object:Gem::Version
|
142
|
+
version: '0'
|
143
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
135
144
|
none: false
|
136
|
-
requirements:
|
137
|
-
- -
|
138
|
-
- !ruby/object:Gem::Version
|
139
|
-
|
140
|
-
- 0
|
141
|
-
version: "0"
|
145
|
+
requirements:
|
146
|
+
- - ! '>='
|
147
|
+
- !ruby/object:Gem::Version
|
148
|
+
version: '0'
|
142
149
|
requirements: []
|
143
|
-
|
144
150
|
rubyforge_project: letsfreckle-client
|
145
|
-
rubygems_version: 1.
|
151
|
+
rubygems_version: 1.8.6.1
|
146
152
|
signing_key:
|
147
153
|
specification_version: 3
|
148
154
|
summary: Ruby client for letsfreckle.com API
|
149
|
-
test_files:
|
155
|
+
test_files:
|
150
156
|
- spec/letsfreckle/configuration_spec.rb
|
151
157
|
- spec/letsfreckle/entry_spec.rb
|
152
158
|
- spec/letsfreckle/project_spec.rb
|