metal_archives 2.1.1 → 2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5b077092f1a7e727aee29d04339faf31468b704b
4
- data.tar.gz: 00674c9f439ba8c1f8a014cd60c4da6ec5289e22
3
+ metadata.gz: 3d67ee1fe72c3fb58bf95f48ee68bda41232857e
4
+ data.tar.gz: cfa4704bb7020f4176ad6a14de0b979249e11976
5
5
  SHA512:
6
- metadata.gz: 9217a15df5ae47a552a8214fba23a374bb9788611103d0366078aff6e72069505bf2d43fcfc0c437624aae8bbf3f9a342bbcfa67abd512ed712473a51dc56a9b
7
- data.tar.gz: 22a44ac5667e462eab891c019c98f17340e2469ffa7ff71d79e5f6dc9b6d6a5eb5482ef10fcba9f0b4a320ad9fb9795d32f7df7b4122dd463bb865192613e6b2
6
+ metadata.gz: be9295ee982e7600ad2aba6f5a9ae60fdcdcb5db1039e51a76c18a2fedc53e7899e3ee3c068763c171a3a7a232cbca325d3885d07f1598c4852f73ba7c4b5e17
7
+ data.tar.gz: 7a121ab78954206854de8d73d1131030684864dccc68c53429ddc2054cb6cc836b7014b5f8044778992bcd27317caa2f8da0f6c020c4a7f72ae848fd1b84aa39
@@ -1,6 +1,9 @@
1
1
  Metrics/LineLength:
2
2
  Max: 120
3
3
 
4
+ Metrics/ClassLength:
5
+ Enabled: false
6
+
4
7
  Metrics/MethodLength:
5
8
  Enabled: false
6
9
 
@@ -20,11 +20,13 @@ require 'metal_archives/models/base_model'
20
20
  require 'metal_archives/models/label'
21
21
  require 'metal_archives/models/artist'
22
22
  require 'metal_archives/models/band'
23
+ require 'metal_archives/models/release'
23
24
 
24
25
  require 'metal_archives/parsers/parser'
25
26
  require 'metal_archives/parsers/label'
26
27
  require 'metal_archives/parsers/artist'
27
28
  require 'metal_archives/parsers/band'
29
+ require 'metal_archives/parsers/release'
28
30
 
29
31
  require 'metal_archives/http_client'
30
32
 
@@ -291,7 +291,7 @@ module MetalArchives
291
291
  # - +:name+: +String+
292
292
  # - +:exact+: +Boolean+
293
293
  # - +:genre+: +String+
294
- # - +:country+: +ISO366::Country+
294
+ # - +:country+: +ISO3166::Country+
295
295
  # - +:year_formation+: rdoc-ref:Range of rdoc-ref:NilDate
296
296
  # - +:comment+: +String+
297
297
  # - +:status+: see rdoc-ref:Band.status
@@ -331,7 +331,7 @@ module MetalArchives
331
331
  # - +:name+: +String+
332
332
  # - +:exact+: +Boolean+
333
333
  # - +:genre+: +String+
334
- # - +:country+: +ISO366::Country+
334
+ # - +:country+: +ISO3166::Country+
335
335
  # - +:year_formation+: rdoc-ref:Range of +Date+
336
336
  # - +:comment+: +String+
337
337
  # - +:status+: see rdoc-ref:Band.status
@@ -363,7 +363,7 @@ module MetalArchives
363
363
  # - +:name+: +String+
364
364
  # - +:exact+: +Boolean+
365
365
  # - +:genre+: +String+
366
- # - +:country+: +ISO366::Country+
366
+ # - +:country+: +ISO3166::Country+
367
367
  # - +:year_formation+: rdoc-ref:Range of +Date+
368
368
  # - +:comment+: +String+
369
369
  # - +:status+: see rdoc-ref:Band.status
