starwars 0.0.1 → 0.0.2

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.
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