syrup 0.0.1 → 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.
@@ -1,10 +1,14 @@
1
- module Syrup
2
- class Transaction
3
- attr_accessor :payee, :amount, :posted_at
4
- def initialize(attr_hash)
5
- attr_hash.each do |k, v|
6
- instance_variable_set "@#{k}", v
7
- end
8
- end
9
- end
1
+ module Syrup
2
+ class Transaction
3
+ # known statuses are :posted and :pending
4
+ attr_accessor :id, :payee, :amount, :posted_at, :status
5
+
6
+ def initialize(attr_hash = nil)
7
+ if attr_hash
8
+ attr_hash.each do |k, v|
9
+ instance_variable_set "@#{k}", v
10
+ end
11
+ end
12
+ end
13
+ end
10
14
  end
data/lib/syrup/version.rb CHANGED
@@ -1,3 +1,3 @@
1
- module Syrup
2
- VERSION = "0.0.1"
3
- end
1
+ module Syrup
2
+ VERSION = "0.0.2"
3
+ end
data/lib/syrup.rb CHANGED
@@ -1,10 +1,27 @@
1
- require 'date'
2
- require 'mechanize'
3
- require 'active_support/json'
4
- require 'syrup/extract'
5
- require 'syrup/account'
6
- require 'syrup/transaction'
7
-
8
- # require all institutions
9
- require 'syrup/institutions/abstract_institution'
10
- Dir[File.dirname(__FILE__) + '/syrup/institutions/*.rb'].each {|file| require file }
1
+ require 'date'
2
+ require 'mechanize'
3
+ require 'active_support/json'
4
+ require 'syrup/information_missing_error'
5
+ require 'syrup/account'
6
+ require 'syrup/transaction'
7
+
8
+ # require all institutions
9
+ require 'syrup/institutions/institution_base'
10
+ Dir[File.dirname(__FILE__) + '/syrup/institutions/*.rb'].each {|file| require file }
11
+
12
+ module Syrup
13
+ extend self
14
+
15
+ def institutions
16
+ Institutions::InstitutionBase.subclasses
17
+ end
18
+
19
+ def setup_institution(institution_id)
20
+ institution = institutions.find { |i| i.id == institution_id }
21
+
22
+ if institution
23
+ i = institution.new
24
+ i.setup { |config| yield config }
25
+ end
26
+ end
27
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,25 +1,15 @@
1
- #require 'rubygems'
2
- #require 'bundler/setup'
3
-
4
- Bundler.require(:default)
5
-
6
- #RSpec.configure do |config|
7
- # config.mock_with :rr
8
- # config.before(:each) do
9
- #
10
- # end
11
- #end
12
-
13
-
14
- # pass in username, password, secret questions
15
-
16
- # zions.fetch_accounts
17
- # should I store things?
18
- # List accounts
19
- # * create an array of Account objects
20
-
21
- # account.transactions OR account.fetch_transactions
22
- # zions.
23
- # When getting transactions
24
- # * create an array of Transaction objects
25
- # * populate as many variables on Account as you can (eg. current_balance, etc.)
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'syrup'
4
+
5
+ RSpec.configure do |config|
6
+ include Syrup
7
+
8
+ config.filter_run_excluding :bank_integration => true
9
+ end
10
+
11
+ module Syrup
12
+ def spec_resource_path
13
+ File.dirname(__FILE__) + '/resources/'
14
+ end
15
+ end
@@ -0,0 +1,53 @@
1
+ require "spec_helper"
2
+
3
+ describe Account do
4
+ before(:each) do
5
+ @institution = double()
6
+ @institution.stub(:populate_account) do
7
+ @account.populated = true
8
+ @account.instance_variable_set :@name, 'my name'
9
+ end
10
+ @institution.stub(:fetch_transactions) do
11
+ [
12
+ Transaction.new(:id => 1, :payee => 'Wal-Mart', :posted_at => Date.today - 1, :amount => 30.14),
13
+ Transaction.new(:id => 2, :payee => 'Pizza Hut', :posted_at => Date.today - 2, :amount => 10.23)
14
+ ]
15
+ end
16
+ @account = Account.new :id => 1, :institution => @institution
17
+ end
18
+
19
+ it "has lots of useful properties" do
20
+ account = Account.new
21
+
22
+ account.should respond_to(:id)
23
+ account.should respond_to(:name)
24
+ account.should respond_to(:type)
25
+ account.should respond_to(:account_number)
26
+ account.should respond_to(:current_balance)
27
+ account.should respond_to(:available_balance)
28
+ account.should respond_to(:prior_day_balance)
29
+ end
30
+
31
+ it "is populated when properties are accessed" do
32
+ @account.instance_variable_get(:@name).should be_nil
33
+ @account.name.should == "my name"
34
+ end
35
+
36
+ it "is considered == if the id is the same" do
37
+ account1 = Account.new :id => 1, :name => "checking"
38
+ account2 = Account.new :id => 1, :name => "savings"
39
+ account3 = Account.new :id => 2, :name => "trash"
40
+
41
+ account1.should == account2
42
+ account1.should_not == account3
43
+ end
44
+
45
+ context "given a date range" do
46
+ it "gets transactions" do
47
+ @account.find_transactions(Date.today - 30)
48
+ end
49
+ #it "only fetches transactions when needed"
50
+ end
51
+
52
+ #it "doesn't allow there to be too many cached transactions"
53
+ end
@@ -0,0 +1,120 @@
1
+ require "spec_helper"
2
+
3
+ include Institutions
4
+
5
+ describe InstitutionBase do
6
+
7
+ before(:each) do
8
+ @institution = InstitutionBase.new
9
+ @institution.stub(:fetch_accounts) do
10
+ [Account.new(:id => 1, :name => 'first')]
11
+ end
12
+ end
13
+
14
+ it "keeps a list of classes that extend it" do
15
+ InstitutionBase.subclasses.should include(ZionsBank)
16
+ end
17
+
18
+ it "can be setup" do
19
+ institution = InstitutionBase.new
20
+ institution.setup do |config|
21
+ config.username = 'username'
22
+ config.password = 'pass'
23
+ config.secret_questions = { 'Do you like candy?' => 'yes' }
24
+ end
25
+
26
+ institution.username.should == 'username'
27
+ institution.password.should == 'pass'
28
+ institution.secret_questions['Do you like candy?'].should == 'yes'
29
+ end
30
+
31
+ context "when accounts are NOT populated" do
32
+ it "fetches them when accessed" do
33
+ @institution.should_receive :fetch_accounts
34
+ @institution.accounts
35
+ end
36
+
37
+ it "returns an account with the id populated" do
38
+ account = @institution.find_account_by_id 21
39
+ account.id.should == 21
40
+ end
41
+
42
+ it "returns a previously created account if one exists" do
43
+ original_account = @institution.find_account_by_id 3
44
+ different_account = Account.new(:id => 3)
45
+
46
+ new_account = @institution.find_account_by_id 3
47
+ new_account.should be(original_account)
48
+ new_account.should_not be(different_account)
49
+ end
50
+ end
51
+
52
+ context "when accounts are populated" do
53
+ before(:each) do
54
+ @institution.populated = true
55
+ end
56
+
57
+ it "doesn't fetch them again" do
58
+ @institution.should_not_receive :fetch_accounts
59
+ @institution.accounts
60
+ end
61
+
62
+ it "returns nil if asked for a non-existent account" do
63
+ account = @institution.find_account_by_id 21
64
+ account.should be_nil
65
+ end
66
+ end
67
+
68
+
69
+ context "while populating accounts" do
70
+ it "filters out non-existent accounts" do
71
+ @institution.find_account_by_id 21
72
+ @institution.accounts.each do |a|
73
+ a.id.should_not be(21)
74
+ end
75
+ end
76
+
77
+ it "populates data in existent accounts" do
78
+ account = @institution.find_account_by_id 1
79
+ @institution.populate_accounts
80
+ account.name.should == 'first'
81
+ end
82
+
83
+ it "marks accounts as populated" do
84
+ @institution.accounts.each do |account|
85
+ account.populated?.should be_true
86
+ end
87
+ end
88
+
89
+ it "marks invalid accounts as invalid" do
90
+ account = @institution.find_account_by_id 21
91
+ @institution.populate_accounts
92
+ account.valid?.should be_false
93
+ end
94
+ end
95
+
96
+ context "when asked to populate one account" do
97
+ it "populates one account" do
98
+ @institution.stub(:fetch_account) do
99
+ Account.new :id => 2, :name => 'single account'
100
+ end
101
+
102
+ account = @institution.populate_account(2)
103
+ account.name.should == 'single account'
104
+ account.populated?.should be_true
105
+ end
106
+
107
+ it "can populate all accounts" do
108
+ @institution.stub(:fetch_account) do
109
+ [Account.new(:id => 2, :name => 'single account')]
110
+ end
111
+
112
+ invalid_account = @institution.find_account_by_id 21
113
+ @institution.populate_account(2)
114
+ @institution.populated?.should be_true
115
+ end
116
+ end
117
+
118
+ # it "populates transactions"
119
+
120
+ end
@@ -1,5 +1,26 @@
1
- require "spec_helper"
2
-
3
- describe Syrup::Institutions::ZionsBank do
4
- it "lists all accounts"
1
+ require "spec_helper"
2
+
3
+ include Institutions
4
+
5
+ describe ZionsBank, :bank_integration => true do
6
+ before(:each) do
7
+ @bank = ZionsBank.new
8
+ @bank.setup do |config|
9
+ config.username = ""
10
+ config.password = ""
11
+ config.secret_questions = {}
12
+ end
13
+ end
14
+
15
+ it "fetches one account"
16
+ it "fetches all accounts" do
17
+ accounts = @bank.fetch_accounts
18
+ accounts.each do |account|
19
+ puts "#{account.id} #{account.name}"
20
+ end
21
+ end
22
+
23
+ it "fetches transactions given a date range" do
24
+ @bank.fetch_transactions
25
+ end
5
26
  end