@@ -0,0 +1,353 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'date'
4
+
5
+ module MetalArchives
6
+ ##
7
+ # Represents a release
8
+ #
9
+ class Release < MetalArchives::BaseModel
10
+ ##
11
+ # :attr_reader: id
12
+ #
13
+ # Returns +Integer+
14
+ #
15
+ property :id, :type => Integer
16
+
17
+ ##
18
+ # :attr_reader: title
19
+ #
20
+ # Returns +String+
21
+ #
22
+ # [Raises]
23
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
24
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
25
+ #
26
+ property :title
27
+
28
+ # TODO: band
29
+
30
+ ##
31
+ # :attr_reader: type
32
+ #
33
+ # Returns +:full_length+, +:live+, +:demo+, +:single+, +:ep+, +:video+, +:boxed_set+, +:split+, +:compilation+, +:split_video+, +:collaboration+
34
+ #
35
+ # [Raises]
36
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
37
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
38
+ #
39
+ enum :type, :values => %i[full_length live demo single ep video boxed_set split compilation split_video collaboration]
40
+
41
+ ##
42
+ # :attr_reader: date_released
43
+ #
44
+ # Returns rdoc-ref:NilDate
45
+ #
46
+ # [Raises]
47
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
48
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
49
+ #
50
+ property :date_released, :type => NilDate
51
+
52
+ ##
53
+ # :attr_reader_: catalog_id
54
+ #
55
+ # Return +String+
56
+ #
57
+ # [Raises]
58
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
59
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
60
+ #
61
+ property :catalog_id
62
+
63
+ ##
64
+ # :attr_reader_: version_description
65
+ #
66
+ # Return +String+
67
+ #
68
+ # [Raises]
69
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
70
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
71
+ #
72
+ property :version_description
73
+
74
+ # TODO: label
75
+
76
+ ##
77
+ # :attr_reader: format
78
+ #
79
+ # Returns +:cd+, +:cassette+, +:vinyl+, +:vhs+, +:dvd+, +:digital+, +:blu_ray+, +:other+
80
+ #
81
+ # [Raises]
82
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
83
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
84
+ #
85
+ property :format
86
+
87
+ ##
88
+ # :attr_reader: limitation
89
+ #
90
+ # Returns +Integer+
91
+ #
92
+ # [Raises]
93
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
94
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
95
+ #
96
+ property :limitation
97
+
98
+ # TODO: reviews
99
+ # TODO: songs
100
+ # TODO: lineup
101
+ # TODO: other versions
102
+ # TODO: links
103
+
104
+ ##
105
+ # :attr_reader: notes
106
+ #
107
+ # Returns raw HTML +String+
108
+ #
109
+ # [Raises]
110
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
111
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
112
+ #
113
+ property :notes
114
+
115
+ protected
116
+
117
+ ##
118
+ # Fetch the data and assemble the model
119
+ #
120
+ # [Raises]
121
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when receiving a status code == 404
122
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
123
+ #
124
+ def assemble # :nodoc:
125
+ ## Base attributes
126
+ url = "#{MetalArchives.config.default_endpoint}albums/view/id/#{id}"
127
+ response = HTTPClient.get url
128
+
129
+ properties = Parsers::Release.parse_html response.body
130
+
131
+ properties
132
+ end
133
+
134
+ class << self
135
+ ##
136
+ # Find by ID
137
+ #
138
+ # Returns rdoc-ref:Release, even when ID is invalid (because the data is lazily fetched)
139
+ #
140
+ # [+id+]
141
+ # +Integer+
142
+ #
143
+ def find(id)
144
+ return cache[id] if cache.include? id
145
+
146
+ Release.new :id => id
147
+ end
148
+
149
+ ##
150
+ # Find by ID (no lazy loading)
151
+ #
152
+ # Returns rdoc-ref:Release
153
+ #
154
+ # [Raises]
155
+ # - rdoc-ref:MetalArchives::Errors::InvalidIDError when no or invalid id
156
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400 (except 404)
157
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
158
+ #
159
+ # [+id+]
160
+ # +Integer+
161
+ #
162
+ def find!(id)
163
+ obj = find id
164
+ obj.load! if obj && !obj.loaded?
165
+
166
+ obj
167
+ end
168
+
169
+ ##
170
+ # Find by attributes
171
+ #
172
+ # Refer to {MA's FAQ}[http://www.metal-archives.com/content/help?index=3#tab_db] for search tips.
173
+ #
174
+ # Returns rdoc-ref:Release or nil when no results
175
+ #
176
+ # [Raises]
177
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400
178
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
179
+ #
180
+ # [+query+]
181
+ # Hash containing one or more of the following keys:
182
+ # - +:band_name+: +String+
183
+ # - +:title+: +String+
184
+ # - +:from_year+: +Integer+
185
+ # - +:from_month+: +Integer+
186
+ # - +:to_year+: +Integer+
187
+ # - +:to_month+: +Integer+
188
+ # - +:country+: +ISO3166::Country+ or +Array+ of ISO3166::Country
189
+ # - +:location+: +String+
190
+ # - +:label_name+: +String+
191
+ # - +:indie+: +Boolean+
192
+ # - +:catalog_id+: +String+
193
+ # - +:identifier+: +String+, identifier (barcode, matrix, etc.)
194
+ # - +:recording_info+: +String+, recording information (studio, city, etc.)
195
+ # - +:version_description+: +String+, version description (country, digipak, etc.)
196
+ # - +:notes+: +String+
197
+ # - +:genre+: +String+
198
+ # - +:types+: +Array+ of +Symbol+, see rdoc-ref:Release.type
199
+ # - +:formats+: +Array+ of +Symbol+, see rdoc-ref:Release.format
200
+ #
201
+ def find_by(query)
202
+ url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/albums"
203
+ params = Parsers::Release.map_params query
204
+
205
+ response = HTTPClient.get url, params
206
+ json = JSON.parse response.body
207
+
208
+ return nil if json['aaData'].empty?
209
+
210
+ data = json['aaData'].first
211
+ id = Nokogiri::HTML(data[1]).xpath('//a/@href').first.value.delete('\\').split('/').last.gsub(/\D/, '').to_i
212
+
213
+ find id
214
+ end
215
+
216
+ ##
217
+ # Find by attributes (no lazy loading)
218
+ #
219
+ # Refer to {MA's FAQ}[http://www.metal-archives.com/content/help?index=3#tab_db] for search tips.
220
+ #
221
+ # Returns rdoc-ref:Release or nil when no results
222
+ #
223
+ # [Raises]
224
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400
225
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
226
+ #
227
+ # [+query+]
228
+ # Hash containing one or more of the following keys:
229
+ # - +:band_name+: +String+
230
+ # - +:title+: +String+
231
+ # - +:from_year+: +Integer+
232
+ # - +:from_month+: +Integer+
233
+ # - +:to_year+: +Integer+
234
+ # - +:to_month+: +Integer+
235
+ # - +:country+: +ISO3166::Country+ or +Array+ of ISO3166::Country
236
+ # - +:location+: +String+
237
+ # - +:label_name+: +String+
238
+ # - +:indie+: +Boolean+
239
+ # - +:catalog_id+: +String+
240
+ # - +:identifier+: +String+, identifier (barcode, matrix, etc.)
241
+ # - +:recording_info+: +String+, recording information (studio, city, etc.)
242
+ # - +:version_description+: +String+, version description (country, digipak, etc.)
243
+ # - +:notes+: +String+
244
+ # - +:genre+: +String+
245
+ # - +:types+: +Array+ of +Symbol+, see rdoc-ref:Release.type
246
+ # - +:formats+: +Array+ of +Symbol+, see rdoc-ref:Release.format
247
+ #
248
+ def find_by!(query)
249
+ obj = find_by query
250
+ obj.load! if obj && !obj.loaded?
251
+
252
+ obj
253
+ end
254
+
255
+ ##
256
+ # Search by attributes
257
+ #
258
+ # Refer to {MA's FAQ}[http://www.metal-archives.com/content/help?index=3#tab_db] for search tips.
259
+ #
260
+ # Returns rdoc-ref:Collection of rdoc-ref:Release
261
+ #
262
+ # [Raises]
263
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400
264
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
265
+ #
266
+ # [+query+]
267
+ # Hash containing one or more of the following keys:
268
+ # - +:band_name+: +String+
269
+ # - +:title+: +String+
270
+ # - +:from_year+: +Integer+
271
+ # - +:from_month+: +Integer+
272
+ # - +:to_year+: +Integer+
273
+ # - +:to_month+: +Integer+
274
+ # - +:country+: +ISO3166::Country+ or +Array+ of ISO3166::Country
275
+ # - +:location+: +String+
276
+ # - +:label_name+: +String+
277
+ # - +:indie+: +Boolean+
278
+ # - +:catalog_id+: +String+
279
+ # - +:identifier+: +String+, identifier (barcode, matrix, etc.)
280
+ # - +:recording_info+: +String+, recording information (studio, city, etc.)
281
+ # - +:version_description+: +String+, version description (country, digipak, etc.)
282
+ # - +:notes+: +String+
283
+ # - +:genre+: +String+
284
+ # - +:types+: +Array+ of +Symbol+, see rdoc-ref:Release.type
285
+ # - +:formats+: +Array+ of +Symbol+, see rdoc-ref:Release.format
286
+ #
287
+ def search_by(query)
288
+ url = "#{MetalArchives.config.default_endpoint}search/ajax-advanced/searching/albums"
289
+
290
+ params = Parsers::Release.map_params query
291
+
292
+ l = lambda do
293
+ @start ||= 0
294
+
295
+ if @max_items && @start >= @max_items
296
+ []
297
+ else
298
+ response = HTTPClient.get url, params.merge(:iDisplayStart => @start)
299
+ json = JSON.parse response.body
300
+
301
+ @max_items = json['iTotalRecords']
302
+
303
+ objects = []
304
+
305
+ json['aaData'].each do |data|
306
+ # Create Release object for every ID in the results list
307
+ id = Nokogiri::HTML(data.first).xpath('//a/@href').first.value.delete('\\').split('/').last.gsub(/\D/, '').to_i
308
+ objects << Release.find(id)
309
+ end
310
+
311
+ @start += 200
312
+
313
+ objects
314
+ end
315
+ end
316
+
317
+ MetalArchives::Collection.new l
318
+ end
319
+
320
+ ##
321
+ # Search by title, resolves to rdoc-ref:Release.search_by <tt>(:title => title)</tt>
322
+ #
323
+ # Refer to {MA's FAQ}[http://www.metal-archives.com/content/help?index=3#tab_db] for search tips.
324
+ #
325
+ # Returns (possibly empty) +Array+ of rdoc-ref:Release
326
+ #
327
+ # [Raises]
328
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400
329
+ # - rdoc-ref:MetalArchives::Errors::ArgumentError when +title+ isn't a +String+
330
+ #
331
+ # [+title+]
332
+ # +String+
333
+ #
334
+ def search(title)
335
+ raise MetalArchives::Errors::ArgumentError unless title.is_a? String
336
+ search_by :title => title
337
+ end
338
+
339
+ ##
340
+ # Get all releases
341
+ #
342
+ # Returns rdoc-ref:Collection of rdoc-ref:Release
343
+ #
344
+ # [Raises]
345
+ # - rdoc-ref:MetalArchives::Errors::APIError when receiving a status code >= 400
346
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
347
+ #
348
+ def all
349
+ search ''
350
+ end
351
+ end
352
+ end
353
+ end
@@ -0,0 +1,233 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'json'
4
+ require 'date'
5
+
6
+ module MetalArchives
7
+ module Parsers
8
+ ##
9
+ # Release parser
10
+ #
11
+ class Release < Parser # :nodoc:
12
+ class << self
13
+ TYPE_TO_QUERY = {
14
+ :full_length => 1,
15
+ :live => 2,
16
+ :demo => 3,
17
+ :single => 4,
18
+ :ep => 5,
19
+ :video => 6,
20
+ :boxed_set => 7,
21
+ :split => 8,
22
+ :compilation => 10,
23
+ :split_video => 12,
24
+ :collaboration => 13
25
+ }.freeze
26
+
27
+ TYPE_TO_SYM = {
28
+ 'Full-length' => :full_length,
29
+ 'Live album' => :live,
30
+ 'Demo' => :demo,
31
+ 'Single' => :single,
32
+ 'EP' => :ep,
33
+ 'Video' => :video,
34
+ 'Boxed set' => :boxed_set,
35
+ 'Split' => :split,
36
+ 'Compilation' => :compilation,
37
+ 'Split video' => :split_video,
38
+ 'Collaboration' => :collaboration
39
+ }.freeze
40
+
41
+ FORMAT_TO_QUERY = {
42
+ :cd => 'CD',
43
+ :cassette => 'Cassette',
44
+ :vinyl => 'Vinyl*',
45
+ :vhs => 'VHS',
46
+ :dvd => 'DVD',
47
+ :digital => 'Digital',
48
+ :blu_ray => 'Blu-ray*',
49
+ :other => 'Other'
50
+ }.freeze
51
+
52
+ FORMAT_TO_SYM = {
53
+ 'CD' => :cd,
54
+ 'Cassette' => :cassette,
55
+ 'VHS' => :vhs,
56
+ 'DVD' => :dvd,
57
+ 'Digital' => :digital,
58
+ 'Other' => :other
59
+ }
60
+
61
+ ##
62
+ # Map attributes to MA attributes
63
+ #
64
+ # Returns +Hash+
65
+ #
66
+ # [+params+]
67
+ # +Hash+
68
+ #
69
+ def map_params(query)
70
+ params = {
71
+ :bandName => query[:band_name] || '',
72
+ :releaseTitle => query[:title] || '',
73
+ :releaseYearFrom => query[:from_year] || '',
74
+ :releaseMonthFrom => query[:from_month] || '',
75
+ :releaseYearTo => query[:to_year] || '',
76
+ :releaseMonthTo => query[:to_month] || '',
77
+ :country => map_countries(query[:country]) || '',
78
+ :location => query[:location] || '',
79
+ :releaseLabelName => query[:label_name] || '',
80
+ :releaseCatalogNumber => query[:catalog_id] || '',
81
+ :releaseIdentifiers => query[:identifier] || '',
82
+ :releaseRecordingInfo => query[:recording_info] || '',
83
+ :releaseDescription => query[:version_description] || '',
84
+ :releaseNotes => query[:notes] || '',
85
+ :genre => query[:genre] || '',
86
+ :releaseType => map_types(query[:types]),
87
+ :releaseFormat => map_formats(query[:formats])
88
+ }
89
+
90
+ params
91
+ end
92
+
93
+ ##
94
+ # Parse main HTML page
95
+ #
96
+ # Returns +Hash+
97
+ #
98
+ # [Raises]
99
+ # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
100
+ #
101
+ def parse_html(response)
102
+ props = {}
103
+ doc = Nokogiri::HTML response
104
+
105
+ props[:title] = sanitize doc.css('#album_info .album_name a').first.content
106
+
107
+ doc.css('#album_info dl').each do |dl|
108
+ dl.search('dt').each do |dt|
109
+ content = sanitize dt.next_element.content
110
+
111
+ next if content == 'N/A'
112
+
113
+ case sanitize(dt.content)
114
+ when 'Type:'
115
+ props[:type] = map_type content
116
+ when 'Release date:'
117
+ begin
118
+ props[:date_released] = NilDate.parse content
119
+ rescue MetalArchives::Errors::ArgumentError => e
120
+ dr = Date.parse content
121
+ props[:date_released] = NilDate.new dr.year, dr.month, dr.day
122
+ end
123
+ when 'Catalog ID:'
124
+ props[:catalog_id] = content
125
+ when 'Identifier:'
126
+ props[:identifier] = content
127
+ when 'Version desc.:'
128
+ props[:version_description] = content
129
+ when 'Label:'
130
+ # TODO: label
131
+ when 'Format:'
132
+ props[:format] = map_format content
133
+ when 'Limitation:'
134
+ props[:limitation] = content.to_i
135
+ when 'Reviews:'
136
+ next if content == 'None yet'
137
+ # TODO: reviews
138
+ else
139
+ raise MetalArchives::Errors::ParserError, "Unknown token: #{dt.content}"
140
+ end
141
+ end
142
+ end
143
+
144
+ props
145
+ rescue => e
146
+ e.backtrace.each { |b| MetalArchives.config.logger.error b }
147
+ raise Errors::ParserError, e
148
+ end
149
+
150
+ private
151
+
152
+ ##
153
+ # Map MA countries to query parameters
154
+ #
155
+ # Returns +Array+ of +ISO3166::Country+
156
+ #
157
+ # [+types+]
158
+ # +Array+ containing one or more +String+s
159
+ #
160
+ def map_countries(countries)
161
+ countries && countries.map { |c| c.alpha2 }
162
+ end
163
+
164
+ ##
165
+ # Map MA release type to query parameters
166
+ #
167
+ # Returns +Array+ of +Integer+
168
+ #
169
+ # [+types+]
170
+ # +Array+ containing one or more +Symbol+, see rdoc-ref:Release.type
171
+ #
172
+ def map_types(type_syms)
173
+ return unless type_syms
174
+
175
+ types = []
176
+ type_syms.each do |type|
177
+ raise MetalArchives::Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_QUERY[type]
178
+
179
+ types << TYPE_TO_QUERY[type]
180
+ end
181
+
182
+ types
183
+ end
184
+
185
+ ##
186
+ # Map MA release type to +Symbol+
187
+ #
188
+ # Returns +Symbol+, see rdoc-ref:Release.type
189
+ #
190
+ def map_type(type)
191
+ raise MetalArchives::Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_SYM[type]
192
+
193
+ TYPE_TO_SYM[type]
194
+ end
195
+
196
+ ##
197
+ # Map MA release format to query parameters
198
+ #
199
+ # Returns +Array+ of +Integer+
200
+ #
201
+ # [+types+]
202
+ # +Array+ containing one or more +Symbol+, see rdoc-ref:Release.type
203
+ #
204
+ def map_formats(format_syms)
205
+ return unless format_syms
206
+
207
+ formats = []
208
+ format_syms.each do |format|
209
+ raise MetalArchives::Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_QUERY[format]
210
+
211
+ formats << FORMAT_TO_QUERY[format]
212
+ end
213
+
214
+ formats
215
+ end
216
+
217
+ ##
218
+ # Map MA release format to +Symbol+
219
+ #
220
+ # Returns +Symbol+, see rdoc-ref:Release.format
221
+ #
222
+ def map_format(format)
223
+ return :vinyl if format =~ /[Vv]inyl/
224
+ return :blu_ray if format =~ /[Bb]lu.?[Rr]ay/
225
+
226
+ raise MetalArchives::Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_SYM[format]
227
+
228
+ FORMAT_TO_SYM[format]
229
+ end
230
+ end
231
+ end
232
+ end
233
+ end
@@ -4,5 +4,5 @@ module MetalArchives
4
4
  ##
