ruby-freshbooks 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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