vinquery 0.4.2 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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