comic_vine 0.1.4 → 1.0.0
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.
- checksums.yaml +5 -5
- data/CHANGELOG.md +104 -0
- data/README.md +105 -42
- data/lib/comic_vine/cv_list.rb +90 -34
- data/lib/comic_vine/cv_object.rb +32 -19
- data/lib/comic_vine/version.rb +4 -1
- data/lib/comic_vine.rb +262 -57
- metadata +18 -98
- data/.gitignore +0 -19
- data/.rspec +0 -2
- data/.travis.yml +0 -4
- data/Gemfile +0 -7
- data/Rakefile +0 -8
- data/changelog +0 -21
- data/comic_vine.gemspec +0 -24
- data/spec/comic_vine_spec.rb +0 -122
- data/spec/spec_helper.rb +0 -34
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 73bf9362c8e1a01699796797ec6173bf728515de3d87f7e9d00643eb9da79a8d
|
|
4
|
+
data.tar.gz: bb9a531d2ba69cc53bbc8933e70f49527892367d79f6c1c6f8c3fcc57a82f573
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 94931bde6c6ece327e406c8cddb65c6049b13c78b16d346aaa06b87ac74d3c6decae2b7adb9dd26abd0bd9a07367de44c36ecdfdfb00daf519e0e1a9eea237fd
|
|
7
|
+
data.tar.gz: ccd3b165209efde156dc98cc6a9de098578f4f5a805dc0bcfeb540fe7aa5e95de9bd3e3368d367acc14c893f45f7c269319c83aebe6b08cd2b590a66109f1b7d
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable changes to this project are documented in this file. The format is
|
|
4
|
+
based on [Keep a Changelog](https://keepachangelog.com/); dates for releases
|
|
5
|
+
before 2026 are taken from the git history.
|
|
6
|
+
|
|
7
|
+
## [1.0.0] — 2026-07-08
|
|
8
|
+
|
|
9
|
+
First stable release. **Breaking**: requires Ruby >= 3.4, and error handling
|
|
10
|
+
and pagination behavior have changed as described below.
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- Error hierarchy under `ComicVine::CVError`: `CVAPIError`, `CVHTTPError`
|
|
15
|
+
(with `#status`), `CVRateLimitError`, `CVConnectionError`, and `CVParseError`.
|
|
16
|
+
- Connection timeouts (`open_timeout` 10s, `read_timeout` 30s), configurable via
|
|
17
|
+
`ComicVine::API.open_timeout = ...` / `read_timeout = ...`.
|
|
18
|
+
- Automatic retries with exponential backoff on HTTP 420/429/5xx and connection
|
|
19
|
+
failures; honors `Retry-After`. Configurable via `max_retries` and
|
|
20
|
+
`retry_base_delay`.
|
|
21
|
+
- Custom User-Agent header, overridable via `ComicVine::API.user_agent = ...`.
|
|
22
|
+
- `respond_to_missing?` on `ComicVine::API` and `CVObject`, so `respond_to?`
|
|
23
|
+
and `method(...)` work for dynamic methods.
|
|
24
|
+
- `ComicVine::API.reset_types_cache!` for tests.
|
|
25
|
+
- RuboCop and YARD configuration; API documentation comments.
|
|
26
|
+
|
|
27
|
+
### Changed
|
|
28
|
+
|
|
29
|
+
- JSON parsing uses the Ruby standard library; the gem now has **no runtime
|
|
30
|
+
dependencies** (`multi_json`, `oj`, and `gson` removed).
|
|
31
|
+
- Class variables replaced with class-level instance variables; the `/types/`
|
|
32
|
+
cache is guarded by a mutex and no longer poisoned by a failed fetch.
|
|
33
|
+
- `next_page`/`prev_page` return `self` on success and `nil` at either end,
|
|
34
|
+
and preserve the original `filter`/`sort`/`field_list` options.
|
|
35
|
+
- Modernized gemspec (metadata URIs, `Dir` glob instead of `git ls-files`),
|
|
36
|
+
RSpec 3 configuration, and WebMock-stubbed specs.
|
|
37
|
+
|
|
38
|
+
### Fixed
|
|
39
|
+
|
|
40
|
+
- Query values are URL-encoded (`CGI.escape`); search queries are no longer
|
|
41
|
+
double-encoded.
|
|
42
|
+
- `search` no longer mutates the caller's options hash.
|
|
43
|
+
- `prev_page` offset math stepped by the current page's size instead of `limit`.
|
|
44
|
+
- `get_details` with an unknown type raises a descriptive `CVError` instead of
|
|
45
|
+
`NoMethodError`.
|
|
46
|
+
- `CVObject#get_*` on a plain value returns the value instead of `nil`.
|
|
47
|
+
- `CVObject` readers are defined on the singleton class instead of polluting
|
|
48
|
+
the shared class.
|
|
49
|
+
|
|
50
|
+
### Removed
|
|
51
|
+
|
|
52
|
+
- Travis CI configuration.
|
|
53
|
+
- Committed build artifacts (`coverage/`, packaged `.gem`, `.DS_Store`).
|
|
54
|
+
|
|
55
|
+
## [0.1.5] — 2017-03-25
|
|
56
|
+
|
|
57
|
+
- Use ComicVine URL with SSL.
|
|
58
|
+
|
|
59
|
+
## [0.1.4] — 2016-02-12
|
|
60
|
+
|
|
61
|
+
- Update ComicVine API URL.
|
|
62
|
+
|
|
63
|
+
## [0.1.1] — 2012-04-27
|
|
64
|
+
|
|
65
|
+
- Escape query on search; remove spaces from resources.
|
|
66
|
+
|
|
67
|
+
## [0.1.0] — 2012-04-24
|
|
68
|
+
|
|
69
|
+
- Fix small bug with types cache; full coverage with RSpec.
|
|
70
|
+
|
|
71
|
+
## [0.0.8] — 2012-04-18
|
|
72
|
+
|
|
73
|
+
- Fix bug exposing API key.
|
|
74
|
+
|
|
75
|
+
## [0.0.7] — 2012-04-18
|
|
76
|
+
|
|
77
|
+
- Fix bug with search.
|
|
78
|
+
|
|
79
|
+
## [0.0.6] — 2012-04-18
|
|
80
|
+
|
|
81
|
+
- Expose the helper methods; add `get_details_by_url`; allow `get_*` for any of
|
|
82
|
+
the resource items returned in the body.
|
|
83
|
+
|
|
84
|
+
## [0.0.5] — 2012-04-12
|
|
85
|
+
|
|
86
|
+
- Behind-the-scenes cleanup. Pure Ruby implementation; `API.key` is set
|
|
87
|
+
manually instead of read from a config file. Removed generator and railties.
|
|
88
|
+
|
|
89
|
+
## [0.0.4] — 2012-04-11
|
|
90
|
+
|
|
91
|
+
- Add `CVObjectList` to carry count vars from result. Simple pagination.
|
|
92
|
+
Include `Enumerable` in the list classes.
|
|
93
|
+
|
|
94
|
+
## [0.0.3] — 2012-04-10
|
|
95
|
+
|
|
96
|
+
- Simple associations; error check on ComicVine response; allow options.
|
|
97
|
+
|
|
98
|
+
## [0.0.2] — 2012-04-09
|
|
99
|
+
|
|
100
|
+
- Create `CVObject`s from resource returns.
|
|
101
|
+
|
|
102
|
+
## [0.0.1] — 2012-04-09
|
|
103
|
+
|
|
104
|
+
- First check-in.
|
data/README.md
CHANGED
|
@@ -1,79 +1,137 @@
|
|
|
1
|
-
[](http://travis-ci.org/Jakanapes/ComicVine)
|
|
2
|
-
|
|
3
1
|
# ComicVine
|
|
4
2
|
|
|
5
|
-
|
|
3
|
+
A simple Ruby interface to the [ComicVine API](https://comicvine.gamespot.com/api/).
|
|
4
|
+
Search for volumes, issues, characters, and other resources, or fetch them by id.
|
|
6
5
|
|
|
7
6
|
## Installation
|
|
8
7
|
|
|
9
8
|
Add this line to your application's Gemfile:
|
|
10
9
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
```ruby
|
|
11
|
+
gem "comic_vine"
|
|
12
|
+
```
|
|
14
13
|
|
|
15
|
-
|
|
14
|
+
And then run `bundle install`, or install it directly:
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
```console
|
|
17
|
+
$ gem install comic_vine
|
|
18
|
+
```
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
You will also need to have a ComicVine API key.
|
|
20
|
+
You will also need a [ComicVine API key](https://comicvine.gamespot.com/api/).
|
|
22
21
|
|
|
23
22
|
## Usage
|
|
24
23
|
|
|
25
|
-
|
|
24
|
+
Set your API key first:
|
|
25
|
+
|
|
26
|
+
```ruby
|
|
27
|
+
ComicVine::API.key = "your-api-key"
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Calls to plural resources return a `CVObjectList`, which carries the result
|
|
31
|
+
array along with the values from the response (`total_count`, `page_count`,
|
|
32
|
+
`offset`, `limit`):
|
|
33
|
+
|
|
34
|
+
```ruby
|
|
35
|
+
chars = ComicVine::API.characters
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
`CVObjectList` includes `Enumerable`, so lists can be looped:
|
|
39
|
+
|
|
40
|
+
```ruby
|
|
41
|
+
chars.each { |c| puts c.name }
|
|
42
|
+
```
|
|
26
43
|
|
|
27
|
-
|
|
44
|
+
Pagination updates the list in place and returns the list, or returns `nil` at
|
|
45
|
+
either end, so it can be used in a loop:
|
|
28
46
|
|
|
47
|
+
```ruby
|
|
48
|
+
chars.next_page
|
|
49
|
+
chars.prev_page
|
|
50
|
+
```
|
|
29
51
|
|
|
30
|
-
Calls to
|
|
52
|
+
Calls to singular resources take an id and return a `CVObject`:
|
|
31
53
|
|
|
32
|
-
|
|
54
|
+
```ruby
|
|
55
|
+
ComicVine::API.volume 766
|
|
56
|
+
```
|
|
33
57
|
|
|
34
|
-
|
|
58
|
+
`search` takes a resource type or types (comma-separated, e.g.
|
|
59
|
+
`"volume,issue"`) and a query string, and returns a `CVSearchList` (also
|
|
60
|
+
paginated):
|
|
35
61
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
chars.next_page
|
|
41
|
-
chars.prev_page
|
|
62
|
+
```ruby
|
|
63
|
+
results = ComicVine::API.search "volume", "batman"
|
|
64
|
+
```
|
|
42
65
|
|
|
43
|
-
|
|
66
|
+
Call `fetch` to retrieve the full object behind a search result or association:
|
|
44
67
|
|
|
45
|
-
|
|
68
|
+
```ruby
|
|
69
|
+
results.first.fetch
|
|
70
|
+
```
|
|
46
71
|
|
|
47
|
-
|
|
72
|
+
### Options: `limit`, `offset`, `filter`, `sort`, `field_list`
|
|
48
73
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Call fetch to retrieve the full object
|
|
52
|
-
|
|
53
|
-
results.first.fetch
|
|
74
|
+
List and detail calls accept an options hash, passed through to the API as
|
|
75
|
+
query parameters (values are URL-encoded for you). The most useful ones:
|
|
54
76
|
|
|
55
|
-
|
|
77
|
+
```ruby
|
|
78
|
+
# Page size and starting offset
|
|
79
|
+
ComicVine::API.characters(limit: 5, offset: 10)
|
|
56
80
|
|
|
57
|
-
|
|
81
|
+
# Filter results — field:value pairs, comma-separated
|
|
82
|
+
ComicVine::API.volumes(filter: "name:Walking Dead")
|
|
58
83
|
|
|
59
|
-
|
|
84
|
+
# Sort by a field — field:asc or field:desc
|
|
85
|
+
ComicVine::API.issues(sort: "cover_date:desc")
|
|
60
86
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
87
|
+
# Only return the fields you need (faster, smaller responses)
|
|
88
|
+
ComicVine::API.characters(field_list: "name,id,image")
|
|
89
|
+
```
|
|
64
90
|
|
|
65
|
-
|
|
91
|
+
These options are remembered across `next_page`/`prev_page`, so a filtered or
|
|
92
|
+
sorted list stays filtered and sorted while you page through it. See the
|
|
93
|
+
[ComicVine API documentation](https://comicvine.gamespot.com/api/documentation)
|
|
94
|
+
for the fields each resource supports.
|
|
66
95
|
|
|
96
|
+
### Associations
|
|
67
97
|
|
|
68
|
-
|
|
98
|
+
Call an association by its key name, prefaced by `get_`, and the gem will
|
|
99
|
+
return either an array of fetched objects or a `CVObject` from the API:
|
|
69
100
|
|
|
101
|
+
```ruby
|
|
102
|
+
volume = ComicVine::API.volume 766
|
|
103
|
+
issues = volume.get_issues
|
|
104
|
+
chars = volume.get_character_credits
|
|
105
|
+
```
|
|
70
106
|
|
|
71
|
-
|
|
72
|
-
More Error checking
|
|
107
|
+
### Errors
|
|
73
108
|
|
|
74
|
-
|
|
109
|
+
All errors raised by the gem inherit from `ComicVine::CVError`:
|
|
75
110
|
|
|
76
|
-
|
|
111
|
+
| Class | Raised when |
|
|
112
|
+
| --- | --- |
|
|
113
|
+
| `CVAPIError` | the API answers with an error status code (bad key, not found, …) |
|
|
114
|
+
| `CVHTTPError` | the server answers with a non-2xx HTTP status (`#status` has the code) |
|
|
115
|
+
| `CVRateLimitError` | HTTP 420/429 persists after retries (~200 requests/resource/hour) |
|
|
116
|
+
| `CVConnectionError` | the connection fails or times out after all retries |
|
|
117
|
+
| `CVParseError` | the response body is not valid JSON |
|
|
118
|
+
|
|
119
|
+
### Configuration
|
|
120
|
+
|
|
121
|
+
Timeouts, retries, and the User-Agent header can be tuned on `ComicVine::API`:
|
|
122
|
+
|
|
123
|
+
```ruby
|
|
124
|
+
ComicVine::API.open_timeout = 10 # seconds (default 10)
|
|
125
|
+
ComicVine::API.read_timeout = 30 # seconds (default 30)
|
|
126
|
+
ComicVine::API.max_retries = 3 # retries on 420/429/5xx and connection errors
|
|
127
|
+
ComicVine::API.retry_base_delay = 1.0 # exponential backoff base, honors Retry-After
|
|
128
|
+
ComicVine::API.user_agent = "my-app/1.0"
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
## Development
|
|
132
|
+
|
|
133
|
+
Run the test suite with `bundle exec rake spec`, the linter with
|
|
134
|
+
`bundle exec rubocop`, and generate API docs with `bundle exec yard`.
|
|
77
135
|
|
|
78
136
|
## Contributing
|
|
79
137
|
|
|
@@ -82,3 +140,8 @@ Tests
|
|
|
82
140
|
3. Commit your changes (`git commit -am 'Added some feature'`)
|
|
83
141
|
4. Push to the branch (`git push origin my-new-feature`)
|
|
84
142
|
5. Create new Pull Request
|
|
143
|
+
|
|
144
|
+
## License
|
|
145
|
+
|
|
146
|
+
This gem is released under the [MIT license](LICENSE). If you find it useful
|
|
147
|
+
in your application, drop me a line and I'll post a link!
|
data/lib/comic_vine/cv_list.rb
CHANGED
|
@@ -1,83 +1,139 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ComicVine
|
|
4
|
+
# Base class for paginated result lists. Carries the count values from the
|
|
5
|
+
# API response (`total_count`, `page_count`, `offset`, `limit`) and includes
|
|
6
|
+
# `Enumerable` over the contained {CVObject}s.
|
|
2
7
|
class CVList
|
|
3
8
|
include Enumerable
|
|
4
|
-
|
|
9
|
+
|
|
10
|
+
# @return [Integer] total results across all pages
|
|
5
11
|
attr_reader :total_count
|
|
12
|
+
# @return [Integer] results on the current page
|
|
6
13
|
attr_reader :page_count
|
|
14
|
+
# @return [Integer] offset of the current page
|
|
7
15
|
attr_reader :offset
|
|
16
|
+
# @return [Integer] page size
|
|
8
17
|
attr_reader :limit
|
|
18
|
+
# @return [Array<CVObject>] the objects on the current page
|
|
9
19
|
attr_reader :cvos
|
|
10
|
-
|
|
11
|
-
|
|
20
|
+
|
|
21
|
+
# @param resp [Hash] a list response from the API
|
|
22
|
+
def initialize(resp)
|
|
12
23
|
@total_count = resp['number_of_total_results']
|
|
13
24
|
@page_count = resp['number_of_page_results']
|
|
14
25
|
@offset = resp['offset']
|
|
15
26
|
@limit = resp['limit']
|
|
16
27
|
end
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
28
|
+
|
|
29
|
+
# Yields each {CVObject} on the current page.
|
|
30
|
+
def each(&)
|
|
31
|
+
@cvos.each(&)
|
|
20
32
|
end
|
|
21
|
-
|
|
33
|
+
|
|
34
|
+
# @return [CVObject, nil] the last object on the current page
|
|
22
35
|
def last
|
|
23
36
|
@cvos.last
|
|
24
37
|
end
|
|
25
|
-
|
|
38
|
+
|
|
39
|
+
# @return [Integer] the current page number (1-based)
|
|
26
40
|
def page
|
|
27
41
|
(@offset / @limit) + 1
|
|
28
42
|
end
|
|
29
|
-
|
|
43
|
+
|
|
30
44
|
protected
|
|
31
|
-
def update_ivals(new_cvol)
|
|
32
|
-
@total_count = new_cvol.total_count
|
|
33
|
-
@offset = new_cvol.offset
|
|
34
|
-
@limit = new_cvol.limit
|
|
35
45
|
|
|
36
|
-
|
|
37
|
-
|
|
46
|
+
def update_ivals(new_cvol)
|
|
47
|
+
@total_count = new_cvol.total_count
|
|
48
|
+
@page_count = new_cvol.page_count
|
|
49
|
+
@offset = new_cvol.offset
|
|
50
|
+
@limit = new_cvol.limit
|
|
51
|
+
|
|
52
|
+
@cvos = new_cvol.cvos
|
|
53
|
+
end
|
|
38
54
|
end
|
|
39
|
-
|
|
55
|
+
|
|
56
|
+
# A paginated list of resources (e.g. from `ComicVine::API.characters`).
|
|
57
|
+
# {#next_page} and {#prev_page} update the list in place, preserving the
|
|
58
|
+
# original options (`:filter`, `:sort`, `:field_list`, ...).
|
|
40
59
|
class CVObjectList < CVList
|
|
60
|
+
# @return [String] the plural resource name this list was fetched from
|
|
41
61
|
attr_reader :resource
|
|
42
|
-
|
|
43
|
-
|
|
62
|
+
|
|
63
|
+
# @param resp [Hash] a list response from the API
|
|
64
|
+
# @param resc [String] the plural resource name
|
|
65
|
+
# @param opts [Hash] the options the list was fetched with
|
|
66
|
+
def initialize(resp, resc, opts = {})
|
|
44
67
|
super(resp)
|
|
45
|
-
|
|
68
|
+
|
|
46
69
|
@resource = resc
|
|
47
|
-
@
|
|
70
|
+
@opts = opts || {}
|
|
71
|
+
@cvos = resp['results'].map { |r| ComicVine::CVObject.new(r) }
|
|
48
72
|
end
|
|
49
|
-
|
|
73
|
+
|
|
74
|
+
# Advances to the next page, updating the list in place.
|
|
75
|
+
#
|
|
76
|
+
# @return [CVObjectList, nil] `self`, or `nil` if already on the last page
|
|
77
|
+
# @raise [CVError]
|
|
50
78
|
def next_page
|
|
51
79
|
return nil if (@offset + @page_count) >= @total_count
|
|
52
|
-
|
|
80
|
+
|
|
81
|
+
update_ivals(ComicVine::API.send(@resource, @opts.merge(:limit => @limit, :offset => (@offset + @limit))))
|
|
82
|
+
self
|
|
53
83
|
end
|
|
54
|
-
|
|
84
|
+
|
|
85
|
+
# Steps back to the previous page, updating the list in place.
|
|
86
|
+
#
|
|
87
|
+
# @return [CVObjectList, nil] `self`, or `nil` if already on the first page
|
|
88
|
+
# @raise [CVError]
|
|
55
89
|
def prev_page
|
|
56
90
|
return nil if @offset == 0
|
|
57
|
-
|
|
91
|
+
|
|
92
|
+
update_ivals(ComicVine::API.send(@resource, @opts.merge(:limit => @limit, :offset => [@offset - @limit, 0].max)))
|
|
93
|
+
self
|
|
58
94
|
end
|
|
59
95
|
end
|
|
60
|
-
|
|
96
|
+
|
|
97
|
+
# A paginated list of search results (from {ComicVine::API.search}).
|
|
61
98
|
class CVSearchList < CVList
|
|
99
|
+
# @return [String] the resource type(s) searched
|
|
62
100
|
attr_reader :resource
|
|
101
|
+
# @return [String] the search query
|
|
63
102
|
attr_reader :query
|
|
64
|
-
|
|
65
|
-
|
|
103
|
+
|
|
104
|
+
# @param resp [Hash] a search response from the API
|
|
105
|
+
# @param resc [String] the resource type(s) searched
|
|
106
|
+
# @param query [String] the search query
|
|
107
|
+
# @param opts [Hash] the options the search was made with
|
|
108
|
+
def initialize(resp, resc, query, opts = {})
|
|
66
109
|
super(resp)
|
|
67
|
-
|
|
110
|
+
|
|
68
111
|
@resource = resc
|
|
69
112
|
@query = query
|
|
70
|
-
@
|
|
113
|
+
@opts = opts || {}
|
|
114
|
+
@cvos = resp['results'].map { |r| ComicVine::CVObject.new(r) }
|
|
71
115
|
end
|
|
72
|
-
|
|
116
|
+
|
|
117
|
+
# Advances to the next page of results, updating the list in place.
|
|
118
|
+
#
|
|
119
|
+
# @return [CVSearchList, nil] `self`, or `nil` if already on the last page
|
|
120
|
+
# @raise [CVError]
|
|
73
121
|
def next_page
|
|
74
122
|
return nil if (@offset + @page_count) >= @total_count
|
|
75
|
-
|
|
123
|
+
|
|
124
|
+
update_ivals(ComicVine::API.search(@resource, @query, @opts.merge(:limit => @limit, :page => page + 1)))
|
|
125
|
+
self
|
|
76
126
|
end
|
|
77
|
-
|
|
127
|
+
|
|
128
|
+
# Steps back to the previous page of results, updating the list in place.
|
|
129
|
+
#
|
|
130
|
+
# @return [CVSearchList, nil] `self`, or `nil` if already on the first page
|
|
131
|
+
# @raise [CVError]
|
|
78
132
|
def prev_page
|
|
79
133
|
return nil if @offset == 0
|
|
80
|
-
|
|
134
|
+
|
|
135
|
+
update_ivals(ComicVine::API.search(@resource, @query, @opts.merge(:limit => @limit, :page => page - 1)))
|
|
136
|
+
self
|
|
81
137
|
end
|
|
82
138
|
end
|
|
83
|
-
end
|
|
139
|
+
end
|
data/lib/comic_vine/cv_object.rb
CHANGED
|
@@ -1,39 +1,52 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
1
3
|
module ComicVine
|
|
4
|
+
# Wraps a single resource returned by the API. Every key in the response
|
|
5
|
+
# becomes a reader method; nested resources that carry an `api_detail_url`
|
|
6
|
+
# become {CVObject}s themselves and can be expanded with `get_<key>`.
|
|
2
7
|
class CVObject
|
|
8
|
+
# @param args [Hash] a resource hash from the API response
|
|
3
9
|
def initialize(args)
|
|
4
|
-
args.each do |k,v|
|
|
5
|
-
|
|
6
|
-
v.collect! { |i| CVObject.new i } if v.
|
|
7
|
-
v = CVObject.new v if v.
|
|
10
|
+
args.each do |k, v|
|
|
11
|
+
singleton_class.class_eval { attr_reader k } unless respond_to?(k)
|
|
12
|
+
v.collect! { |i| CVObject.new i } if v.is_a?(Array) && v.first.is_a?(Hash) && v.first.key?("api_detail_url")
|
|
13
|
+
v = CVObject.new v if v.is_a?(Hash) && v.key?("api_detail_url")
|
|
8
14
|
instance_variable_set "@#{k}", v
|
|
9
15
|
end
|
|
10
16
|
end
|
|
11
|
-
|
|
17
|
+
|
|
18
|
+
# Retrieves the full object from this object's `api_detail_url`.
|
|
19
|
+
#
|
|
20
|
+
# @return [CVObject]
|
|
21
|
+
# @raise [CVError]
|
|
12
22
|
def fetch
|
|
13
23
|
ComicVine::API.get_details_by_url(@api_detail_url)
|
|
14
24
|
end
|
|
15
|
-
|
|
16
|
-
|
|
25
|
+
|
|
26
|
+
# Resolves `get_<key>` calls: fetches the full object(s) behind an
|
|
27
|
+
# association, or returns the plain value if it isn't an association.
|
|
28
|
+
def method_missing(method_sym, *arguments, &)
|
|
17
29
|
if method_sym.to_s =~ /^get_(.*)$/
|
|
18
|
-
key =
|
|
30
|
+
key = $1
|
|
19
31
|
if instance_variable_defined?("@#{key}")
|
|
20
32
|
item = instance_variable_get("@#{key}")
|
|
21
|
-
if item.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
end
|
|
28
|
-
if item.kind_of?(CVObject)
|
|
29
|
-
return item.fetch
|
|
33
|
+
if item.is_a?(Array) && item.first.is_a?(CVObject)
|
|
34
|
+
item.map(&:fetch)
|
|
35
|
+
elsif item.is_a?(CVObject)
|
|
36
|
+
item.fetch
|
|
37
|
+
else
|
|
38
|
+
item
|
|
30
39
|
end
|
|
31
40
|
else
|
|
32
41
|
super
|
|
33
42
|
end
|
|
34
|
-
|
|
43
|
+
else
|
|
35
44
|
super
|
|
36
45
|
end
|
|
37
46
|
end
|
|
47
|
+
|
|
48
|
+
def respond_to_missing?(method_sym, include_private = false)
|
|
49
|
+
method_sym.to_s =~ /^get_(.*)$/ ? instance_variable_defined?("@#{$1}") : super
|
|
50
|
+
end
|
|
38
51
|
end
|
|
39
|
-
end
|
|
52
|
+
end
|