starwars 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +1 -1
- data/.travis.yml +1 -0
- data/README.md +63 -19
- data/lib/starwars.rb +16 -7
- data/lib/starwars/base.rb +129 -25
- data/lib/starwars/cursor.rb +110 -0
- data/lib/starwars/error.rb +63 -0
- data/lib/starwars/overrides/ostruct.rb +16 -0
- data/lib/starwars/request.rb +80 -0
- data/lib/starwars/resources/film.rb +79 -0
- data/lib/starwars/resources/paginated/films.rb +8 -0
- data/lib/starwars/resources/paginated/people.rb +8 -0
- data/lib/starwars/resources/paginated/planets.rb +9 -0
- data/lib/starwars/resources/paginated/species.rb +8 -0
- data/lib/starwars/resources/paginated/starships.rb +8 -0
- data/lib/starwars/resources/paginated/vehicles.rb +8 -0
- data/lib/starwars/resources/person.rb +124 -0
- data/lib/starwars/{planet.rb → resources/planet.rb} +0 -13
- data/lib/starwars/{specie.rb → resources/specie.rb} +1 -15
- data/lib/starwars/resources/starship.rb +115 -0
- data/lib/starwars/resources/vehicle.rb +106 -0
- data/lib/starwars/version.rb +1 -1
- data/spec/fixtures/404.json +1 -0
- data/spec/fixtures/planets_page1.json +1 -0
- data/spec/fixtures/planets_page2.json +1 -0
- data/spec/starwars/base_spec.rb +17 -0
- data/spec/starwars/cursor_spec.rb +76 -0
- data/spec/starwars/person_spec.rb +1 -1
- data/spec/starwars/request_spec.rb +29 -0
- data/spec/starwars/resources/paginated/planets_spec.rb +38 -0
- data/starwars.gemspec +0 -1
- metadata +32 -23
- data/lib/starwars/fetcher.rb +0 -40
- data/lib/starwars/film.rb +0 -35
- data/lib/starwars/person.rb +0 -39
- data/lib/starwars/starship.rb +0 -40
- data/lib/starwars/vehicle.rb +0 -38
@@ -0,0 +1,63 @@
|
|
1
|
+
module Starwars
|
2
|
+
# Custom error class for rescuing from all Starwars errors
|
3
|
+
class Error < StandardError
|
4
|
+
class << self
|
5
|
+
# Return a hash of error classes
|
6
|
+
# @return [Hash]
|
7
|
+
# @example get the total number of pages
|
8
|
+
# Starwars::Error.errors
|
9
|
+
# @api public
|
10
|
+
def errors
|
11
|
+
@errors ||= {
|
12
|
+
400 => Starwars::Error::BadRequest,
|
13
|
+
401 => Starwars::Error::Unauthorized,
|
14
|
+
403 => Starwars::Error::Forbidden,
|
15
|
+
404 => Starwars::Error::NotFound,
|
16
|
+
500 => Starwars::Error::InternalServerError,
|
17
|
+
503 => Starwars::Error::ServiceUnavailableError
|
18
|
+
}
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Initializes a new Error object
|
23
|
+
#
|
24
|
+
# @param message [Exception, String]
|
25
|
+
# @param _status [Exception, status]
|
26
|
+
# @return [Starwars::Error]
|
27
|
+
# @example
|
28
|
+
# Starwars::Error.new('I am your father', nil)
|
29
|
+
# @api public
|
30
|
+
def initialize(message = '', _status = nil)
|
31
|
+
super(message)
|
32
|
+
end
|
33
|
+
|
34
|
+
class ArgumentError < self; end
|
35
|
+
|
36
|
+
# Raised when Starwars returns a 4xx HTTP status status_code
|
37
|
+
class ClientError < self; end
|
38
|
+
|
39
|
+
# Raised when Starwars returns the HTTP status status_code 400
|
40
|
+
class BadRequest < ClientError; end
|
41
|
+
|
42
|
+
# Raised when Starwars returns the HTTP status status_code 401
|
43
|
+
class Unauthorized < ClientError; end
|
44
|
+
|
45
|
+
# Raised when Starwars returns the HTTP status status_code 403
|
46
|
+
class Forbidden < ClientError; end
|
47
|
+
|
48
|
+
# Raised when Starwars returns the HTTP status status_code 404
|
49
|
+
class NotFound < ClientError; end
|
50
|
+
|
51
|
+
# Raised when Starwars returns a 5xx HTTP status code
|
52
|
+
class ServerError < self; end
|
53
|
+
|
54
|
+
# Raised when Starwars returns the HTTP status status_code 500
|
55
|
+
class InternalServerError < ServerError; end
|
56
|
+
|
57
|
+
# Raised when Starwars returns the HTTP status status_code 503
|
58
|
+
class ServiceUnavailableError < ServerError; end
|
59
|
+
|
60
|
+
# Raised when the request times out
|
61
|
+
class RequestTimeout < self; end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'ostruct'
|
2
|
+
|
3
|
+
#
|
4
|
+
# ostruct for ruby 1.9 doesn't implement [] operater
|
5
|
+
# This a monkey patch my copying the ruby 2.0 version
|
6
|
+
class OpenStruct
|
7
|
+
#
|
8
|
+
# Fetch an object by id or URL
|
9
|
+
# @param [String] name
|
10
|
+
# @return [Object]
|
11
|
+
#
|
12
|
+
# @api private
|
13
|
+
def [](name)
|
14
|
+
@table[name.to_sym]
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'starwars/error'
|
2
|
+
|
3
|
+
module Starwars
|
4
|
+
# Wrap request attrs
|
5
|
+
class Request
|
6
|
+
BASE_URL = 'http://swapi.co/api'
|
7
|
+
FORMAT = 'application/json'
|
8
|
+
|
9
|
+
# The format of the HTTP request
|
10
|
+
# @return [String]
|
11
|
+
# @api private
|
12
|
+
attr_accessor :as
|
13
|
+
|
14
|
+
# The http method for the request
|
15
|
+
# @return [Symbol]
|
16
|
+
# @api private
|
17
|
+
attr_accessor :method
|
18
|
+
|
19
|
+
# The resouce object that we going to call to fetch the data
|
20
|
+
# @return [Person, Film, Planet, Specie, Starship, Vehicle]
|
21
|
+
# @api private
|
22
|
+
attr_accessor :resource
|
23
|
+
|
24
|
+
# The remote url for the resource that we want to fetch
|
25
|
+
# @return [String]
|
26
|
+
# @api private
|
27
|
+
attr_accessor :uri
|
28
|
+
|
29
|
+
# Extra params we want to send with the http request
|
30
|
+
# @return [Hash]
|
31
|
+
# @api private
|
32
|
+
attr_accessor :params
|
33
|
+
|
34
|
+
# Initializer
|
35
|
+
# @param [Hash] attrs request attributes
|
36
|
+
# @option attrs [Starwars::] :resource
|
37
|
+
# @option attrs [Symbol] :method
|
38
|
+
# @option attrs [String] :uri
|
39
|
+
# @option attrs [Hash] :params
|
40
|
+
# @option attrs [String] :as
|
41
|
+
# @return [Starwars::Request]
|
42
|
+
# @example
|
43
|
+
# data = Request.new(resource: Person.new(id: 1), uri: "/something")
|
44
|
+
# @api public
|
45
|
+
def initialize(attrs)
|
46
|
+
self.resource = attrs.fetch(:resource)
|
47
|
+
self.method = attrs.fetch(:method) { :get }
|
48
|
+
self.uri = attrs.fetch(:uri)
|
49
|
+
self.as = attrs.fetch(:as) { FORMAT }
|
50
|
+
self.params = attrs.fetch(:params) { {} }
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Delegate to the Roar client to fetch data from api
|
55
|
+
# @return [Person, Film, Planet, Specie, Starship, Vehicle]
|
56
|
+
# @example
|
57
|
+
# request.perform_request
|
58
|
+
# @raise [Starwars::Error]
|
59
|
+
# @api public
|
60
|
+
def perform_request
|
61
|
+
resource.send(method, uri: uri, as: as)
|
62
|
+
|
63
|
+
rescue Roar::Transport::Error => e
|
64
|
+
raise_http_errors(e.response.code.to_i, e.response.msg)
|
65
|
+
end
|
66
|
+
|
67
|
+
private
|
68
|
+
|
69
|
+
#
|
70
|
+
# Check the response code and raise exceptions if needed
|
71
|
+
# @param status [Integer]
|
72
|
+
# @param message [String]
|
73
|
+
# @return [void]
|
74
|
+
# @api private
|
75
|
+
def raise_http_errors(status, message)
|
76
|
+
error_class = Starwars::Error.errors[status]
|
77
|
+
fail(error_class.new(message, status)) if error_class
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module Starwars
|
2
|
+
#
|
3
|
+
# A Film resource is an single film.
|
4
|
+
#
|
5
|
+
class Film < Starwars::Base
|
6
|
+
# Define the source name in the starwars api
|
7
|
+
RESOURCE_NAME = 'films'
|
8
|
+
|
9
|
+
# The title of this film
|
10
|
+
# @return [String]
|
11
|
+
# @example
|
12
|
+
# film.title #=> 'A New Hope'
|
13
|
+
# @api public
|
14
|
+
property :title
|
15
|
+
|
16
|
+
# The opening paragraphs at the beginning of this film
|
17
|
+
# @return [String]
|
18
|
+
# @example
|
19
|
+
# film.opening_crawl #=> 'It is a period of civil war ...'
|
20
|
+
# @api public
|
21
|
+
property :opening_crawl
|
22
|
+
|
23
|
+
# The name of the director of this film
|
24
|
+
# @return [String]
|
25
|
+
# @example
|
26
|
+
# film.director #=> 'George Lucas'
|
27
|
+
# @api public
|
28
|
+
property :director
|
29
|
+
|
30
|
+
# The name(s) of the producer(s) of this film. Comma seperated
|
31
|
+
# @return [String]
|
32
|
+
# @example
|
33
|
+
# film.producer #=> 'Gary Kurtz, Rick McCallum'
|
34
|
+
# @api public
|
35
|
+
property :producer
|
36
|
+
|
37
|
+
# The episode number of this film
|
38
|
+
# @return [Integer]
|
39
|
+
# @example
|
40
|
+
# film.episode_id #=> 1
|
41
|
+
# @api public
|
42
|
+
property :episode_id, type: Integer
|
43
|
+
|
44
|
+
# List of people
|
45
|
+
# @return [Array<Person>]
|
46
|
+
# @example
|
47
|
+
# film.characters
|
48
|
+
# @api public
|
49
|
+
collection :characters, class: Starwars::Person, deserialize: ->(_, fragment, _) { Person.new(url: fragment) }
|
50
|
+
|
51
|
+
# List of planets
|
52
|
+
# @return [Array<Person>]
|
53
|
+
# @example
|
54
|
+
# film.characters
|
55
|
+
# @api public
|
56
|
+
collection :planets, class: Starwars::Planet, deserialize: ->(_, fragment, _) { Planet.new(url: fragment) }
|
57
|
+
|
58
|
+
# List of starships
|
59
|
+
# @return [Array<Starship>]
|
60
|
+
# @example
|
61
|
+
# film.starships
|
62
|
+
# @api public
|
63
|
+
collection :starships, class: Starwars::Starship, deserialize: ->(_, fragment, _) { Starship.new(url: fragment) }
|
64
|
+
|
65
|
+
# List of vehicles
|
66
|
+
# @return [Array<Vehicle>]
|
67
|
+
# @example
|
68
|
+
# film.vehicles
|
69
|
+
# @api public
|
70
|
+
collection :vehicles, class: Starwars::Vehicle, deserialize: ->(_, fragment, _) { Vehicle.new(url: fragment) }
|
71
|
+
|
72
|
+
# List of species
|
73
|
+
# @return [Array<Specie>]
|
74
|
+
# @example
|
75
|
+
# film.species
|
76
|
+
# @api public
|
77
|
+
collection :species, class: Starwars::Specie, deserialize: ->(_, fragment, _) { Specie.new(url: fragment) }
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module Starwars
|
2
|
+
#
|
3
|
+
# A Planet resource is a large mass, planet or planetoid in
|
4
|
+
# the Star Wars Universe, at the time of 0 ABY.
|
5
|
+
#
|
6
|
+
class Planets < Starwars::Cursor
|
7
|
+
collection :results, class: Starwars::Planet, deserialize: ->(_, fragment, _) { Planet.new(fragment) }
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
module Starwars
|
2
|
+
#
|
3
|
+
# A People resource is an individual person or character within the Star Wars universe.
|
4
|
+
#
|
5
|
+
class Person < Starwars::Base
|
6
|
+
#
|
7
|
+
# Define the source name in the starwars api
|
8
|
+
#
|
9
|
+
RESOURCE_NAME = 'people'
|
10
|
+
|
11
|
+
# The name of this person
|
12
|
+
# @return [String]
|
13
|
+
# @example
|
14
|
+
# person.name
|
15
|
+
# @api public
|
16
|
+
property :name
|
17
|
+
|
18
|
+
# The skin color of this person
|
19
|
+
# @return [String]
|
20
|
+
# @example
|
21
|
+
# person.skin_color
|
22
|
+
# @api public
|
23
|
+
property :skin_color
|
24
|
+
|
25
|
+
# The eye color of this person
|
26
|
+
#
|
27
|
+
# @return [String]
|
28
|
+
#
|
29
|
+
# @note Will be "unknown" if not known or "n/a"
|
30
|
+
# if the person does not have an eye
|
31
|
+
#
|
32
|
+
# @example
|
33
|
+
# person.eye_color
|
34
|
+
# @api public
|
35
|
+
property :eye_color
|
36
|
+
|
37
|
+
# The hair color of this person
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
#
|
41
|
+
# @note: Will be "unknown" if not known or "n/a"
|
42
|
+
# if the person does not have hair
|
43
|
+
#
|
44
|
+
# @example
|
45
|
+
# person.hair_color
|
46
|
+
# @api public
|
47
|
+
property :hair_color
|
48
|
+
|
49
|
+
# The birth year of the person
|
50
|
+
#
|
51
|
+
# @return [String]
|
52
|
+
#
|
53
|
+
# @note using the in-universe standard of
|
54
|
+
# BBY or ABY - Before the Battle of Yavin or After the Battle of Yavin.
|
55
|
+
# The Battle of Yavin is a battle that occurs at the end of Star Wars
|
56
|
+
# episode IV: A New Hope
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# person.birth_year
|
60
|
+
# @api public
|
61
|
+
property :birth_year
|
62
|
+
|
63
|
+
# The gender of this person
|
64
|
+
#
|
65
|
+
# @return [String]
|
66
|
+
#
|
67
|
+
# @note Either "Male", "Female" or "unknown", "n/a"
|
68
|
+
# if the person does not have a gender
|
69
|
+
#
|
70
|
+
# @example
|
71
|
+
# person.gender
|
72
|
+
# @api public
|
73
|
+
property :gender
|
74
|
+
|
75
|
+
# The height of the person in centimeters
|
76
|
+
# @return [Integer]
|
77
|
+
# @example
|
78
|
+
# person.height
|
79
|
+
# @api public
|
80
|
+
property :height, type: Integer
|
81
|
+
|
82
|
+
# The mass of the person in kilograms
|
83
|
+
# @return [Integer]
|
84
|
+
# @example
|
85
|
+
# person.mass
|
86
|
+
# @api public
|
87
|
+
property :mass, type: Integer
|
88
|
+
|
89
|
+
# List of homeworlds
|
90
|
+
# @return [Array<Planet>]
|
91
|
+
# @example
|
92
|
+
# person.homeworlds
|
93
|
+
# @api public
|
94
|
+
property :homeworld, class: Starwars::Planet, deserialize: ->(_, fragment, _) { Planet.new(url: fragment) }
|
95
|
+
|
96
|
+
# List of films
|
97
|
+
# @return [Array<Film>]
|
98
|
+
# @example
|
99
|
+
# person.films
|
100
|
+
# @api public
|
101
|
+
collection :films, class: Starwars::Film, deserialize: ->(_, fragment, _) { Film.new(url: fragment) }
|
102
|
+
|
103
|
+
# List of species
|
104
|
+
# @return [Array<Specie>]
|
105
|
+
# @example
|
106
|
+
# person.species
|
107
|
+
# @api public
|
108
|
+
collection :species, class: Starwars::Specie, deserialize: ->(_, fragment, _) { Specie.new(url: fragment) }
|
109
|
+
|
110
|
+
# List of vehicles
|
111
|
+
# @return [Array<Vehicle>]
|
112
|
+
# @example
|
113
|
+
# person.vehicles
|
114
|
+
# @api public
|
115
|
+
collection :vehicles, class: Starwars::Vehicle, deserialize: ->(_, fragment, _) { Vehicle.new(url: fragment) }
|
116
|
+
|
117
|
+
# List of tarships
|
118
|
+
# @return [Array<Starship>]
|
119
|
+
# @example
|
120
|
+
# person.starships
|
121
|
+
# @api public
|
122
|
+
collection :starships, class: Starwars::Starship, deserialize: ->(_, fragment, _) { Starship.new(url: fragment) }
|
123
|
+
end
|
124
|
+
end
|
@@ -9,28 +9,15 @@ module Starwars
|
|
9
9
|
#
|
10
10
|
RESOURCE_NAME = 'planets'
|
11
11
|
|
12
|
-
include Starwars::Fetcher
|
13
|
-
|
14
|
-
# @return [String]
|
15
12
|
property :name
|
16
13
|
property :climate
|
17
14
|
property :gravity
|
18
15
|
property :terrain
|
19
|
-
property :url
|
20
|
-
|
21
|
-
# @return [Integer]
|
22
|
-
property :id, type: Integer
|
23
16
|
property :population, type: Integer
|
24
17
|
property :rotation_period, type: Integer
|
25
18
|
property :orbital_period, type: Integer
|
26
19
|
property :surface_water, type: Integer
|
27
20
|
property :diameter, type: Integer
|
28
|
-
|
29
|
-
# @return [Time]
|
30
|
-
property :created, type: Time
|
31
|
-
property :edited, type: Time
|
32
|
-
|
33
|
-
# @return [Array]
|
34
21
|
collection :residents, class: Starwars::Person, deserialize: ->(_, fragment, _) { Person.new(url: fragment) }
|
35
22
|
collection :films, class: Starwars::Film, deserialize: ->(_, fragment, _) { Film.new(url: fragment) }
|
36
23
|
end
|