ncua 0.5.0 → 0.6.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d80b3ab492107fa4574336a527522217465ac829
4
- data.tar.gz: 89b3e21b98a1feaa85d3555d4fe7a3a7b01535dc
3
+ metadata.gz: ddc3ec546e01ed562477979e46f561a9d2d92a35
4
+ data.tar.gz: 083c148ab6e1d1a38018095dc8356b6be59d1a8a
5
5
  SHA512:
6
- metadata.gz: 7f1ece268d4b81aebc6b6ac37654aa67dd1b5c2b0772caa7258b9aaa9bd87a2174f3fee57e2c838e61fcec4b8348762c6826e8ca29634216f0aebad534872457
7
- data.tar.gz: adead7d121f4afa6b779b1e8fab4890d90e0423ec508b7156e30fc39e7e984e2d677f3d09ea8858dfd0b4cd711269231900e91231bfb7f1bef58018f7e601e60
6
+ metadata.gz: ebe48264ba4e9aee02ac366b7256a73f8654406c70ba785da3076c2b29acc02c2b0955bb9f072367ff3b867e1e31872d326ae4ba0b7db84b35f433dd921e4ace
7
+ data.tar.gz: b68cff3ab80ea08baac13ac9e8a8d09221414b0095dfa46ddb83845473bb3f7bc2f090b2e555fb16466738754ed670cdb2d092411c3071c0f2760777f6c83dee
data/.gitignore CHANGED
@@ -8,3 +8,4 @@ ncua-*.gem
8
8
  /pkg/
9
9
  /spec/reports/
10
10
  /tmp/
11
+ /private/
data/README.md CHANGED
@@ -28,44 +28,81 @@ Or install it yourself as:
28
28
 
29
29
  Currently all of our features are namespaced under the `NCUA` module.
30
30
 
31
- The NCUA lets you find a Credit Union office by its name, charter number, or within an address:
31
+ The NCUA lets you find a Credit Union Office by its name, charter number, or within an address:
32
32
 
33
33
  ```ruby
34
- credit_unions = NCUA.find_by_name('Federal') #=> [NCUA::CreditUnion, ... ]
34
+ credit_unions = NCUA.find_office_by_name('Federal') #=> [NCUA::CreditUnion::Office, ... ]
35
35
  ```
36
36
 
37
- You can `find_by` `name`, `address`, `charter_number`. Searching by address takes an optional radius argument to limit the scope of the address query (units are in miles):
37
+ You can also find an office by `name`, `address`, `charter_number`. Searching by address takes an optional radius argument to limit the scope of the address query (units are in miles):
38
38
  ```ruby
39
- credit_unions = NCUA.find_by_charter_number(12345) #=> [NCUA::CreditUnion, ... ]
39
+ credit_unions = NCUA.find_office_by_charter_number(12345) #=> [NCUA::CreditUnion::Office, ... ]
40
40
 
41
- credit_unions = NCUA.find_by_address("125 Main St., Anywhere, CT", radius: 50) #=> [NCUA::CreditUnion, ... ]
42
-
41
+ credit_unions = NCUA.find_office_by_address("125 Main St., Anywhere, CT", radius: 50) #=> [NCUA::CreditUnion::Office, ... ]
43
42
  ```
44
43
 