@@ -0,0 +1,41 @@
1
+ require "spec_helper"
2
+
3
+ describe Syrup do
4
+ it "lists all institutions" do
5
+ institution_list = Syrup.institutions
6
+
7
+ institution_list.size.should be(1)
8
+
9
+ institution_list.should include(Institutions::ZionsBank)
10
+
11
+ institution_list.each do |institution|
12
+ institution.should respond_to(:name)
13
+ institution.should respond_to(:id)
14
+
15
+ inst = institution.new
16
+ inst.should respond_to(:fetch_account)
17
+ inst.should respond_to(:fetch_accounts)
18
+ inst.should respond_to(:fetch_transactions)
19
+ end
20
+ end
21
+
22
+ it "returns nil if you try to setup an unknown institution" do
23
+ Syrup.setup_institution('unknown').should be_nil
24
+ end
25
+
26
+ it "sets up a Zions Bank institution" do
27
+ username = "user"
28
+ password = "pass"
29
+ secret_questions = { 'Do you eat?' => 'yes' }
30
+
31
+ zions = Syrup.setup_institution('zions_bank') do |config|
32
+ config.username = username
33
+ config.password = password
34
+ config.secret_questions = secret_questions
35
+ end
36
+
37
+ zions.should_not be_nil
38
+ zions.class.should be(Syrup::Institutions::ZionsBank)
39
+ zions.username.should be(username)
40
+ end
41
+ end
@@ -1,20 +1,21 @@
1
- require "spec_helper"
2
-
3
- describe Syrup::Transaction do
4
- before(:all) do
5
- @transaction = Syrup::Transaction.new :amount => 10, :payee => "Newegg", :posted_at => DateTime.now
6
- end
7
-
8
- it "has an amount" do
9
- @transaction.amount.should_not be_nil
10
- end
11
-
12
- it "has a payee" do
13
- @transaction.payee.should_not be_nil
14
- end
15
-
16
- it "has a posted-at date" do
17
- @transaction.posted_at.should_not be_nil
18
- end
19
-
1
+ require "spec_helper"
2
+
3
+ describe Syrup::Transaction do
4
+
5
+ before(:all) do
6
+ @transaction = Transaction.new :amount => 10, :payee => "Newegg", :posted_at => DateTime.now
7
+ end
8
+
9
+ it "has an amount" do
10
+ @transaction.amount.should_not be_nil
11
+ end
12
+
13
+ it "has a payee" do
14
+ @transaction.payee.should_not be_nil
15
+ end
16
+
17
+ it "has a posted-at date" do
18
+ @transaction.posted_at.should_not be_nil
19
+ end
20
+
20
21
  end
