uatu-marvel 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +4 -1
  5. data/Gemfile +2 -1
  6. data/README.md +5 -3
  7. data/bin/console +7 -0
  8. data/lib/uatu.rb +13 -2
  9. data/lib/uatu/base.rb +10 -55
  10. data/lib/uatu/configuration.rb +3 -5
  11. data/lib/uatu/connection.rb +48 -41
  12. data/lib/uatu/endpoints/collection.rb +16 -0
  13. data/lib/uatu/endpoints/nested.rb +23 -0
  14. data/lib/uatu/endpoints/single.rb +17 -0
  15. data/lib/uatu/resource.rb +21 -19
  16. data/lib/uatu/resources.rb +3 -0
  17. data/lib/uatu/response.rb +1 -4
  18. data/lib/uatu/version.rb +1 -1
  19. data/spec/integration/characters_spec.rb +25 -0
  20. data/spec/integration/comics_spec.rb +17 -0
  21. data/spec/integration/creators_spec.rb +19 -0
  22. data/spec/integration/events_spec.rb +19 -0
  23. data/spec/integration/series_spec.rb +19 -0
  24. data/spec/integration/stories_spec.rb +19 -0
  25. data/spec/spec_helper.rb +18 -0
  26. data/spec/support/fake_marvel_api.rb +24 -0
  27. data/spec/support/fake_marvel_api/characters/list.json +381 -0
  28. data/spec/support/fake_marvel_api/characters/show.json +381 -0
  29. data/spec/support/fake_marvel_api/comics/list.json +1479 -0
  30. data/spec/support/fake_marvel_api/comics/show.json +134 -0
  31. data/spec/support/fake_marvel_api/creators/list.json +180 -0
  32. data/spec/support/fake_marvel_api/creators/show.json +323 -0
  33. data/spec/support/fake_marvel_api/events/list.json +2224 -0
  34. data/spec/support/fake_marvel_api/events/show.json +474 -0
  35. data/spec/support/fake_marvel_api/series/list.json +739 -0
  36. data/spec/support/fake_marvel_api/series/show.json +101 -0
  37. data/spec/support/fake_marvel_api/stories/list.json +523 -0
  38. data/spec/support/fake_marvel_api/stories/show.json +69 -0
  39. data/spec/uatu/configuration_spec.rb +26 -0
  40. data/spec/uatu/connection_spec.rb +54 -0
  41. data/spec/uatu/resource_spec.rb +40 -0
  42. data/spec/uatu_spec.rb +9 -0
  43. data/uatu.gemspec +6 -4
  44. metadata +123 -34
  45. data/test/helper.rb +0 -9
  46. data/test/uatu/base_test.rb +0 -51
  47. data/test/uatu/configuration_test.rb +0 -19
  48. data/test/uatu/connection_test.rb +0 -31
  49. data/test/uatu/resource_test.rb +0 -33
  50. data/test/uatu/uatu_test.rb +0 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 330a8356b2d7b0966db9894575503533baaaeeb2
4
- data.tar.gz: b1d0e32f6c552458b8e2ee146d071ae28e43cba0
3
+ metadata.gz: 12cb79ee340c489b05fa468e7f63ed1ec925ad41
4
+ data.tar.gz: d8492dfd4266976a1e7561be0071fe4341b79029
5
5
  SHA512:
6
- metadata.gz: 497fed44e916e0f6527ac0786e1bdb6b5ba7c4c58c0510f3c31323f689f116da0dc7dc1e4336f260342dbe9624a8c60e019046fa8ecbeb0d507817eb71734b65
7
- data.tar.gz: 37f432df0a3fe7ceba0d92fd44e5ab4d7487c7006c91b113a91aa0c30bda9a0b0e786c4bddcda7359aa29f8d58a884318db731e35ea7e53b5f29e246f0bc3e73
6
+ metadata.gz: 63608df002443e53cc4788fe4b1dde3507b26d60c8176d7a2cd1cecfed934d6b439badd8d9bb24ddda774ad791ecd4e488ff85a42dac730f7ba28dc6a538b1e9
7
+ data.tar.gz: c539f388152af2778f090ae1a36f2cc698fef51a76c42a43c803d06c4a5b7d0cf8e9b7b5af1457fab4e08f1a8de86258d5ac86d7560a420989351b90c129b004
data/.gitignore CHANGED
@@ -16,3 +16,4 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  .ruby-version
19
+ .rspec_status
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -1,3 +1,6 @@
1
+ sudo: false
1
2
  language: ruby