45
- Right now, an `NCUA::CreditUnion` has all of the following getters:
46
-
47
- | ----------------------------- | ------------------------------------------------------------- |
48
- | Method | Explanation |
49
- | ----------------------------- | ------------------------------------------------------------- |
50
- | `name` | The Credit Union's Name |
51
- | `long` | The Longitude of the Credit Union |
52
- | `lat` | The Latitude of the Credit Union |
53
- | `site_name` | The name of the Credit Union office or branch |
54
- | `charter_number` | The Credit Union's Charter Number |
55
- | `city` | The Credit Union's City |
56
- | `country` | The Credit Union's Country |
57
- | `main_office?` | Whether the Credit Union office is the Main Office |
58
- | `phone` | The Credit Union's phone number |
59
- | `site_functions` | The Credit Union's Site functions.\* |
60
- | `site_id` | The Credit Union's Site ID |
61
- | `state` | The Credit Union's State |
62
- | `url` | The Credit Union's Url |
63
- | `zip` | The Credit Union's Zip Code |
64
- | `distance_from_query_address` | The Distance between the queried address and the Credit Union |
65
- | `street` | The Credit Union's Street address |
66
- | ----------------------------- | ------------------------------------------------------------- |
67
-
68
- \*Currently these are limited to `Member Services`, `Drive Through` and `ATM`
44
+ Right now, an `NCUA::CreditUnion::Office` has all of the following getters:
45
+
46
+ ```
47
+ | --------------------------- | ------------------------------------------------------------- |
48
+ | Method | Explanation |
49
+ | --------------------------- | ------------------------------------------------------------- |
50
+ | name | The Credit Union's Name |
51
+ | long | The Longitude of the Credit Union |
52
+ | lat | The Latitude of the Credit Union |
53
+ | site_name | The name of the Credit Union office or branch |
54
+ | charter_number | The Credit Union's Charter Number |
55
+ | city | The Credit Union's City |
56
+ | country | The Credit Union's Country |
57
+ | main_office? | Whether the Credit Union office is the Main Office |
58
+ | phone | The Credit Union's phone number |
59
+ | site_functions | The Credit Union's Site functions.* |
60
+ | site_id | The Credit Union's Site ID |
61
+ | state | The Credit Union's State |
62
+ | url | The Credit Union's Url |
63
+ | zip | The Credit Union's Zip Code |
64
+ | distance_from_query_address | The Distance between the queried address and the Credit Union |
65
+ | street | The Credit Union's Street address |
66
+ | --------------------------- | ------------------------------------------------------------- |
67
+
68
+ *Currently these are limited to `Member Services`, `Drive Through` and `ATM`
69
+ ```
70
+
71
+ `NCUA::CreditUnion::Office` also exposes a `#details` method. This scrapes the NCUA's show page for a particular credit union, and returns an `NCUA::CreditUnion::Details` object. This object contains the details of a particular Credit Union, instead of a particular office location.
72
+
73
+ Keep in mind, this _scrapes_ data from html, so this might break regularly.
74
+
75
+ Right now, an `NCUA::CreditUnion::Details` object has the following getters:
76
+ ```
77
+ | field | description |
78
+ | -------------------------- | ------------------------------------------------------------------------------------------------------------ |
79
+ | credit_union_name | The Credit Union's name |
80
+ | charter_number | The Credit Union's NCUA charter number |
81
+ | credit_union_type | The Type of Credit Union (Either Federal Credit Union [FCU] or Federally Insured State Credit Union [FISCU]) |
82
+ | active? | Whether the Credit Union is active or not |
83
+ | corporate_credit_union? | Whether the Credit Union is a corporate credit union or not |
84
+ | credit_union_charter_year | The year the Credit Union was chartered |
85
+ | current_charter_issue_date | The date the current charter was issued |
86
+ | date_insured | The date that the Credit Union was insured as of |
87
+ | charter_state | The charter state of the Credit Union |
88
+ | region | The Credit Union's region |
89
+ | field_of_membership_type | The Credit Union's field of membership type |
90
+ | low_income_designation? | Whether the Credit Union has low income designation |
91
+ | member_of_fhlb? | Whether the Credit Union is a member of the Federal Home Loan Bank System |
92
+ | assets | The total assets of the Credit Union, as a floating point decimal |
93
+ | peer_group | The Credit Union's Peer Group |
94
+ | number_of_members | The Credit Union's number of Members |
95
+ | address | The street address of the Credit Union |
96
+ | city_state_zip_code | The City, State and Zip code of the Credit Union |
97
+ | country | The Country of the Credit Union |
98
+ | county | The County of the Credit Union |
99
+ | phone | The Phone number of the Credit Union |
100
+ | website | The Website of the Credit Union |
101
+ | ceo_or_manager | The name of the CEO or Manager of the Credit Union |
102
+ | -------------------------- | ------------------------------------------------------------------------------------------------------------ |
103
+ ```
104
+
105
+ You can also scrape this directly from the NCUA module by calling `NCUA.find_credit_union(charter_number)`
69
106
 
