carvoyant-api-ruby 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +9 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +29 -0
- data/Rakefile +9 -0
- data/carvoyant-api-ruby.gemspec +39 -0
- data/lib/carvoyant-api-ruby.rb +10 -0
- data/lib/carvoyant_api/errors.rb +47 -0
- data/lib/carvoyant_api/resources.rb +2 -0
- data/lib/carvoyant_api/resources/account.rb +19 -0
- data/lib/carvoyant_api/resources/base.rb +53 -0
- data/lib/carvoyant_api/resources/data_point.rb +27 -0
- data/lib/carvoyant_api/resources/data_set.rb +11 -0
- data/lib/carvoyant_api/resources/trip.rb +75 -0
- data/lib/carvoyant_api/resources/vehicle.rb +34 -0
- data/lib/carvoyant_api/resources/waypoint.rb +13 -0
- data/lib/carvoyant_api/version.rb +3 -0
- data/test/fixtures/deviceId_error.json +13 -0
- data/test/fixtures/error.json +7 -0
- data/test/fixtures/vehicle.json +22 -0
- data/test/fixtures/vehicle_without_label.json +20 -0
- data/test/fixtures/vehicles.json +103 -0
- data/test/test_helper.rb +59 -0
- data/test/vehicle_test.rb +51 -0
- metadata +252 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0bcbf14f2f7e2e86bad095841e9ef91d9dbc1a97
|
4
|
+
data.tar.gz: 48f2befd2a16f601c3238fc796d741c042c01253
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1cb131cf9c00609aa4ec2f223f9fdb2640d6d06a1456384cdcf0657215dc6904889f593dcfea06fe7fe7d3f10f0b16a25a29ebba581fa8e52acac0c4de05a5d5
|
7
|
+
data.tar.gz: 1ce21f59df89f37961cd0f29b3d0ebc5bff1f8cc8036467d36e61b393ed85521e738beafd210e4d31fc8df4bf7c4f2373ce63a6c3671df473c507f2ff4a725e7
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Younility Inc.
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# CarvoyantApi
|
2
|
+
|
3
|
+
TODO: Write a gem description
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add this line to your application's Gemfile:
|
8
|
+
|
9
|
+
gem 'carvoyant-api-ruby'
|
10
|
+
|
11
|
+
And then execute:
|
12
|
+
|
13
|
+
$ bundle
|
14
|
+
|
15
|
+
Or install it yourself as:
|
16
|
+
|
17
|
+
$ gem install carvoyant-api-ruby
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
TODO: Write usage instructions here
|
22
|
+
|
23
|
+
## Contributing
|
24
|
+
|
25
|
+
1. Fork it ( https://github.com/[my-github-username]/carvoyant-api-ruby/fork )
|
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 a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'carvoyant_api/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "carvoyant-api-ruby"
|
8
|
+
spec.version = CarvoyantAPI::VERSION
|
9
|
+
spec.authors = ["Farrukh Abdulkadyrov"]
|
10
|
+
spec.email = ["farrukhabdul@gmail.com"]
|
11
|
+
spec.summary = %q{The Carvoyant API gem is a lightweight gem for accessing Carvoyant REST services}
|
12
|
+
spec.description = %q{The Carvoyant API gem allows Ruby developers to programmatically access the Carvoyant Resources. The API is implemented as JSON over HTTP using all four verbs (GET/POST/PUT/DELETE). Each resource, like Vehicle, Trip, or DataSet, has its own URL and is manipulated in isolation.}
|
13
|
+
spec.homepage = "http://younility.com/"
|
14
|
+
spec.license = "MIT"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0")
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
20
|
+
|
21
|
+
spec.add_dependency 'activeresource', '~> 4.0', '>= 4.0.0'
|
22
|
+
spec.add_dependency 'ruby-units', '~> 1.4.5', '>= 1.4.5'
|
23
|
+
|
24
|
+
spec.add_development_dependency "bundler", "~> 1.6"
|
25
|
+
|
26
|
+
dev_dependencies = [['mocha', '~> 0.9.8', '>= 0.9.8'],
|
27
|
+
['fakeweb', '~> 1.3.0', '>= 1.3.0'],
|
28
|
+
['minitest', '~> 5.8.0', '>= 5.8.0'],
|
29
|
+
['rake', '~> 10.4.2', '>= 10.4.2'],
|
30
|
+
['byebug', '~> 6.0.2', '>= 6.0.2'],
|
31
|
+
['timecop', '~> 0.8.0', '>= 0.8.0']
|
32
|
+
]
|
33
|
+
|
34
|
+
if spec.respond_to?(:add_development_dependency)
|
35
|
+
dev_dependencies.each { |dep| spec.add_development_dependency(*dep) }
|
36
|
+
else
|
37
|
+
dev_dependencies.each { |dep| spec.add_dependency(*dep) }
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
# CarvoyantAPI Validation Errors are returned in a specific format. By default ActiveResource is unable to parse API errors correctly.
|
3
|
+
# ActiveResource `from_json` and `from_hash` methods need to be overridden to correctly parse errors returned by CarvoyantAPI
|
4
|
+
class Errors < ActiveResource::Errors
|
5
|
+
def from_json(json, save_cache = false)
|
6
|
+
decoded = ActiveSupport::JSON.decode(json) || {} rescue {}
|
7
|
+
errors = decoded['error'] || decoded
|
8
|
+
from_hash errors, save_cache
|
9
|
+
end
|
10
|
+
|
11
|
+
def from_hash(messages, save_cache = false)
|
12
|
+
unless save_cache
|
13
|
+
clear
|
14
|
+
end
|
15
|
+
|
16
|
+
if messages['fieldErrors']
|
17
|
+
messages['fieldErrors'].each do |field_error|
|
18
|
+
key = field_error['fieldName']
|
19
|
+
error = field_error['errorDisplay']
|
20
|
+
if @base.known_attributes.include?(key)
|
21
|
+
add key, error
|
22
|
+
elsif key == 'base'
|
23
|
+
self[:base] << error
|
24
|
+
else
|
25
|
+
# Errors that might have an unknown key should be added to base
|
26
|
+
self[:base] << "#{key.humanize} #{error}"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
elsif messages['errorDisplay']
|
30
|
+
self[:base] << messages['errorDisplay']
|
31
|
+
else
|
32
|
+
self[:base] << 'An unknown error has occured.'
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# CarvoyantAPI returns error messages which have attribute name in the message.
|
37
|
+
# For example: "The deviceId is in use by another vehicle."
|
38
|
+
# Overrides ActiveModel::Errors method
|
39
|
+
def full_message(attribute, message)
|
40
|
+
I18n.t(:"carvoyant_errors.format", {
|
41
|
+
default: '%{message}',
|
42
|
+
message: message,
|
43
|
+
attribute: attribute
|
44
|
+
})
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class AccountJsonFormatter
|
3
|
+
include ActiveResource::Formats::JsonFormat
|
4
|
+
|
5
|
+
def decode(json)
|
6
|
+
ActiveSupport::JSON.decode(json)['account']
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Account < Base
|
11
|
+
self.format = AccountJsonFormatter.new
|
12
|
+
self.primary_key = :id
|
13
|
+
|
14
|
+
schema do
|
15
|
+
integer 'id'
|
16
|
+
string 'firstName', 'lastName', 'username', 'dateCreated', 'email', 'zipcode', 'phone', 'timeZone', 'preferredContact', 'accessToken'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class Base < ActiveResource::Base
|
3
|
+
self.site = 'https://api.carvoyant.com'
|
4
|
+
self.prefix = '/v1/api/'
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def element_path(id, prefix_options = {}, query_options = nil)
|
8
|
+
check_prefix_options(prefix_options)
|
9
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
10
|
+
"#{prefix(prefix_options)}#{element_name}/#{URI.parser.escape id.to_s}#{query_string(query_options)}"
|
11
|
+
end
|
12
|
+
|
13
|
+
def collection_path(prefix_options = {}, query_options = nil)
|
14
|
+
prefix_options, query_options = split_options(prefix_options) if query_options.nil?
|
15
|
+
"#{prefix(prefix_options)}#{element_name}/#{query_string(query_options)}"
|
16
|
+
end
|
17
|
+
|
18
|
+
def headers
|
19
|
+
if defined?(@headers)
|
20
|
+
@headers
|
21
|
+
elsif superclass != Object && superclass.headers
|
22
|
+
superclass.headers
|
23
|
+
else
|
24
|
+
@headers ||= {}
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def activate_session(token)
|
29
|
+
headers.merge!({ 'Authorization' => "Bearer #{token}" })
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def update
|
34
|
+
run_callbacks :update do
|
35
|
+
connection.post(element_path(prefix_options), encode, self.class.headers).tap do |response|
|
36
|
+
load_attributes_from_response(response)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def save
|
42
|
+
super
|
43
|
+
rescue ActiveResource::ServerError, ActiveResource::ResourceInvalid => error
|
44
|
+
@remote_errors = error
|
45
|
+
load_remote_errors(@remote_errors, true)
|
46
|
+
false
|
47
|
+
end
|
48
|
+
|
49
|
+
def errors
|
50
|
+
@errors ||= Errors.new(self)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class DataPoint
|
3
|
+
|
4
|
+
attr_reader :id, :timestamp, :key, :value, :translated_value, :waypoint
|
5
|
+
|
6
|
+
def initialize(attributes = {}, unit_format = :metric)
|
7
|
+
@id = attributes[:id]
|
8
|
+
@timestamp = attributes[:timestamp]
|
9
|
+
@key = attributes[:key]
|
10
|
+
@value = attributes[:value]
|
11
|
+
@translated_value = attributes[:translatedValue]
|
12
|
+
case @key
|
13
|
+
when 'GEN_WAYPOINT'
|
14
|
+
latitude, longitude = @value.split(',')
|
15
|
+
@waypoint = Waypoint.new(timestamp: @timestamp, latitude: latitude, longitude: longitude)
|
16
|
+
when 'GEN_ENGINE_COOLANT_TEMP'
|
17
|
+
@translated_value = unit_format == :imperial ? Unit(@translated_value.gsub(' ', '')) : Unit(@translated_value.gsub(' ', '')).convert_to('degC')
|
18
|
+
@value = @translated_value.scalar.to_f
|
19
|
+
@translated_value = @translated_value.to_s('%.2f')
|
20
|
+
when 'GEN_SPEED'
|
21
|
+
@translated_value = unit_format == :imperial ? Unit(@translated_value) : Unit(@translated_value).convert_to('kph')
|
22
|
+
@value = @translated_value.scalar.to_f
|
23
|
+
@translated_value = @translated_value.to_s('%.2f')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class DataSet
|
3
|
+
attr_reader :id, :timestamp, :ignition_status, :data_points
|
4
|
+
|
5
|
+
def initialize(attributes={}, unit_format = :metric)
|
6
|
+
@timestamp = Time.parse(attributes[:timestamp])
|
7
|
+
@ignition_status = attributes[:ignitionStatus]
|
8
|
+
@data_points = attributes[:datum].map { |data_point| [data_point.key, DataPoint.new(data_point.attributes, unit_format)] }.to_h
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class TripJsonFormatter
|
3
|
+
include ActiveResource::Formats::JsonFormat
|
4
|
+
|
5
|
+
def decode(json)
|
6
|
+
ActiveSupport::JSON.decode(json)['trip']
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Trip < Base
|
11
|
+
|
12
|
+
self.prefix = '/v1/api/vehicle/:vehicle_id/'
|
13
|
+
self.format = TripJsonFormatter.new
|
14
|
+
self.primary_key = :id
|
15
|
+
|
16
|
+
schema do
|
17
|
+
integer 'id'
|
18
|
+
string 'startTime', 'endTime', 'startWaypoint', 'endWaypoint', 'data'
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :start_waypoint, :end_waypoint, :start_time, :end_time, :in_progress, :data_sets
|
22
|
+
|
23
|
+
|
24
|
+
class << self
|
25
|
+
def unit_format(unit_format = :metric)
|
26
|
+
Thread.current["active.resource.unit_formats.#{self.object_id}"] = unit_format
|
27
|
+
self
|
28
|
+
end
|
29
|
+
|
30
|
+
def current_unit_format
|
31
|
+
Thread.current["active.resource.unit_formats.#{self.object_id}"] || :metric
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
def initialize(attributes = {}, persisted = false)
|
37
|
+
super
|
38
|
+
@start_waypoint = Waypoint.new(startWaypoint.attributes) if startWaypoint
|
39
|
+
@end_waypoint = Waypoint.new(endWaypoint.attributes) if endWaypoint
|
40
|
+
@start_time = Time.parse(startTime) if startTime
|
41
|
+
@end_time = endTime ? Time.parse(endTime) : Time.current
|
42
|
+
@in_progress = endTime.nil?
|
43
|
+
@data_sets = data.map { |data_set| DataSet.new(data_set.attributes, self.class.current_unit_format) } if data
|
44
|
+
@mileage = Unit("#{self.attributes[:mileage] || 0} miles")
|
45
|
+
@mileage = @mileage.convert_to('km') if metric?
|
46
|
+
end
|
47
|
+
|
48
|
+
def locations
|
49
|
+
@data_sets.each.map { |data_set| data_set.data_points['GEN_WAYPOINT'].try(:waypoint)}.compact
|
50
|
+
end
|
51
|
+
|
52
|
+
def average_speed
|
53
|
+
speed = @mileage.scalar / ((@end_time - @start_time) / 1.hours)
|
54
|
+
speed = imperial? ? Unit("#{speed} mph") : Unit("#{speed} kph")
|
55
|
+
speed.to_s('%0.2f')
|
56
|
+
end
|
57
|
+
|
58
|
+
def max_speed
|
59
|
+
speed = @data_sets.map { |data_set| data_set.data_points['GEN_SPEED'].try(:value) }.compact.max
|
60
|
+
speed = imperial? ? Unit("#{speed} mph") : Unit("#{speed} kph")
|
61
|
+
speed.to_s('%0.2f')
|
62
|
+
end
|
63
|
+
|
64
|
+
def mileage
|
65
|
+
@mileage
|
66
|
+
end
|
67
|
+
def imperial?
|
68
|
+
self.class.current_unit_format == :imperial
|
69
|
+
end
|
70
|
+
|
71
|
+
def metric?
|
72
|
+
!imperial?
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module CarvoyantAPI
|
2
|
+
class VehicleJsonFormatter
|
3
|
+
include ActiveResource::Formats::JsonFormat
|
4
|
+
|
5
|
+
def decode(json)
|
6
|
+
ActiveSupport::JSON.decode(json)['vehicle']
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
class Vehicle < Base
|
11
|
+
self.format = VehicleJsonFormatter.new
|
12
|
+
self.primary_key = :vehicleId
|
13
|
+
|
14
|
+
attr_reader :last_waypoint, :last_running_timestamp
|
15
|
+
|
16
|
+
schema do
|
17
|
+
integer 'id'
|
18
|
+
string 'label', 'name', 'vin', 'lastWaypoint', 'year', 'make', 'model', 'running', 'deviceId', 'lastRunningTimestamp'
|
19
|
+
float 'mileage'
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize(attributes = {}, persisted = false)
|
23
|
+
super
|
24
|
+
self.attributes['deviceId'] ||= ''
|
25
|
+
self.attributes['label'] ||= ''
|
26
|
+
@last_waypoint = Waypoint.new(lastWaypoint.attributes) if lastWaypoint
|
27
|
+
@last_running_timestamp = Time.parse(lastRunningTimestamp) if lastRunningTimestamp
|
28
|
+
end
|
29
|
+
|
30
|
+
def running?
|
31
|
+
running == 'true'
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class CarvoyantAPI::Waypoint
|
2
|
+
attr_reader :timestamp, :latitude, :longitude
|
3
|
+
|
4
|
+
def initialize(attributes = {})
|
5
|
+
@timestamp = Time.parse(attributes[:timestamp])
|
6
|
+
@latitude = attributes[:latitude].to_f
|
7
|
+
@longitude = attributes[:longitude].to_f
|
8
|
+
end
|
9
|
+
|
10
|
+
def to_s
|
11
|
+
"#{@latitude}, #{@longitude}"
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
{
|
2
|
+
"error": {
|
3
|
+
"httpStatus": 500,
|
4
|
+
"errorCode": "CANNOTPERSIST",
|
5
|
+
"detail": "Could not add vehicle.",
|
6
|
+
"errorDisplay": "Could not add vehicle.",
|
7
|
+
"fieldErrors": [{
|
8
|
+
"fieldName": "deviceId",
|
9
|
+
"errorCode": "UNIQUE",
|
10
|
+
"errorDisplay": "The deviceId is in use by another vehicle."
|
11
|
+
}]
|
12
|
+
}
|
13
|
+
}
|
@@ -0,0 +1,22 @@
|
|
1
|
+
{
|
2
|
+
"vehicle": {
|
3
|
+
"name": "2014 Ford Focus SE",
|
4
|
+
"label": "Ryan Cassels",
|
5
|
+
"vehicleId": 2230,
|
6
|
+
"deviceId": "C201401286",
|
7
|
+
"vin": "1FADP3F2XEL352103",
|
8
|
+
"mileage": 1238.0,
|
9
|
+
"lastWaypoint": {
|
10
|
+
"timestamp": "20150415T174210+0000",
|
11
|
+
"latitude": 45.330289,
|
12
|
+
"longitude": -75.723374
|
13
|
+
},
|
14
|
+
"lastRunningTimestamp": "20150415T174210+0000",
|
15
|
+
"year": "2014",
|
16
|
+
"make": "Ford",
|
17
|
+
"model": "Focus",
|
18
|
+
"autoAssignDevice": true,
|
19
|
+
"mil": false
|
20
|
+
}
|
21
|
+
}
|
22
|
+
|
@@ -0,0 +1,20 @@
|
|
1
|
+
{
|
2
|
+
"vehicle": {
|
3
|
+
"name": "2014 Mazda Mazda2 Sport",
|
4
|
+
"vehicleId": 2230,
|
5
|
+
"deviceId": "C201401288",
|
6
|
+
"vin": "JM1DE1KY5E0181759",
|
7
|
+
"mileage": 168.0,
|
8
|
+
"lastWaypoint": {
|
9
|
+
"timestamp": "20150429T111112+0000",
|
10
|
+
"latitude": 45.330392,
|
11
|
+
"longitude": -75.723559
|
12
|
+
},
|
13
|
+
"lastRunningTimestamp": "20150429T110132+0000",
|
14
|
+
"year": "2014",
|
15
|
+
"make": "Mazda",
|
16
|
+
"model": "Mazda2",
|
17
|
+
"autoAssignDevice": true,
|
18
|
+
"mil": false
|
19
|
+
}
|
20
|
+
}
|
@@ -0,0 +1,103 @@
|
|
1
|
+
{
|
2
|
+
"vehicle": [{
|
3
|
+
"name": "Unidentified Vehicle",
|
4
|
+
"label": "Paul Robertson(old)",
|
5
|
+
"vehicleId": 2229,
|
6
|
+
"mileage": 163857.0,
|
7
|
+
"lastWaypoint": {
|
8
|
+
"timestamp": "20150413T215800+0000",
|
9
|
+
"latitude": 45.330372,
|
10
|
+
"longitude": -75.723658
|
11
|
+
},
|
12
|
+
"running": true,
|
13
|
+
"lastRunningTimestamp": "20150427T183809+0000",
|
14
|
+
"autoAssignDevice": true,
|
15
|
+
"mil": false
|
16
|
+
}, {
|
17
|
+
"name": "2014 Ford Focus SE",
|
18
|
+
"label": "Ryan Cassels",
|
19
|
+
"vehicleId": 2230,
|
20
|
+
"deviceId": "C201401286",
|
21
|
+
"vin": "1FADP3F2XEL352103",
|
22
|
+
"mileage": 1238.0,
|
23
|
+
"lastWaypoint": {
|
24
|
+
"timestamp": "20150415T174210+0000",
|
25
|
+
"latitude": 45.330289,
|
26
|
+
"longitude": -75.723374
|
27
|
+
},
|
28
|
+
"lastRunningTimestamp": "20150415T160918+0000",
|
29
|
+
"year": "2014",
|
30
|
+
"make": "Ford",
|
31
|
+
"model": "Focus",
|
32
|
+
"autoAssignDevice": true,
|
33
|
+
"mil": false
|
34
|
+
}, {
|
35
|
+
"name": "2013 Mazda Mazda5 Touring",
|
36
|
+
"label": "Chris Cameron",
|
37
|
+
"vehicleId": 2249,
|
38
|
+
"vin": "JM1CW2CLXD0155495",
|
39
|
+
"mileage": 3034.0,
|
40
|
+
"lastWaypoint": {
|
41
|
+
"timestamp": "20150426T172546+0000",
|
42
|
+
"latitude": 45.330408,
|
43
|
+
"longitude": -75.723596
|
44
|
+
},
|
45
|
+
"running": true,
|
46
|
+
"lastRunningTimestamp": "20150427T183809+0000",
|
47
|
+
"year": "2013",
|
48
|
+
"make": "Mazda",
|
49
|
+
"model": "Mazda5",
|
50
|
+
"autoAssignDevice": true,
|
51
|
+
"mil": false
|
52
|
+
}, {
|
53
|
+
"name": "2015 Jeep Wrangler Unlimited Sahara",
|
54
|
+
"label": "Ben Burford",
|
55
|
+
"vehicleId": 2691,
|
56
|
+
"vin": "1C4HJWEG4FL529001",
|
57
|
+
"mileage": 159774.0,
|
58
|
+
"lastWaypoint": {
|
59
|
+
"timestamp": "20150220T190447+0000",
|
60
|
+
"latitude": 40.63675,
|
61
|
+
"longitude": -111.48571
|
62
|
+
},
|
63
|
+
"lastRunningTimestamp": "20150221T010420+0000",
|
64
|
+
"year": "2015",
|
65
|
+
"make": "Jeep",
|
66
|
+
"model": "Wrangler",
|
67
|
+
"autoAssignDevice": true,
|
68
|
+
"mil": false
|
69
|
+
}, {
|
70
|
+
"name": "Unidentified Vehicle",
|
71
|
+
"label": "Paul Robertson(new)",
|
72
|
+
"vehicleId": 8854,
|
73
|
+
"deviceId": "013777002274965",
|
74
|
+
"mileage": 427.0,
|
75
|
+
"lastWaypoint": {
|
76
|
+
"timestamp": "20150427T180836+0000",
|
77
|
+
"latitude": 45.334686,
|
78
|
+
"longitude": -75.72609
|
79
|
+
},
|
80
|
+
"lastRunningTimestamp": "20150427T180831+0000",
|
81
|
+
"autoAssignDevice": true,
|
82
|
+
"mil": false
|
83
|
+
}, {
|
84
|
+
"name": "2014 Mazda Mazda2 Sport",
|
85
|
+
"vehicleId": 11660,
|
86
|
+
"deviceId": "C201401288",
|
87
|
+
"vin": "JM1DE1KY5E0181759",
|
88
|
+
"mileage": 39.0,
|
89
|
+
"lastWaypoint": {
|
90
|
+
"timestamp": "20150427T183741+0000",
|
91
|
+
"latitude": 45.361303,
|
92
|
+
"longitude": -75.715953
|
93
|
+
},
|
94
|
+
"running": true,
|
95
|
+
"lastRunningTimestamp": "20150427T183809+0000",
|
96
|
+
"year": "2014",
|
97
|
+
"make": "Mazda",
|
98
|
+
"model": "Mazda2",
|
99
|
+
"autoAssignDevice": true,
|
100
|
+
"mil": false
|
101
|
+
}],
|
102
|
+
"totalRecords": 6
|
103
|
+
}
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'fakeweb'
|
3
|
+
require 'minitest/autorun'
|
4
|
+
require 'mocha/setup'
|
5
|
+
require 'byebug'
|
6
|
+
require 'timecop'
|
7
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
|
+
require 'carvoyant-api-ruby'
|
10
|
+
|
11
|
+
FakeWeb.allow_net_connect = false
|
12
|
+
|
13
|
+
# setup ShopifyAPI with fake api_key and secret
|
14
|
+
|
15
|
+
class Minitest::Test
|
16
|
+
def self.test(string, &block)
|
17
|
+
define_method("test:#{string}", &block)
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.should(string, &block)
|
21
|
+
self.test("should_#{string}", &block)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.context(string)
|
25
|
+
yield
|
26
|
+
end
|
27
|
+
|
28
|
+
def setup
|
29
|
+
end
|
30
|
+
|
31
|
+
def teardown
|
32
|
+
FakeWeb.clean_registry
|
33
|
+
end
|
34
|
+
|
35
|
+
# Custom Assertions
|
36
|
+
def assert_not(expression)
|
37
|
+
assert_block("Expected <#{expression}> to be false!") { not expression }
|
38
|
+
end
|
39
|
+
|
40
|
+
def load_fixture(name, format=:json)
|
41
|
+
File.read(File.dirname(__FILE__) + "/fixtures/#{name}.#{format}")
|
42
|
+
end
|
43
|
+
|
44
|
+
def fake(endpoint, options={})
|
45
|
+
|
46
|
+
body = options.has_key?(:body) ? options.delete(:body) : load_fixture(endpoint)
|
47
|
+
format = options.delete(:format) || :json
|
48
|
+
method = options.delete(:method) || :get
|
49
|
+
extension = ".#{options.delete(:extension)||'json'}" unless options[:extension]==false
|
50
|
+
|
51
|
+
url = if options.has_key?(:url)
|
52
|
+
options[:url]
|
53
|
+
else
|
54
|
+
"https://api.carvoyant.com#{endpoint}"
|
55
|
+
end
|
56
|
+
|
57
|
+
FakeWeb.register_uri(method, url, {:body => body, :status => 200, :content_type => "text/#{format}", :content_length => 1}.merge(options))
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
class VehicleTest < Minitest::Test
|
3
|
+
|
4
|
+
def test_get_vehicle
|
5
|
+
fake "/v1/api/vehicle/2230", :method => :get, :body => load_fixture('vehicle')
|
6
|
+
vehicle = CarvoyantAPI::Vehicle.find(2230)
|
7
|
+
assert_equal 2230, vehicle.vehicleId
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_post_vehicle
|
11
|
+
fake "/v1/api/vehicle/", :method => :post, :body => load_fixture('vehicle')
|
12
|
+
vehicle = CarvoyantAPI::Vehicle.create(deviceId: "C201401286", vin: "1FADP3F2XEL352103")
|
13
|
+
assert_equal 2230, vehicle.id
|
14
|
+
assert_equal "C201401286", vehicle.deviceId
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_get_vehicles
|
18
|
+
fake "/v1/api/vehicle/", :method => :get, :body => load_fixture('vehicles')
|
19
|
+
vehicles = CarvoyantAPI::Vehicle.all
|
20
|
+
assert_equal 6, vehicles.length
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_update_vehicle
|
24
|
+
skip
|
25
|
+
fake "/v1/api/vehicle/2230", method: :get, body: load_fixture('vehicle')
|
26
|
+
fake "/v1/api/vehicle/2230", method: :post, body: load_fixture('vehicle')
|
27
|
+
|
28
|
+
# add lines to test update here
|
29
|
+
|
30
|
+
assert_equal vehicle.vin, '1FADP3F2XEL352103'
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_not_running
|
34
|
+
fake "/v1/api/vehicle/2230", method: :get, body: load_fixture('vehicle')
|
35
|
+
vehicle = CarvoyantAPI::Vehicle.find(2230)
|
36
|
+
assert_equal false, vehicle.running?
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_vehicle_without_label
|
40
|
+
fake "/v1/api/vehicle/2230", method: :get, body: load_fixture('vehicle_without_label')
|
41
|
+
vehicle = CarvoyantAPI::Vehicle.find(2230)
|
42
|
+
assert_equal false, vehicle.label.nil?
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_error_handling
|
46
|
+
fake "/v1/api/vehicle/", :method => :post, body: load_fixture('deviceId_error'), status: ["500", "Internal Server Error"]
|
47
|
+
vehicle = CarvoyantAPI::Vehicle.create(deviceId: "C201401288")
|
48
|
+
assert_includes vehicle.errors["deviceId"], "The deviceId is in use by another vehicle."
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
metadata
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: carvoyant-api-ruby
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Farrukh Abdulkadyrov
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-09-24 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: activeresource
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 4.0.0
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - "~>"
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '4.0'
|
30
|
+
- - ">="
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 4.0.0
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: ruby-units
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: 1.4.5
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: 1.4.5
|
43
|
+
type: :runtime
|
44
|
+
prerelease: false
|
45
|
+
version_requirements: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - "~>"
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 1.4.5
|
50
|
+
- - ">="
|
51
|
+
- !ruby/object:Gem::Version
|
52
|
+
version: 1.4.5
|
53
|
+
- !ruby/object:Gem::Dependency
|
54
|
+
name: bundler
|
55
|
+
requirement: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - "~>"
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: '1.6'
|
60
|
+
type: :development
|
61
|
+
prerelease: false
|
62
|
+
version_requirements: !ruby/object:Gem::Requirement
|
63
|
+
requirements:
|
64
|
+
- - "~>"
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.6'
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
name: mocha
|
69
|
+
requirement: !ruby/object:Gem::Requirement
|
70
|
+
requirements:
|
71
|
+
- - "~>"
|
72
|
+
- !ruby/object:Gem::Version
|
73
|
+
version: 0.9.8
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.9.8
|
77
|
+
type: :development
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - "~>"
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.9.8
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
version: 0.9.8
|
87
|
+
- !ruby/object:Gem::Dependency
|
88
|
+
name: fakeweb
|
89
|
+
requirement: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - "~>"
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: 1.3.0
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: 1.3.0
|
97
|
+
type: :development
|
98
|
+
prerelease: false
|
99
|
+
version_requirements: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: 1.3.0
|
104
|
+
- - ">="
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: 1.3.0
|
107
|
+
- !ruby/object:Gem::Dependency
|
108
|
+
name: minitest
|
109
|
+
requirement: !ruby/object:Gem::Requirement
|
110
|
+
requirements:
|
111
|
+
- - "~>"
|
112
|
+
- !ruby/object:Gem::Version
|
113
|
+
version: 5.8.0
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 5.8.0
|
117
|
+
type: :development
|
118
|
+
prerelease: false
|
119
|
+
version_requirements: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - "~>"
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: 5.8.0
|
124
|
+
- - ">="
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: 5.8.0
|
127
|
+
- !ruby/object:Gem::Dependency
|
128
|
+
name: rake
|
129
|
+
requirement: !ruby/object:Gem::Requirement
|
130
|
+
requirements:
|
131
|
+
- - "~>"
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: 10.4.2
|
134
|
+
- - ">="
|
135
|
+
- !ruby/object:Gem::Version
|
136
|
+
version: 10.4.2
|
137
|
+
type: :development
|
138
|
+
prerelease: false
|
139
|
+
version_requirements: !ruby/object:Gem::Requirement
|
140
|
+
requirements:
|
141
|
+
- - "~>"
|
142
|
+
- !ruby/object:Gem::Version
|
143
|
+
version: 10.4.2
|
144
|
+
- - ">="
|
145
|
+
- !ruby/object:Gem::Version
|
146
|
+
version: 10.4.2
|
147
|
+
- !ruby/object:Gem::Dependency
|
148
|
+
name: byebug
|
149
|
+
requirement: !ruby/object:Gem::Requirement
|
150
|
+
requirements:
|
151
|
+
- - "~>"
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: 6.0.2
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: 6.0.2
|
157
|
+
type: :development
|
158
|
+
prerelease: false
|
159
|
+
version_requirements: !ruby/object:Gem::Requirement
|
160
|
+
requirements:
|
161
|
+
- - "~>"
|
162
|
+
- !ruby/object:Gem::Version
|
163
|
+
version: 6.0.2
|
164
|
+
- - ">="
|
165
|
+
- !ruby/object:Gem::Version
|
166
|
+
version: 6.0.2
|
167
|
+
- !ruby/object:Gem::Dependency
|
168
|
+
name: timecop
|
169
|
+
requirement: !ruby/object:Gem::Requirement
|
170
|
+
requirements:
|
171
|
+
- - "~>"
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: 0.8.0
|
174
|
+
- - ">="
|
175
|
+
- !ruby/object:Gem::Version
|
176
|
+
version: 0.8.0
|
177
|
+
type: :development
|
178
|
+
prerelease: false
|
179
|
+
version_requirements: !ruby/object:Gem::Requirement
|
180
|
+
requirements:
|
181
|
+
- - "~>"
|
182
|
+
- !ruby/object:Gem::Version
|
183
|
+
version: 0.8.0
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: 0.8.0
|
187
|
+
description: The Carvoyant API gem allows Ruby developers to programmatically access
|
188
|
+
the Carvoyant Resources. The API is implemented as JSON over HTTP using all four
|
189
|
+
verbs (GET/POST/PUT/DELETE). Each resource, like Vehicle, Trip, or DataSet, has
|
190
|
+
its own URL and is manipulated in isolation.
|
191
|
+
email:
|
192
|
+
- farrukhabdul@gmail.com
|
193
|
+
executables: []
|
194
|
+
extensions: []
|
195
|
+
extra_rdoc_files: []
|
196
|
+
files:
|
197
|
+
- ".gitignore"
|
198
|
+
- Gemfile
|
199
|
+
- LICENSE
|
200
|
+
- README.md
|
201
|
+
- Rakefile
|
202
|
+
- carvoyant-api-ruby.gemspec
|
203
|
+
- lib/carvoyant-api-ruby.rb
|
204
|
+
- lib/carvoyant_api/errors.rb
|
205
|
+
- lib/carvoyant_api/resources.rb
|
206
|
+
- lib/carvoyant_api/resources/account.rb
|
207
|
+
- lib/carvoyant_api/resources/base.rb
|
208
|
+
- lib/carvoyant_api/resources/data_point.rb
|
209
|
+
- lib/carvoyant_api/resources/data_set.rb
|
210
|
+
- lib/carvoyant_api/resources/trip.rb
|
211
|
+
- lib/carvoyant_api/resources/vehicle.rb
|
212
|
+
- lib/carvoyant_api/resources/waypoint.rb
|
213
|
+
- lib/carvoyant_api/version.rb
|
214
|
+
- test/fixtures/deviceId_error.json
|
215
|
+
- test/fixtures/error.json
|
216
|
+
- test/fixtures/vehicle.json
|
217
|
+
- test/fixtures/vehicle_without_label.json
|
218
|
+
- test/fixtures/vehicles.json
|
219
|
+
- test/test_helper.rb
|
220
|
+
- test/vehicle_test.rb
|
221
|
+
homepage: http://younility.com/
|
222
|
+
licenses:
|
223
|
+
- MIT
|
224
|
+
metadata: {}
|
225
|
+
post_install_message:
|
226
|
+
rdoc_options: []
|
227
|
+
require_paths:
|
228
|
+
- lib
|
229
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
230
|
+
requirements:
|
231
|
+
- - ">="
|
232
|
+
- !ruby/object:Gem::Version
|
233
|
+
version: '0'
|
234
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
235
|
+
requirements:
|
236
|
+
- - ">="
|
237
|
+
- !ruby/object:Gem::Version
|
238
|
+
version: '0'
|
239
|
+
requirements: []
|
240
|
+
rubyforge_project:
|
241
|
+
rubygems_version: 2.4.6
|
242
|
+
signing_key:
|
243
|
+
specification_version: 4
|
244
|
+
summary: The Carvoyant API gem is a lightweight gem for accessing Carvoyant REST services
|
245
|
+
test_files:
|
246
|
+
- test/fixtures/deviceId_error.json
|
247
|
+
- test/fixtures/error.json
|
248
|
+
- test/fixtures/vehicle.json
|
249
|
+
- test/fixtures/vehicle_without_label.json
|
250
|
+
- test/fixtures/vehicles.json
|
251
|
+
- test/test_helper.rb
|
252
|
+
- test/vehicle_test.rb
|