data/syrup.gemspec CHANGED
@@ -1,26 +1,26 @@
1
- # -*- encoding: utf-8 -*-
2
- $:.push File.expand_path("../lib", __FILE__)
3
- require "syrup/version"
4
-
5
- Gem::Specification.new do |s|
6
- s.name = "syrup"
7
- s.version = Syrup::VERSION
8
- s.platform = Gem::Platform::RUBY
9
- s.authors = ["Don Wilson"]
10
- s.email = ["dontangg@gmail.com"]
11
- s.homepage = "http://github.com/dontangg/syrup"
12
- s.summary = %q{Simple account balance/transactions extractor.}
13
- s.description = %q{Simple account balance/transactions extractor by scraping bank websites.}
14
-
15
- s.add_dependency "mechanize"
16
- s.add_dependency "activesupport"
17
-
18
- s.add_development_dependency "rspec"
19
-
20
- s.rubyforge_project = s.name
21
-
22
- s.files = `git ls-files`.split("\n")
23
- s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
- s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
- s.require_paths = ["lib"]
26
- end
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "syrup/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "syrup"
7
+ s.version = Syrup::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Don Wilson"]
10
+ s.email = ["dontangg@gmail.com"]
11
+ s.homepage = "http://github.com/dontangg/syrup"
12
+ s.summary = %q{Simple account balance and transactions extractor.}
13
+ s.description = %q{Simple account balance and transactions extractor by scraping bank websites.}
14
+
15
+ s.add_dependency "mechanize"
16
+ s.add_dependency "activesupport"
17
+
18
+ s.add_development_dependency "rspec"
19
+
20
+ s.rubyforge_project = s.name
21
+
22
+ s.files = `git ls-files`.split("\n")
23
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
24
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
25
+ s.require_paths = ["lib"]
26
+ end
metadata CHANGED
@@ -1,109 +1,99 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: syrup
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
4
5
  prerelease:
