vinquery 0.4.2 → 0.5.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.
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- vinquery (0.4.1)
4
+ vinquery (0.4.2)
5
5
  nokogiri (>= 1.4.4)
6
6
 
7
7
  GEM
@@ -21,7 +21,7 @@ GEM
21
21
  rspec-mocks (2.6.0)
22
22
  vin_exploder (0.4.3)
23
23
  webmock (1.6.4)
24
- addressable (> 2.2.5, ~> 2.2)
24
+ addressable (~> 2.2, > 2.2.5)
25
25
  crack (>= 0.1.7)
26
26
 
27
27
  PLATFORMS
@@ -1,80 +1,71 @@
1
1
  require 'net/http'
2
2
  require 'nokogiri'
3
3
  require 'logger'
4
+ require 'vinquery/vinquery_exception'
4
5
 
5
6
  class Vinquery
6
7
  attr_reader :attributes, :errors, :result
7
-
8
+
8
9
  def self.get(vin, options={})
9
- request = Vinquery.new(options[:url], options[:access_code], options[:report_type], options[:logger])
10
- doc = request.fetch vin
11
- result = request.parse doc
10
+ request = Vinquery.new(vin, options[:url], options[:access_code], options[:report_type], options[:logger])
11
+ request.fetch
12
+ request.parse
12
13
  request
13
14
  end
14
15
 
15
- def initialize(url, access_code, report_type, log = nil)
16
+ def initialize(vin, url, access_code, report_type, log = nil)
17
+ @vin = vin
16
18
  @url = url
19
+ @errors = []
17
20
  @access_code = access_code
18
21
  @report_type = report_type
19
22
  log ||= Logger.new(nil)
20
23
  @log = log
21
24
  end
22
25
 
23
- def fetch(vin)
26
+ def fetch
24
27
  # use reducable=FALSE to get additional fields like fuel_type
25
28
  # use vt=true to get vehicle_type
29
+ # use gvwr=TRUE to get GVWR
26
30
  # http://www.vinquery.com/ws_POQCXTYNO1D/xml_v100_QA7RTS8Y.aspx?accessCode=6958785b-ac0a-4303-8b28-40e14aa836ce&vin=YourVINToDecode&reportType=0&vt=true&gvwr=true
27
31
  @uri ||= "#{@url}?accessCode=#{@access_code}&reportType=#{@report_type}&reducable=FALSE&vt=TRUE&gvwr=TRUE"
28
- url_s = @uri + "&vin=#{vin}"
32
+ url_s = @uri + "&vin=#{@vin}"
29
33
  @log.info{"Vinquery#fetch - uri: #{url_s}"}
30
34
  url = URI.parse(url_s)
31
35
  begin
32
36
  @result = Net::HTTP.get url
33
37
  @log.debug{"Vinquery#fetch - result: #{@result}"}
38
+ @doc = Nokogiri::HTML(@result)
34
39
  rescue Exception => e
35
- @log.error{"ERROR - #{e.message}"}
36
- @log.error{"ERROR - #{e.backtrace[0]}"}
37
- xml = Nokogiri::XML::Builder.new do |doc|
38
- doc.vin(:number => vin,:status => "FAILED") {
39
- doc.message(:Key => "VinQuery unavailable", :Value => "Oops, it looks like our VIN decoder is unavailable at the moment. Please try again later.")
40
- }
41
- end
42
- @result = xml.to_xml
40
+ raise VinqueryException.new(e.message, e)
43
41
  end
44
- @doc = Nokogiri::HTML(@result)
45
42
  end
46
43
 
47
- def parse(doc)
48
- set_attributes doc
49
- set_errors_hash doc
50
- attributes
51
- end
44
+ def parse
45
+ raise create_exception unless valid?
52
46
 
53
- def set_attributes(doc)
54
47
  attributes = {}
55
- doc.xpath('//vehicle[1]/item').each do |item|
48
+ @doc.xpath('//vehicle[1]/item').each do |item|
56
49
  attributes[item.attributes['key'].value.downcase.gsub('.', '').gsub(/ /, '_').to_sym] = item.attributes['value'].value
57
50
  end
58
51
  @log.info{"Vinquery#set_attributes - number of attributes parsed: #{attributes.size}"}
59
52
  if attributes.size > 0
