ruby-freshbooks 0.2.0 → 0.3.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/CHANGELOG +3 -0
- data/VERSION +1 -1
- data/lib/freshbooks.rb +45 -6
- data/ruby-freshbooks.gemspec +1 -1
- data/spec/freshbooks_spec.rb +9 -9
- metadata +37 -17
data/CHANGELOG
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
data/lib/freshbooks.rb
CHANGED
@@ -71,7 +71,8 @@ module FreshBooks
|
|
71
71
|
# takes nested Hash/Array combos and generates isomorphic
|
72
72
|
# XML bodies to be POSTed to FreshBooks API
|
73
73
|
def self.xml_body(method, params)
|
74
|
-
xml = Builder::XmlMarkup.new
|
74
|
+
xml = Builder::XmlMarkup.new(:indent => 2)
|
75
|
+
xml.instruct! :xml, :version=>"1.0", :encoding=>"utf-8"
|
75
76
|
xml.tag!("request", :method => method) do
|
76
77
|
build_xml(params, xml)
|
77
78
|
end
|
@@ -79,8 +80,7 @@ module FreshBooks
|
|
79
80
|
end
|
80
81
|
|
81
82
|
# helper method to xml_body
|
82
|
-
def self.build_xml(obj,
|
83
|
-
xml = Builder::XmlMarkup.new(:target => target)
|
83
|
+
def self.build_xml(obj, xml=Builder::XmlMarkup.new)
|
84
84
|
# ZOMG! haven't you ever heard of polymorphism?!?
|
85
85
|
# of course. I'm simply electing not to pollute the
|
86
86
|
# method space of two of the most common Ruby classes.
|
@@ -88,9 +88,15 @@ module FreshBooks
|
|
88
88
|
# be used in a context where some other library hasn't
|
89
89
|
# already defined #to_xml on Hash...
|
90
90
|
case obj
|
91
|
-
when Hash
|
92
|
-
|
93
|
-
|
91
|
+
when Hash
|
92
|
+
obj.each do |k,v|
|
93
|
+
if [Hash, Array].include?(v.class)
|
94
|
+
xml.tag!(k) { build_xml(v, xml) }
|
95
|
+
else
|
96
|
+
xml.__send__(k, v)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
when Array then obj.each { |e| build_xml(e, xml) }
|
94
100
|
end
|
95
101
|
xml.target!
|
96
102
|
end
|
@@ -110,6 +116,39 @@ module FreshBooks
|
|
110
116
|
client.post "#{namespace}.#{sym}", *args
|
111
117
|
end
|
112
118
|
end
|
119
|
+
|
120
|
+
class FreshBooksAPIRequest < HTTParty::Request
|
121
|
+
private
|
122
|
+
# HACK
|
123
|
+
# FreshBooks' API unfortunately redirects to a login search
|
124
|
+
# html page if you specify an endpoint that doesn't exist
|
125
|
+
# (i.e. typo in subdomain) instead of returning a 404
|
126
|
+
def handle_response
|
127
|
+
if loc = last_response['location'] and loc.match /loginSearch\.php$/
|
128
|
+
resp = Net::HTTPNotFound.new(1.1, 404, "Not Found")
|
129
|
+
resp.instance_variable_set :@read, true
|
130
|
+
resp.instance_variable_set :@body, <<EOS
|
131
|
+
<?xml version="1.0" encoding="utf-8"?>
|
132
|
+
<response xmlns="http://www.freshbooks.com/api/" status="fail">
|
133
|
+
<error>Not Found. Verify FreshBooks API endpoint</error>
|
134
|
+
</response>
|
135
|
+
EOS
|
136
|
+
self.last_response = resp
|
137
|
+
end
|
138
|
+
super
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
def self.post(path, options={}) # :nodoc:
|
143
|
+
perform_freshbooks_api_request Net::HTTP::Post, path, options
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
def self.perform_freshbooks_api_request(http_method, path, options) #:nodoc:
|
148
|
+
options = default_options.dup.merge(options)
|
149
|
+
process_cookies(options)
|
150
|
+
FreshBooksAPIRequest.new(http_method, path, options).perform
|
151
|
+
end
|
113
152
|
end
|
114
153
|
|
115
154
|
# Basic Auth client. uses an account's API token.
|
data/ruby-freshbooks.gemspec
CHANGED
@@ -4,7 +4,7 @@ Gem::Specification.new do |s|
|
|
4
4
|
|
5
5
|
s.required_rubygems_version = Gem::Requirement.new(">= 1.2") if s.respond_to? :required_rubygems_version=
|
6
6
|
s.authors = ["Justin Giancola"]
|
7
|
-
s.date =
|
7
|
+
s.date = Date.today.to_s
|
8
8
|
s.description = %q{simple FreshBooks API wrapper. supports both OAuth and API token authentication}
|
9
9
|
s.email = %q{elucid@gmail.com}
|
10
10
|
s.files = ["README.md", "LICENSE", "VERSION", "CHANGELOG", "ruby-freshbooks.gemspec", "lib/freshbooks.rb", "lib/ruby-freshbooks.rb", "spec/freshbooks_spec.rb"]
|
data/spec/freshbooks_spec.rb
CHANGED
@@ -1,56 +1,56 @@
|
|
1
|
-
require 'freshbooks'
|
1
|
+
require 'lib/ruby-freshbooks'
|
2
2
|
|
3
3
|
def build_xml(data)
|
4
|
-
FreshBooks::Client.build_xml data
|
4
|
+
FreshBooks::Client.build_xml data, Builder::XmlMarkup.new(:indent => 2)
|
5
5
|
end
|
6
6
|
|
7
7
|
describe "XML generation:" do
|
8
8
|
describe "simple hash" do
|
9
9
|
it "should serialize correctly" do
|
10
10
|
data = {"foo" => "bar"}
|
11
|
-
build_xml(data).should == "<foo>bar</foo
|
11
|
+
build_xml(data).should == "<foo>bar</foo>\n"
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
15
|
describe "simple hash with Fixnum value" do
|
16
16
|
it "should serialize correctly, coercing to string" do
|
17
17
|
data = {"foo" => 1}
|
18
|
-
build_xml(data).should == "<foo>1</foo
|
18
|
+
build_xml(data).should == "<foo>1</foo>\n"
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "simple hash value containing entity" do
|
23
23
|
it "should serialize correctly, escaping entity" do
|
24
24
|
data = {"foo" => "b&r"}
|
25
|
-
build_xml(data).should == "<foo>b&r</foo
|
25
|
+
build_xml(data).should == "<foo>b&r</foo>\n"
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
29
|
describe "nested hash" do
|
30
30
|
it "should serialize correctly" do
|
31
31
|
data = {"foo" => {"bar" => "baz"}}
|
32
|
-
build_xml(data).should == "<foo
|
32
|
+
build_xml(data).should == "<foo>\n <bar>baz</bar>\n</foo>\n"
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
describe "deeply nested hash" do
|
37
37
|
it "should serialize correctly" do
|
38
38
|
data = {"foo" => {"bar" => {"baz" => "bat"}}}
|
39
|
-
build_xml(data).should == "<foo
|
39
|
+
build_xml(data).should == "<foo>\n <bar>\n <baz>bat</baz>\n </bar>\n</foo>\n"
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
43
|
describe "array" do
|
44
44
|
it "should serialize correctly" do
|
45
45
|
data = [{"bar" => "baz"}, {"bar" => "baz"}]
|
46
|
-
build_xml(data).should == "<bar>baz</bar
|
46
|
+
build_xml(data).should == "<bar>baz</bar>\n<bar>baz</bar>\n"
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
50
|
describe "hash with array" do
|
51
51
|
it "should serialize correctly" do
|
52
52
|
data = {"foo" => [{"bar" => "baz"}, {"bar" => "baz"}]}
|
53
|
-
build_xml(data).should == "<foo
|
53
|
+
build_xml(data).should == "<foo>\n <bar>baz</bar>\n <bar>baz</bar>\n</foo>\n"
|
54
54
|
end
|
55
55
|
end
|
56
56
|
end
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-freshbooks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 3
|
8
|
+
- 0
|
9
|
+
version: 0.3.0
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Justin Giancola
|
@@ -9,39 +14,51 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-05-26 00:00:00 -04:00
|
13
18
|
default_executable:
|
14
19
|
dependencies:
|
15
20
|
- !ruby/object:Gem::Dependency
|
16
21
|
name: httparty
|
17
|
-
|
18
|
-
|
19
|
-
version_requirements: !ruby/object:Gem::Requirement
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
20
24
|
requirements:
|
21
25
|
- - ">="
|
22
26
|
- !ruby/object:Gem::Version
|
27
|
+
segments:
|
28
|
+
- 0
|
29
|
+
- 5
|
30
|
+
- 0
|
23
31
|
version: 0.5.0
|
24
|
-
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
25
34
|
- !ruby/object:Gem::Dependency
|
26
35
|
name: builder
|
27
|
-
|
28
|
-
|
29
|
-
version_requirements: !ruby/object:Gem::Requirement
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
30
38
|
requirements:
|
31
39
|
- - ">="
|
32
40
|
- !ruby/object:Gem::Version
|
41
|
+
segments:
|
42
|
+
- 2
|
43
|
+
- 1
|
44
|
+
- 2
|
33
45
|
version: 2.1.2
|
34
|
-
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
35
48
|
- !ruby/object:Gem::Dependency
|
36
49
|
name: rspec
|
37
|
-
|
38
|
-
|
39
|
-
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
40
52
|
requirements:
|
41
53
|
- - ">="
|
42
54
|
- !ruby/object:Gem::Version
|
55
|
+
segments:
|
56
|
+
- 1
|
57
|
+
- 3
|
58
|
+
- 0
|
43
59
|
version: 1.3.0
|
44
|
-
|
60
|
+
type: :development
|
61
|
+
version_requirements: *id003
|
45
62
|
description: simple FreshBooks API wrapper. supports both OAuth and API token authentication
|
46
63
|
email: elucid@gmail.com
|
47
64
|
executables: []
|
@@ -72,18 +89,21 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
72
89
|
requirements:
|
73
90
|
- - ">="
|
74
91
|
- !ruby/object:Gem::Version
|
92
|
+
segments:
|
93
|
+
- 0
|
75
94
|
version: "0"
|
76
|
-
version:
|
77
95
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
78
96
|
requirements:
|
79
97
|
- - ">="
|
80
98
|
- !ruby/object:Gem::Version
|
99
|
+
segments:
|
100
|
+
- 1
|
101
|
+
- 2
|
81
102
|
version: "1.2"
|
82
|
-
version:
|
83
103
|
requirements: []
|
84
104
|
|
85
105
|
rubyforge_project:
|
86
|
-
rubygems_version: 1.3.
|
106
|
+
rubygems_version: 1.3.6
|
87
107
|
signing_key:
|
88
108
|
specification_version: 3
|
89
109
|
summary: simple FreshBooks API wrapper. supports both OAuth and API token authentication
|