70
107
  ## Contributing
71
108
 
@@ -2,23 +2,28 @@ require 'httparty'
2
2
  require 'nokogiri'
3
3
  require 'ncua/version'
4
4
  require 'ncua/client'
5
- require 'ncua/record'
6
- require 'ncua/credit_union'
7
- require 'ncua/scraper'
5
+ require 'ncua/credit_union/record'
6
+ require 'ncua/credit_union/office'
7
+ require 'ncua/credit_union/details'
8
+ require 'ncua/credit_union/scraper'
8
9
 
9
10
  module NCUA
10
- def self.find_by_address(address, opts={radius: 100})
11
+ def self.find_office_by_address(address, opts={radius: 100})
11
12
  resp = Client.new.find_credit_union_by_address(address, opts[:radius])
12
- resp["list"].map { |result| CreditUnion.new(result) }
13
+ resp["list"].map { |result| CreditUnion::Office.new(result) }
13
14
  end
14
15
 
15
- def self.find_by_name(name)
16
+ def self.find_office_by_name(name)
16
17
  resp = Client.new.find_credit_union_by_name(name)
17
- resp["list"].map { |result| CreditUnion.new(result) }
18
+ resp["list"].map { |result| CreditUnion::Office.new(result) }
18
19
  end
19
20
 
20
- def self.find_by_charter_number(charter_number)
21
+ def self.find_office_by_charter_number(charter_number)
21
22
  resp = Client.new.find_credit_union_by_charter_number(charter_number)
22
- resp["list"].map { |result| CreditUnion.new(result) }
23
+ resp["list"].map { |result| CreditUnion::Office.new(result) }
24
+ end
25
+
26
+ def self.find_credit_union(charter_number)
27
+ CreditUnion::Details.new(CreditUnion::Scraper.new(charter_number).scrape!)
23
28
  end
24
29
  end
