kelredd-wesabe 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/README.rdoc ADDED
@@ -0,0 +1,39 @@
1
+ = Wesabe
2
+
3
+ == Description
4
+
5
+ A simplistic gem to assist in consuming the Wesabe API.
6
+
7
+ == Installation
8
+
9
+ sudo gem install kelredd-wesabe --source http://gems.github.com
10
+
11
+ == Usage
12
+
13
+ require 'wesabe'
14
+ # then include any wesabe helpers into your own models or scripts
15
+
16
+ == License
17
+
18
+ Copyright (c) 2009 Kelly Redding
19
+
20
+ Permission is hereby granted, free of charge, to any person
21
+ obtaining a copy of this software and associated documentation
22
+ files (the "Software"), to deal in the Software without
23
+ restriction, including without limitation the rights to use,
24
+ copy, modify, merge, publish, distribute, sublicense, and/or sell
25
+ copies of the Software, and to permit persons to whom the
26
+ Software is furnished to do so, subject to the following
27
+ conditions:
28
+
29
+ The above copyright notice and this permission notice shall be
30
+ included in all copies or substantial portions of the Software.
31
+
32
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
33
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
34
+ OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
35
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
36
+ HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
37
+ WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
38
+ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
39
+ OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,41 @@
1
+ require 'rubygems'
2
+ require 'rake/gempackagetask'
3
+ require 'rake/testtask'
4
+
5
+ require 'lib/wesabe/version'
6
+
7
+ task :default => :test
8
+
9
+ spec = Gem::Specification.new do |s|
10
+ s.name = 'wesabe'
11
+ s.version = Wesabe::Version.to_s
12
+ s.has_rdoc = true
13
+ s.extra_rdoc_files = %w(README.rdoc)
14
+ s.rdoc_options = %w(--main README.rdoc)
15
+ s.summary = "A simplistic gem to assist in consuming the Wesabe API."
16
+ s.author = 'Kelly Redding'
17
+ s.email = 'kelly@kelredd.com'
18
+ s.homepage = ''
19
+ s.files = %w(README.rdoc Rakefile) + Dir.glob("{lib,test}/**/*")
20
+ # s.executables = ['wesabe']
21
+
22
+ s.add_dependency('nokogiri', '> 1.2.3')
23
+ s.add_dependency('rest-client', '> 0.9.2')
24
+ end
25
+
26
+ Rake::GemPackageTask.new(spec) do |pkg|
27
+ pkg.gem_spec = spec
28
+ end
29
+
30
+ Rake::TestTask.new do |t|
31
+ t.libs << 'test'
32
+ t.test_files = FileList["test/**/*_test.rb"]
33
+ t.verbose = true
34
+ end
35
+
36
+ desc 'Generate the gemspec to serve this Gem from Github'
37
+ task :github do
38
+ file = File.dirname(__FILE__) + "/#{spec.name}.gemspec"
39
+ File.open(file, 'w') {|f| f << spec.to_ruby }
40
+ puts "Created gemspec: #{file}"
41
+ end
@@ -0,0 +1,5 @@
1
+ module Wesabe
2
+ API_SITE = 'https://www.wesabe.com'
3
+ API_CONTENT_TYPES = ['application/xml']
4
+ API_DEFAULT_CONTENT_TYPE = API_CONTENT_TYPES.first
5
+ end
@@ -0,0 +1,8 @@
1
+ module Wesabe
2
+ class NotConfigured < StandardError
3
+ end
4
+ class ResourceAPIError < StandardError
5
+ end
6
+ class ResourceParseError < StandardError
7
+ end
8
+ end
@@ -0,0 +1,60 @@
1
+ require 'cgi'
2
+
3
+ module Wesabe
4
+ module Extensions
5
+ module String
6
+
7
+ module ClassMethods; end
8
+ def self.included(klass)
9
+ klass.extend(ClassMethods) if klass.kind_of?(Class)
10
+ end
11
+
12
+ module ClassMethods
13
+ end
14
+
15
+ def to_datetime
16
+ DateTime.strptime(self) rescue nil
17
+ end
18
+ def to_date
19
+ Date.strptime(self) rescue nil
20
+ end
21
+
22
+ end
23
+ end
24
+ end
25
+
26
+ module Wesabe
27
+ module Extensions
28
+ module Hash
29
+
30
+ module ClassMethods; end
31
+ def self.included(klass)
32
+ klass.extend(ClassMethods) if klass.kind_of?(Class)
33
+ end
34
+
35
+ module ClassMethods
36
+ end
37
+
38
+ # Returns string formatted for HTTP URL encoded name-value pairs.
39
+ # For example,
40
+ # {:id => 'thomas_hardy'}.to_http_str
41
+ # # => "id=thomas_hardy"
42
+ # {:id => 23423, :since => Time.now}.to_http_str
43
+ # # => "since=Thu,%2021%20Jun%202007%2012:10:05%20-0500&id=23423"
44
+ def to_http_query_str(opts = {})
45
+ opts[:prepend] ||= '?'
46
+ opts[:append] ||= ''
47
+ self.empty? ? '' : "#{opts[:prepend]}#{self.collect{|key, val| "#{key.to_s}=#{CGI.escape(val.to_s)}"}.join('&')}#{opts[:append]}"
48
+ end
49
+
50
+ end
51
+ end
52
+ end
53
+
54
+ class String
55
+ include Wesabe::Extensions::String
56
+ end
57
+
58
+ class Hash
59
+ include Wesabe::Extensions::Hash
60
+ end
@@ -0,0 +1,50 @@
1
+ %w(base institution).each do |file|
2
+ require File.join(File.dirname(__FILE__), "#{file}.rb")
3
+ end
4
+
5
+ module Wesabe
6
+ module Model
7
+ class Account < Wesabe::Model::Base
8
+
9
+ def self.find(id)
10
+ case id
11
+ when :all
12
+ find_collection("/accounts", "//accounts/account")
13
+ else
14
+ super("/accounts/#{id}", "//account")
15
+ end
16
+ end
17
+
18
+ attribute :id, :integer, :path => "id"
19
+ attribute :key, :string, :path => "guid"
20
+ attribute :number, :string, :path => "account-number"
21
+ attribute :name, :string, :path => "name"
22
+ attribute :account_type, :string, :path => "account-type"
23
+ attribute :balance, :float, :path => "current-balance"
24
+ attribute :last_uploaded_at, :datetime, :path => "last-uploaded-at"
25
+ attribute :oldest_transaction_on, :date, :path => "oldest-txaction"
26
+ attribute :newest_transaction_on, :date, :path => "newest-txaction"
27
+
28
+ def institution
29
+ @institution ||= Wesabe::Model::Institution.new(get_node('./financial-institution'))
30
+ end
31
+
32
+ def currency
33
+ node = get_node('./currency')
34
+ @currency ||= {
35
+ :symbol => node['symbol'],
36
+ :delimiter => node['delimiter'],
37
+ :separator => node['separator'],
38
+ :decimal_places => node['decimal_places'],
39
+ :type => node.content.to_s
40
+ }
41
+ end
42
+
43
+ def to_s
44
+ self.id
45
+ end
46
+
47
+ end
48
+
49
+ end
50
+ end
@@ -0,0 +1,136 @@
1
+ %w(rubygems rest_client nokogiri).each do |lib|
2
+ require lib
3
+ end
4
+ %w(configuration exceptions extensions).each do |file|
5
+ require File.join(File.dirname(__FILE__), "..", "#{file}.rb")
6
+ end
7
+
8
+ module Wesabe
9
+ module Model
10
+
11
+ class Base
12
+ @@user = nil
13
+ @@password = nil
14
+ @@content_type = Wesabe::API_DEFAULT_CONTENT_TYPE
15
+
16
+ def self.resource
17
+ RestClient::Resource.new(Wesabe::API_SITE, :user => @@user, :password => @@password, :content_type => @@content_type)
18
+ end
19
+ @@api = resource
20
+ @@api_cache = {}
21
+
22
+ attr_reader :xml
23
+
24
+ def self.configure(opts={})
25
+ @@user = opts[:user]
26
+ @@password = opts[:password]
27
+ @@content_type = opts[:content_type] if opts[:content_type] && Wesabe::API_CONTENT_TYPES.include?(opts[:content_type])
28
+ @@api = resource
29
+ end
30
+
31
+ def self.find(path, xpath)
32
+ new(get_xml(path).xpath(xpath))
33
+ end
34
+ def self.find_collection(path, xpath)
35
+ get_xml(path).xpath(xpath).collect{|item_xml| new(item_xml)}
36
+ end
37
+
38
+ def initialize(xml)
39
+ @xml = xml
40
+ end
41
+
42
+ protected
43
+
44
+ def self.get_xml(path)
45
+ self.resource_xml(:get, path)
46
+ end
47
+ def self.resource_xml(verb, path, force=false)
48
+ summary = "#{verb.to_s.upcase} #{@@api.url}#{path}"
49
+ key = cache_key(verb, path)
50
+ begin
51
+ resp = @@api_cache[key]
52
+ if resp.nil? || force
53
+ base_config_check
54
+ p "** Wesabe API: #{summary}"
55
+ resp = case verb.to_sym
56
+ when :get
57
+ @@api["#{path}"].get
58
+ end
59
+ @@api_cache[key] = resp
60
+ else
61
+ p "** Wesabe API: [cache] #{summary}."
62
+ end
63
+ rescue Exception => err
64
+ raise Wesabe::ResourceAPIError, "error with API resource: #{summary}: #{err.message}"
65
+ end
66
+ begin
67
+ xml = Nokogiri::XML(resp.to_s)
68
+ rescue Exception => err
69
+ raise Wesabe::ResourceParseError, "error parsing API resource [#{@@content_type}]: #{summary}: #{err.message}: Response: #{resp.to_s}"
70
+ end
71
+ xml
72
+ end
73
+
74
+ def self.attribute(name, type, config)
75
+ raise Wesabe::NotConfigured, "no path provided for selecting the attribute '#{name}'." unless config[:path]
76
+ content_method = case type.to_sym
77
+ when :string
78
+ 'to_s'
79
+ when :integer
80
+ 'to_i'
81
+ when :float
82
+ 'to_f'
83
+ when :date
84
+ 'to_date'
85
+ when :datetime
86
+ 'to_datetime'
87
+ else
88
+ 'to_s'
89
+ end
90
+ define_method(name) do
91
+ instance_variable_get("@#{name}") || instance_variable_set("@#{name}", get_node("./#{config[:path]}").content.send(content_method))
92
+ end
93
+ end
94
+ def self.get_node(xml, path)
95
+ xml.xpath(path.to_s).first
96
+ end
97
+ def get_node(path)
98
+ self.class.get_node(@xml, path)
99
+ end
100
+
101
+ def self.xml_root_name(xml)
102
+ xml.root.name
103
+ end
104
+ def xml_root_name
105
+ self.class.xml_root_name(@xml)
106
+ end
107
+
108
+ def self.cache_key(path, verb)
109
+ "#{verb}_#{path}"
110
+ end
111
+
112
+ def self.clear_cache
113
+ @@api_cache = {}
114
+ end
115
+
116
+ def self.base_config_check
117
+ raise Wesabe::NotConfigured, "No user provided to access the Wesabe API" if blank?(@@user)
118
+ raise Wesabe::NotConfigured, "No password provided to access the Wesabe API" if blank?(@@password)
119
+ raise Wesabe::NotConfigured, "Wesabe not configured to access the API." if blank?(@@api)
120
+ end
121
+ def base_config_check
122
+ self.class.base_config_check
123
+ end
124
+
125
+ def self.blank?(value)
126
+ value.nil? || (value.respond_to?('empty?') ? value.empty? : false)
127
+ end
128
+ def blank?(value)
129
+ self.class.blank?(value)
130
+ end
131
+
132
+
133
+ end
134
+
135
+ end
136
+ end
@@ -0,0 +1,16 @@
1
+ %w(base).each do |file|
2
+ require File.join(File.dirname(__FILE__), "#{file}.rb")
3
+ end
4
+
5
+ module Wesabe
6
+ module Model
7
+
8
+ class Institution < Wesabe::Model::Base
9
+
10
+ attribute :key, :string, :path => "id"
11
+ attribute :name, :string, :path => "name"
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,16 @@
1
+ %w(base).each do |file|
2
+ require File.join(File.dirname(__FILE__), "#{file}.rb")
3
+ end
4
+
5
+ module Wesabe
6
+ module Model
7
+
8
+ class Merchant < Wesabe::Model::Base
9
+
10
+ attribute :key, :string, :path => "id"
11
+ attribute :name, :string, :path => "name"
12
+
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,38 @@
1
+ %w(base account merchant).each do |file|
2
+ require File.join(File.dirname(__FILE__), "#{file}.rb")
3
+ end
4
+
5
+ module Wesabe
6
+ module Model
7
+ class Txaction < Wesabe::Model::Base
8
+
9
+ def self.find(opts={})
10
+ acct = opts.delete(:account)
11
+ path = (acct ? "/accounts/#{acct.to_s}.xml" : "/transactions.xml")
12
+ path += opts.to_http_query_str if opts.respond_to?('to_http_query_str')
13
+ find_collection(path, "//txactions/txaction")
14
+ end
15
+
16
+ attribute :key, :string, :path => "guid"
17
+ attribute :account_id, :string, :path => "account-id"
18
+ attribute :date, :date, :path => "date"
19
+ attribute :original_date, :date, :path => "original-date"
20
+ attribute :amount, :float, :path => "amount"
21
+ attribute :display_name, :string, :path => "display-name"
22
+ attribute :raw_name, :string, :path => "raw-name"
23
+ attribute :raw_type, :string, :path => "raw-txntype"
24
+ attribute :memo, :string, :path => "memo"
25
+ attribute :transfer_key, :string, :path => "transfer/guid"
26
+
27
+ def account
28
+ @account ||= Wesabe::Model::Account.find(self.account_id)
29
+ end
30
+
31
+ def merchant
32
+ @merchant ||= (get_node('./merchant') ? Wesabe::Model::Merchant.new(get_node('./merchant')) : nil)
33
+ end
34
+
35
+ end
36
+
37
+ end
38
+ end
@@ -0,0 +1,3 @@
1
+ Dir[File.join(File.dirname(__FILE__), "model" ,"*.rb")].each do |file|
2
+ require file
3
+ end
@@ -0,0 +1,13 @@
1
+ module Wesabe
2
+ module Version
3
+
4
+ MAJOR = 0
5
+ MINOR = 0
6
+ TINY = 2
7
+
8
+ def self.to_s # :nodoc:
9
+ [MAJOR, MINOR, TINY].join('.')
10
+ end
11
+
12
+ end
13
+ end
data/lib/wesabe.rb ADDED
@@ -0,0 +1,4 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'wesabe/model'
4
+
@@ -0,0 +1,10 @@
1
+ # http://sneaq.net/textmate-wtf
2
+ $:.reject! { |e| e.include? 'TextMate' }
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'matchy'
7
+ require 'context'
8
+ require 'mocha'
9
+
10
+ require File.dirname(__FILE__) + '/../lib/wesabe'
@@ -0,0 +1,13 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class WesabeTest < Test::Unit::TestCase
4
+
5
+ describe "An instance of the Wesabe class" do
6
+
7
+ it "should flunk" do
8
+ flunk "Please provide some tests"
9
+ end
10
+
11
+ end
12
+
13
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kelredd-wesabe
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Kelly Redding
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-06-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: nokogiri
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 1.2.3
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: rest-client
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: 0.9.2
34
+ version:
35
+ description:
36
+ email: kelly@kelredd.com
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.rdoc
43
+ files:
44
+ - README.rdoc
45
+ - Rakefile
46
+ - lib/wesabe
47
+ - lib/wesabe/configuration.rb
48
+ - lib/wesabe/exceptions.rb
49
+ - lib/wesabe/extensions.rb
50
+ - lib/wesabe/model
51
+ - lib/wesabe/model/account.rb
52
+ - lib/wesabe/model/base.rb
53
+ - lib/wesabe/model/institution.rb
54
+ - lib/wesabe/model/merchant.rb
55
+ - lib/wesabe/model/txaction.rb
56
+ - lib/wesabe/model.rb
57
+ - lib/wesabe/version.rb
58
+ - lib/wesabe.rb
59
+ - test/test_helper.rb
60
+ - test/unit
61
+ - test/unit/wesabe_test.rb
62
+ has_rdoc: true
63
+ homepage: ""
64
+ post_install_message:
65
+ rdoc_options:
66
+ - --main
67
+ - README.rdoc
68
+ require_paths:
69
+ - lib
70
+ required_ruby_version: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: "0"
75
+ version:
76
+ required_rubygems_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - ">="
79
+ - !ruby/object:Gem::Version
80
+ version: "0"
81
+ version:
82
+ requirements: []
83
+
84
+ rubyforge_project:
85
+ rubygems_version: 1.2.0
86
+ signing_key:
87
+ specification_version: 2
88
+ summary: A simplistic gem to assist in consuming the Wesabe API.
89
+ test_files: []
90
+