metal_archives 2.1.1 → 3.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
##
|