carrier_info 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 +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/carrier_info.gemspec +19 -0
- data/lib/carrier_info/carrier.rb +66 -0
- data/lib/carrier_info/sources/safer.rb +261 -0
- data/lib/carrier_info/sources.rb +1 -0
- data/lib/carrier_info/version.rb +3 -0
- data/lib/carrier_info.rb +6 -0
- metadata +72 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Sean Devine
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# CarrierInfo
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'carrier_info'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install carrier_info
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it
|
26
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
27
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
29
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'carrier_info/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |gem|
|
7
|
+
gem.name = "carrier_info"
|
8
|
+
gem.version = CarrierInfo::VERSION
|
9
|
+
gem.authors = ["Sean Devine"]
|
10
|
+
gem.email = ["barelyknown@icloud.com"]
|
11
|
+
gem.description = %q{Fetch carrier info off the internet}
|
12
|
+
gem.summary = %q{Fetch carrier info off the internet}
|
13
|
+
gem.homepage = "https://github.com/buytruckload/carrier_info"
|
14
|
+
gem.add_dependency 'nokogiri'
|
15
|
+
gem.files = `git ls-files`.split($/)
|
16
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
17
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
|
+
gem.require_paths = ["lib"]
|
19
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module CarrierInfo
|
2
|
+
class Carrier
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :sources
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.load_sources
|
9
|
+
self.sources = []
|
10
|
+
Dir.new(File.dirname(__FILE__) + "/sources").each do |file|
|
11
|
+
unless File.directory?(file)
|
12
|
+
self.sources << ("CarrierInfo::Sources::" + file.split(".")[0].camelize).constantize
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
load_sources
|
17
|
+
|
18
|
+
attr_accessor :docket_prefix, :docket_number, :usdot_number, :legal_name, :dba_name, :phone, :power_units,
|
19
|
+
:drivers, :duns_number, :state_id_number, :mcs_150_form_date,
|
20
|
+
:mcs_150_mileage, :mcs_150_mileage_year, :out_of_service_date, :safer_active,
|
21
|
+
:operating_status, :entity_type, :physical_street, :physical_city, :physical_state,
|
22
|
+
:physical_postal_code, :mailing_street, :mailing_city, :mailing_state,
|
23
|
+
:mailing_postal_code, :safer_last_updated
|
24
|
+
|
25
|
+
# Operation Classification (http://safer.fmcsa.dot.gov/saferhelp.aspx#Class)
|
26
|
+
attr_accessor :classification_authorized_for_hire, :classification_exempt_for_hire,
|
27
|
+
:classification_private_property, :classification_private_passenger_business,
|
28
|
+
:classification_private_passenger_non_business, :classification_migrant,
|
29
|
+
:classification_us_mail, :classification_federal_government, :classification_state_government,
|
30
|
+
:classification_local_government, :classification_indian_tribe, :classification_other
|
31
|
+
|
32
|
+
# Carrier Operation (http://safer.fmcsa.dot.gov/saferhelp.aspx#CarrierOP)
|
33
|
+
attr_accessor :interstate, :instrastate_non_hazardous, :intrastate_hazardous
|
34
|
+
|
35
|
+
# Equipment Type
|
36
|
+
attr_accessor :equipment_vans, :equipment_household_vans, :equipment_flatbeds, :equipment_car_carriers,
|
37
|
+
:equipment_tow_trucks, :equipment_mobile_homes, :equipment_reefers, :equipment_tanks,
|
38
|
+
:equipment_intermodal_containers, :equipment_buses, :equipment_livestock_rack,
|
39
|
+
:equipment_hopper_bottom, :equipment_coal_trailers, :equipment_garbage_trucks,
|
40
|
+
:equipment_beverage_trucks, :equipment_utility_trucks,
|
41
|
+
:equipment_well_trucks
|
42
|
+
|
43
|
+
def initialize(args={})
|
44
|
+
self.docket_number = args[:docket_number]
|
45
|
+
self.usdot_number = args[:usdot_number]
|
46
|
+
end
|
47
|
+
|
48
|
+
def equipment_names
|
49
|
+
self.methods.select { |var| var =~ /equipment_.+[^=]\Z/ && var != :equipment_names }
|
50
|
+
end
|
51
|
+
|
52
|
+
def classification_names
|
53
|
+
self.methods.select { |var| var =~ /classification_.+[^=]\Z/ && var != :classification_names }
|
54
|
+
end
|
55
|
+
|
56
|
+
def sources
|
57
|
+
self.class.sources.collect { |source| source.new(self) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_all_sources!
|
61
|
+
sources.each(&:parse!)
|
62
|
+
self
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,261 @@
|
|
1
|
+
module CarrierInfo
|
2
|
+
module Sources
|
3
|
+
class Safer
|
4
|
+
|
5
|
+
EQUIPMENT_CARGO_CARRIED = {
|
6
|
+
equipment_vans: ["General Freight", "US Mail", "Paper Products"],
|
7
|
+
equipment_household_vans: ["Household Goods"],
|
8
|
+
equipment_flatbeds: ["Metal: sheets, coils, rolls", "Logs, Poles, Beams, Lumber", "Building Materials", "Construction", "Machinery, Large Objects"],
|
9
|
+
equipment_car_carriers: ["Motor Vehicles"],
|
10
|
+
equipment_tow_trucks: ["Drive/Tow away"],
|
11
|
+
equipment_mobile_homes: ["Mobile Homes"],
|
12
|
+
equipment_reefers: ["Fresh Produce", "Meat", "Refrigerated Food"],
|
13
|
+
equipment_tanks: ["Liquids/Gases", "Chemicals"],
|
14
|
+
equipment_intermodal_containers: ["Intermodal Cont."],
|
15
|
+
equipment_buses: ["Passengers"],
|
16
|
+
equipment_livestock_rack: ["Livestock"],
|
17
|
+
equipment_hopper_bottom: ["Commodities Dry Bulk", "Grain, Feed, Hay", "Agricultural/Farm Supplies"],
|
18
|
+
equipment_coal_trailers: ["Coal/Coke"],
|
19
|
+
equipment_garbage_trucks: ["Garbage/Refuse"],
|
20
|
+
equipment_beverage_trucks: ["Beverages"],
|
21
|
+
equipment_utility_trucks: ["Utilities"],
|
22
|
+
equipment_well_trucks: ["Water Well"]
|
23
|
+
}
|
24
|
+
|
25
|
+
CLASSIFICATION_LABEL = {
|
26
|
+
classification_authorized_for_hire: "Auth. For Hire",
|
27
|
+
classification_exempt_for_hire: "Exempt For Hire",
|
28
|
+
classification_private_property: "Private(Property)",
|
29
|
+
classification_private_passenger_business: "Priv. Pass. (Business)",
|
30
|
+
classification_private_passenger_non_business: "Priv. Pass.(Non-business)",
|
31
|
+
classification_migrant: "Migrant",
|
32
|
+
classification_us_mail: "U.S. Mail",
|
33
|
+
classification_federal_government: "Fed. Gov't",
|
34
|
+
classification_state_government: "State Gov't",
|
35
|
+
classification_local_government: "Local Gov't",
|
36
|
+
classification_indian_tribe: "Indian Nation",
|
37
|
+
classification_other: "Other"
|
38
|
+
}
|
39
|
+
|
40
|
+
attr_accessor :content, :carrier
|
41
|
+
|
42
|
+
def initialize(carrier)
|
43
|
+
@carrier = carrier
|
44
|
+
end
|
45
|
+
|
46
|
+
def query_param
|
47
|
+
carrier.usdot_number ? "USDOT" : "MC_MX"
|
48
|
+
end
|
49
|
+
|
50
|
+
def query_string
|
51
|
+
carrier.usdot_number || carrier.docket_number
|
52
|
+
end
|
53
|
+
|
54
|
+
def request_params
|
55
|
+
params = {
|
56
|
+
query_param: query_param,
|
57
|
+
query_string: query_string,
|
58
|
+
searchtype: 'ANY',
|
59
|
+
query_type: 'queryCarrierSnapshot',
|
60
|
+
button1: 'Search'
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def response
|
65
|
+
@response ||= request_response
|
66
|
+
end
|
67
|
+
|
68
|
+
def request_response
|
69
|
+
Nokogiri::HTML(Net::HTTP.post_form(URI.parse('http://safer.fmcsa.dot.gov/query.asp'), request_params).body)
|
70
|
+
end
|
71
|
+
|
72
|
+
def parse!
|
73
|
+
carrier.safer_active = parse_safer_active
|
74
|
+
if carrier.safer_active
|
75
|
+
carrier.usdot_number = parse_usdot_number
|
76
|
+
carrier.docket_prefix = parse_docket_prefix
|
77
|
+
carrier.docket_number = parse_docket_number
|
78
|
+
carrier.legal_name = parse_legal_name
|
79
|
+
carrier.dba_name = parse_dba_name
|
80
|
+
carrier.phone = parse_phone
|
81
|
+
carrier.power_units = parse_power_units
|
82
|
+
carrier.drivers = parse_drivers
|
83
|
+
carrier.duns_number = parse_duns_number
|
84
|
+
carrier.state_id_number = parse_state_id_number
|
85
|
+
carrier.mcs_150_form_date = parse_mcs_150_form_date
|
86
|
+
carrier.mcs_150_mileage = parse_mcs_150_mileage
|
87
|
+
carrier.mcs_150_mileage_year = parse_mcs_150_mileage_year
|
88
|
+
carrier.out_of_service_date = parse_out_of_service_date
|
89
|
+
carrier.operating_status = parse_operating_status
|
90
|
+
carrier.entity_type = parse_entity_type
|
91
|
+
[:physical, :mailing].each do |type|
|
92
|
+
[:street, :city, :state, :postal_code].each do |address|
|
93
|
+
carrier.send("#{type}_#{address}=", parse_address(type, address))
|
94
|
+
end
|
95
|
+
end
|
96
|
+
carrier.equipment_names.each do |equipment_name|
|
97
|
+
carrier.send("#{equipment_name}=", parse_equipment(equipment_name))
|
98
|
+
end
|
99
|
+
carrier.interstate = parse_interstate
|
100
|
+
carrier.instrastate_non_hazardous = parse_intrastate_non_hazardous
|
101
|
+
carrier.intrastate_hazardous = parse_intrastate_hazardous
|
102
|
+
carrier.classification_names.each do |classification_name|
|
103
|
+
carrier.send("#{classification_name}=", parse_classification(classification_name))
|
104
|
+
end
|
105
|
+
carrier.safer_last_updated = parse_safer_last_updated
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
def parse_standard_info_field(name, args={})
|
111
|
+
value = response.xpath("//a[text()='#{name}:']").find do |field|
|
112
|
+
field.attr("class") == "querylabel"
|
113
|
+
end.parent.next_element.text.gsub(/[\u0080-\u00ff]/,"").strip
|
114
|
+
if args[:integer]
|
115
|
+
value.gsub!(/\D/, "")
|
116
|
+
value = value.to_i
|
117
|
+
end
|
118
|
+
value
|
119
|
+
end
|
120
|
+
|
121
|
+
def parse_legal_name
|
122
|
+
parse_standard_info_field("Legal Name")
|
123
|
+
end
|
124
|
+
|
125
|
+
def parse_dba_name
|
126
|
+
parse_standard_info_field("DBA Name")
|
127
|
+
end
|
128
|
+
|
129
|
+
def parse_phone
|
130
|
+
parse_standard_info_field("Phone")
|
131
|
+
end
|
132
|
+
|
133
|
+
def parse_power_units
|
134
|
+
parse_standard_info_field("Power Units", integer: true)
|
135
|
+
end
|
136
|
+
|
137
|
+
def parse_drivers
|
138
|
+
parse_standard_info_field("Drivers", integer: true)
|
139
|
+
end
|
140
|
+
|
141
|
+
def parse_usdot_number
|
142
|
+
parse_standard_info_field("USDOT Number", integer: true)
|
143
|
+
end
|
144
|
+
|
145
|
+
def parse_docket_prefix
|
146
|
+
docket = parse_standard_info_field("MC or MX Number")
|
147
|
+
docket.split("-")[0] if docket =~ /-/
|
148
|
+
end
|
149
|
+
|
150
|
+
def parse_docket_number
|
151
|
+
docket = parse_standard_info_field("MC or MX Number")
|
152
|
+
docket.split("-")[1].to_i if docket =~ /-/
|
153
|
+
end
|
154
|
+
|
155
|
+
def parse_duns_number
|
156
|
+
duns = parse_standard_info_field("DUNS Number", integer: true)
|
157
|
+
duns == 0 ? nil : duns
|
158
|
+
end
|
159
|
+
|
160
|
+
def parse_state_id_number
|
161
|
+
parse_standard_info_field("State Carrier ID Number")
|
162
|
+
end
|
163
|
+
|
164
|
+
def parse_mcs_150_form_date
|
165
|
+
date_parts = parse_standard_info_field("MCS-150 Form Date").split("/").collect(&:to_i)
|
166
|
+
Date.new(date_parts[2], date_parts[0], date_parts[1]) if date_parts.count == 3
|
167
|
+
end
|
168
|
+
|
169
|
+
def parse_mcs_150_mileage
|
170
|
+
parts = parse_standard_info_field("MCS-150 Mileage (Year)").split(" ")
|
171
|
+
parts[0].gsub(/\D/,"").to_i if parts.count == 2
|
172
|
+
end
|
173
|
+
|
174
|
+
def parse_mcs_150_mileage_year
|
175
|
+
parts = parse_standard_info_field("MCS-150 Mileage (Year)").split(" ")
|
176
|
+
parts[1].gsub(/\D/,"").to_i if parts.count == 2
|
177
|
+
end
|
178
|
+
|
179
|
+
def parse_out_of_service_date
|
180
|
+
parse_standard_info_field("Out of Service Date")
|
181
|
+
# date_parts = parse_standard_info_field("Out of Service Date").split("/").collect(&:to_i)
|
182
|
+
# Date.new(date_parts[2], date_parts[0], date_parts[1]) if date_parts.count == 3
|
183
|
+
end
|
184
|
+
|
185
|
+
def parse_safer_active
|
186
|
+
!(response.xpath("//text()='Record Inactive'") || response.xpath("//text()='Record Not Found'"))
|
187
|
+
end
|
188
|
+
|
189
|
+
def parse_operating_status
|
190
|
+
parse_standard_info_field("Operating Status")
|
191
|
+
end
|
192
|
+
|
193
|
+
def parse_entity_type
|
194
|
+
parse_standard_info_field("Entity Type")
|
195
|
+
end
|
196
|
+
|
197
|
+
def parse_address(type, part)
|
198
|
+
address = parse_standard_info_field("#{type.to_s.titleize} Address")
|
199
|
+
send("parse_#{part}", address)
|
200
|
+
end
|
201
|
+
|
202
|
+
def parse_street(address)
|
203
|
+
address.split("\n")[0].strip
|
204
|
+
end
|
205
|
+
|
206
|
+
def parse_city(address)
|
207
|
+
address.split("\n")[1].split(",")[0].strip
|
208
|
+
end
|
209
|
+
|
210
|
+
def parse_state(address)
|
211
|
+
address.split("\n")[1].split(",")[1].strip =~ /\A(\w*)\s*(\S*)\s*\Z/
|
212
|
+
$1
|
213
|
+
end
|
214
|
+
|
215
|
+
def parse_postal_code(address)
|
216
|
+
address.split("\n")[1].split(",")[1].strip =~ /\A(\w*)\s*(\S*)\s*\Z/
|
217
|
+
$2
|
218
|
+
end
|
219
|
+
|
220
|
+
def parse_equipment(equipment_name)
|
221
|
+
!!EQUIPMENT_CARGO_CARRIED[equipment_name].find do |cargo_carried|
|
222
|
+
check_box = response.xpath("//font[text()='#{cargo_carried}']").first.parent.previous_element
|
223
|
+
check_box.text == "X" ? true : false
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def parse_checkbox_field(field_name)
|
228
|
+
if label = response.xpath(%Q(//font[text()="#{field_name}"])).first
|
229
|
+
check_box = label.parent.previous_element
|
230
|
+
check_box.text == "X" ? true : false
|
231
|
+
else
|
232
|
+
false
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
def parse_interstate
|
237
|
+
parse_checkbox_field("Interstate")
|
238
|
+
end
|
239
|
+
|
240
|
+
def parse_intrastate_non_hazardous
|
241
|
+
parse_checkbox_field("Intrastate Only (Non-HM)")
|
242
|
+
end
|
243
|
+
|
244
|
+
def parse_intrastate_hazardous
|
245
|
+
parse_checkbox_field("Intrastate Only (HM)")
|
246
|
+
end
|
247
|
+
|
248
|
+
def parse_classification(classification_name)
|
249
|
+
parse_checkbox_field(CLASSIFICATION_LABEL[classification_name])
|
250
|
+
end
|
251
|
+
|
252
|
+
def parse_safer_last_updated
|
253
|
+
if last_updated = response.at_xpath("//b[starts-with(.,'The information below reflects the content')]").xpath("./font").text.strip
|
254
|
+
date_parts = last_updated.split("/").collect(&:to_i)
|
255
|
+
Date.new(date_parts[2], date_parts[0], date_parts[1]) if date_parts.count == 3
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'carrier_info/sources/safer'
|
data/lib/carrier_info.rb
ADDED
metadata
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carrier_info
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Sean Devine
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-10-31 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nokogiri
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
description: Fetch carrier info off the internet
|
31
|
+
email:
|
32
|
+
- barelyknown@icloud.com
|
33
|
+
executables: []
|
34
|
+
extensions: []
|
35
|
+
extra_rdoc_files: []
|
36
|
+
files:
|
37
|
+
- .gitignore
|
38
|
+
- Gemfile
|
39
|
+
- LICENSE.txt
|
40
|
+
- README.md
|
41
|
+
- Rakefile
|
42
|
+
- carrier_info.gemspec
|
43
|
+
- lib/carrier_info.rb
|
44
|
+
- lib/carrier_info/carrier.rb
|
45
|
+
- lib/carrier_info/sources.rb
|
46
|
+
- lib/carrier_info/sources/safer.rb
|
47
|
+
- lib/carrier_info/version.rb
|
48
|
+
homepage: https://github.com/buytruckload/carrier_info
|
49
|
+
licenses: []
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
require_paths:
|
53
|
+
- lib
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ! '>='
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '0'
|
60
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
61
|
+
none: false
|
62
|
+
requirements:
|
63
|
+
- - ! '>='
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: '0'
|
66
|
+
requirements: []
|
67
|
+
rubyforge_project:
|
68
|
+
rubygems_version: 1.8.24
|
69
|
+
signing_key:
|
70
|
+
specification_version: 3
|
71
|
+
summary: Fetch carrier info off the internet
|
72
|
+
test_files: []
|