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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ad657666a52a78f6326d5781ee9f1c12f19e5b54
4
- data.tar.gz: 07fefe6fd93d76fb5bf6184093608379a7252147
3
+ metadata.gz: 8b3c2a3fcfdfe161e04b8f4e5680513ce45fb5ed
4
+ data.tar.gz: 2c0a63b841991f163d15156d2f42ec1644eb7320
5
5
  SHA512:
6
- metadata.gz: 6b9c5802184691e8e1337a9048488e5b2d0fd8d258c799e9526fc065c7456d1f3bfff9a3ccc83a3a05d8978007ea55d661fae4f38f75dc91b8d36589034ce952
7
- data.tar.gz: bda6c580a84b436c3eb057ee174de48f3253556eb13f227c140d5d92c23c60f09ced5d58088b97640ee233bbd3d1367714dbe7bfd04718a104c2557ec9a9d279
6
+ metadata.gz: 438b2c0f53551ed7bf5ee790bbe2bd052282f5838636ff4e4b1ec9c47c167f9ca9db11bfbddb9291eb520b7383bf52e4ea8f6a93ea0fa9be35a9a017199c15b6
7
+ data.tar.gz: 6638b91db1386184b23ed1f29d9841f3d2f177738126d289c496028560bdd6714ea70f7c4d5775e9c7a1adf9a0b5d8f0736970e2ab89512cb7256bdfb3dd1d50
@@ -1,2 +1,2 @@
1
1
  Metrics/LineLength:
2
- Max: 140
2
+ Max: 160
@@ -19,6 +19,7 @@ matrix:
19
19
  - rvm: jruby-20mode
20
20
  - rvm: jruby-21mode
21
21
  - rvm: rbx-2
22
+ - rvm: jruby-19mode
22
23
  fast_finish: true
23
24
  branches:
24
25
  only: master
data/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Starwars
2
2
 