60
- vin = doc.css('vin').first.attributes['number'].value
53
+ vin = @doc.css('vin').first.attributes['number'].value
61
54
  attributes[:vin_key] = make_vin_key(vin)
62
- attributes[:vendor_result] = doc.to_xml
55
+ attributes[:vendor_result] = @doc.to_xml
63
56
  attributes[:number_of_cylinders] = attributes[:engine_type].upcase.match(/ [LV](\d{1,2}) /) ? $1 : nil
64
57
  attributes[:has_turbo] = attributes[:engine_type].upcase.match(/ ([TURBO|SUPERCHARGED]) /) ? true : false
65
58
  end
66
59
  @attributes = attributes
67
60
  end
68
61
 
69
- def set_errors_hash(doc)
70
- @errors = []
71
- @valid = doc.css('vin').first.attributes['status'].value == "SUCCESS"
72
- doc.css('message').each{|msg| @errors << {msg.attributes['key'].value => msg.attributes['value'].value} } unless valid?
73
- @errors.each{|msg| @log.error{"Vinquery#set_errors_hash - error: #{msg.to_s}"}} unless @errors.empty?
62
+ def create_exception
63
+ @doc.css('message').each{|msg| @errors << {msg.attributes['key'].value => msg.attributes['value'].value} }
64
+ VinqueryException.new(@errors.map{|msg| "#{msg.keys[0]}: #{msg.values[0]}"}.join("\n")) unless @errors.empty?
74
65
  end
75
66
 
76
67
  def valid?
77
- @valid
68
+ @valid ||= @doc.css('vin').first.attributes['status'].value == "SUCCESS" rescue false
78
69
  end
79
70
 
80
71
  def make_vin_key(vin)
@@ -1,3 +1,3 @@
1
1
  class Vinquery
2
- VERSION = '0.4.2'
2
+ VERSION = '0.5.0'
3
3
  end
@@ -0,0 +1,7 @@
1
+ class VinqueryException < StandardError
2
+ attr_accessor :original_exception
3
+ def initialize(msg=nil, exception=nil)
4
+ super(msg)
5
+ original_exception = exception
6
+ end
7
+ end
@@ -9,7 +9,7 @@ describe VinqueryAdapter do
9
9
 
10
10
  before(:each) do
11
11
 
12
- @query = Vinquery.new 'http://www.vinlookupservice.com', 'access_code', 'report_type_2'
12
+ @query = Vinquery.new 'valid_vin', 'http://www.vinlookupservice.com', 'access_code', 'report_type_2'
13
13
  @adapter = VinqueryAdapter.new({})
14
14
  @test_xml_data ||= File.new("#{File.dirname(__FILE__)}/vinquery_test.xml", "r").read
15
15
  stub_request(:any, /.*vinlookupservice.*/).to_return(:body => @test_xml_data, :status => 200, :headers => { 'Content-Length' => @test_xml_data.length})
@@ -26,14 +26,16 @@ describe VinqueryAdapter do
26
26
  hash[:errors].empty?.should == true
27
27
  end
28
28
 
29
- it 'should include an errors hash with an invalid vin number' do
29
+ it 'should raise an error with an invalid vin number' do
30
30
  res = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n<VINquery Version="1.0.0" Report_Type="BASIC" Date="2/19/2011">\r\n <VIN Number="ABCDEFGHIJKLMNOPQ" Status="FAILED">\r\n <Message Key="5" Value="Invalid VIN number: This VIN number contains invalid letters: I,O or Q." />\r\n </VIN>\r\n</VINquery>'
31
31
  stub_request(:any, /.*invalidvin.*/).to_return(:body => res, :status => 200, :headers => { 'Content-Length' => res.length})
32
- query = Vinquery.new('http://www.invalidvin.com', 'access_code', 'report_type_2')
32
+ query = Vinquery.new('BAD_VIN', 'http://www.invalidvin.com', 'access_code', 'report_type_2')
33
33
  Vinquery.should_receive(:new){ query }
34
- hash = @adapter.explode('BAD_VIN')
35
- hash[:errors].size.should == 1
36
- hash[:errors].first['5'].should == 'Invalid VIN number: This VIN number contains invalid letters: I,O or Q.'
34
+
35
+ expect { @adapter.explode('BAD_VIN') }.to raise_error(VinqueryException, /Invalid VIN number/)
36
+
37
+ # hash[:errors].size.should == 1
38
+ # hash[:errors].first['5'].should == 'Invalid VIN number: This VIN number contains invalid letters: I,O or Q.'
37
39
  end