5
- version: 0.0.1
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Don Wilson
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
-
13
- date: 2011-02-25 00:00:00 -07:00
14
- default_executable:
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
12
+ date: 2011-06-27 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
17
15
  name: mechanize
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
16
+ requirement: &22805304 !ruby/object:Gem::Requirement
20
17
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
24
- version: "0"
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
25
22
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: activesupport
29
23
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
24
+ version_requirements: *22805304
25
+ - !ruby/object:Gem::Dependency
26
+ name: activesupport
27
+ requirement: &22805052 !ruby/object:Gem::Requirement
31
28
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: "0"
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
36
33
  type: :runtime
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: rspec
40
34
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
35
+ version_requirements: *22805052
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ requirement: &22804800 !ruby/object:Gem::Requirement
42
39
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
46
- version: "0"
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
47
44
  type: :development
48
- version_requirements: *id003
49
- description: Simple account balance/transactions extractor by scraping bank websites.
50
- email:
45
+ prerelease: false
46
+ version_requirements: *22804800
47
+ description: Simple account balance and transactions extractor by scraping bank websites.
48
+ email:
51
49
  - dontangg@gmail.com
52
50
  executables: []
53
-
54
51
  extensions: []
55
-
56
52
  extra_rdoc_files: []
57
-
58
- files:
53
+ files:
59
54
  - .gitignore
