metal_archives 2.1.1 → 3.1.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/.github/workflows/ci.yml +93 -0
- data/.gitignore +6 -6
- data/.overcommit.yml +35 -0
- data/.rspec +2 -0
- data/.rubocop.yml +69 -6
- data/CHANGELOG.md +29 -0
- data/Gemfile +1 -1
- data/LICENSE.md +17 -4
- data/README.md +65 -86
- data/Rakefile +8 -7
- data/bin/console +38 -0
- data/bin/setup +8 -0
- data/config/inflections.rb +7 -0
- data/config/initializers/.keep +0 -0
- data/docker-compose.yml +23 -0
- data/lib/metal_archives.rb +82 -25
- 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/{utils/collection.rb → collection.rb} +3 -5
- data/lib/metal_archives/configuration.rb +33 -50
- data/lib/metal_archives/{error.rb → errors.rb} +9 -1
- data/lib/metal_archives/http_client.rb +45 -44
- data/lib/metal_archives/models/artist.rb +90 -45
- data/lib/metal_archives/models/band.rb +80 -55
- data/lib/metal_archives/models/base.rb +218 -0
- data/lib/metal_archives/models/label.rb +14 -15
- data/lib/metal_archives/models/release.rb +349 -0
- data/lib/metal_archives/parsers/artist.rb +86 -50
- data/lib/metal_archives/parsers/band.rb +155 -88
- 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 +39 -31
- data/lib/metal_archives/parsers/parser.rb +16 -63
- data/lib/metal_archives/parsers/release.rb +242 -0
- data/lib/metal_archives/parsers/year.rb +29 -0
- data/lib/metal_archives/version.rb +12 -1
- data/metal_archives.env.example +10 -0
- data/metal_archives.gemspec +43 -28
- data/nginx/default.conf +60 -0
- metadata +181 -72
- data/.travis.yml +0 -12
- data/lib/metal_archives/middleware/cache_check.rb +0 -20
- 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/models/base_model.rb +0 -215
- data/lib/metal_archives/utils/lru_cache.rb +0 -61
- data/lib/metal_archives/utils/nil_date.rb +0 -99
- data/lib/metal_archives/utils/range.rb +0 -66
- data/spec/configuration_spec.rb +0 -96
- data/spec/factories/artist_factory.rb +0 -37
- data/spec/factories/band_factory.rb +0 -60
- data/spec/factories/nil_date_factory.rb +0 -9
- data/spec/factories/range_factory.rb +0 -8
- data/spec/models/artist_spec.rb +0 -138
- data/spec/models/band_spec.rb +0 -164
- data/spec/models/base_model_spec.rb +0 -219
- data/spec/parser_spec.rb +0 -19
- data/spec/spec_helper.rb +0 -111
- data/spec/support/factory_girl.rb +0 -5
- data/spec/support/metal_archives.rb +0 -33
- data/spec/utils/collection_spec.rb +0 -72
- data/spec/utils/lru_cache_spec.rb +0 -53
- data/spec/utils/nil_date_spec.rb +0 -156
- data/spec/utils/range_spec.rb +0 -62
@@ -32,7 +32,15 @@ module MetalArchives
|
|
32
32
|
##
|
33
33
|
# Error in backend response
|
34
34
|
#
|
35
|
-
class APIError < Error
|
35
|
+
class APIError < Error
|
36
|
+
attr_reader :code
|
37
|
+
|
38
|
+
def initialize(response)
|
39
|
+
super("#{response.reason}: #{response.body}")
|
40
|
+
|
41
|
+
@code = response.code
|
42
|
+
end
|
43
|
+
end
|
36
44
|
|
37
45
|
##
|
38
46
|
# Error in method argument
|
@@ -1,61 +1,62 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require 'faraday_throttler'
|
3
|
+
require "http"
|
5
4
|
|
6
5
|
module MetalArchives
|
7
6
|
##
|
8
|
-
# HTTP
|
7
|
+
# Generic HTTP client
|
9
8
|
#
|
10
|
-
class HTTPClient
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
9
|
+
class HTTPClient
|
10
|
+
attr_reader :endpoint, :metrics
|
11
|
+
|
12
|
+
def initialize(endpoint = MetalArchives.config.endpoint)
|
13
|
+
@endpoint = endpoint
|
14
|
+
@metrics = { hit: 0, miss: 0 }
|
15
|
+
end
|
16
|
+
|
17
|
+
def get(path, params = {})
|
18
|
+
response = http
|
19
|
+
.get(url_for(path), params: params)
|
20
|
+
|
21
|
+
# Log cache status
|
22
|
+
status = response.headers["x-cache-status"]&.downcase&.to_sym
|
23
|
+
MetalArchives.config.logger.info "Cache #{status} for #{path}" if status
|
24
|
+
|
25
|
+
case status
|
26
|
+
when :hit
|
27
|
+
metrics[:hit] += 1
|
28
|
+
when :miss, :bypass, :expired, :stale, :updating, :revalidated
|
29
|
+
metrics[:miss] += 1
|
29
30
|
end
|
31
|
+
raise Errors::InvalidIDError, response if response.code == 404
|
32
|
+
raise Errors::APIError, response unless response.status.success?
|
30
33
|
|
31
|
-
|
34
|
+
response
|
35
|
+
end
|
32
36
|
|
33
|
-
|
34
|
-
# Retrieve a HTTP client
|
35
|
-
#
|
36
|
-
#
|
37
|
-
def client
|
38
|
-
raise Errors::InvalidConfigurationError, 'Not configured yet' unless MetalArchives.config
|
37
|
+
private
|
39
38
|
|
40
|
-
|
41
|
-
|
42
|
-
|
39
|
+
def http
|
40
|
+
@http ||= HTTP
|
41
|
+
.headers(headers)
|
42
|
+
.use(logging: { logger: MetalArchives.config.logger })
|
43
|
+
.encoding("utf-8")
|
43
44
|
|
44
|
-
|
45
|
-
f.use MetalArchives::Middleware::CacheCheck
|
46
|
-
f.use MetalArchives::Middleware::RewriteEndpoint
|
47
|
-
f.use MetalArchives::Middleware::Encoding
|
45
|
+
return @http unless MetalArchives.config.endpoint_user && MetalArchives.config.endpoint_password
|
48
46
|
|
49
|
-
|
47
|
+
@http
|
48
|
+
.basic_auth(user: MetalArchives.config.endpoint_user, pass: MetalArchives.config.endpoint_password)
|
49
|
+
end
|
50
50
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
51
|
+
def headers
|
52
|
+
{
|
53
|
+
user_agent: "#{MetalArchives.config.app_name}/#{MetalArchives.config.app_version} (#{MetalArchives.config.app_contact})",
|
54
|
+
accept: "application/json",
|
55
|
+
}
|
56
|
+
end
|
55
57
|
|
56
|
-
|
57
|
-
|
58
|
-
end
|
58
|
+
def url_for(path)
|
59
|
+
"#{endpoint}#{path}"
|
59
60
|
end
|
60
61
|
end
|
61
62
|
end
|
@@ -1,19 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "date"
|
4
|
+
require "countries"
|
5
|
+
require "nokogiri"
|
5
6
|
|
6
7
|
module MetalArchives
|
7
8
|
##
|
8
9
|
# Represents a single performer (but not a solo artist)
|
9
10
|
#
|
10
|
-
class Artist <
|
11
|
+
class Artist < Base
|
11
12
|
##
|
12
13
|
# :attr_reader: id
|
13
14
|
#
|
14
15
|
# Returns +Integer+
|
15
16
|
#
|
16
|
-
property :id, :
|
17
|
+
property :id, type: Integer
|
17
18
|
|
18
19
|
##
|
19
20
|
# :attr_reader: name
|
@@ -35,7 +36,7 @@ module MetalArchives
|
|
35
36
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
36
37
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
37
38
|
#
|
38
|
-
property :aliases, :
|
39
|
+
property :aliases, multiple: true
|
39
40
|
|
40
41
|
##
|
41
42
|
# :attr_reader: country
|
@@ -46,7 +47,7 @@ module MetalArchives
|
|
46
47
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
47
48
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
48
49
|
#
|
49
|
-
property :country, :
|
50
|
+
property :country, type: ISO3166::Country
|
50
51
|
|
51
52
|
##
|
52
53
|
# :attr_reader: location
|
@@ -62,24 +63,24 @@ module MetalArchives
|
|
62
63
|
##
|
63
64
|
# :attr_reader: date_of_birth
|
64
65
|
#
|
65
|
-
# Returns rdoc-ref:
|
66
|
+
# Returns rdoc-ref:Date
|
66
67
|
#
|
67
68
|
# [Raises]
|
68
69
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
69
70
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
70
71
|
#
|
71
|
-
property :date_of_birth, :
|
72
|
+
property :date_of_birth, type: Date
|
72
73
|
|
73
74
|
##
|
74
75
|
# :attr_reader: date_of_death
|
75
76
|
#
|
76
|
-
# Returns rdoc-ref:
|
77
|
+
# Returns rdoc-ref:Date
|
77
78
|
#
|
78
79
|
# [Raises]
|
79
80
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
80
81
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
81
82
|
#
|
82
|
-
property :date_of_death, :
|
83
|
+
property :date_of_death, type: Date
|
83
84
|
|
84
85
|
##
|
85
86
|
# :attr_reader: cause_of_death
|
@@ -101,7 +102,7 @@ module MetalArchives
|
|
101
102
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
102
103
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
103
104
|
#
|
104
|
-
enum :gender, :
|
105
|
+
enum :gender, values: [:male, :female]
|
105
106
|
|
106
107
|
##
|
107
108
|
# :attr_reader: biography
|
@@ -145,17 +146,67 @@ module MetalArchives
|
|
145
146
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
146
147
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
147
148
|
#
|
148
|
-
# [+
|
149
|
+
# [+links+]
|
149
150
|
# - +:url+: +String+
|
150
151
|
# - +:type+: +Symbol+, either +:official+, +:unofficial+ or +:unlisted_bands+
|
151
152
|
# - +:title+: +String+
|
152
153
|
#
|
153
|
-
property :links, :
|
154
|
+
property :links, multiple: true
|
154
155
|
|
155
|
-
|
156
|
-
#
|
157
|
-
#
|
158
|
-
#
|
156
|
+
##
|
157
|
+
# :attr_reader: bands
|
158
|
+
#
|
159
|
+
# Returns +Array+ of +Hash+ containing the following keys
|
160
|
+
#
|
161
|
+
# [Raises]
|
162
|
+
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
163
|
+
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
164
|
+
#
|
165
|
+
# [+bands+]
|
166
|
+
# - +:band+: rdoc-ref:Band
|
167
|
+
# - +:active+: Boolean
|
168
|
+
# - +:years_active+: +Array+ of rdoc-ref:Range containing +Integer+
|
169
|
+
# - +:role+: +String+
|
170
|
+
#
|
171
|
+
property :bands, type: Hash, multiple: true
|
172
|
+
|
173
|
+
# TODO: guest/session bands
|
174
|
+
# TODO: misc bands
|
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
|
159
210
|
|
160
211
|
protected
|
161
212
|
|
@@ -168,28 +219,24 @@ module MetalArchives
|
|
168
219
|
#
|
169
220
|
def assemble # :nodoc:
|
170
221
|
## Base attributes
|
171
|
-
|
172
|
-
response = HTTPClient.get url
|
222
|
+
response = MetalArchives.http.get "/artist/view/id/#{id}"
|
173
223
|
|
174
|
-
properties = Parsers::Artist.parse_html response.
|
224
|
+
properties = Parsers::Artist.parse_html response.to_s
|
175
225
|
|
176
226
|
## Biography
|
177
|
-
|
178
|
-
response = HTTPClient.get url
|
227
|
+
response = MetalArchives.http.get "/artist/read-more/id/#{id}/field/biography"
|
179
228
|
|
180
|
-
properties[:biography] = response.
|
229
|
+
properties[:biography] = response.to_s
|
181
230
|
|
182
231
|
## Trivia
|
183
|
-
|
184
|
-
response = HTTPClient.get url
|
232
|
+
response = MetalArchives.http.get "/artist/read-more/id/#{id}/field/trivia"
|
185
233
|
|
186
|
-
properties[:trivia] = response.
|
234
|
+
properties[:trivia] = response.to_s
|
187
235
|
|
188
236
|
## Related links
|
189
|
-
|
190
|
-
response = HTTPClient.get url
|
237
|
+
response = MetalArchives.http.get "/link/ajax-list/type/person/id/#{id}"
|
191
238
|
|
192
|
-
properties[:links] = Parsers::Artist.parse_links_html response.
|
239
|
+
properties[:links] = Parsers::Artist.parse_links_html response.to_s
|
193
240
|
|
194
241
|
properties
|
195
242
|
end
|
@@ -204,9 +251,9 @@ module MetalArchives
|
|
204
251
|
# +Integer+
|
205
252
|
#
|
206
253
|
def find(id)
|
207
|
-
return cache[id] if cache.include? id
|
254
|
+
return MetalArchives.cache[id] if MetalArchives.cache.include? id
|
208
255
|
|
209
|
-
Artist.new :
|
256
|
+
Artist.new id: id
|
210
257
|
end
|
211
258
|
|
212
259
|
##
|
@@ -246,16 +293,15 @@ module MetalArchives
|
|
246
293
|
def find_by(query)
|
247
294
|
raise MetalArchives::Errors::ArgumentError unless query.include? :name
|
248
295
|
|
249
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-artist-search/"
|
250
296
|
params = Parsers::Artist.map_params query
|
251
297
|
|
252
|
-
response =
|
253
|
-
json = JSON.parse response.
|
298
|
+
response = MetalArchives.http.get "/search/ajax-artist-search/", params
|
299
|
+
json = JSON.parse response.to_s
|
254
300
|
|
255
|
-
return nil if json[
|
301
|
+
return nil if json["aaData"].empty?
|
256
302
|
|
257
|
-
data = json[
|
258
|
-
id = Nokogiri::HTML(data.first).xpath(
|
303
|
+
data = json["aaData"].first
|
304
|
+
id = Nokogiri::HTML(data.first).xpath("//a/@href").first.value.delete('\\').split("/").last.gsub(/\D/, "").to_i
|
259
305
|
|
260
306
|
find id
|
261
307
|
end
|
@@ -298,8 +344,7 @@ module MetalArchives
|
|
298
344
|
def search(name)
|
299
345
|
raise MetalArchives::Errors::ArgumentError unless name.is_a? String
|
300
346
|
|
301
|
-
|
302
|
-
query = { :name => name }
|
347
|
+
query = { name: name }
|
303
348
|
|
304
349
|
params = Parsers::Artist.map_params query
|
305
350
|
|
@@ -309,16 +354,16 @@ module MetalArchives
|
|
309
354
|
if @max_items && @start >= @max_items
|
310
355
|
[]
|
311
356
|
else
|
312
|
-
response =
|
313
|
-
json = JSON.parse response.
|
357
|
+
response = MetalArchives.http.get "/search/ajax-artist-search/", params.merge(iDisplayStart: @start)
|
358
|
+
json = JSON.parse response.to_s
|
314
359
|
|
315
|
-
@max_items = json[
|
360
|
+
@max_items = json["iTotalRecords"]
|
316
361
|
|
317
362
|
objects = []
|
318
363
|
|
319
|
-
json[
|
364
|
+
json["aaData"].each do |data|
|
320
365
|
# Create Artist object for every ID in the results list
|
321
|
-
id = Nokogiri::HTML(data.first).xpath(
|
366
|
+
id = Nokogiri::HTML(data.first).xpath("//a/@href").first.value.delete('\\').split("/").last.gsub(/\D/, "").to_i
|
322
367
|
objects << Artist.find(id)
|
323
368
|
end
|
324
369
|
|
@@ -341,7 +386,7 @@ module MetalArchives
|
|
341
386
|
# - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
|
342
387
|
#
|
343
388
|
def all
|
344
|
-
search
|
389
|
+
search ""
|
345
390
|
end
|
346
391
|
end
|
347
392
|
end
|
@@ -1,19 +1,20 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
3
|
+
require "date"
|
4
|
+
require "countries"
|
5
|
+
require "nokogiri"
|
5
6
|
|
6
7
|
module MetalArchives
|
7
8
|
##
|
8
9
|
# Represents an band (person or group)
|
9
10
|
#
|
10
|
-
class Band <
|
11
|
+
class Band < Base
|
11
12
|
##
|
12
13
|
# :attr_reader: id
|
13
14
|
#
|
14
15
|
# Returns +Integer+
|
15
16
|
#
|
16
|
-
property :id, :
|
17
|
+
property :id, type: Integer
|
17
18
|
|
18
19
|
##
|
19
20
|
# :attr_reader: name
|
@@ -35,7 +36,7 @@ module MetalArchives
|
|
35
36
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
36
37
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
37
38
|
#
|
38
|
-
property :aliases, :
|
39
|
+
property :aliases, multiple: true
|
39
40
|
|
40
41
|
##
|
41
42
|
# :attr_reader: country
|
@@ -46,7 +47,7 @@ module MetalArchives
|
|
46
47
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
47
48
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
48
49
|
#
|
49
|
-
property :country, :
|
50
|
+
property :country, type: ISO3166::Country
|
50
51
|
|
51
52
|
##
|
52
53
|
# :attr_reader: location
|
@@ -62,24 +63,24 @@ module MetalArchives
|
|
62
63
|
##
|
63
64
|
# :attr_reader: date_formed
|
64
65
|
#
|
65
|
-
# Returns rdoc-ref:
|
66
|
+
# Returns rdoc-ref:Date
|
66
67
|
#
|
67
68
|
# [Raises]
|
68
69
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
69
70
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
70
71
|
#
|
71
|
-
property :date_formed, :
|
72
|
+
property :date_formed, type: Date
|
72
73
|
|
73
74
|
##
|
74
|
-
# :attr_reader:
|
75
|
+
# :attr_reader: years_active
|
75
76
|
#
|
76
|
-
# Returns +Array+ of rdoc-ref:Range
|
77
|
+
# Returns +Array+ of rdoc-ref:Range containing +Integer+
|
77
78
|
#
|
78
79
|
# [Raises]
|
79
80
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
80
81
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
81
82
|
#
|
82
|
-
property :
|
83
|
+
property :years_active, type: Range, multiple: true
|
83
84
|
|
84
85
|
##
|
85
86
|
# :attr_reader: genres
|
@@ -90,7 +91,7 @@ module MetalArchives
|
|
90
91
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
91
92
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
92
93
|
#
|
93
|
-
property :genres, :
|
94
|
+
property :genres, multiple: true
|
94
95
|
|
95
96
|
##
|
96
97
|
# :attr_reader: lyrical_themes
|
@@ -101,7 +102,7 @@ module MetalArchives
|
|
101
102
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
102
103
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
103
104
|
#
|
104
|
-
property :lyrical_themes, :
|
105
|
+
property :lyrical_themes, multiple: true
|
105
106
|
|
106
107
|
##
|
107
108
|
# :attr_reader: label
|
@@ -112,7 +113,7 @@ module MetalArchives
|
|
112
113
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
113
114
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
114
115
|
#
|
115
|
-
property :label, :
|
116
|
+
property :label, type: Label
|
116
117
|
|
117
118
|
##
|
118
119
|
# :attr_reader: independent
|
@@ -123,7 +124,7 @@ module MetalArchives
|
|
123
124
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
124
125
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
125
126
|
#
|
126
|
-
enum :independent, :
|
127
|
+
enum :independent, values: [true, false]
|
127
128
|
|
128
129
|
##
|
129
130
|
# :attr_reader: comment
|
@@ -145,10 +146,35 @@ module MetalArchives
|
|
145
146
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
146
147
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
147
148
|
#
|
148
|
-
enum :status, :
|
149
|
+
enum :status, values: [:active, :split_up, :on_hold, :unknown, :changed_name, :disputed]
|
149
150
|
|
150
|
-
|
151
|
-
#
|
151
|
+
##
|
152
|
+
# :attr_reader: releases
|
153
|
+
#
|
154
|
+
# Returns +Array+ of rdoc-ref:Release
|
155
|
+
#
|
156
|
+
# [Raises]
|
157
|
+
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
158
|
+
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
159
|
+
#
|
160
|
+
property :releases, type: Release, multiple: true
|
161
|
+
|
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
|
152
178
|
|
153
179
|
##
|
154
180
|
# :attr_reader: similar
|
@@ -163,7 +189,7 @@ module MetalArchives
|
|
163
189
|
# - +:band+: rdoc-ref:Band
|
164
190
|
# - +:score+: +Integer+
|
165
191
|
#
|
166
|
-
property :similar, :
|
192
|
+
property :similar, type: Hash, multiple: true
|
167
193
|
|
168
194
|
##
|
169
195
|
# :attr_reader: logo
|
@@ -196,12 +222,12 @@ module MetalArchives
|
|
196
222
|
# - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
|
197
223
|
# - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
|
198
224
|
#
|
199
|
-
# [+
|
225
|
+
# [+links+]
|
200
226
|
# - +:url+: +String+
|
201
227
|
# - +:type+: +Symbol+, either +:official+ or +:merchandise+
|
202
228
|
# - +:title+: +String+
|
203
229
|
#
|
204
|
-
property :links, :
|
230
|
+
property :links, multiple: true
|
205
231
|
|
206
232
|
protected
|
207
233
|
|
@@ -214,28 +240,29 @@ module MetalArchives
|
|
214
240
|
#
|
215
241
|
def assemble # :nodoc:
|
216
242
|
## Base attributes
|
217
|
-
|
218
|
-
response = HTTPClient.get url
|
243
|
+
response = MetalArchives.http.get "/band/view/id/#{id}"
|
219
244
|
|
220
|
-
properties = Parsers::Band.parse_html response.
|
245
|
+
properties = Parsers::Band.parse_html response.to_s
|
221
246
|
|
222
247
|
## Comment
|
223
|
-
|
224
|
-
response = HTTPClient.get url
|
248
|
+
response = MetalArchives.http.get "/band/read-more/id/#{id}"
|
225
249
|
|
226
|
-
properties[:comment] = response.
|
250
|
+
properties[:comment] = response.to_s
|
227
251
|
|
228
252
|
## Similar artists
|
229
|
-
|
230
|
-
response = HTTPClient.get url
|
253
|
+
response = MetalArchives.http.get "/band/ajax-recommendations/id/#{id}"
|
231
254
|
|
232
|
-
properties[:similar] = Parsers::Band.parse_similar_bands_html response.
|
255
|
+
properties[:similar] = Parsers::Band.parse_similar_bands_html response.to_s
|
233
256
|
|
234
257
|
## Related links
|
235
|
-
|
236
|
-
|
258
|
+
response = MetalArchives.http.get "/link/ajax-list/type/band/id/#{id}"
|
259
|
+
|
260
|
+
properties[:links] = Parsers::Band.parse_related_links_html response.to_s
|
261
|
+
|
262
|
+
## Releases
|
263
|
+
response = MetalArchives.http.get "/band/discography/id/#{id}/tab/all"
|
237
264
|
|
238
|
-
properties[:
|
265
|
+
properties[:releases] = Parsers::Band.parse_releases_html response.to_s
|
239
266
|
|
240
267
|
properties
|
241
268
|
end
|
@@ -250,9 +277,9 @@ module MetalArchives
|
|
250
277
|
# +Integer+
|
251
278
|
#
|
252
279
|
def find(id)
|
253
|
-
return cache[id] if cache.include? id
|
280
|
+
return MetalArchives.cache[id] if MetalArchives.cache.include? id
|
254
281
|
|
255
|
-
Band.new :
|
282
|
+
Band.new id: id
|
256
283
|
end
|
257
284
|
|
258
285
|
##
|
@@ -291,8 +318,8 @@ module MetalArchives
|
|
291
318
|
# - +:name+: +String+
|
292
319
|
# - +:exact+: +Boolean+
|
293
320
|
# - +:genre+: +String+
|
294
|
-
# - +:country+: +
|
295
|
-
# - +:year_formation+: rdoc-ref:Range
|
321
|
+
# - +:country+: +ISO3166::Country+
|
322
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
296
323
|
# - +:comment+: +String+
|
297
324
|
# - +:status+: see rdoc-ref:Band.status
|
298
325
|
# - +:lyrical_themes+: +String+
|
@@ -301,16 +328,15 @@ module MetalArchives
|
|
301
328
|
# - +:independent+: boolean
|
302
329
|
#
|
303
330
|
def find_by(query)
|
304
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/bands"
|
305
331
|
params = Parsers::Band.map_params query
|
306
332
|
|
307
|
-
response =
|
308
|
-
json = JSON.parse response.
|
333
|
+
response = MetalArchives.http.get "/search/ajax-advanced/searching/bands", params
|
334
|
+
json = JSON.parse response.to_s
|
309
335
|
|
310
|
-
return nil if json[
|
336
|
+
return nil if json["aaData"].empty?
|
311
337
|
|
312
|
-
data = json[
|
313
|
-
id = Nokogiri::HTML(data.first).xpath(
|
338
|
+
data = json["aaData"].first
|
339
|
+
id = Nokogiri::HTML(data.first).xpath("//a/@href").first.value.delete('\\').split("/").last.gsub(/\D/, "").to_i
|
314
340
|
|
315
341
|
find id
|
316
342
|
end
|
@@ -331,8 +357,8 @@ module MetalArchives
|
|
331
357
|
# - +:name+: +String+
|
332
358
|
# - +:exact+: +Boolean+
|
333
359
|
# - +:genre+: +String+
|
334
|
-
# - +:country+: +
|
335
|
-
# - +:year_formation+: rdoc-ref:Range
|
360
|
+
# - +:country+: +ISO3166::Country+
|
361
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
336
362
|
# - +:comment+: +String+
|
337
363
|
# - +:status+: see rdoc-ref:Band.status
|
338
364
|
# - +:lyrical_themes+: +String+
|
@@ -363,8 +389,8 @@ module MetalArchives
|
|
363
389
|
# - +:name+: +String+
|
364
390
|
# - +:exact+: +Boolean+
|
365
391
|
# - +:genre+: +String+
|
366
|
-
# - +:country+: +
|
367
|
-
# - +:year_formation+: rdoc-ref:Range
|
392
|
+
# - +:country+: +ISO3166::Country+
|
393
|
+
# - +:year_formation+: rdoc-ref:Range containing rdoc-ref:Date
|
368
394
|
# - +:comment+: +String+
|
369
395
|
# - +:status+: see rdoc-ref:Band.status
|
370
396
|
# - +:lyrical_themes+: +String+
|
@@ -373,8 +399,6 @@ module MetalArchives
|
|
373
399
|
# - +:independent+: boolean
|
374
400
|
#
|
375
401
|
def search_by(query)
|
376
|
-
url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/bands"
|
377
|
-
|
378
402
|
params = Parsers::Band.map_params query
|
379
403
|
|
380
404
|
l = lambda do
|
@@ -383,16 +407,16 @@ module MetalArchives
|
|
383
407
|
if @max_items && @start >= @max_items
|
384
408
|
[]
|
385
409
|
else
|
386
|
-
response =
|
387
|
-
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
|
388
412
|
|
389
|
-
@max_items = json[
|
413
|
+
@max_items = json["iTotalRecords"]
|
390
414
|
|
391
415
|
objects = []
|
392
416
|
|
393
|
-
json[
|
417
|
+
json["aaData"].each do |data|
|
394
418
|
# Create Band object for every ID in the results list
|
395
|
-
id = Nokogiri::HTML(data.first).xpath(
|
419
|
+
id = Nokogiri::HTML(data.first).xpath("//a/@href").first.value.delete('\\').split("/").last.gsub(/\D/, "").to_i
|
396
420
|
objects << Band.find(id)
|
397
421
|
end
|
398
422
|
|
@@ -421,7 +445,8 @@ module MetalArchives
|
|
421
445
|
#
|
422
446
|
def search(name)
|
423
447
|
raise MetalArchives::Errors::ArgumentError unless name.is_a? String
|
424
|
-
|
448
|
+
|
449
|
+
search_by name: name
|
425
450
|
end
|
426
451
|
|
427
452
|
##
|