38
40
 
39
41
  end
@@ -6,7 +6,7 @@ describe Vinquery do
6
6
 
7
7
  before(:each) do
8
8
 
9
- @query = Vinquery.new 'http://www.vinlookupservice.com', 'access_code', 'report_type_2'
9
+ @query = Vinquery.new 'valid_vin', 'http://www.vinlookupservice.com', 'access_code', 'report_type_2'
10
10
 
11
11
  @test_xml_data ||= File.new("#{File.dirname(__FILE__)}/vinquery_test.xml", "r").read
12
12
  stub_request(:any, /.*vinlookupservice.*/).to_return(:body => @test_xml_data, :status => 200, :headers => { 'Content-Length' => @test_xml_data.length})
@@ -16,63 +16,54 @@ describe Vinquery do
16
16
  WebMock.reset!
17
17
  end
18
18
 
19
- describe 'set attributes' do
20
- it 'should return a set of vehicle attributes given a Nokogiri document' do
19
+ describe '#valid?' do
20
+ it 'should return true when the returned doc has a status of SUCCESS' do
21
21
  doc = Nokogiri::HTML(@test_xml_data)
22
- @query.set_attributes(doc)
23
- # @query.attributes.each_pair{|k,v| puts "#{k} - #{v}"}
24
- @query.attributes[:body_style].should == "CREW CAB PICKUP 4-DR"
25
- @query.attributes[:vin_key].should == "3D7LU38C3G"
22
+
23
+ @query.instance_variable_set("@doc", doc)
24
+ @query.valid?.should == true
26
25
  end
27
26
 
28
- it 'should recover from poorly formatted or unexpected xml document' do
29
- xml_s = '<?xml version="1.0"?>\\n<blah status="FAILED" number="vin"\\n'
30
- doc = Nokogiri::HTML(xml_s)
31
- @query.set_attributes(doc).should == {}
27
+ it 'should return false when status is anything other than SUCCESS' do
28
+ doc = Nokogiri::HTML(@test_xml_data.gsub(/SUCCESS/, 'FAILED'))
29
+
30
+ @query.instance_variable_set("@doc", doc)
31
+ @query.valid?.should == false
32
32
  end
33
33
  end
34
34
 
35
- describe '#set_errors_hash' do
36
- it 'should give the reason for failure within an errors hash' do
35
+ describe '#create_exception' do
36
+ it 'should return a VinqueryException with the vinquery error message' do
37
37
  doc = Nokogiri::HTML '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n<VINquery Version="1.0.0" Report_Type="BASIC" Date="2/19/2011">\r\n <VIN Number="ABCDEFGHIJKLMNOPQ" Status="FAILED">\r\n <Message Key="5" Value="Invalid VIN number: This VIN number contains invalid letters: I,O or Q." />\r\n </VIN>\r\n</VINquery>'
38
- @query.set_errors_hash(doc)
38
+ @query.instance_variable_set("@doc", doc)
39
39
  @query.valid?.should == false
40
- @query.errors.should == [{"5" => "Invalid VIN number: This VIN number contains invalid letters: I,O or Q."}]
40
+ e = @query.create_exception
41
+ e.class.should == VinqueryException
42
+ e.message.should == "5: Invalid VIN number: This VIN number contains invalid letters: I,O or Q."
41
43
  end
42
44
  end
43
45
 
44
- describe 'get_doc' do
45
- it "should return valid xml parsed by nokogiri pulled from VinQuery.com" do
46
- n_xml = @query.fetch('abcdefghijklmnopq')
47
-
48
- n_xml.class.should equal(Nokogiri::HTML::Document)
49
- !!n_xml.css('vin').should == true
46
+ describe '#parse' do
47
+ it "should return a hash with all vin attributes" do
48
+ doc = Nokogiri::HTML(@test_xml_data)
49
+
50
+ @query.instance_variable_set("@doc", doc)
51
+ @query.valid?.should == true
52
+ h = @query.parse
53
+ h.class.should == Hash
54
+ h[:vin_key].should == '3D7LU38C3G'
50
55
  end
51
56
 
