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 CHANGED
@@ -1,3 +1,6 @@
1
+ == 0.3.0
2
+ * added LoggingClient example, pretty printing for generated xml, terrible hack to cover weird response FreshBooks' API gives instead of 404s
3
+
1
4
  == 0.2.0
2
5
  * added support for OAuth authentication
3
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.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, target='')
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 then obj.each { |k,v| xml.tag!(k) { build_xml(v, xml) } }
92
- when Array then obj.each { |e| build_xml(e ,xml) }
93
- else xml.text! obj.to_s
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.
@@ -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 = %q{2010-04-25}
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"]
@@ -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&amp;r</foo>"
25
+ build_xml(data).should == "<foo>b&amp;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><bar>baz</bar></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><bar><baz>bat</baz></bar></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><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><bar>baz</bar><bar>baz</bar></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
- version: 0.2.0
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-04-25 00:00:00 -04:00
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
- type: :runtime
18
- version_requirement:
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
- version:
32
+ type: :runtime
33
+ version_requirements: *id001
25
34
  - !ruby/object:Gem::Dependency
26
35
  name: builder
27
- type: :runtime
28
- version_requirement:
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
- version:
46
+ type: :runtime
47
+ version_requirements: *id002
35
48
  - !ruby/object:Gem::Dependency
36
49
  name: rspec
37
- type: :development
38
- version_requirement:
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
- version:
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.5
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