@@ -0,0 +1,29 @@
1
+ module NCUA
2
+ module CreditUnion
3
+ class Details < Record
4
+ field :credit_union_name
5
+ field :charter_number
6
+ field :credit_union_type
7
+ field(:active?, :credit_union_status) { |value| value == "Active" }
8
+ field(:corporate_credit_union?, :corporate_credit_union) { |value| value == "Yes" }
9
+ field :credit_union_charter_year
10
+ field(:current_charter_issue_date) { |value| Date.strptime(value, '%m/%d/%Y') }
11
+ field(:date_insured) { |value| Date.strptime(value, '%m/%d/%Y') }
12
+ field :charter_state
13
+ field :region
14
+ field :field_of_membership_type
15
+ field(:low_income_designation?, :low_income_designation) { |value| value == "Yes" }
16
+ field(:member_of_fhlb?, :member_of_fhlb) { |value| value == "Yes" }
17
+ field(:assets) { |value| value.gsub(/[$,]/,"").to_f }
18
+ field :peer_group
19
+ field(:number_of_members) { |value| value.gsub(",","").to_i }
20
+ field :address
21
+ field :city_state_zip_code
22
+ field :country
23
+ field :county
24
+ field :phone
25
+ field :website
26
+ field :ceo_or_manager
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,32 @@
1
+ module NCUA
2
+ module CreditUnion
3
+ class Office < Record
4
+ field :name, 'CU_NAME'
5
+ field :long, 'AddressLongitude'
6
+ field :lat, 'AddressLatitude'
7
+ field :site_name, 'CU_SITENAME'
8
+ field :charter_number, 'CU_NUMBER'
9
+ field :city, 'City'
10
+ field :country, 'Country'
11
+ field :main_office?, 'IsMainOffice'
12
+ field :phone, 'Phone'
13
+ field(:site_functions, 'SiteFunctions') { |value| value.split(";") }
14
+ field :site_id, 'SiteId'
15
+ field :state, 'State'
16
+ field :url, 'URL'
17
+ field :zip, 'Zipcode'
18
+ field(:distance_from_query_address, 'distance') { |value| nil if value < 0 }
19
+ field(:street, 'Street', &:strip)
20
+
21
+ def details
22
+ @details ||= Details.new(get_details!)
23
+ end
24
+
25
+ private
26
+
27
+ def get_details!
28
+ @scraped_attributes ||= Scraper.new(charter_number).scrape!
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,34 @@
1
+ module NCUA
2
+ module CreditUnion
3
+ class Record
4
+ def initialize(attributes)
5
+ @attributes = attributes
6
+ @attributes.freeze
7
+ end
8
+
9
+ attr_reader :attributes
10
+
11
+ def self.field(method_name, response_key=method_name, &munger)
12
+ munger ||= lambda { |x| x }
13
+ define_method(method_name) {
14
+ if response_key.is_a? Symbol
15
+ value = attributes[response_key]
16
+ else
17
+ value = attributes[response_key.to_s]
18
+ end
19
+ value && munger.call(value)
20
+ }
21
+ end
22
+
23
+ def self.int_field(method_name, response_key=method_name)
24
+ field(method_name, response_key, &:to_i)
25
+ end
26
+
27
+ def self.date_field(method_name, response_key=method_name)
28
+ field(method_name, response_key) { |value|
29
+ Date.parse(value)
30
+ }
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ module NCUA
2
+ module CreditUnion
3
+ class Scraper
4
+ #This bit is as brittle as glass, as coupled as conjoined twins, and as stinky as bad cheese
5
+ include HTTParty
6
+
7
+ base_uri 'http://mapping.ncua.gov'
8
+ def initialize(charter_number)
9
+ @charter_number = charter_number
10
+ end
11
+
12
+ def scrape!
13
+ Hash[html_doc.at_css("table#MainContent_newDetails").css("tr").map do |tr|
14
+ if tr.at_css("td.dvHeader") && tr.at_css("td.dvHeader + td")
15
+ [clean_header(tr.at_css("td.dvHeader").text), clean_value(tr.at_css("td.dvHeader + td").text)]
16
+ end
17
+ end]
18
+ end
19
+
20
+ private
21
+
22
+ def clean_header(text)
23
+ text.gsub(/[,:]/,"").
24
+ gsub("/", " or ").
25
+ gsub(" ","_").
26
+ downcase.
27
+ to_sym
28
+ end
29
+
30
+ def clean_value(text)
31
+ text.gsub(/[\n\r]/,"").strip
32
+ end
33
+
34
+ def html_doc
35
+ Nokogiri::HTML(request.body)
36
+ end
37
+
38
+ def request
39
+ self.class.get(endpoint, query: {
40
+ "ID" => @charter_number
41
+ })
42
+ end
43
+
44
+ def endpoint
45
+ '/SingleResult.aspx'
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,3 +1,3 @@
1
1
  module NCUA
2
- VERSION = "0.5.0"
2
+ VERSION = "0.6.0"
3
3
  end
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
21
21
  spec.require_paths = ["lib"]
22
22
 
23
23
  spec.add_runtime_dependency "httparty", "~> 0.13"
24
- spec.add_runtime_dependency "nokogiri", "~> 1.6.0"
24
+ spec.add_runtime_dependency 'nokogiri', '~> 1.6', '>= 1.6.0'
25
25
  spec.add_development_dependency "bundler", "~> 1.10"
26
26
  spec.add_development_dependency "rake", "~> 10.0"
27
27
  spec.add_development_dependency "rspec", "~> 3.0"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ncua
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tom Reznick
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2015-09-09 00:00:00.000000000 Z
11
+ date: 2015-09-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: httparty
@@ -29,6 +29,9 @@ dependencies:
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ - - ">="
32
35
  - !ruby/object:Gem::Version
33
36
  version: 1.6.0
34
37
  type: :runtime
@@ -36,6 +39,9 @@ dependencies:
36
39
  version_requirements: !ruby/object:Gem::Requirement
37
40
  requirements:
38
41
  - - "~>"
42
+ - !ruby/object:Gem::Version
43
+ version: '1.6'
44
+ - - ">="
39
45
  - !ruby/object:Gem::Version
40
46
  version: 1.6.0
41
47
  - !ruby/object:Gem::Dependency
@@ -98,9 +104,10 @@ files:
98
104
  - bin/setup