52
- it "should rescue from error if the request misfires" do
53
- stub_request(:any, /.*bad\.service\.url.*/).to_timeout
54
- @query.instance_variable_set(:@url,"http://bad.service.url")
55
- doc = @query.fetch('')
56
- doc.css('vin').first.attributes['status'].value.should == "FAILED"
57
- doc.css('message').first.attributes['key'].value.should == "VinQuery unavailable"
58
- doc.css('message').first.attributes['value'].value.should == "Oops, it looks like our VIN decoder is unavailable at the moment. Please try again later."
59
- end
60
- end
61
-
62
- describe 'parse_doc' do
63
- it 'should take nokogiri document and separate to attributes and errors hash' do
64
- doc = Nokogiri::HTML(@test_xml_data)
65
- @query.should_receive(:set_attributes).with(an_instance_of(Nokogiri::HTML::Document))
66
- @query.parse(doc)
57
+ it "should raise an VinException if request FAILED" do
58
+ doc = Nokogiri::HTML '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n<VINquery Version="1.0.0" Report_Type="BASIC" Date="2/19/2011">\r\n <VIN Number="ABCDEFGHIJKLMNOPQ" Status="FAILED">\r\n <Message Key="5" Value="Invalid VIN number: This VIN number contains invalid letters: I,O or Q." />\r\n </VIN>\r\n</VINquery>'
59
+ @query.instance_variable_set("@doc", doc)
60
+ @query.valid?.should == false
61
+ expect { @query.parse }.to raise_error(VinqueryException, /Invalid VIN number/)
67
62
  end
68
63
  end
69
64
 
70
- describe 'request' do
71
- before(:each) do
72
-
73
- end
74
-
75
- it 'should make the call to VinQuery.com and return attributes on valid number' do
65
+ describe '#get' do
66
+ it 'should make the call to VinQuery.com and return attributes on valid vin' do
76
67
  stub_request(:any, /.*fakeurl.*/).to_return(:body => @test_xml_data, :status => 200, :headers => { 'Content-Length' => @test_xml_data.length})
77
68
  query = Vinquery.get('1G1ND52F14M587843', {:url => 'http://www.fakeurl.com', :access_code => 'access_code', :report_type => 'report_type_2'})
78
69
  query.valid?.should == true
@@ -81,12 +72,10 @@ describe Vinquery do
81
72
  query.attributes[:make].should == 'Dodge'
82
73
  end
83
74
 
84
- it 'should return an errors array with an invalid vin number' do
75
+ it 'should raise an exception with an invalid vin number' do
85
76
  res = '<?xml version="1.0" encoding="utf-8" standalone="yes"?>\r\n<VINquery Version="1.0.0" Report_Type="BASIC" Date="2/19/2011">\r\n <VIN Number="ABCDEFGHIJKLMNOPQ" Status="FAILED">\r\n <Message Key="5" Value="Invalid VIN number: This VIN number contains invalid letters: I,O or Q." />\r\n </VIN>\r\n</VINquery>'
86
77
  stub_request(:any, /.*invalidvin.*/).to_return(:body => res, :status => 200, :headers => { 'Content-Length' => res.length})
87
- results = Vinquery.get('BADVIN', {:url => 'http://www.invalidvin.com', :access_code => 'access_code', :report_type => 'report_type_2'})
88
- results.valid?.should == false
89
- results.errors.class.should == Array
78
+ expect { Vinquery.get('BADVIN', {:url => 'http://www.invalidvin.com', :access_code => 'access_code', :report_type => 'report_type_2'}) }.to raise_error(VinqueryException)
90
79
  end
91
80
  end
92
81
 
metadata CHANGED
@@ -1,76 +1,74 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: vinquery
3
- version: !ruby/object:Gem::Version
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.5.0
4
5
  prerelease:
5
- version: 0.4.2
6
6
  platform: ruby
7
- authors:
7
+ authors:
8
8
  - Jake Mallory
9
9
  - George South
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
-
14
- date: 2011-08-08 00:00:00 Z
15
- dependencies:
16
- - !ruby/object:Gem::Dependency
13
+ date: 2011-10-28 00:00:00.000000000Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
17
16
  name: nokogiri
18
- prerelease: false
19
- requirement: &id001 !ruby/object:Gem::Requirement
17
+ requirement: &70282070376260 !ruby/object:Gem::Requirement
20
18
  none: false
21
- requirements:
22
- - - ">="
23
- - !ruby/object:Gem::Version
19
+ requirements:
20
+ - - ! '>='
21
+ - !ruby/object:Gem::Version
24
22
  version: 1.4.4
