starwars 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +1 -1
  3. data/.travis.yml +1 -0
  4. data/README.md +63 -19
  5. data/lib/starwars.rb +16 -7
  6. data/lib/starwars/base.rb +129 -25
  7. data/lib/starwars/cursor.rb +110 -0
  8. data/lib/starwars/error.rb +63 -0
  9. data/lib/starwars/overrides/ostruct.rb +16 -0
  10. data/lib/starwars/request.rb +80 -0
  11. data/lib/starwars/resources/film.rb +79 -0
  12. data/lib/starwars/resources/paginated/films.rb +8 -0
  13. data/lib/starwars/resources/paginated/people.rb +8 -0
  14. data/lib/starwars/resources/paginated/planets.rb +9 -0
  15. data/lib/starwars/resources/paginated/species.rb +8 -0
  16. data/lib/starwars/resources/paginated/starships.rb +8 -0
  17. data/lib/starwars/resources/paginated/vehicles.rb +8 -0
  18. data/lib/starwars/resources/person.rb +124 -0
  19. data/lib/starwars/{planet.rb → resources/planet.rb} +0 -13
  20. data/lib/starwars/{specie.rb → resources/specie.rb} +1 -15
  21. data/lib/starwars/resources/starship.rb +115 -0
  22. data/lib/starwars/resources/vehicle.rb +106 -0
  23. data/lib/starwars/version.rb +1 -1
  24. data/spec/fixtures/404.json +1 -0
  25. data/spec/fixtures/planets_page1.json +1 -0
  26. data/spec/fixtures/planets_page2.json +1 -0
  27. data/spec/starwars/base_spec.rb +17 -0
  28. data/spec/starwars/cursor_spec.rb +76 -0
  29. data/spec/starwars/person_spec.rb +1 -1
  30. data/spec/starwars/request_spec.rb +29 -0
  31. data/spec/starwars/resources/paginated/planets_spec.rb +38 -0
  32. data/starwars.gemspec +0 -1
  33. metadata +32 -23
  34. data/lib/starwars/fetcher.rb +0 -40
  35. data/lib/starwars/film.rb +0 -35
  36. data/lib/starwars/person.rb +0 -39
  37. data/lib/starwars/starship.rb +0 -40
  38. 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,8 @@
1
+ module Starwars
2
+ #
3
+ # Films container
4
+ #
5
+ class Films < Starwars::Cursor
6
+ collection :results, class: Starwars::Film, deserialize: ->(_, fragment, _) { Film.new(fragment) }
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Starwars
2
+ #
3
+ # People container
4
+ #
5
+ class People < Starwars::Cursor
6
+ collection :results, class: Starwars::Person, deserialize: ->(_, fragment, _) { Person.new(fragment) }
7
+ end
8
+ 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,8 @@
1
+ module Starwars
2
+ #
3
+ # Species container
4
+ #
5
+ class Species < Starwars::Cursor
6
+ collection :results, class: Starwars::Specie, deserialize: ->(_, fragment, _) { Specie.new(fragment) }
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Starwars
2
+ #
3
+ # Starships Container
4
+ #
5
+ class Starships < Starwars::Cursor
6
+ collection :results, class: Starwars::Starship, deserialize: ->(_, fragment, _) { Starship.new(fragment) }
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ module Starwars
2
+ #
3
+ # Starships Container
4
+ #
5
+ class Vehicles < Starwars::Cursor
6
+ collection :results, class: Starwars::Vehicle, deserialize: ->(_, fragment, _) { Vehicle.new(fragment) }
7
+ end
8
+ 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