5
5
  # MetalArchives API version
6
6
  #
7
- VERSION = '2.1.1'
7
+ VERSION = '2.2.0'
8
8
  end
@@ -0,0 +1,133 @@
1
+ # frozen_string_literal: true
2
+
3
+ RSpec.describe MetalArchives::Release do
4
+ describe 'properties' do
5
+ it 'Tales of Ancient Prophecies has properties' do
6
+ release = MetalArchives::Release.find 416934
7
+
8
+ expect(release).to be_instance_of MetalArchives::Release
9
+ expect(release.id).to eq 416934
10
+ expect(release.title).to eq 'Tales of Ancient Prophecies'
11
+ expect(release.type).to eq :full_length
12
+ expect(release.date_released).to eq MetalArchives::NilDate.new(2014, 6, 4)
13
+ expect(release.catalog_id).to eq 'BLOD091CD'
14
+ expect(release.version_description).to be_nil
15
+ expect(release.format).to eq :cd
16
+ expect(release.limitation).to be_nil
17
+ expect(release.notes).to be_nil
18
+ end
19
+
20
+ it '...And Oceans has properties' do
21
+ release = MetalArchives::Release.find 123563
22
+
23
+ expect(release).to be_instance_of MetalArchives::Release
24
+ expect(release.id).to eq 123563
25
+ expect(release.title).to eq '...and Oceans'
26
+ expect(release.type).to eq :compilation
27
+ expect(release.date_released).to eq MetalArchives::NilDate.new(2000)
28
+ expect(release.catalog_id).to eq 'NMLP 025'
29
+ expect(release.version_description).to be_nil
30
+ expect(release.format).to eq :vinyl
31
+ expect(release.limitation).to be_nil
32
+ expect(release.notes).to be_nil
33
+ end
34
+
35
+ it 'uses NilDate' do
36
+ release = MetalArchives::Release.find 123563
37
+
38
+ expect(release.title).to eq '...and Oceans'
39
+ expect(release.date_released).to be_instance_of MetalArchives::NilDate
40
+ expect(release.date_released).to eq MetalArchives::NilDate.new(2000, nil, nil)
41
+ end
42
+ end
43
+
44
+ describe 'methods' do
45
+ describe 'find' do
46
+ it 'finds a release' do
47
+ release = MetalArchives::Release.find 416934
48
+
49
+ expect(release).not_to be_nil
50
+ expect(release).to be_instance_of MetalArchives::Release
51
+ expect(release.id).to eq 416934
52
+ expect(release.title).to eq 'Tales of Ancient Prophecies'
53
+ end
54
+
55
+ it 'lazily loads' do
56
+ release = MetalArchives::Release.find -1
57
+
58
+ expect(release).to be_instance_of MetalArchives::Release
59
+ end
60
+ end
61
+
62
+ describe 'find!' do
63
+ it 'finds a release' do
64
+ release = MetalArchives::Release.find! 416934
65
+
66
+ expect(release).to be_instance_of MetalArchives::Release
67
+ expect(release.title).to eq 'Tales of Ancient Prophecies'
68
+ end
69
+
70
+ it 'raises on invalid id' do
71
+ expect(-> { MetalArchives::Release.find! -1 }).to raise_error MetalArchives::Errors::APIError
72
+ expect(-> { MetalArchives::Release.find! 0 }).to raise_error MetalArchives::Errors::InvalidIDError
73
+ expect(-> { MetalArchives::Release.find! nil }).to raise_error MetalArchives::Errors::InvalidIDError
74
+ end
75
+ end
76
+
77
+ describe 'find_by' do
78
+ it 'finds a release by title' do
79
+ release = MetalArchives::Release.find_by :title => 'Tales of Ancient Prophecies'
80
+
81
+ expect(release).to be_instance_of MetalArchives::Release
82
+ expect(release.id).to eq 416934
83
+ end
84
+
85
+ it 'returns nil on invalid id' do
86
+ release = MetalArchives::Release.find_by :title => 'SomeNonExistantName'
87
+
88
+ expect(release).to be_nil
89
+ end
90
+ end
91
+
92
+ describe 'find_by!' do
93
+ it 'finds a release' do
94
+ release = MetalArchives::Release.find_by! :title => 'Tales of Ancient Prophecies'
95
+
96
+ expect(release).to be_instance_of MetalArchives::Release
97
+ expect(release.id).to eq 416934
98
+ end
99
+
100
+ it 'returns nil on invalid id' do
101
+ release = MetalArchives::Release.find_by! :title => 'SomeNonExistantName'
102
+
103
+ expect(release).to be_nil
104
+ end
105
+ end
106
+
107
+ describe 'search' do
108
+ it 'returns a collection' do
109
+ collection = MetalArchives::Release.search 'Rhapsody'
110
+
111
+ expect(collection).to be_instance_of MetalArchives::Collection
112
+ expect(collection.first).to be_instance_of MetalArchives::Release
113
+ end
114
+
115
+ it 'returns an empty collection' do
116
+ expect(MetalArchives::Release.search 'SomeNoneExistantName').to be_empty
117
+ end
118
+
119
+ it 'searches by title' do
120
+ expect(MetalArchives::Release.search_by(:title => 'Rhapsody').count).to eq 13
121
+ # expect(MetalArchives::Release.search_by(:title => 'Lost Horizon').count).to eq 3
122
+ # expect(MetalArchives::Release.search_by(:title => 'Lost Horizon', :exact => true).count).to eq 2
123
+ # expect(MetalArchives::Release.search_by(:title => 'Alquimia', :genre => 'Melodic Power').count).to eq 2
124
+ end
125
+ end
126
+
127
+ describe 'all' do
128
+ it 'returns a collection' do
129
+ expect(MetalArchives::Release.all).to be_instance_of MetalArchives::Collection
130
+ end
131
+ end
132
+ end
133
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: metal_archives
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.1
4
+ version: 2.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Florian Dejonckheere
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-06-12 00:00:00.000000000 Z
11
+ date: 2017-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -220,10 +220,12 @@ files:
220
220
  - lib/metal_archives/models/band.rb