2
3
  rvm:
3
- - 2.1.0
4
+ - 2.4.1
5
+ - 2.2
6
+ before_install: gem install bundler -v 1.14.6
data/Gemfile CHANGED
@@ -1,4 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Specify your gem's dependencies in uatu.gemspec
4
3
  gemspec
4
+
5
+ gem 'pry'
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
+ [![Build Status](https://travis-ci.org/eltercero/uatu.png)](https://travis-ci.org/eltercero/uatu)
2
+
1
3
  # Uatu
2
4
 
3
- Uatu is a Wrapper for the Marvel API. See [the API](http://developer.marvel.com) for more details. It relies on OpenStruct to build ruby objects with the API response.
5
+ Uatu is a Wrapper for the Marvel API. See [the API](http://developer.marvel.com) for more details. It relies on OpenStruct to build ruby objects with the API response.
4
6
 
5
7
  Uatu is [also](http://en.wikipedia.org/wiki/Uatu) a member of The Watchers, that nice extraterrestrial race who monitor life of other species.
6
8
 
@@ -45,14 +47,14 @@ random_hero = watcher.characters(limit: 1, offset: rand(1000)).first.name
45
47
  random_heroes_team = watcher.characters(limit: 20, offset: rand(1000)).map(&:name)
46
48
  => ["Rumiko Fujikawa", "Runaways", "Russian", "S.H.I.E.L.D.", "Sabra", "Sabretooth", "Sabretooth (Age of Apocalypse)", "Sabretooth (House of M)", "Sabretooth (Ultimate)", "Sage", "Salem's Seven (Ultimate)", "Sally Floyd", "Salo", "Sandman", "Santa Claus", "Saracen (Muzzafar Lambert)", "Sasquatch (Walter Langkowski)", "Satana", "Sauron", "Scalphunter"]
47
49
 
48
- # Parameters are in ruby style. This means no camel case like firstName
50
+ # Parameters are in ruby style. This means no camel case like firstName
49
51
  irish_fella = watcher.creators(first_name: 'Garth', last_name: 'Ennis').first
50
52
  irish_fella.comics.available
51
53
  => 103
52
54
 
53
55
  #You can also search by id
54
56
  character = watcher.character(1009262)
55
- character.thumbnail
57
+ character.thumbnail
56
58
  => "http://i.annihil.us/u/prod/marvel/i/mg/d/50/50febb79985ee.jpg"
57
59
 
58
60
  #There is also a handy method for checking out the last url you requested
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "uatu"
5
+
6
+ require "pry"
7
+ Pry.start
@@ -3,13 +3,24 @@ require 'digest/md5'
3
3
  require 'json'
4
4
  require 'hashie/mash'
5
5
  require 'active_support/inflector'
6
+ require 'faraday'
6
7
 
7
- require 'uatu/configuration'
8
8
  require 'uatu/version'
9
+ require 'uatu/resources'
10
+
11
+ require 'uatu/endpoints/single'
12
+ require 'uatu/endpoints/collection'
13
+ require 'uatu/endpoints/nested'
9
14
 
10
15
  require 'uatu/base'
11
16
 
17
+ require 'uatu/response'
18
+ require 'uatu/configuration'
19
+ require 'uatu/connection'
20
+ require 'uatu/resource'
21
+ require 'uatu/error'
22
+
12
23
  module Uatu
13
- extend Configuration
24
+ extend Uatu::Configuration
14
25
  end
15
26
 
@@ -1,70 +1,25 @@
1
- require 'uatu/connection'
2
- require 'uatu/resource'
3
- require 'pry'
4
-
5
1
  module Uatu
6
2
  class Base
7
- include Uatu::Connection
3
+ include Uatu::Endpoints::Single
4
+ include Uatu::Endpoints::Collection
5
+ include Uatu::Endpoints::Nested
8
6
 
9
- attr_accessor *Configuration::VALID_CONFIG_KEYS
10
7
  attr_accessor :last_request_url
11
- RESOURCES = %w(comic serie character event story creator)
12
-
13
- def initialize
14
- Configuration::VALID_CONFIG_KEYS.each do |key|
15
- send("#{key}=", Uatu.options[key])
16
- end
17
- end
18
8
 
19
- RESOURCES.each do |method_name|
20
- # Singular
21
- # example: GET /v1/public/characters/{characterId} => Uatu::Base.new.character
22
- define_method method_name do |id, options={}|
23
- raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
24
- options.merge!("#{method_name}_id".to_sym => id)
25
- output = request_and_build(method_name, options)
26
- output.first
27
- end
28
-
29
- # Plural
30
- # example: GET /v1/public/characters => Uatu::Base.new.characters
31
- define_method method_name.pluralize do |options={}|
32
- raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
33
- request_and_build(method_name, options)
34
- end
9
+ private
35
10
 
36
- # Combined
37
- # example: GET /v1/public/characters/{characterId}/comics => Uatu::Base.new.character_comics
38
- RESOURCES.each do |combined|
39
- unless combined == method_name
40
- define_method "#{method_name}_#{combined.pluralize}" do |id, options={}|
41
- raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
42
- options.merge!("#{method_name}_id".to_sym => id)
43
- request_and_build("#{method_name}_#{combined.pluralize}", options)
44
- end
45
- end
46
- end
47
- end
48
-
49
- def request_and_build(method_name, options)
50
- response = request(method_name, options, conn_options)
11
+ def request_and_build connection
12
+ response = connection.request
51
13
  parsed_body = JSON.parse(response.body)
52
14
 
53
- self.last_request_url = response.env.url.to_s
15
+ @last_request_url = response.to_hash[:url].to_s
54
16
 
55
17
  output = parsed_body['data']['results'].map do |resource_hash|
56
- "Uatu::#{method_name.split('_').last.classify}".constantize.new(resource_hash)
18
+ "Uatu::#{connection.resource.split('_').last.classify}".constantize.new(resource_hash)
57
19
  end
58
20
 
59
- output
21
+ output
60
22
  end
61
23
 
62
- def conn_options
63
- _conn_options = Hashie::Mash.new
64
- Configuration::VALID_CONFIG_KEYS.each{|key| _conn_options[key] = send(key)}
65
- _conn_options
66
- end
67
-
68
-
69
24
  end
70
- end
25
+ end
@@ -1,12 +1,11 @@
1
1
  module Uatu
2
2
  module Configuration
3
3
 
4
- VALID_CONFIG_KEYS = [:base_url, :public_key, :private_key]
4
+ VALID_CONFIG_KEYS = [:public_key, :private_key]
5
5
 
6
- BASE_URL = "http://gateway.marvel.com"
7
6
  PUBLIC_KEY = ENV["MARVEL_PUBLIC_KEY"]
8
7
  PRIVATE_KEY = ENV["MARVEL_PRIVATE_KEY"]
9
-
8
+
10
9
  attr_accessor *VALID_CONFIG_KEYS
11
10
 
12
11
  def self.extended(base)
@@ -17,12 +16,11 @@ module Uatu
17
16
  yield self
18
17
  end
19
18
 
20
- def options
19
+ def credentials
21
20
  Hash[ * VALID_CONFIG_KEYS.map { |key| [key, send(key)] }.flatten ]
22
21
  end
23
22
 
24
23
  def reset
25
- self.base_url = BASE_URL
26
24
  self.public_key = PUBLIC_KEY
27
25
  self.private_key = PRIVATE_KEY
28
26
  end
@@ -1,75 +1,82 @@
1
- require 'faraday'
2
- require 'uatu/response'
3
-
4
1
  module Uatu
5
- module Connection
6
-
7
- def request(method, options, conn_options)
8
- conn = build_connection(conn_options)
9
- conn_params = prepare_options(options).merge(mandatory_params(conn_options))
10
- conn_route = build_route(method, options)
11
-
12
- conn.get conn_route, conn_params
2
+ class Connection
3
+
4
+ BASE_URL = "http://gateway.marvel.com"
5
+
6
+ attr_reader :resource, :options
7
+
8
+ def initialize resource, options
9
+ @resource = resource
10
+ @options = options
13
11
  end
14
12
 
15
- def build_connection(conn_options)
16
- Faraday.new(url: conn_options.base_url) do |faraday|
17
- faraday.use Uatu::Response::RaiseMarvelError
13
+ def request
14
+ connection.get path, params
15
+ end
16
+
17
+ private
18
18
 
19
- faraday.request :url_encoded
20
- faraday.adapter Faraday.default_adapter
19
+ def connection
20
+ @connection ||= Faraday.new(url: BASE_URL) do |faraday|
21
+ faraday.use Uatu::Response::RaiseMarvelError
22
+ faraday.request :url_encoded
23
+ faraday.adapter Faraday.default_adapter
21
24
  end
22
25
  end
23
26
 
24
- def build_route(method, options={})
25
- route = "/v1/public/#{valid_method(method)}"
26
- if resource_id = options["#{valid_method(method).singularize}_id".to_sym]
27
+ def path
28
+ route = "/v1/public/#{resource_path}"
29
+ if resource_id = options["#{resource_path.singularize}_id".to_sym]
27
30
  route += "/#{resource_id}"
28
31
  end
29
32
 
30
- # If it is combined, it comes afet the '_'
31
- if method.split('_').count>1 && combined_path = method.split('_').last
33
+ # If it is combined, it comes after the '_'
34
+ if resource.split('_').count>1 && combined_path = resource.split('_').last
32
35
  route += "/#{combined_path}"
33
36
  end
34
37
 
35
38
  route
36
39
  end
37
40
 
38
- def prepare_options(options)
39
- valid_opts = {}
40
-
41
- # We remove innecessary keys that should go on the route
42
- _options = options.reject{|key, value| key.to_s.match(/.*_id/)}
41
+ def params
42
+ request_params = {}
43
+
44
+ # We remove unnecessary keys that should go on the route
45
+ temp_params = options.reject{|key, value| key.to_s.match(/.*_id/)}
43
46
 
44
- # We change the names, so 'format_type' becomes 'formatType'
45
- _options.each{|key, value| valid_opts[key.to_s.camelize(:lower).to_sym] = value }
47
+ # We change the names, so 'format_type' becomes 'formatType'
48
+ temp_params.each{|key, value| request_params[key.to_s.camelize(:lower).to_sym] = value }
46
49
 
47
50
  # An array should become a string with comma separated values
48
- valid_opts.each{|key, value| valid_opts[key] = value.join(',') if value.is_a?(Array) }
51
+ request_params.each{|key, value| request_params[key] = value.join(',') if value.is_a?(Array) }
49
52
 
50
- valid_opts
53
+ request_params.merge(mandatory_params)
51
54
  end
52
55
 
53
56
  # character => characters
54
57
  # characters => characters
55
58
  # character_comics => characters
56
- def valid_method(method)
57
- _method = method.split('_').first.pluralize
58
- raise Uatu::Error.new('InvalidMethod') unless Uatu::Base::RESOURCES.map(&:pluralize).include?(_method)
59
- _method
59
+ def resource_path
60
+ @resource_path ||= resource.split('_').first.pluralize.tap do |path|
61
+ raise Uatu::Error.new('InvalidMethod') unless Uatu::RESOURCES.map(&:pluralize).include?(path)
62
+ end
60
63
  end
61
64
 
62
- def current_timestamp
63
- @ts ||= DateTime.now.to_s
65
+ def mandatory_params
66
+ {
67
+ :apikey => Uatu.public_key,
68
+ :ts => current_timestamp,
69
+ :hash => hash(current_timestamp)
70
+ }
64
71
  end
65
72
 
66
- def hash(timestamp, conn_options)
67
- Digest::MD5.hexdigest("#{timestamp}#{conn_options.private_key}#{conn_options.public_key}")
73
+ def current_timestamp
74
+ @ts ||= DateTime.now.to_s
68
75
  end
69
76
 
70
- def mandatory_params(conn_options)
71
- {apikey: conn_options.public_key, ts: current_timestamp, hash: hash(current_timestamp, conn_options)}
77
+ def hash timestamp
78
+ Digest::MD5.hexdigest("#{timestamp}#{Uatu.private_key}#{Uatu.public_key}")
72
79
  end
73
80
 
74
81
  end
75
- end
82
+ end
@@ -0,0 +1,16 @@
1
+ module Uatu
2
+ module Endpoints
3
+ module Collection
4
+
5
+ Uatu::RESOURCES.each do |resource|
6
+ # example: GET /v1/public/characters => Uatu::Base.new.characters
7
+ define_method resource.pluralize do |options={}|
8
+ raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
9
+ connection = Uatu::Connection.new resource, options
10
+ request_and_build connection
11
+ end
12
+ end
13
+
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,23 @@
1
+ module Uatu
2
+ module Endpoints
3
+ module Nested
4
+
5
+ Uatu::RESOURCES.each do |resource|
6
+ # example: GET /v1/public/characters/{characterId}/comics => Uatu::Base.new.character_comics
7
+ RESOURCES.each do |nested_resource|
8
+ unless nested_resource == resource
9
+ define_method "#{resource}_#{nested_resource.pluralize}" do |id, options={}|
10
+ raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
11
+ options.merge!("#{resource}_id".to_sym => id)
12
+ resource = "#{resource}_#{nested_resource.pluralize}"
13
+ connection = Uatu::Connection.new resource, options
14
+
15
+ request_and_build connection
16
+ end
17
+ end
18
+ end
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module Uatu
2
+ module Endpoints
3
+ module Single
4
+
5
+ Uatu::RESOURCES.each do |resource|
6
+ # example: GET /v1/public/characters/{characterId} => Uatu::Base.new.character
7
+ define_method resource do |id, options={}|
8
+ raise Uatu::Error::BadRequest.new('options must be in a Hash') unless options.is_a?(Hash)
9
+ options.merge!("#{resource}_id".to_sym => id)
10
+ connection = Uatu::Connection.new resource, options
11
+ request_and_build(connection).first
12
+ end
13
+ end
14
+
15
+ end
16
+ end
17
+ end
@@ -5,16 +5,18 @@ module Uatu
5
5
  super(improve_values(underscore_keys(original_hash)))
6
6
  end
7
7
 
8
+ private
9
+
8
10
  # Underscore names of the Hash. I mean... this is Ruby, right?.
9
11
  def underscore_keys(hash)
10
12
  _hash = {}
11
- hash.each do |k, v|
12
- _hash[k.to_s.underscore] = if v.is_a?(Hash)
13
- underscore_keys(v)
14
- elsif v.is_a?(Array) and v.first.is_a?(Hash)
15
- v.map{|h| underscore_keys(h)}
13
+ hash.each do |key, value|
14
+ _hash[key.to_s.underscore] = if value.is_a?(Hash)
15
+ underscore_keys(value)
16
+ elsif value.is_a?(Array) and value.first.is_a?(Hash)
17
+ value.map{|h| underscore_keys(h)}
16
18
  else
17
- v
19
+ value
18
20
  end
19
21
  end
20
22
  _hash
@@ -24,24 +26,24 @@ module Uatu
24
26
  # The 'thumbnail' hash drives me crazy, we convert it to a single value.
25
27
  def improve_values(hash)
26
28
  _hash = {}
27
- hash.each do |k,v|
28
- _hash[k] = if k.to_s=='thumbnail'
29
- [v['path'],v['extension']].join('.')
30
- elsif v.is_a?(Hash)
31
- Hashie::Mash.new(v)
29
+ hash.each do |key, value|
30
+ _hash[key] = if key.to_s=='thumbnail' && !value.nil?
31
+ [value['path'],value['extension']].join('.')
32
+ elsif value.is_a?(Hash)
33
+ Hashie::Mash.new(value)
32
34
  else
33
- v
35
+ value
34
36
  end
35
37
  end
36
38
  _hash
37
39
  end
38
40
 
39
41
  end
42
+ end
40
43
 
41
- class Character < Resource ; end
42
- class Event < Resource ; end
43
- class Comic < Resource ; end
44
- class Story < Resource ; end
45
- class Serie < Resource ; end
46
- class Creator < Resource ; end
47
- end
44
+ class Uatu::Character < Uatu::Resource ; end
45
+ class Uatu::Event < Uatu::Resource ; end
46
+ class Uatu::Comic < Uatu::Resource ; end
47
+ class Uatu::Story < Uatu::Resource ; end
48
+ class Uatu::Serie < Uatu::Resource ; end
49
+ class Uatu::Creator < Uatu::Resource ; end