99
105
  - lib/ncua.rb
100
106
  - lib/ncua/client.rb
101
- - lib/ncua/credit_union.rb
102
- - lib/ncua/record.rb
103
- - lib/ncua/scraper.rb
107
+ - lib/ncua/credit_union/details.rb
108
+ - lib/ncua/credit_union/office.rb
109
+ - lib/ncua/credit_union/record.rb
110
+ - lib/ncua/credit_union/scraper.rb
104
111
  - lib/ncua/version.rb
105
112
  - ncua.gemspec
106
113
  homepage: https://github.com/ContinuityControl/ncua
@@ -1,28 +0,0 @@
1
- module NCUA
2
- class CreditUnion < Record
3
- field :name, 'CU_NAME'
4
- field :long, 'AddressLongitude'
5
- field :lat, 'AddressLatitude'
6
- field :site_name, 'CU_SITENAME'
7
- field :charter_number, 'CU_NUMBER'
8
- field :city, 'City'
9
- field :country, 'Country'
10
- field :main_office?, 'IsMainOffice'
11
- field :phone, 'Phone'
12
- field(:site_functions, 'SiteFunctions') { |value| value.split(";") }
13
- field :site_id, 'SiteId'
14
- field :state, 'State'
15
- field :url, 'URL'
16
- field :zip, 'Zipcode'
17
- field(:distance_from_query_address, 'distance') { |value| nil if value < 0 }
18
- field(:street, 'Street', &:strip)
19
-
20
- def munge!
21
- @scraped_attributes ||= Scraper.new(charter_number).scrape!
22
- end
23
-
24
- def additional_attributes
25
- @scraped_attributes
26
- end
27
- end
28
- end
@@ -1,34 +0,0 @@
1
- module NCUA
2
- class Record
3
- def initialize(attributes)
4
- @attributes = attributes
5
- @attributes.freeze
6
- end
7
-
8
- attr_reader :attributes
9
-
10
- def self.field(method_name, response_key=method_name, &munger)
11
- munger ||= lambda { |x| x }
12
- define_method(method_name) {
13
- value = attributes[response_key.to_s]
14
- value && munger.call(value)
15
- }
16
- end
17
-
18
- def self.int_field(method_name, response_key=method_name)
19
- field(method_name, response_key, &:to_i)
20
- end
21
-
22
- def self.currency_field(method_name, response_key=method_name)
23
- field(method_name, response_key) { |value|
24
- value.to_f * 1000
25
- }
26
- end
27
-
28
- def self.date_field(method_name, response_key=method_name)
29
- field(method_name, response_key) { |value|
30
- Date.parse(value)
31
- }
32
- end
33
- end
34
- end
@@ -1,47 +0,0 @@
1
- module NCUA
2
- class Scraper
3
- #This bit is as brittle as glass, as coupled as conjoined twins, and as stinky as bad cheese
4
- include HTTParty
5
-
6
- base_uri 'http://mapping.ncua.gov'
7
- def initialize(charter_number)
8
- @charter_number = charter_number
9
- end
10
-
11
- def scrape!
12
- Hash[html_doc.at_css("table#MainContent_newDetails").css("tr").map do |tr|
13
- if tr.at_css("td.dvHeader") && tr.at_css("td.dvHeader + td")
14
- [clean_header(tr.at_css("td.dvHeader").text), clean_value(tr.at_css("td.dvHeader + td").text)]
15
- end
16
- end]
17
- end
18
-
19
- private
20
-
21
- def clean_header(text)
22
- text.gsub(/[,:]/,"").
23
- gsub("/", " or ").
24
- gsub(" ","_").
25
- downcase.
26
- to_sym
27
- end
28
-
29
- def clean_value(text)
30
- text.gsub(/[\n\r]/,"").strip
31
- end
32
-
33
- def html_doc
34
- Nokogiri::HTML(request.body)
35
- end
36
-
37
- def request
38
- self.class.get(endpoint, query: {
39
- "ID" => @charter_number
40
- })
41
- end
42
-
43
- def endpoint
44
- '/SingleResult.aspx'
45
- end
46
- end
47
- end