ansi_codes 0.0.1
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/.gitignore +40 -0
- data/.rspec +2 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +29 -0
- data/Rakefile +4 -0
- data/ansi_codes.gemspec +24 -0
- data/data/national_county.txt +3236 -0
- data/data/state.txt +58 -0
- data/lib/ansi_codes.rb +5 -0
- data/lib/ansi_codes/county.rb +86 -0
- data/lib/ansi_codes/state.rb +87 -0
- data/lib/ansi_codes/version.rb +3 -0
- data/spec/county_spec.rb +132 -0
- data/spec/spec_helper.rb +18 -0
- data/spec/state_spec.rb +142 -0
- metadata +116 -0
data/data/state.txt
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
STATE|STUSAB|STATE_NAME|STATENS
|
|
2
|
+
01|AL|Alabama|01779775
|
|
3
|
+
02|AK|Alaska|01785533
|
|
4
|
+
04|AZ|Arizona|01779777
|
|
5
|
+
05|AR|Arkansas|00068085
|
|
6
|
+
06|CA|California|01779778
|
|
7
|
+
08|CO|Colorado|01779779
|
|
8
|
+
09|CT|Connecticut|01779780
|
|
9
|
+
10|DE|Delaware|01779781
|
|
10
|
+
11|DC|District of Columbia|01702382
|
|
11
|
+
12|FL|Florida|00294478
|
|
12
|
+
13|GA|Georgia|01705317
|
|
13
|
+
15|HI|Hawaii|01779782
|
|
14
|
+
16|ID|Idaho|01779783
|
|
15
|
+
17|IL|Illinois|01779784
|
|
16
|
+
18|IN|Indiana|00448508
|
|
17
|
+
19|IA|Iowa|01779785
|
|
18
|
+
20|KS|Kansas|00481813
|
|
19
|
+
21|KY|Kentucky|01779786
|
|
20
|
+
22|LA|Louisiana|01629543
|
|
21
|
+
23|ME|Maine|01779787
|
|
22
|
+
24|MD|Maryland|01714934
|
|
23
|
+
25|MA|Massachusetts|00606926
|
|
24
|
+
26|MI|Michigan|01779789
|
|
25
|
+
27|MN|Minnesota|00662849
|
|
26
|
+
28|MS|Mississippi|01779790
|
|
27
|
+
29|MO|Missouri|01779791
|
|
28
|
+
30|MT|Montana|00767982
|
|
29
|
+
31|NE|Nebraska|01779792
|
|
30
|
+
32|NV|Nevada|01779793
|
|
31
|
+
33|NH|New Hampshire|01779794
|
|
32
|
+
34|NJ|New Jersey|01779795
|
|
33
|
+
35|NM|New Mexico|00897535
|
|
34
|
+
36|NY|New York|01779796
|
|
35
|
+
37|NC|North Carolina|01027616
|
|
36
|
+
38|ND|North Dakota|01779797
|
|
37
|
+
39|OH|Ohio|01085497
|
|
38
|
+
40|OK|Oklahoma|01102857
|
|
39
|
+
41|OR|Oregon|01155107
|
|
40
|
+
42|PA|Pennsylvania|01779798
|
|
41
|
+
44|RI|Rhode Island|01219835
|
|
42
|
+
45|SC|South Carolina|01779799
|
|
43
|
+
46|SD|South Dakota|01785534
|
|
44
|
+
47|TN|Tennessee|01325873
|
|
45
|
+
48|TX|Texas|01779801
|
|
46
|
+
49|UT|Utah|01455989
|
|
47
|
+
50|VT|Vermont|01779802
|
|
48
|
+
51|VA|Virginia|01779803
|
|
49
|
+
53|WA|Washington|01779804
|
|
50
|
+
54|WV|West Virginia|01779805
|
|
51
|
+
55|WI|Wisconsin|01779806
|
|
52
|
+
56|WY|Wyoming|01779807
|
|
53
|
+
60|AS|American Samoa|01802701
|
|
54
|
+
66|GU|Guam|01802705
|
|
55
|
+
69|MP|Northern Mariana Islands|01779809
|
|
56
|
+
72|PR|Puerto Rico|01779808
|
|
57
|
+
74|UM|U.S. Minor Outlying Islands|01878752
|
|
58
|
+
78|VI|U.S. Virgin Islands|01802710
|
data/lib/ansi_codes.rb
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
module AnsiCodes
|
|
2
|
+
# A representation of US counties and equivalent census areas.
|
|
3
|
+
# County instances are created at class load time and are immutable.
|
|
4
|
+
class County
|
|
5
|
+
# @return [State] the {State} that this county belongs to
|
|
6
|
+
attr_reader :state
|
|
7
|
+
# @return [String] the three digit ANSI code for this county
|
|
8
|
+
attr_reader :ansi_code
|
|
9
|
+
# @return [String] the county's full name in title case
|
|
10
|
+
attr_reader :name
|
|
11
|
+
# @return [String] the county name, minus the designation
|
|
12
|
+
# @note some cities have no designation, so this attribute will be the same as {#name}
|
|
13
|
+
attr_reader :short_name
|
|
14
|
+
# @return [String] the census designation (County, Parish, Municipio, etc.)
|
|
15
|
+
# @note some cities have no designation, in which case this will return the empty string
|
|
16
|
+
attr_reader :designation
|
|
17
|
+
|
|
18
|
+
private
|
|
19
|
+
|
|
20
|
+
# Suffixes for counties (parishes, etc.) to help split names into their parts.
|
|
21
|
+
Designations = /(.*) (city|Borough|County|City and Borough|Census Area|Municipality|Parish|Islands?|District|Municipio)$/
|
|
22
|
+
|
|
23
|
+
# Create a new County instance.
|
|
24
|
+
# @note This is only meant to be called internally during class loading.
|
|
25
|
+
# You cannot call #new directly.
|
|
26
|
+
# @param state_ansi [String] the two-digit state ANSI code
|
|
27
|
+
# @param county_ansi [String] the three-digit county ANSI code
|
|
28
|
+
# @param name [String] the county name
|
|
29
|
+
def initialize(state_ansi, county_ansi, name)
|
|
30
|
+
@state = State.find(state_ansi)
|
|
31
|
+
@ansi_code = county_ansi
|
|
32
|
+
@name = name
|
|
33
|
+
match = name.match(Designations)
|
|
34
|
+
@short_name = match && match[1] || name
|
|
35
|
+
@designation = match && match[2] || ''
|
|
36
|
+
freeze
|
|
37
|
+
self.class.instance_variable_get(:@counties)[@state].tap do |counties|
|
|
38
|
+
counties[:ansi_code][@ansi_code.downcase] =
|
|
39
|
+
counties[:name][@name.downcase] = self
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
public
|
|
44
|
+
|
|
45
|
+
# @param [State] state an optional {State} object to narrow the results
|
|
46
|
+
# @return [Array<County>] all counties or all of a {State}'s counties if one is provided
|
|
47
|
+
def self.all(state = nil)
|
|
48
|
+
state ? @counties[state][:ansi_code].values :
|
|
49
|
+
@counties.values.flat_map {|values| values[:ansi_code]}.flat_map(&:values)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Look up a county by state and county ANSI code or name
|
|
53
|
+
# @param [State, Fixnum, String] state the state portion of the query.
|
|
54
|
+
# This method will accept a {State} object or anything that {State.find} will accept.
|
|
55
|
+
# @param [Fixnum, String] county the county ANSI code or name to look up
|
|
56
|
+
# @return [County] the {County} associated with the query parameters
|
|
57
|
+
# @raise [ArgumentError] if the county parameter is not a Fixnum or String,
|
|
58
|
+
# or if the state parameter is not a {State}, Fixnum, or String.
|
|
59
|
+
# @raise [RuntimeError] if no associated {State} or {County} is found
|
|
60
|
+
def self.find(state, county)
|
|
61
|
+
state = state.is_a?(State) ? state : State.find(state)
|
|
62
|
+
case county
|
|
63
|
+
when Fixnum
|
|
64
|
+
county, selector = '%03d' % county, :ansi_code
|
|
65
|
+
when String
|
|
66
|
+
selector = county =~ /^[0-9]{3}$/ ? :ansi_code : :name
|
|
67
|
+
else raise(ArgumentError, 'Argument must be an integer or a string.')
|
|
68
|
+
end
|
|
69
|
+
@counties[state][selector][county.downcase].tap do |result|
|
|
70
|
+
raise(RuntimeError, "No county found for lookup '#{county}' in state #{state.name}") unless result
|
|
71
|
+
yield result if block_given?
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
@counties = Hash[State.all.map {|state| [state, { ansi_code: {}, name: {} }] }]
|
|
76
|
+
data_file = File.expand_path('../../../data/national_county.txt', __FILE__)
|
|
77
|
+
options = { headers: true, header_converters: :symbol }
|
|
78
|
+
CSV.foreach(data_file, options) do |row|
|
|
79
|
+
new row[:state_ansi], row[:county_ansi], row[:county_name]
|
|
80
|
+
end
|
|
81
|
+
@counties.values.flat_map(&:values).map(&:freeze)
|
|
82
|
+
@counties.values.map &:freeze
|
|
83
|
+
@counties.freeze
|
|
84
|
+
freeze
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
require 'csv'
|
|
2
|
+
|
|
3
|
+
module AnsiCodes
|
|
4
|
+
# A representation of US states and equivalent census areas.
|
|
5
|
+
# State instances are created at class load time and are immutable.
|
|
6
|
+
class State
|
|
7
|
+
# @return [String] the two-digit ANSI code string
|
|
8
|
+
# @api public
|
|
9
|
+
attr_reader :ansi_code
|
|
10
|
+
# @return [String] the state name in title case
|
|
11
|
+
# @api public
|
|
12
|
+
attr_reader :name
|
|
13
|
+
# @return [String] the two-letter state abbreviation in caps
|
|
14
|
+
# @api public
|
|
15
|
+
attr_reader :abbreviation
|
|
16
|
+
|
|
17
|
+
private
|
|
18
|
+
|
|
19
|
+
# Create a new State instance.
|
|
20
|
+
# @note This is only meant to be called internally during class loading.
|
|
21
|
+
# You cannot call #new directly.
|
|
22
|
+
# @param ansi_code [String] the two-digit state ANSI code
|
|
23
|
+
# @param name [String] the state name
|
|
24
|
+
# @param abbreviation [String] the two-letter state abbreviation
|
|
25
|
+
def initialize(ansi_code, name, abbreviation)
|
|
26
|
+
@ansi_code = ansi_code
|
|
27
|
+
@name = name
|
|
28
|
+
@abbreviation = abbreviation
|
|
29
|
+
freeze
|
|
30
|
+
self.class.instance_variable_get(:@states).tap do |states|
|
|
31
|
+
states[:ansi_code][@ansi_code.downcase] =
|
|
32
|
+
states[:name][@name.downcase] =
|
|
33
|
+
states[:abbreviation][@abbreviation.downcase] = self
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
public
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# @return [Array<County>] all of this state's counties
|
|
41
|
+
# @api public
|
|
42
|
+
# @!attribute [r] counties
|
|
43
|
+
def counties
|
|
44
|
+
County.all(self)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Look up a state by ANSI code, abbreviation, or name
|
|
48
|
+
# @param [Fixnum, String] value the lookup query
|
|
49
|
+
# @return [State] the {State} associated with the query parameter
|
|
50
|
+
# @raise [ArgumentError] if the argument is not a Fixnum or String
|
|
51
|
+
# @raise [RuntimeError] if no associated {State} is found
|
|
52
|
+
def self.find(value)
|
|
53
|
+
case value
|
|
54
|
+
when Fixnum
|
|
55
|
+
value = '%02d' % value
|
|
56
|
+
selector = :ansi_code
|
|
57
|
+
when String
|
|
58
|
+
begin
|
|
59
|
+
Integer(value, 10)
|
|
60
|
+
selector = :ansi_code
|
|
61
|
+
rescue ArgumentError
|
|
62
|
+
selector = value.size == 2 ? :abbreviation : :name
|
|
63
|
+
end
|
|
64
|
+
else raise(ArgumentError, 'Argument must be an integer or a string.')
|
|
65
|
+
end
|
|
66
|
+
@states[selector][value.downcase].tap do |result|
|
|
67
|
+
raise(RuntimeError, "No state found for lookup '#{value}'") unless result
|
|
68
|
+
yield result if block_given?
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# @return [Array<State>] an array of all states
|
|
73
|
+
def self.all
|
|
74
|
+
@states[:ansi_code].values
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
@states = { ansi_code: {}, name: {}, abbreviation: {} }
|
|
78
|
+
data_file = File.expand_path('../../../data/state.txt', __FILE__)
|
|
79
|
+
options = { col_sep: '|', headers: true, header_converters: :symbol }
|
|
80
|
+
CSV.foreach(data_file, options) do |row|
|
|
81
|
+
new row[:state], row[:state_name], row[:stusab]
|
|
82
|
+
end
|
|
83
|
+
@states.values.map &:freeze
|
|
84
|
+
@states.freeze
|
|
85
|
+
freeze
|
|
86
|
+
end
|
|
87
|
+
end
|
data/spec/county_spec.rb
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe AnsiCodes::County do
|
|
4
|
+
|
|
5
|
+
it 'should not be instantiable' do
|
|
6
|
+
expect{AnsiCodes::County.new('01', '001', 'Autauga County')}.to raise_error(RuntimeError)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it 'should not be modifiable' do
|
|
10
|
+
expect{AnsiCodes::County.extend Module.new}.to raise_error
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
describe '#ansi_code' do
|
|
14
|
+
it 'should return a three-digit string' do
|
|
15
|
+
AnsiCodes::County.all.each do |county|
|
|
16
|
+
county.ansi_code.should match(/^[0-9]{3}$/)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should return the same county when looked up by result' do
|
|
21
|
+
AnsiCodes::County.all.each do |county|
|
|
22
|
+
AnsiCodes::County.find(county.state, county.ansi_code).should be(county)
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe '#name' do
|
|
28
|
+
before(:each) { @names = AnsiCodes::County.all.map(&:name) }
|
|
29
|
+
|
|
30
|
+
it 'should return a string' do
|
|
31
|
+
@names.each {|name| name.should be_a(String)}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should be at least 4 characters long' do
|
|
35
|
+
@names.each {|name| name.should have_at_least(4).items}
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it 'should return the same county when looked up by result' do
|
|
39
|
+
AnsiCodes::County.all.each do |county|
|
|
40
|
+
AnsiCodes::County.find(county.state, county.name).should be(county)
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe '#short_name' do
|
|
46
|
+
before(:each) { @short_names = AnsiCodes::County.all.map(&:short_name) }
|
|
47
|
+
|
|
48
|
+
it 'should return a string' do
|
|
49
|
+
@short_names.each {|short_name| short_name.should be_a(String)}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it 'should be no longer than #name' do
|
|
53
|
+
AnsiCodes::County.all.each do |county|
|
|
54
|
+
county.short_name.should have_at_most(county.name.size).characters
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
describe '#designation' do
|
|
60
|
+
before(:each) { @designations = AnsiCodes::County.all.map(&:designation) }
|
|
61
|
+
|
|
62
|
+
it 'should return a string' do
|
|
63
|
+
@designations.each {|designation| designation.should be_a(String)}
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
it 'should be shorter than #name' do
|
|
67
|
+
AnsiCodes::County.all.each do |county|
|
|
68
|
+
county.designation.should have_at_most(county.name.size - 1).characters
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
describe '#state' do
|
|
74
|
+
before(:each) { @states = AnsiCodes::County.all.map(&:state) }
|
|
75
|
+
|
|
76
|
+
it 'should return an AnsiCodes::State' do
|
|
77
|
+
@states.each {|state| state.should be_an(AnsiCodes::State)}
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe '.all' do
|
|
82
|
+
it 'should return 3235 elements' do
|
|
83
|
+
AnsiCodes::County.all.should have(3235).items
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it 'should return an array of AnsiCodes::County' do
|
|
87
|
+
AnsiCodes::County.all.tap do |counties|
|
|
88
|
+
counties.should be_an(Array)
|
|
89
|
+
counties.each {|county| county.should be_an_instance_of(AnsiCodes::County)}
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
describe '.find' do
|
|
95
|
+
it 'should accept a string as first param' do
|
|
96
|
+
expect{AnsiCodes::County.find '01', '001'}.not_to raise_error
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should accept an integer as first param' do
|
|
100
|
+
expect{AnsiCodes::County.find 1, '001'}.not_to raise_error
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'should accept an AnsiCodes::State as first param' do
|
|
104
|
+
expect{AnsiCodes::County.find AnsiCodes::State.all.first, '001'}.not_to raise_error
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should accept a string as second param' do
|
|
108
|
+
expect{AnsiCodes::County.find 1, '001'}.not_to raise_error
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should accept an integer as second param' do
|
|
112
|
+
expect{AnsiCodes::County.find 1, 1}.not_to raise_error
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it 'should raise an ArgumentError on any other type as second param' do
|
|
116
|
+
expect{AnsiCodes::County.find 1, nil}.to raise_error(ArgumentError)
|
|
117
|
+
expect{AnsiCodes::County.find 1, 1.0}.to raise_error(ArgumentError)
|
|
118
|
+
expect{AnsiCodes::County.find 1, /really?/}.to raise_error(ArgumentError)
|
|
119
|
+
expect{AnsiCodes::County.find 1, {}}.to raise_error(ArgumentError)
|
|
120
|
+
expect{AnsiCodes::County.find 1, []}.to raise_error(ArgumentError)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it 'should yield the result if a block is given' do
|
|
124
|
+
county = AnsiCodes::County.find 'Virginia', 'Norfolk city'
|
|
125
|
+
expect { |b| AnsiCodes::County.find('Virginia', 'Norfolk city', &b) }.to yield_with_args(county)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'should raise an exception if no county is found' do
|
|
129
|
+
expect{AnsiCodes::County.find 45, 1000}.to raise_error
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
data/spec/spec_helper.rb
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
begin
|
|
2
|
+
require 'simplecov'
|
|
3
|
+
SimpleCov.start do
|
|
4
|
+
add_filter '/spec/'
|
|
5
|
+
add_filter {|source| source.lines.count < 10}
|
|
6
|
+
end
|
|
7
|
+
rescue LoadError
|
|
8
|
+
STDERR.puts 'SimpleCov not installed. Not generating coverage report.'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
require 'ansi_codes'
|
|
12
|
+
|
|
13
|
+
RSpec.configure do |config|
|
|
14
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
|
15
|
+
config.run_all_when_everything_filtered = true
|
|
16
|
+
config.filter_run :focus
|
|
17
|
+
config.order = 'random'
|
|
18
|
+
end
|
data/spec/state_spec.rb
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe AnsiCodes::State do
|
|
4
|
+
it 'should not be instantiable' do
|
|
5
|
+
expect{AnsiCodes::State.new('01', 'AL', 'Alabame')}.to raise_error(RuntimeError)
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
it 'should not be modifiable' do
|
|
9
|
+
expect{AnsiCodes::State.extend Module.new}.to raise_error
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe '#ansi_code' do
|
|
13
|
+
it 'should return a two-digit string' do
|
|
14
|
+
AnsiCodes::State.all.each do |state|
|
|
15
|
+
state.ansi_code.should match(/^[0-9]{2}$/)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
it 'should return the same state when result is looked up' do
|
|
20
|
+
AnsiCodes::State.all.each do |state|
|
|
21
|
+
AnsiCodes::State.find(state.ansi_code).should be(state)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe '#name' do
|
|
27
|
+
it 'should return a string longer than 2 characters' do
|
|
28
|
+
AnsiCodes::State.all.each do |state|
|
|
29
|
+
state.name.should have_at_least(3).items
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'should return a proper name' do
|
|
34
|
+
AnsiCodes::State.all.each do |state|
|
|
35
|
+
state.name.should match(/^[A-Z].*[a-z]/)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it 'should return the same state when result is looked up' do
|
|
40
|
+
AnsiCodes::State.all.each do |state|
|
|
41
|
+
AnsiCodes::State.find(state.name).should be(state)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe '#abbreviation' do
|
|
47
|
+
it 'should return a two-character uppercase string' do
|
|
48
|
+
AnsiCodes::State.all.each do |state|
|
|
49
|
+
state.abbreviation.should match(/^[A-Z]{2}$/)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'should return the same state when result is looked up' do
|
|
54
|
+
AnsiCodes::State.all.each do |state|
|
|
55
|
+
AnsiCodes::State.find(state.abbreviation).should be(state)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
describe '#counties' do
|
|
61
|
+
it 'should return an array of AnsiCodes::County' do
|
|
62
|
+
counties = AnsiCodes::State.all.first.counties
|
|
63
|
+
counties.should be_an(Array)
|
|
64
|
+
counties.each do |county|
|
|
65
|
+
county.should be_a(AnsiCodes::County)
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe '.all' do
|
|
71
|
+
it 'should return 57 elements' do
|
|
72
|
+
AnsiCodes::State.all.should have(57).items
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it 'should return an array' do
|
|
76
|
+
AnsiCodes::State.all.should be_an(Array)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it 'should contain AnsiCodes::State instances' do
|
|
80
|
+
AnsiCodes::State.all.each do |state|
|
|
81
|
+
state.should be_an_instance_of(AnsiCodes::State)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
describe '.find' do
|
|
87
|
+
it 'should raise ArgumentError with no arguments' do
|
|
88
|
+
expect{AnsiCodes::State.find}.to raise_error(ArgumentError)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it 'should raise ArgumentError with more than one argument' do
|
|
92
|
+
expect{AnsiCodes::State.find 1, 2}.to raise_error(ArgumentError)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
it 'should accept an integer argument' do
|
|
96
|
+
expect{AnsiCodes::State.find 12}.not_to raise_error
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it 'should accept a string argument' do
|
|
100
|
+
expect{AnsiCodes::State.find '12'}.not_to raise_error
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it 'should return Alabama with lookup = 1' do
|
|
104
|
+
AnsiCodes::State.find(1).name.should == 'Alabama'
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
it 'should return Alabama with lookup = "01"' do
|
|
108
|
+
AnsiCodes::State.find('01').name.should == 'Alabama'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it 'should be case-insensitive' do
|
|
112
|
+
AnsiCodes::State.find('wi').should == AnsiCodes::State.find('WI')
|
|
113
|
+
AnsiCodes::State.find('NEW JERSEY').should == AnsiCodes::State.find('nEw JeRsEy')
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
it 'should raise an ArgumentError on any other type as second param' do
|
|
117
|
+
expect{AnsiCodes::State.find nil}.to raise_error(ArgumentError)
|
|
118
|
+
expect{AnsiCodes::State.find 1.0}.to raise_error(ArgumentError)
|
|
119
|
+
expect{AnsiCodes::State.find /really?/}.to raise_error(ArgumentError)
|
|
120
|
+
expect{AnsiCodes::State.find {}}.to raise_error(ArgumentError)
|
|
121
|
+
expect{AnsiCodes::State.find []}.to raise_error(ArgumentError)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it 'should raise a RuntimeError if no match is found' do
|
|
125
|
+
expect{AnsiCodes::State.find 'chimichanga'}.to raise_error(RuntimeError)
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it 'should yield the result if a block is given' do
|
|
129
|
+
state = AnsiCodes::State.find 'New York'
|
|
130
|
+
expect { |b| AnsiCodes::State.find('New York', &b) }.to yield_with_args(state)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it 'should return identical objects with the same parameters' do
|
|
134
|
+
AnsiCodes::State.find('01').should eql(AnsiCodes::State.find('01'))
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it 'should return identical objects when lookup result is same' do
|
|
138
|
+
AnsiCodes::State.find('AL').should eql(AnsiCodes::State.find('01'))
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
end
|