25
23
  type: :runtime
26
- version_requirements: *id001
27
- - !ruby/object:Gem::Dependency
28
- name: rspec
29
24
  prerelease: false
30
- requirement: &id002 !ruby/object:Gem::Requirement
25
+ version_requirements: *70282070376260
26
+ - !ruby/object:Gem::Dependency
27
+ name: rspec
28
+ requirement: &70282070375780 !ruby/object:Gem::Requirement
31
29
  none: false
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
35
33
  version: 2.6.0
36
34
  type: :development
37
- version_requirements: *id002
38
- - !ruby/object:Gem::Dependency
39
- name: webmock
40
35
  prerelease: false
41
- requirement: &id003 !ruby/object:Gem::Requirement
36
+ version_requirements: *70282070375780
37
+ - !ruby/object:Gem::Dependency
38
+ name: webmock
39
+ requirement: &70282070375300 !ruby/object:Gem::Requirement
42
40
  none: false
43
- requirements:
44
- - - ">="
45
- - !ruby/object:Gem::Version
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
46
44
  version: 1.6.4
47
45
  type: :development
48
- version_requirements: *id003
49
- - !ruby/object:Gem::Dependency
50
- name: vin_exploder
51
46
  prerelease: false
52
- requirement: &id004 !ruby/object:Gem::Requirement
47
+ version_requirements: *70282070375300
48
+ - !ruby/object:Gem::Dependency
49
+ name: vin_exploder
50
+ requirement: &70282070374820 !ruby/object:Gem::Requirement
53
51
  none: false
54
- requirements:
55
- - - ">="
56
- - !ruby/object:Gem::Version
52
+ requirements:
53
+ - - ! '>='
54
+ - !ruby/object:Gem::Version
57
55
  version: 0.4.0
58
56
  type: :development
59
- version_requirements: *id004
57
+ prerelease: false
58
+ version_requirements: *70282070374820
60
59
  description: A client for the Vinquery.com vin decoding web service.
61
60
  email: tinomen@gmail.com
62
61
  executables: []
63
-
64
62
  extensions: []
65
-
66
- extra_rdoc_files:
63
+ extra_rdoc_files:
67
64
  - Gemfile
68
65
  - Gemfile.lock
69
66
  - Rakefile
70
67
  - README.textile
71
- files:
68
+ files:
72
69
  - lib/vinquery/version.rb
73
70
  - lib/vinquery/vin_exploder/adapter.rb
71
+ - lib/vinquery/vinquery_exception.rb
74
72
  - lib/vinquery.rb
75
73
  - Gemfile
76
74
  - Gemfile.lock
@@ -82,37 +80,35 @@ files:
82
80
  - spec/vinquery_test.xml
83
81
  homepage: http://github.com/tinomen/vinquery
84
82
  licenses: []
85
-
86
83
  post_install_message:
87
- rdoc_options:
84
+ rdoc_options:
88
85
  - --title
89
86
  - A client for vinquery.com
90
87
  - --main
91
88
  - README.rdoc
92
89
  - --line-numbers
93
90
  - --charset=UTF-8
94
- require_paths:
91
+ require_paths:
95
92
  - lib
96
- required_ruby_version: !ruby/object:Gem::Requirement
93
+ required_ruby_version: !ruby/object:Gem::Requirement
97
94
  none: false
98
- requirements:
99
- - - ">="
100
- - !ruby/object:Gem::Version
101
- version: "0"
102
- required_rubygems_version: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - ! '>='
97
+ - !ruby/object:Gem::Version
98
+ version: '0'
99
+ required_rubygems_version: !ruby/object:Gem::Requirement
103
100
  none: false
104
- requirements:
105
- - - ">="
106
- - !ruby/object:Gem::Version
101
+ requirements:
102
+ - - ! '>='
103
+ - !ruby/object:Gem::Version
107
104
  version: 1.3.6
108
105
  requirements: []
109
-
110
106
  rubyforge_project:
111
- rubygems_version: 1.7.2
107
+ rubygems_version: 1.8.10
112
108
  signing_key:
113
109
  specification_version: 3
114
110
  summary: A client for vinquery.com
115
- test_files:
111
+ test_files:
116
112
  - spec/spec_helper.rb
117
113
  - spec/vin_exploder_adapter_spec.rb
118
114
  - spec/vinquery_spec.rb