metal_archives 2.1.1 → 2.2.0

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