221
221
  - lib/metal_archives/models/base_model.rb
222
222
  - lib/metal_archives/models/label.rb
223
+ - lib/metal_archives/models/release.rb
223
224
  - lib/metal_archives/parsers/artist.rb
224
225
  - lib/metal_archives/parsers/band.rb
225
226
  - lib/metal_archives/parsers/label.rb
226
227
  - lib/metal_archives/parsers/parser.rb
228
+ - lib/metal_archives/parsers/release.rb
227
229
  - lib/metal_archives/utils/collection.rb
228
230
  - lib/metal_archives/utils/lru_cache.rb
229
231
  - lib/metal_archives/utils/nil_date.rb
@@ -239,6 +241,7 @@ files:
239
241
  - spec/models/artist_spec.rb
240
242
  - spec/models/band_spec.rb
241
243
  - spec/models/base_model_spec.rb
244
+ - spec/models/release_spec.rb
242
245
  - spec/parser_spec.rb
243
246
  - spec/spec_helper.rb
244
247
  - spec/support/factory_girl.rb
@@ -280,6 +283,7 @@ test_files:
280
283
  - spec/models/artist_spec.rb
281
284
  - spec/models/band_spec.rb
282
285
  - spec/models/base_model_spec.rb
286
+ - spec/models/release_spec.rb
283
287
  - spec/parser_spec.rb
284
288
  - spec/spec_helper.rb
285
289
  - spec/support/factory_girl.rb