60
55
  - .rspec
61
56
  - CHANGELOG.rdoc
62
57
  - Gemfile
63
58
  - README.rdoc
64
59
  - Rakefile
60
+ - TODO.rdoc
65
61
  - lib/syrup.rb
66
62
  - lib/syrup/account.rb
67
- - lib/syrup/extract.rb
68
- - lib/syrup/institutions/abstract_institution.rb
63
+ - lib/syrup/information_missing_error.rb
64
+ - lib/syrup/institutions/institution_base.rb
69
65
  - lib/syrup/institutions/zions_bank.rb
70
66
  - lib/syrup/transaction.rb
71
67
  - lib/syrup/version.rb
72
68
  - spec/spec_helper.rb
73
- - spec/syrup/extract_spec.rb
69
+ - spec/syrup/account_spec.rb
70
+ - spec/syrup/institutions/institution_base_spec.rb
74
71
  - spec/syrup/institutions/zions_bank_spec.rb
72
+ - spec/syrup/syrup_spec.rb
75
73
  - spec/syrup/transaction_spec.rb
76
74
  - syrup.gemspec
77
- has_rdoc: true
78
75
  homepage: http://github.com/dontangg/syrup
79
76
  licenses: []
80
-
81
77
  post_install_message:
82
78
  rdoc_options: []
83
-
84
- require_paths:
79
+ require_paths:
85
80
  - lib
86
- required_ruby_version: !ruby/object:Gem::Requirement
81
+ required_ruby_version: !ruby/object:Gem::Requirement
87
82
  none: false
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: "0"
92
- required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ! '>='
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ required_rubygems_version: !ruby/object:Gem::Requirement
93
88
  none: false
94
- requirements:
95
- - - ">="
96
- - !ruby/object:Gem::Version
97
- version: "0"
89
+ requirements:
90
+ - - ! '>='
91
+ - !ruby/object:Gem::Version
92
+ version: '0'
98
93
  requirements: []
99
-
100
94
  rubyforge_project: syrup
101
- rubygems_version: 1.5.0
95
+ rubygems_version: 1.8.5
102
96
  signing_key:
103
97
  specification_version: 3
104
- summary: Simple account balance/transactions extractor.
105
- test_files:
106
- - spec/spec_helper.rb
107
- - spec/syrup/extract_spec.rb
108
- - spec/syrup/institutions/zions_bank_spec.rb
109
- - spec/syrup/transaction_spec.rb
98
+ summary: Simple account balance and transactions extractor.
99
+ test_files: []
data/lib/syrup/extract.rb DELETED
@@ -1,14 +0,0 @@
1
- module Syrup
2
- class Extract
3
- def self.from_institution(institution_sym)
4
- class_name = institution_sym.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
5
- Institutions.const_get(class_name).new
6
- end
7
-
8
- def self.list_institutions
9
- Institutions::AbstractInstitution.subclasses.map do |subclass|
10
- subclass.institution_name
11
- end
12
- end
13
- end
14
- end
@@ -1,26 +0,0 @@
1
- module Syrup
2
- module Institutions
3
- class AbstractInstitution
4
-
5
- def self.inherited(subclass)
6
- @subclasses ||= []
7
- @subclasses << subclass
8
- end
9
-
10
- def self.subclasses
11
- @subclasses
12
- end
13
-
14
- protected
15
-
16
- def agent
17
- @agent || Mechanize.new
18
- end
19
-
20
- def parse_currency(currency)
21
- currency.scan(/[0-9.]/).join.to_f
22
- end
23
-
24
- end
25
- end
26
- end
@@ -1,12 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe Syrup::Extract do
4
- it "lists all institutions" do
5
- Syrup::Extract.list_institutions.size.should == 1
6
- puts Syrup::Extract.list_institutions
7
- end
8
-
9
- it "creates a Zions Bank institution" do
10
- Syrup::Extract.from_institution(:zions_bank).class.should == Syrup::Institutions::ZionsBank
11
- end
12
- end