metal_archives 2.2.3 → 3.2.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 +4 -4
- data/.github/workflows/ci.yml +59 -12
- data/.rspec +1 -0
- data/.rubocop.yml +34 -20
- data/CHANGELOG.md +16 -1
- data/LICENSE.md +17 -4
- data/README.md +37 -29
- data/bin/console +8 -11
- data/config/inflections.rb +7 -0
- data/config/initializers/.keep +0 -0
- data/docker-compose.yml +10 -1
- data/lib/metal_archives.rb +57 -21
- data/lib/metal_archives/cache/base.rb +40 -0
- data/lib/metal_archives/cache/memory.rb +68 -0
- data/lib/metal_archives/cache/null.rb +22 -0
- data/lib/metal_archives/cache/redis.rb +49 -0
- data/lib/metal_archives/collection.rb +3 -5
- data/lib/metal_archives/configuration.rb +28 -21
- data/lib/metal_archives/errors.rb +9 -1
- data/lib/metal_archives/http_client.rb +42 -46
- data/lib/metal_archives/models/artist.rb +55 -26
- data/lib/metal_archives/models/band.rb +43 -36
- data/lib/metal_archives/models/{base_model.rb → base.rb} +57 -50
- data/lib/metal_archives/models/label.rb +7 -8
- data/lib/metal_archives/models/release.rb +21 -18
- data/lib/metal_archives/parsers/artist.rb +41 -36
- data/lib/metal_archives/parsers/band.rb +73 -29
- data/lib/metal_archives/parsers/base.rb +14 -0
- data/lib/metal_archives/parsers/country.rb +21 -0
- data/lib/metal_archives/parsers/date.rb +31 -0
- data/lib/metal_archives/parsers/genre.rb +67 -0
- data/lib/metal_archives/parsers/label.rb +21 -13
- data/lib/metal_archives/parsers/parser.rb +17 -77
- data/lib/metal_archives/parsers/release.rb +29 -18
- data/lib/metal_archives/parsers/year.rb +31 -0
- data/lib/metal_archives/version.rb +3 -3
- data/metal_archives.env.example +7 -4
- data/metal_archives.gemspec +7 -4
- data/nginx/default.conf +2 -2
- metadata +76 -32
- data/.github/workflows/release.yml +0 -69
- data/.rubocop_todo.yml +0 -92
- data/lib/metal_archives/lru_cache.rb +0 -61
- data/lib/metal_archives/middleware/cache_check.rb +0 -18
- data/lib/metal_archives/middleware/encoding.rb +0 -16
- data/lib/metal_archives/middleware/headers.rb +0 -38
- data/lib/metal_archives/middleware/rewrite_endpoint.rb +0 -38
- data/lib/metal_archives/nil_date.rb +0 -91
- data/lib/metal_archives/range.rb +0 -69
@@ -8,7 +8,7 @@ module MetalArchives
|
|
8
8
|
##
|
9
9
|
# Represents a single performer (but not a solo artist)
|
10
10
|
#
|
11
|
-
class Artist <
|
11
|
+
class Artist < Base
|
12
12
|
##
|
13
13
|
# :attr_reader: id
|
14
14
|
#
|
@@ -63,24 +63,24 @@ module MetalArchives
|
|
63
63
|
##
|
64
64
|
# :attr_reader: date_of_birth
|
65
65
|
#
|
66
|
-
# Returns rdoc-ref:
|
66
|
+
# Returns rdoc-ref:Date
|
67
67
|
#
|
68
68
|
# [Raises]
|
69
69
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
70
70
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
71
71
|
#
|
72
|
-
property :date_of_birth, type:
|
72
|
+
property :date_of_birth, type: Date
|
73
73
|
|
74
74
|
##
|
75
75
|
# :attr_reader: date_of_death
|
76
76
|
#
|
77
|
-
# Returns rdoc-ref:
|
77
|
+
# Returns rdoc-ref:Date
|
78
78
|
#
|
79
79
|
# [Raises]
|
80
80
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
81
81
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
82
82
|
#
|
83
|
-
property :date_of_death, type:
|
83
|
+
property :date_of_death, type: Date
|
84
84
|
|
85
85
|
##
|
86
86
|
# :attr_reader: cause_of_death
|
@@ -102,7 +102,7 @@ module MetalArchives
|
|
102
102
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
103
103
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
104
104
|
#
|
105
|
-
enum :gender, values:
|
105
|
+
enum :gender, values: [:male, :female]
|
106
106
|
|
107
107
|
##
|
108
108
|
# :attr_reader: biography
|
@@ -165,7 +165,7 @@ module MetalArchives
|
|
165
165
|
# [+bands+]
|
166
166
|
# - +:band+: rdoc-ref:Band
|
167
167
|
# - +:active+: Boolean
|
168
|
-
# - +:
|
168
|
+
# - +:years_active+: +Array+ of rdoc-ref:Range containing +Integer+
|
169
169
|
# - +:role+: +String+
|
170
170
|
#
|
171
171
|
property :bands, type: Hash, multiple: true
|
@@ -173,6 +173,41 @@ module MetalArchives
|
|
173
173
|
# TODO: guest/session bands
|
174
174
|
# TODO: misc bands
|
175
175
|
|
176
|
+
##
|
177
|
+
# Serialize to hash
|
178
|
+
#
|
179
|
+
def to_h
|
180
|
+
{
|
181
|
+
type: "artist",
|
182
|
+
id: id,
|
183
|
+
name: name,
|
184
|
+
aliases: aliases || [],
|
185
|
+
country: country&.alpha3,
|
186
|
+
location: location,
|
187
|
+
date_of_birth: date_of_birth&.iso8601,
|
188
|
+
date_of_death: date_of_death&.iso8601,
|
189
|
+
cause_of_death: cause_of_death,
|
190
|
+
gender: gender,
|
191
|
+
biography: biography,
|
192
|
+
trivia: trivia,
|
193
|
+
photo: photo,
|
194
|
+
links: links || [],
|
195
|
+
bands: bands || [],
|
196
|
+
}
|
197
|
+
end
|
198
|
+
|
199
|
+
##
|
200
|
+
# Deserialize from hash
|
201
|
+
#
|
202
|
+
def self.from_h(hash)
|
203
|
+
return unless hash.fetch(:type) == "artist"
|
204
|
+
|
205
|
+
new(hash.slice(:id, :name, :aliases, :location, :cause_of_death, :gender, :biography, :trivial, :photo, :links, :bands))
|
206
|
+
.tap { |m| m.country = ISO3166::Country[hash[:country]] }
|
207
|
+
.tap { |m| m.date_of_birth = Date.parse(hash[:date_of_birth]) if hash[:date_of_birth] }
|
208
|
+
.tap { |m| m.date_of_death = Date.parse(hash[:date_of_death]) if hash[:date_of_death] }
|
209
|
+
end
|
210
|
+
|
176
211
|
protected
|
177
212
|
|
178
213
|
##
|
@@ -184,28 +219,24 @@ module MetalArchives
|
|
184
219
|
#
|
185
220
|
def assemble # :nodoc:
|
186
221
|
## Base attributes
|
187
|
-
|
188
|
-
response = HTTPClient.get url
|
222
|
+
response = MetalArchives.http.get "/artist/view/id/#{id}"
|
189
223
|
|
190
|
-
properties = Parsers::Artist.parse_html response.
|
224
|
+
properties = Parsers::Artist.parse_html response.to_s
|
191
225
|
|
192
226
|
## Biography
|
193
|
-
|
194
|
-
response = HTTPClient.get url
|
227
|
+
response = MetalArchives.http.get "/artist/read-more/id/#{id}/field/biography"
|
195
228
|
|
196
|
-
properties[:biography] = response.
|
229
|
+
properties[:biography] = response.to_s
|
197
230
|
|
198
231
|
## Trivia
|
199
|
-
|
200
|
-
response = HTTPClient.get url
|
232
|
+
response = MetalArchives.http.get "/artist/read-more/id/#{id}/field/trivia"
|
201
233
|
|
202
|
-
properties[:trivia] = response.
|
234
|
+
properties[:trivia] = response.to_s
|
203
235
|
|
204
236
|
## Related links
|
205
|
-
|
206
|
-
response = HTTPClient.get url
|
237
|
+
response = MetalArchives.http.get "/link/ajax-list/type/person/id/#{id}"
|
207
238
|
|
208
|
-
properties[:links] = Parsers::Artist.parse_links_html response.
|
239
|
+
properties[:links] = Parsers::Artist.parse_links_html response.to_s
|
209
240
|
|
210
241
|
properties
|
211
242
|
end
|
@@ -220,7 +251,7 @@ module MetalArchives
|
|
220
251
|
# +Integer+
|
221
252
|
#
|
222
253
|
def find(id)
|
223
|
-
return cache[id] if cache.include? id
|
254
|
+
return MetalArchives.cache[cache(id)] if MetalArchives.cache.include? cache(id)
|
224
255
|
|
225
256
|
Artist.new id: id
|
226
257
|
end
|
@@ -262,11 +293,10 @@ module MetalArchives
|
|
262
293
|
def find_by(query)
|
263
294
|
raise MetalArchives::Errors::ArgumentError unless query.include? :name
|
264
295
|
|
265
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-artist-search/"
|
266
296
|
params = Parsers::Artist.map_params query
|
267
297
|
|
268
|
-
response =
|
269
|
-
json = JSON.parse response.
|
298
|
+
response = MetalArchives.http.get "/search/ajax-artist-search/", params
|
299
|
+
json = JSON.parse response.to_s
|
270
300
|
|
271
301
|
return nil if json["aaData"].empty?
|
272
302
|
|
@@ -314,7 +344,6 @@ module MetalArchives
|
|
314
344
|
def search(name)
|
315
345
|
raise MetalArchives::Errors::ArgumentError unless name.is_a? String
|
316
346
|
|
317
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-artist-search/"
|
318
347
|
query = { name: name }
|
319
348
|
|
320
349
|
params = Parsers::Artist.map_params query
|
@@ -325,8 +354,8 @@ module MetalArchives
|
|
325
354
|
if @max_items && @start >= @max_items
|
326
355
|
[]
|
327
356
|
else
|
328
|
-
response =
|
329
|
-
json = JSON.parse response.
|
357
|
+
response = MetalArchives.http.get "/search/ajax-artist-search/", params.merge(iDisplayStart: @start)
|
358
|
+
json = JSON.parse response.to_s
|
330
359
|
|
331
360
|
@max_items = json["iTotalRecords"]
|
332
361
|
|
@@ -8,7 +8,7 @@ module MetalArchives
|
|
8
8
|
##
|
9
9
|
# Represents an band (person or group)
|
10
10
|
#
|
11
|
-
class Band <
|
11
|
+
class Band < Base
|
12
12
|
##
|
13
13
|
# :attr_reader: id
|
14
14
|
#
|
@@ -63,24 +63,24 @@ module MetalArchives
|
|
63
63
|
##
|
64
64
|
# :attr_reader: date_formed
|
65
65
|
#
|
66
|
-
# Returns rdoc-ref:
|
66
|
+
# Returns rdoc-ref:Date
|
67
67
|
#
|
68
68
|
# [Raises]
|
69
69
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
70
70
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
71
71
|
#
|
72
|
-
property :date_formed, type:
|
72
|
+
property :date_formed, type: Date
|
73
73
|
|
74
74
|
##
|
75
|
-
# :attr_reader:
|
75
|
+
# :attr_reader: years_active
|
76
76
|
#
|
77
|
-
# Returns +Array+ of rdoc-ref:Range containing
|
77
|
+
# Returns +Array+ of rdoc-ref:Range containing +Integer+
|
78
78
|
#
|
79
79
|
# [Raises]
|
80
80
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
81
81
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
82
82
|
#
|
83
|
-
property :
|
83
|
+
property :years_active, type: Range, multiple: true
|
84
84
|
|
85
85
|
##
|
86
86
|
# :attr_reader: genres
|
@@ -113,7 +113,7 @@ module MetalArchives
|
|
113
113
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
114
114
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
115
115
|
#
|
116
|
-
property :label, type:
|
116
|
+
property :label, type: Label
|
117
117
|
|
118
118
|
##
|
119
119
|
# :attr_reader: independent
|
@@ -146,7 +146,7 @@ module MetalArchives
|
|
146
146
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
147
147
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
148
148
|
#
|
149
|
-
enum :status, values:
|
149
|
+
enum :status, values: [:active, :split_up, :on_hold, :unknown, :changed_name, :disputed]
|
150
150
|
|
151
151
|
##
|
152
152
|
# :attr_reader: releases
|
@@ -157,9 +157,24 @@ module MetalArchives
|
|
157
157
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
158
158
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
159
159
|
#
|
160
|
-
property :releases, type:
|
160
|
+
property :releases, type: Release, multiple: true
|
161
161
|
|
162
|
-
|
162
|
+
##
|
163
|
+
# :attr_reader: members
|
164
|
+
#
|
165
|
+
# Returns +Array+ of +Hash+ containing the following keys
|
166
|
+
#
|
167
|
+
# [Raises]
|
168
|
+
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
169
|
+
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
170
|
+
#
|
171
|
+
# [+members+]
|
172
|
+
# - +:artist+: rdoc-ref:Artist
|
173
|
+
# - +:current+: Boolean
|
174
|
+
# - +:years_active+: +Array+ of rdoc-ref:Range containing +Integer+
|
175
|
+
# - +:role+: +String+
|
176
|
+
#
|
177
|
+
property :members, type: Artist, multiple: true
|
163
178
|
|
164
179
|
##
|
165
180
|
# :attr_reader: similar
|
@@ -225,34 +240,29 @@ module MetalArchives
|
|
225
240
|
#
|
226
241
|
def assemble # :nodoc:
|
227
242
|
## Base attributes
|
228
|
-
|
229
|
-
response = HTTPClient.get url
|
243
|
+
response = MetalArchives.http.get "/band/view/id/#{id}"
|
230
244
|
|
231
|
-
properties = Parsers::Band.parse_html response.
|
245
|
+
properties = Parsers::Band.parse_html response.to_s
|
232
246
|
|
233
247
|
## Comment
|
234
|
-
|
235
|
-
response = HTTPClient.get url
|
248
|
+
response = MetalArchives.http.get "/band/read-more/id/#{id}"
|
236
249
|
|
237
|
-
properties[:comment] = response.
|
250
|
+
properties[:comment] = response.to_s
|
238
251
|
|
239
252
|
## Similar artists
|
240
|
-
|
241
|
-
response = HTTPClient.get url
|
253
|
+
response = MetalArchives.http.get "/band/ajax-recommendations/id/#{id}"
|
242
254
|
|
243
|
-
properties[:similar] = Parsers::Band.parse_similar_bands_html response.
|
255
|
+
properties[:similar] = Parsers::Band.parse_similar_bands_html response.to_s
|
244
256
|
|
245
257
|
## Related links
|
246
|
-
|
247
|
-
response = HTTPClient.get url
|
258
|
+
response = MetalArchives.http.get "/link/ajax-list/type/band/id/#{id}"
|
248
259
|
|
249
|
-
properties[:links] = Parsers::Band.parse_related_links_html response.
|
260
|
+
properties[:links] = Parsers::Band.parse_related_links_html response.to_s
|
250
261
|
|
251
262
|
## Releases
|
252
|
-
|
253
|
-
response = HTTPClient.get url
|
263
|
+
response = MetalArchives.http.get "/band/discography/id/#{id}/tab/all"
|
254
264
|
|
255
|
-
properties[:releases] = Parsers::Band.parse_releases_html response.
|
265
|
+
properties[:releases] = Parsers::Band.parse_releases_html response.to_s
|
256
266
|
|
257
267
|
properties
|
258
268
|
end
|
@@ -267,7 +277,7 @@ module MetalArchives
|
|
267
277
|
# +Integer+
|
268
278
|
#
|
269
279
|
def find(id)
|
270
|
-
return cache[id] if cache.include? id
|
280
|
+
return MetalArchives.cache[cache(id)] if MetalArchives.cache.include? cache(id)
|
271
281
|
|
272
282
|
Band.new id: id
|
273
283
|
end
|
@@ -309,7 +319,7 @@ module MetalArchives
|
|
309
319
|
# - +:exact+: +Boolean+
|
310
320
|
# - +:genre+: +String+
|
311
321
|
# - +:country+: +ISO3166::Country+
|
312
|
-
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:
|
322
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
313
323
|
# - +:comment+: +String+
|
314
324
|
# - +:status+: see rdoc-ref:Band.status
|
315
325
|
# - +:lyrical_themes+: +String+
|
@@ -318,11 +328,10 @@ module MetalArchives
|
|
318
328
|
# - +:independent+: boolean
|
319
329
|
#
|
320
330
|
def find_by(query)
|
321
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/bands"
|
322
331
|
params = Parsers::Band.map_params query
|
323
332
|
|
324
|
-
response =
|
325
|
-
json = JSON.parse response.
|
333
|
+
response = MetalArchives.http.get "/search/ajax-advanced/searching/bands", params
|
334
|
+
json = JSON.parse response.to_s
|
326
335
|
|
327
336
|
return nil if json["aaData"].empty?
|
328
337
|
|
@@ -349,7 +358,7 @@ module MetalArchives
|
|
349
358
|
# - +:exact+: +Boolean+
|
350
359
|
# - +:genre+: +String+
|
351
360
|
# - +:country+: +ISO3166::Country+
|
352
|
-
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:
|
361
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
353
362
|
# - +:comment+: +String+
|
354
363
|
# - +:status+: see rdoc-ref:Band.status
|
355
364
|
# - +:lyrical_themes+: +String+
|
@@ -381,7 +390,7 @@ module MetalArchives
|
|
381
390
|
# - +:exact+: +Boolean+
|
382
391
|
# - +:genre+: +String+
|
383
392
|
# - +:country+: +ISO3166::Country+
|
384
|
-
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:
|
393
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
385
394
|
# - +:comment+: +String+
|
386
395
|
# - +:status+: see rdoc-ref:Band.status
|
387
396
|
# - +:lyrical_themes+: +String+
|
@@ -390,8 +399,6 @@ module MetalArchives
|
|
390
399
|
# - +:independent+: boolean
|
391
400
|
#
|
392
401
|
def search_by(query)
|
393
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/bands"
|
394
|
-
|
395
402
|
params = Parsers::Band.map_params query
|
396
403
|
|
397
404
|
l = lambda do
|
@@ -400,8 +407,8 @@ module MetalArchives
|
|
400
407
|
if @max_items && @start >= @max_items
|
401
408
|
[]
|
402
409
|
else
|
403
|
-
response =
|
404
|
-
json = JSON.parse response.
|
410
|
+
response = MetalArchives.http.get "/search/ajax-advanced/searching/bands", params.merge(iDisplayStart: @start)
|
411
|
+
json = JSON.parse response.to_s
|
405
412
|
|
406
413
|
@max_items = json["iTotalRecords"]
|
407
414
|
|
@@ -4,48 +4,49 @@ module MetalArchives
|
|
4
4
|
##
|
5
5
|
# Abstract model class
|
6
6
|
#
|
7
|
-
class
|
7
|
+
class Base
|
8
8
|
##
|
9
9
|
# Generic shallow copy constructor
|
10
10
|
#
|
11
|
-
def initialize(
|
12
|
-
raise Errors::NotImplementedError, "no :id property in model" unless respond_to? :id
|
11
|
+
def initialize(attributes = {})
|
12
|
+
raise Errors::NotImplementedError, "no :id property in model" unless respond_to? :id
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
14
|
+
set(**attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
##
|
18
|
+
# Set properties
|
19
|
+
#
|
20
|
+
def set(**attributes)
|
21
|
+
attributes.each { |key, value| instance_variable_set(:"@#{key}", value) }
|
17
22
|
end
|
18
23
|
|
19
24
|
##
|
20
25
|
# Returns true if two objects have the same type and id
|
21
26
|
#
|
22
|
-
def ==(
|
23
|
-
|
27
|
+
def ==(other)
|
28
|
+
other.is_a?(self.class) &&
|
29
|
+
id == other.id
|
24
30
|
end
|
25
31
|
|
26
32
|
##
|
27
33
|
# Fetch, parse and load the data
|
28
34
|
#
|
29
35
|
# [Raises]
|
30
|
-
# - rdoc-ref:
|
31
|
-
# - rdoc-ref:
|
36
|
+
# - rdoc-ref:Errors::InvalidIDError when no id
|
37
|
+
# - rdoc-ref:Errors::APIError when receiving a status code >= 400 (except 404)
|
32
38
|
#
|
33
39
|
def load!
|
34
40
|
raise Errors::InvalidIDError, "no id present" unless id
|
35
41
|
|
36
42
|
# Use constructor to set attributes
|
37
|
-
|
38
|
-
|
39
|
-
# Set empty properties to nil
|
40
|
-
self.class.properties.each do |prop|
|
41
|
-
instance_variable_set("@#{prop}", nil) unless instance_variable_defined? "@#{prop}"
|
42
|
-
end
|
43
|
+
set(**assemble)
|
43
44
|
|
44
45
|
@loaded = true
|
45
|
-
self.class.cache
|
46
|
+
MetalArchives.cache[self.class.cache(id)] = self
|
46
47
|
rescue StandardError => e
|
47
48
|
# Don't cache invalid requests
|
48
|
-
self.class.cache
|
49
|
+
MetalArchives.cache.delete self.class.cache(id)
|
49
50
|
raise e
|
50
51
|
end
|
51
52
|
|
@@ -53,14 +54,21 @@ module MetalArchives
|
|
53
54
|
# Whether or not the object is currently loaded
|
54
55
|
#
|
55
56
|
def loaded?
|
56
|
-
|
57
|
+
@loaded ||= false
|
57
58
|
end
|
58
59
|
|
59
60
|
##
|
60
61
|
# Whether or not the object is currently cached
|
61
62
|
#
|
62
63
|
def cached?
|
63
|
-
loaded? &&
|
64
|
+
loaded? && MetalArchives.cache.include?(self.class.cache(id))
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# String representation
|
69
|
+
#
|
70
|
+
def inspect
|
71
|
+
"#<#{self.class.name} @id=#{@id} @name=\"#{@name}\">"
|
64
72
|
end
|
65
73
|
|
66
74
|
protected
|
@@ -71,8 +79,8 @@ module MetalArchives
|
|
71
79
|
# Override this method
|
72
80
|
#
|
73
81
|
# [Raises]
|
74
|
-
# - rdoc-ref:
|
75
|
-
# - rdoc-ref:
|
82
|
+
# - rdoc-ref:Errors::InvalidIDError when no or invalid id
|
83
|
+
# - rdoc-ref:Errors::APIError when receiving a status code >= 400 (except 404)
|
76
84
|
#
|
77
85
|
def assemble
|
78
86
|
raise Errors::NotImplementedError, "method :assemble not implemented"
|
@@ -80,15 +88,17 @@ module MetalArchives
|
|
80
88
|
|
81
89
|
class << self
|
82
90
|
##
|
83
|
-
#
|
91
|
+
# Declared properties
|
84
92
|
#
|
85
|
-
|
93
|
+
def properties
|
94
|
+
@properties ||= {}
|
95
|
+
end
|
86
96
|
|
87
97
|
##
|
88
|
-
#
|
98
|
+
# Generate cache key for id
|
89
99
|
#
|
90
|
-
def cache
|
91
|
-
|
100
|
+
def cache(id)
|
101
|
+
"#{self.class.name}//#{id}"
|
92
102
|
end
|
93
103
|
|
94
104
|
protected
|
@@ -110,42 +120,38 @@ module MetalArchives
|
|
110
120
|
# turns it into an +Array+ of +type+)
|
111
121
|
#
|
112
122
|
def property(name, opts = {})
|
113
|
-
|
123
|
+
properties[name] = opts
|
114
124
|
|
115
125
|
# property
|
116
126
|
define_method(name) do
|
117
|
-
|
118
|
-
|
127
|
+
# Load only when not loaded or id property
|
128
|
+
load! unless loaded? || name == :id
|
129
|
+
|
130
|
+
instance_variable_get(:"@#{name}")
|
119
131
|
end
|
120
132
|
|
121
133
|
# property?
|
122
134
|
define_method("#{name}?") do
|
123
|
-
|
124
|
-
|
125
|
-
property = instance_variable_get("@#{name}")
|
126
|
-
property.respond_to?(:empty?) ? !property.empty? : !property.nil?
|
135
|
+
send(name).present?
|
127
136
|
end
|
128
137
|
|
129
138
|
# property=
|
130
139
|
define_method("#{name}=") do |value|
|
131
|
-
if value.nil?
|
132
|
-
instance_variable_set "@#{name}", value
|
133
|
-
return
|
134
|
-
end
|
140
|
+
return instance_variable_set(:"@#{name}", value) if value.nil?
|
135
141
|
|
136
142
|
# Check value type
|
137
143
|
type = opts[:type] || String
|
138
144
|
if opts[:multiple]
|
139
|
-
raise
|
145
|
+
raise Errors::TypeError, "invalid type #{value.class}, must be Array for #{name}" unless value.is_a? Array
|
140
146
|
|
141
147
|
value.each do |val|
|
142
|
-
raise
|
148
|
+
raise Errors::TypeError, "invalid type #{val.class}, must be #{type} for #{name}" unless val.is_a? type
|
143
149
|
end
|
144
150
|
else
|
145
|
-
raise
|
151
|
+
raise Errors::TypeError, "invalid type #{value.class}, must be #{type} for #{name}" unless value.is_a? type
|
146
152
|
end
|
147
153
|
|
148
|
-
instance_variable_set
|
154
|
+
instance_variable_set(:"@#{name}", value)
|
149
155
|
end
|
150
156
|
end
|
151
157
|
|
@@ -166,19 +172,20 @@ module MetalArchives
|
|
166
172
|
def enum(name, opts)
|
167
173
|
raise ArgumentError, "opts[:values] is required" unless opts && opts[:values]
|
168
174
|
|
169
|
-
|
175
|
+
properties[name] = opts
|
170
176
|
|
171
177
|
# property
|
172
178
|
define_method(name) do
|
173
|
-
load! unless loaded?
|
174
|
-
|
179
|
+
load! unless loaded?
|
180
|
+
|
181
|
+
instance_variable_get(:"@#{name}")
|
175
182
|
end
|
176
183
|
|
177
184
|
# property?
|
178
185
|
define_method("#{name}?") do
|
179
186
|
load! unless loaded? && instance_variable_defined?("@#{name}")
|
180
187
|
|
181
|
-
property = instance_variable_get("@#{name}")
|
188
|
+
property = instance_variable_get(:"@#{name}")
|
182
189
|
property.respond_to?(:empty?) ? !property.empty? : !property.nil?
|
183
190
|
end
|
184
191
|
|
@@ -186,16 +193,16 @@ module MetalArchives
|
|
186
193
|
define_method("#{name}=") do |value|
|
187
194
|
# Check enum type
|
188
195
|
if opts[:multiple]
|
189
|
-
raise
|
196
|
+
raise Errors::TypeError, "invalid enum value #{value}, must be Array for #{name}" unless value.is_a? Array
|
190
197
|
|
191
198
|
value.each do |val|
|
192
|
-
raise
|
199
|
+
raise Errors::TypeError, "invalid enum value #{val} for #{name}" unless opts[:values].include? val
|
193
200
|
end
|
194
201
|
else
|
195
|
-
raise
|
202
|
+
raise Errors::TypeError, "invalid enum value #{value} for #{name}" unless opts[:values].include? value
|
196
203
|
end
|
197
204
|
|
198
|
-
instance_variable_set
|
205
|
+
instance_variable_set(:"@#{name}", value)
|
199
206
|
end
|
200
207
|
end
|
201
208
|
|