3
+ [![Coverage Status](https://coveralls.io/repos/moski/starwars/badge.png?branch=master)](https://coveralls.io/r/moski/starwars?branch=master)
4
+ [![Build Status](https://travis-ci.org/moski/starwars.svg?branch=master)](https://travis-ci.org/moski/starwars)
5
+ [![Inline docs](http://inch-ci.org/github/moski/starwars.svg?branch=master&style=flat)](http://inch-ci.org/github/moski/starwars)
6
+
3
7
  A Ruby interface for http://swapi.co/ - the Star Wars API
4
8
  ![Starwars](https://s3.amazonaws.com/f.cl.ly/items/1r2F2K460v1R2o011n1M/star-wars-evolution-evolution-funny.jpg)
5
9
 
@@ -26,29 +30,69 @@ Or install it yourself as:
26
30
 
27
31
  $ gem install starwars
28
32
 
33
+
34
+ ## Available Resources
35
+
36
+ * `Starwars::Person` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/person.rb))
37
+ * `Starwars::Film` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/film.rb))
38
+ * `Starwars::Planet` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/planet.rb))
39
+ * `Starwars::Specie` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/specie.rb))
40
+ * `Starwars::Starship` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/starship.rb))
41
+ * `Starwars::Vehicle` ([see docs](https://github.com/moski/starwars/blob/master/lib/starwars/resources/vehicle.rb))
42
+
29
43
  ## Usage
30
- require "starwars"
31
- luke = Starwars::Person.fetch(1)
32
- puts luke.name
33
- puts luke.height
34
44
 
35
- falcon = Starwars::Spaceship.new(id: 10)
36
- falcon.fetch
37
- puts falcon.name
38
- puts falcon.pilots
45
+ All the resources defined above have 2 functions, `#fetch` and `#fetch_all`
46
+
47
+ ## #Fetch
48
+
49
+ `#fetch` is used to fetch a single resource via ID or Resource URL
50
+
51
+ ```ruby
52
+ Starwars::Person.fetch(1).name
53
+ Starwars::Person.fetch('http://swapi.co/api/people/3/').name
54
+ ```
55
+
56
+ ## #fetch_all
57
+
58
+ `#fetch_all` is used to fetch all resources via pagination
59
+
60
+ ```ruby
61
+ planets = Starwars::Planet.fetch_all
62
+
63
+ # to access the items use #items
64
+ planets.items.map(&:name)
65
+ planets.items.each{|item| p item.inspect}
66
+
67
+ # you can also use #results instead of iteams
68
+ planets.results.map(&:name)
69
+ ```
70
+
71
+ ## Pagination
72
+
73
+ using `#fetch_all` will yield a pagination response:
74
+
75
+ ```ruby
76
+ starships = Starwars::Starship.fetch_all
77
+ p starships.number_of_pages
78
+ p starships.last_page?
79
+ p starships.next_page?
80
+ ```
81
+
82
+ To iterate pages you can use the following interface:
83
+
84
+ ```ruby
85
+ Starwars::Starship.fetch_all.each{|page|
86
+ p page.next
87
+ p page.previous
88
+ p page.results.size
89
+ }
90
+ ```
39
91
 
40
- you can also nest the quries, such as:
41
-
42
- falcon.pilots.each do |piolt|
43
- puts piolt.fetch.name
44
- end
92
+ ## Documentation
45
93
 
46
- You can load a resouce by url:
94
+ the gem is fairly documented. Browse the YARD [documentaion](http://rubydoc.info/gems/starwars/) for more information.
47
95
 
48
- aldeeran = Starwars::Planet.new(url: 'http://swapi.co/api/planets/3/').fetch
49
- puts aldeeran.name
50
- puts aldeeran.residents
51
- puts aldeeran.population
52
96
 
53
97
  ## Contributing
54
98
 
@@ -56,4 +100,4 @@ Or install it yourself as:
56
100
  2. Create your feature branch (`git checkout -b my-new-feature`)
57
101
  3. Commit your changes (`git commit -am 'Add some feature'`)
58
102
  4. Push to the branch (`git push origin my-new-feature`)
59
- 5. Create a new Pull Request
103
+ 5. Create a new Pull Request
@@ -1,6 +1,7 @@
1
1
  require 'starwars/version'
2
2
  require 'starwars/base'
3
- require 'starwars/fetcher'
3
+ require 'starwars/request'
4
+ require 'starwars/cursor'
4
5
 
5
6
  # Avoid circuler require issues :(
6
7
  module Starwars
@@ -11,9 +12,17 @@ module Starwars
11
12
  class Vehicle < Starwars::Base; end
12
13
  class Starship < Starwars::Base; end
13
14
  end
14
- require 'starwars/planet'
15
- require 'starwars/person'
16
- require 'starwars/specie'
17
- require 'starwars/vehicle'
18
- require 'starwars/starship'
19
- require 'starwars/film'
15
+ require 'starwars/resources/planet'
16
+ require 'starwars/resources/person'
17
+ require 'starwars/resources/specie'
18
+ require 'starwars/resources/vehicle'
19
+ require 'starwars/resources/starship'
20
+ require 'starwars/resources/film'
21
+
22
+ # Resources with pagination
23
+ require 'starwars/resources/paginated/planets'
24
+ require 'starwars/resources/paginated/films'
25
+ require 'starwars/resources/paginated/people'
26
+ require 'starwars/resources/paginated/species'
27
+ require 'starwars/resources/paginated/starships'
28
+ require 'starwars/resources/paginated/vehicles'
@@ -1,8 +1,7 @@
1
1
  require 'roar/json'
2
2
  require 'roar/client'
3
3
  require 'roar/coercion'
4
- require 'ostruct'
5
- require 'equalizer'
4
+ require 'starwars/overrides/ostruct'
6
5
  require 'virtus'
7
6
 
8
7
  module Starwars
@@ -10,6 +9,10 @@ module Starwars
10
9
  # Base Class for fetching all the data from the remote api.
11
10
  # All Classes should inhert from this class.
12
11
  #
12
+ # Abstract base class for the different resources.
13
+ # Provides some helper methods for the resources.
14
+ #
15
+ # @abstract
13
16
  class Base < OpenStruct
14
17
  include Roar::JSON
15
18
  include Roar::Client
@@ -18,36 +21,137 @@ module Starwars
18
21
  BASE_URL = 'http://swapi.co/api'
19
22
  FORMAT = 'application/json'
20
23
 
24
+ #
25
+ # Class level methods for resources to fetch data from api
26
+ # @abstract
27
+ class << self
28
+ #
29
+ # Fetch an object by id or URL
30
+ # @param [String, Integer] param String for full resouce url or the resouce id
31
+ # @return [Person, Film, Planet, Specie, Starship, Vehicle]
32
+ # @example Fetch person by id
33
+ # Starwars::Person.fetch(1)
34
+ #
35
+ # @example Fetch person by url
36
+ # Starwars::Person.fetch("http://swapi.co/api/people/2/")
37
+ # @api public
38
+ def fetch(param)
39
+ object = new(url: link(param))
40
+ Starwars::Request.new(object.request_attributes).perform_request
41
+ end
42
+
43
+ #
44
+ # Fetch all resource data page by page
45
+ # @return [People, Films, Planets, Species, Starships, Vehicles]
46
+ # @example Fetch Planets page by page
47
+ # Starwars::Planet.fetch_all.each do |page|
48
+ # puts page.items.size
49
+ # end
50
+ # @api public
51
+ def fetch_all
52
+ klass_name = Starwars.const_get(name.split('::').last).const_get('RESOURCE_NAME')
53
+ object = Starwars.const_get("#{klass_name.capitalize}").new(url: "#{Starwars::Base::BASE_URL}/#{klass_name}/")
54
+ Starwars::Request.new(resource: object, uri: object.url, params: {}).perform_request
55
+ end
56
+
57
+ protected
58
+
59
+ #
60
+ # Generate a resource link based on the passed params
61
+ # @param [String, Integer] param String for full resouce url or the resouce id
62
+ # @return [String] resouce link
63
+ # @api private
64
+ def link(param)
65
+ if param.is_a? String
66
+ param
67
+ else
68
+ "#{Starwars::Base::BASE_URL}/#{const_get('RESOURCE_NAME')}/#{param}/"
69
+ end
70
+ end
71
+ end
72
+
73
+ # The time the resource was created
74
+ # @return [Time]
75
+ # @example
76
+ # film.created
77
+ # @api public
78
+ property :created, type: Time
79
+
80
+ # The time the resource was edited
81
+ # @return [Time]
82
+ # @example
83
+ # film.edited
84
+ # @api public
85
+ property :edited, type: Time
86
+
87
+ # The resource unique id
88
+ # @return [Integer]
89
+ # @example
90
+ # film.id #=> 1
91
+ # @api public
92
+ property :id, type: Integer
93
+
94
+ # The hypermedia URL of this resource
95
+ # @return [String]
96
+ # @example
97
+ # film.url #=> 'http://swapi.co/api/films/1/'
98
+ # @api public
99
+ property :url
100
+
101
+ #
102
+ # Overide the == method for any resource to check the ID and URL
103
+ # @param [People, Films, Planets, Species, Starships, Vehicles] other
104
+ # @return [Boolean]
105
+ # @example If id's and urls are equal
106
+ # Starwars::Planet.new(id: 1, url: "/some") == Starwars::Planet.new(id: 1, url: "/some") #=> true
107
+ # @example If id's and urls are equal
108
+ # Starwars::Planet.new(id: 2, url: "/some") == Starwars::Planet.new(id: 1, url: "/some") #=> false
109
+ # @example If id's and urls are equal
110
+ # Starwars::Planet.new(id: 1, url: "/some1") == Starwars::Planet.new(id: 1, url: "/some") #=> false
111
+ # @api public
21
112
  def ==(other)
22
113
  id == other.id && url == other.url
23
114
  end
24
115
 
25
- def fetch(resource_name)
26
- #
27
- # If the url is set, then fetch using the resource url
28
- #
116
+ #
117
+ # Fetch a resource if the ID or URL is set
118
+ # @return [Person, Film, Planet, Specie, Starship, Vehicle]
119
+ # @example Fetch person by id
120
+ # Starwars::Person.new(id: 1).fetch
121
+ #
122
+ # @example Fetch person by url
123
+ # Starwars::Person.new(url: "http://swapi.co/api/people/2/").fetch
124
+ # @api public
125
+ def fetch
126
+ Starwars::Request.new(request_attributes).perform_request
127
+ end
128
+
129
+ #
130
+ # Generate the Request initialize params
131
+ # @param [Hash] opts the options to create a Request with.
132
+ # @option opts [Person, Film, Planet, Specie, Starship, Vehicle] :resource
133
+ # @option opts [String] :uri resource uri
134
+ # @option opts [Hash] :params other params
135
+ # @return [Hash]
136
+ # @api private
137
+ def request_attributes(opts = {})
138
+ { resource: self, uri: link, params: {} }.merge(opts)
139
+ end
140
+
141
+ protected
142
+
143
+ #
144
+ # Generate a resource link from the URL or id
145
+ # @return [String] resource link
146
+ # @raise [Starwars::Error::ArgumentError] if no id or url
147
+ # @api private
148
+ def link
29
149
  if url
30
- get(uri: url, as: FORMAT)
31
- #
32
- # Try to fetch using the resource name and ID
33
- #
150
+ url
34
151
  elsif id
35
- get(uri: "#{BASE_URL}/#{resource_name}/#{id}/", as: FORMAT)
152
+ "#{Starwars::Base::BASE_URL}/#{self.class::RESOURCE_NAME}/#{id}/"
36
153
  else
37
- fail 'error'
38
- end
39
- end
40
- class << self
41
- def fetch(resources, id)
42
- #
43
- # Special case for person and people, instead of removing the s
44
- #
45
- if (resources == 'people')
46
- resources = 'person'
47
- else
48
- resources.slice!(-1, 1)
49
- end
50
- Starwars.const_get(resources.capitalize).new(id: id).fetch
154
+ fail(Starwars::Error::ArgumentError.new('Please use id or url to fetch resouce', nil))
51
155
  end
52
156
  end
53
157
  end
@@ -0,0 +1,110 @@
1
+ module Starwars
2
+ #
3
+ # A pagination container for starwars
4
+ #
5
+ class Cursor < Starwars::Base
6
+ include Enumerable
7
+
8
+ #
9
+ # including Enumerable adds a "count" method to the class
10
+ # and for some reason:
11
+ # property :count, as: number_of_pages
12
+ # is not working, i am not sure it's a roar thing or from the representable gem.
13
+ # As a workaround, lets create "number_of_pages" method that returns
14
+ # the count property
15
+ # @todo - check why as: is not working
16
+ property :count
17
+
18
+ #
19
+ # Next holds the URL for the next page. If there is no next page, next
20
+ # should be set to nil
21
+ property :next
22
+
23
+ #
24
+ # Previous holds the URL for the previous page. If there is no previous
25
+ # page previous should be set to nil
26
+ property :previous
27
+
28
+ # Results contains the results within the page.
29
+ #
30
+ collection :results
31
+
32
+ # A wrapper to get the pages count from the api
33
+ # @return [Integer]
34
+ # @example get the total number of pages
35
+ # Starwars::Planet.fetch_all.number_of_pages
36
+ # @example get the total number of pages
37
+ # Starwars::Starship.fetch_all.number_of_pages
38
+ # @api public
39
+ def number_of_pages
40
+ self[:count]
41
+ end
42
+
43
+ # A wrapper to get the results within a page
44
+ # @note This wrapper is needed to define the items alias method
45
+ # @return [Array]
46
+ # @example Return the items array within the page
47
+ # Starwars::Planet.fetch_all.results
48
+ # Starwars::Planet.fetch_all.items
49
+ # @api public
50
+ def results
51
+ self[:results]
52
+ end
53
+
54
+ # Checks wheather this is the last page
55
+ # @return [Boolean]
56
+ # @example are we at the last page?
57
+ # Starwars::Planet.fetch_all.last_page?
58
+ # @api public
59
+ def last_page?
60
+ !next_page?
61
+ end
62
+
63
+ # Checks wheather this there is more pages
64
+ # @return [Boolean]
65
+ # @example do we have a next page?
66
+ # Starwars::Planet.fetch_all.next_page?
67
+ # @api public
68
+ def next_page?
69
+ !self.next.nil?
70
+ end
71
+
72
+ # Returns the next page
73
+ # @return [Starwars::Base]
74
+ # @example fetch the next page
75
+ # page = Starwars::Planet.fetch_all
76
+ # page.next_page
77
+ # @api public
78
+ def next_page
79
+ return if last_page?
80
+ perform_request
81
+ end
82
+
83
+ # Yields the subsequent page responses to a given block
84
+ # @yieldparam [Starwars::Base] response
85
+ # @return [Enumerable, nil]
86
+ # @example fetch the next page
87
+ # Starwars::Planet.fetch_all.each_page{|page| p page.items.map(&:name)}
88
+ # Starwars::Planet.fetch_all.each{|page| p page.items.map(&:name)}
89
+ # Starwars::Planet.fetch_all.each_with_index{|page, index|
90
+ # p page.items.map(&:name)
91
+ # }
92
+ # @api public
93
+ def each_page
94
+ return to_enum(__callee__) unless block_given?
95
+ yield(next_page) until last_page?
96
+ end
97
+
98
+ alias_method :each, :each_page
99
+ alias_method :items, :results
100
+
101
+ private
102
+
103
+ # Delegate to the request class to perform fetch data from remote server
104
+ # @return [People, Films, Planets, Species, Starships, Vehicles]
105
+ # @api private
106
+ def perform_request
107
+ Request.new(request_attributes(uri: self.next)).perform_request
108
+ end
109
+ end
110
+ end