metal_archives 2.2.0 → 3.1.1

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.
Files changed (71) hide show
  1. checksums.yaml +5 -5
  2. data/.github/workflows/ci.yml +93 -0
  3. data/.gitignore +6 -6
  4. data/.overcommit.yml +35 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +66 -6
  7. data/CHANGELOG.md +33 -0
  8. data/Gemfile +1 -1
  9. data/LICENSE.md +17 -4
  10. data/README.md +65 -86
  11. data/Rakefile +8 -7
  12. data/bin/console +38 -0
  13. data/bin/setup +8 -0
  14. data/config/inflections.rb +7 -0
  15. data/config/initializers/.keep +0 -0
  16. data/docker-compose.yml +23 -0
  17. data/lib/metal_archives.rb +82 -27
  18. data/lib/metal_archives/cache/base.rb +40 -0
  19. data/lib/metal_archives/cache/memory.rb +68 -0
  20. data/lib/metal_archives/cache/null.rb +22 -0
  21. data/lib/metal_archives/cache/redis.rb +49 -0
  22. data/lib/metal_archives/{utils/collection.rb → collection.rb} +3 -5
  23. data/lib/metal_archives/configuration.rb +33 -50
  24. data/lib/metal_archives/{error.rb → errors.rb} +9 -1
  25. data/lib/metal_archives/http_client.rb +45 -44
  26. data/lib/metal_archives/models/artist.rb +90 -45
  27. data/lib/metal_archives/models/band.rb +77 -52
  28. data/lib/metal_archives/models/base.rb +225 -0
  29. data/lib/metal_archives/models/label.rb +14 -15
  30. data/lib/metal_archives/models/release.rb +25 -29
  31. data/lib/metal_archives/parsers/artist.rb +86 -50
  32. data/lib/metal_archives/parsers/band.rb +155 -88
  33. data/lib/metal_archives/parsers/base.rb +14 -0
  34. data/lib/metal_archives/parsers/country.rb +21 -0
  35. data/lib/metal_archives/parsers/date.rb +31 -0
  36. data/lib/metal_archives/parsers/genre.rb +67 -0
  37. data/lib/metal_archives/parsers/label.rb +39 -31
  38. data/lib/metal_archives/parsers/parser.rb +18 -63
  39. data/lib/metal_archives/parsers/release.rb +98 -89
  40. data/lib/metal_archives/parsers/year.rb +31 -0
  41. data/lib/metal_archives/version.rb +12 -1
  42. data/metal_archives.env.example +10 -0
  43. data/metal_archives.gemspec +43 -28
  44. data/nginx/default.conf +60 -0
  45. metadata +179 -74
  46. data/.travis.yml +0 -12
  47. data/lib/metal_archives/middleware/cache_check.rb +0 -20
  48. data/lib/metal_archives/middleware/encoding.rb +0 -16
  49. data/lib/metal_archives/middleware/headers.rb +0 -38
  50. data/lib/metal_archives/middleware/rewrite_endpoint.rb +0 -38
  51. data/lib/metal_archives/models/base_model.rb +0 -215
  52. data/lib/metal_archives/utils/lru_cache.rb +0 -61
  53. data/lib/metal_archives/utils/nil_date.rb +0 -99
  54. data/lib/metal_archives/utils/range.rb +0 -66
  55. data/spec/configuration_spec.rb +0 -96
  56. data/spec/factories/artist_factory.rb +0 -37
  57. data/spec/factories/band_factory.rb +0 -60
  58. data/spec/factories/nil_date_factory.rb +0 -9
  59. data/spec/factories/range_factory.rb +0 -8
  60. data/spec/models/artist_spec.rb +0 -138
  61. data/spec/models/band_spec.rb +0 -164
  62. data/spec/models/base_model_spec.rb +0 -219
  63. data/spec/models/release_spec.rb +0 -133
  64. data/spec/parser_spec.rb +0 -19
  65. data/spec/spec_helper.rb +0 -111
  66. data/spec/support/factory_girl.rb +0 -5
  67. data/spec/support/metal_archives.rb +0 -33
  68. data/spec/utils/collection_spec.rb +0 -72
  69. data/spec/utils/lru_cache_spec.rb +0 -53
  70. data/spec/utils/nil_date_spec.rb +0 -156
  71. data/spec/utils/range_spec.rb +0 -62
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetalArchives
4
+ module Parsers
5
+ ##
6
+ # Abstract base class
7
+ #
8
+ class Base
9
+ def self.parse(_input)
10
+ raise Errors::NotImplementedError, "method .parse not implemented"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "countries"
4
+
5
+ module MetalArchives
6
+ module Parsers
7
+ ##
8
+ # Country parser
9
+ #
10
+ class Country < Base
11
+ ##
12
+ # Parse a country
13
+ #
14
+ # Returns +ISO3166::Country+
15
+ #
16
+ def self.parse(input)
17
+ ISO3166::Country.find_country_by_name(input)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetalArchives
4
+ module Parsers
5
+ ##
6
+ # Date parser
7
+ #
8
+ class Date < Base
9
+ ##
10
+ # Parse a date
11
+ #
12
+ # Returns +Date+
13
+ #
14
+ def self.parse(input)
15
+ ::Date.parse(input)
16
+ rescue ::Date::Error
17
+ components = input
18
+ .split("-")
19
+ .map(&:to_i)
20
+ .reject(&:zero?)
21
+ .compact
22
+
23
+ return if components.empty?
24
+
25
+ ::Date.new(*components)
26
+ rescue TypeError
27
+ nil
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ module MetalArchives
4
+ module Parsers
5
+ ##
6
+ # Genre parser
7
+ #
8
+ class Genre < Base
9
+ SUFFIXES = %w((early) (later) metal).freeze
10
+
11
+ ##
12
+ # Opinionated parsing of genres
13
+ #
14
+ # Returns an +Array+ of +String+
15
+ #
16
+ # The following components are omitted:
17
+ # - Metal
18
+ # - (early)
19
+ # - (later)
20
+ #
21
+ # All genres are capitalized.
22
+ #
23
+ # For examples on how genres are parsed, refer to +gnre_spec.rb+
24
+ #
25
+ def self.parse(input)
26
+ genres = []
27
+ # Split fields
28
+ input.split(/[,;]/).each do |genre|
29
+ ##
30
+ # Start with a single empty genre string. Split the genre by spaces
31
+ # and process each component. If a component does not have a slash,
32
+ # concatenate it to all genre strings present in +temp+. If it does
33
+ # have a slash present, duplicate all genre strings, and concatenate
34
+ # the first component (before the slash) to the first half, and the
35
+ # last component to the last half. +temp+ now has an array of genre
36
+ # combinations.
37
+ #
38
+ # 'Traditional Heavy/Power Metal' => ['Traditional Heavy', 'Traditional Power']
39
+ # 'Traditional/Classical Heavy/Power Metal' => [
40
+ # 'Traditional Heavy', 'Traditional Power',
41
+ # 'Classical Heavy', 'Classical Power']
42
+ #
43
+ temp = [""]
44
+
45
+ genre.downcase.split.reject { |g| SUFFIXES.include? g }.each do |g|
46
+ if g.include? "/"
47
+ # Duplicate all WIP genres
48
+ temp2 = temp.dup
49
+
50
+ # Assign first and last components to temp and temp2 respectively
51
+ split = g.split "/"
52
+ temp.map! { |t| t.empty? ? split.first.capitalize : "#{t.capitalize} #{split.first.capitalize}" }
53
+ temp2.map! { |t| t.empty? ? split.last.capitalize : "#{t.capitalize} #{split.last.capitalize}" }
54
+
55
+ # Add both genre trees
56
+ temp += temp2
57
+ else
58
+ temp.map! { |t| t.empty? ? g.capitalize : "#{t.capitalize} #{g.capitalize}" }
59
+ end
60
+ end
61
+ genres += temp
62
+ end
63
+ genres.uniq
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
- require 'nokogiri'
3
+ require "date"
4
+ require "nokogiri"
5
5
 
6
6
  module MetalArchives
7
7
  module Parsers
@@ -11,53 +11,61 @@ module MetalArchives
11
11
  class Label # :nodoc:
12
12
  class << self
13
13
  def find_endpoint(params)
14
- "#{MetalArchives.config.default_endpoint}labels/#{params[:name]}/#{params[:id]}"
14
+ "#{MetalArchives.config.endpoint}labels/#{params[:name]}/#{params[:id]}"
15
15
  end
16
16
 
17
17
  def parse(response)
18
- props = {}
18
+ # Set default props
19
+ props = {
20
+ name: nil,
21
+ contact: [],
22
+ address: nil,
23
+ country: nil,
24
+ phone: nil,
25
+ status: nil,
26
+ specialization: [],
27
+ date_founded: nil,
28
+
29
+ online_shopping: nil,
30
+ }
31
+
19
32
  doc = Nokogiri::HTML(response)
20
33
 
21
- props[:name] = doc.css('#label_info .label_name').first.content
34
+ props[:name] = doc.css("#label_info .label_name").first.content
22
35
 
23
- props[:contact] = []
24
- doc.css('#label_contact a').each do |contact|
36
+ doc.css("#label_contact a").each do |contact|
25
37
  props[:contact] << {
26
- :title => contact.content,
27
- :content => contact.attr(:href)
38
+ title: contact.content,
39
+ content: contact.attr(:href),
28
40
  }
29
41
  end
30
42
 
31
- doc.css('#label_info dl').each do |dl|
32
- dl.search('dt').each do |dt|
43
+ doc.css("#label_info dl").each do |dl|
44
+ dl.search("dt").each do |dt|
33
45
  content = sanitize(dt.next_element.content)
34
46
 
35
- next if content == 'N/A'
47
+ next if content == "N/A"
36
48
 
37
49
  case sanitize(dt.content)
38
- when 'Address:'
50
+ when "Address:"
39
51
  props[:address] = content
40
- when 'Country:'
41
- props[:country] = ParserHelper.parse_country css('a').first.content
42
- when 'Phone number:'
52
+ when "Country:"
53
+ props[:country] = Country.parse(css("a").first.content)
54
+ when "Phone number:"
43
55
  props[:phone] = content
44
- when 'Status:'
45
- props[:status] = content.downcase.tr(' ', '_').to_sym
46
- when 'Specialised in:'
47
- props[:specializations] = ParserHelper.parse_genre content
48
- when 'Founding date :'
49
- begin
50
- dof = Date.parse content
51
- props[:date_founded] = NilDate.new dof.year, dof.month, dof.day
52
- rescue ArgumentError => e
53
- props[:date_founded] = NilDate.parse content
54
- end
55
- when 'Sub-labels:'
56
+ when "Status:"
57
+ props[:status] = content.downcase.tr(" ", "_").to_sym
58
+ when "Specialised in:"
59
+ props[:specializations] = Parsers::Genre.parse(content)
60
+ when "Founding date :"
61
+ props[:date_founded] = Parsers::Date.parse(content)
62
+ when "Sub-labels:"
56
63
  # TODO
57
- when 'Online shopping:'
58
- if content == 'Yes'
64
+ when "Online shopping:"
65
+ case content
66
+ when "Yes"
59
67
  props[:online_shopping] = true
60
- elsif content == 'No'
68
+ when "No"
61
69
  props[:online_shopping] = false
62
70
  end
63
71
  else
@@ -1,88 +1,43 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'date'
4
- require 'countries'
3
+ require "date"
5
4
 
6
5
  module MetalArchives
7
- ##
8
- # Mapping layer from and to MA Web Service
9
- #
10
- module Parsers # :nodoc:
6
+ module Parsers
11
7
  ##
12
8
  # Parser base class
13
9
  #
14
10
  class Parser
15
11
  class << self
16
- ##
17
- # Parse a country
18
- #
19
- # Returns +ISO3166::Country+
20
- #
21
- def parse_country(input)
22
- ISO3166::Country.find_country_by_name input
23
- end
24
-
25
12
  ##
26
13
  # Sanitize a string
27
14
  #
28
15
  # Return +String+
29
16
  #
30
17
  def sanitize(input)
31
- input.gsub(/^"/, '').gsub(/"$/, '').strip
18
+ return if input.blank?
19
+
20
+ input
21
+ .gsub(/^"/, "")
22
+ .gsub(/"$/, "")
23
+ .gsub(/[[:space:]]/, " ")
24
+ .strip
32
25
  end
33
26
 
34
27
  ##
35
- # Opinionated parsing of genres
36
- #
37
- # Returns an +Array+ of +String+
38
- #
39
- # The following components are omitted:
40
- # - Metal
41
- # - (early)
42
- # - (later)
43
- #
44
- # All genres are capitalized.
28
+ # Rewrite a URL
45
29
  #
46
- # For examples on how genres are parsed, refer to +ParserTest#test_parse_genre+
30
+ # Return +URI+
47
31
  #
48
- def parse_genre(input)
49
- genres = []
50
- # Split fields
51
- input.split(',').each do |genre|
52
- ##
53
- # Start with a single empty genre string. Split the genre by spaces
54
- # and process each component. If a component does not have a slash,
55
- # concatenate it to all genre strings present in +temp+. If it does
56
- # have a slash present, duplicate all genre strings, and concatenate
57
- # the first component (before the slash) to the first half, and the
58
- # last component to the last half. +temp+ now has an array of genre
59
- # combinations.
60
- #
61
- # 'Traditional Heavy/Power Metal' => ['Traditional Heavy', 'Traditional Power']
62
- # 'Traditional/Classical Heavy/Power Metal' => [
63
- # 'Traditional Heavy', 'Traditional Power',
64
- # 'Classical Heavy', 'Classical Power']
65
- #
66
- temp = ['']
67
- genre.downcase.split.reject { |g| ['(early)', '(later)', 'metal'].include? g }.each do |g|
68
- if g.include? '/'
69
- # Duplicate all WIP genres
70
- temp2 = temp.dup
32
+ def rewrite(input)
33
+ return input unless MetalArchives.config.endpoint
71
34
 
72
- # Assign first and last components to temp and temp2 respectively
73
- split = g.split '/'
74
- temp.map! { |t| t.empty? ? split.first.capitalize : "#{t.capitalize} #{split.first.capitalize}" }
75
- temp2.map! { |t| t.empty? ? split.last.capitalize : "#{t.capitalize} #{split.last.capitalize}" }
35
+ endpoint = URI(MetalArchives.config.endpoint)
76
36
 
77
- # Add both genre trees
78
- temp += temp2
79
- else
80
- temp.map! { |t| t.empty? ? g.capitalize : "#{t.capitalize} #{g.capitalize}" }
81
- end
82
- end
83
- genres += temp
84
- end
85
- genres.uniq
37
+ URI(input)
38
+ .tap { |u| u.host = endpoint.host }
39
+ .tap { |u| u.scheme = endpoint.scheme }
40
+ .to_s
86
41
  end
87
42
  end
88
43
  end
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'json'
4
- require 'date'
3
+ require "json"
4
+ require "date"
5
5
 
6
6
  module MetalArchives
7
7
  module Parsers
@@ -11,52 +11,56 @@ module MetalArchives
11
11
  class Release < Parser # :nodoc:
12
12
  class << self
13
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
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
25
  }.freeze
26
26
 
27
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
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
39
  }.freeze
40
40
 
41
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'
42
+ cd: "CD",
43
+ cassette: "Cassette",
44
+ vinyl: "Vinyl*",
45
+ vhs: "VHS",
46
+ dvd: "DVD",
47
+ "2dvd": "2DVD",
48
+ digital: "Digital",
49
+ blu_ray: "Blu-ray*",
50
+ other: "Other",
51
+ unknown: "Unknown",
50
52
  }.freeze
51
53
 
52
54
  FORMAT_TO_SYM = {
53
- 'CD' => :cd,
54
- 'Cassette' => :cassette,
55
- 'VHS' => :vhs,
56
- 'DVD' => :dvd,
57
- 'Digital' => :digital,
58
- 'Other' => :other
59
- }
55
+ "CD" => :cd,
56
+ "Cassette" => :cassette,
57
+ "VHS" => :vhs,
58
+ "DVD" => :dvd,
59
+ "2DVD" => :"2dvd",
60
+ "Digital" => :digital,
61
+ "Other" => :other,
62
+ "Unknown" => :unknown,
63
+ }.freeze
60
64
 
61
65
  ##
62
66
  # Map attributes to MA attributes
@@ -67,27 +71,25 @@ module MetalArchives
67
71
  # +Hash+
68
72
  #
69
73
  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])
74
+ {
75
+ bandName: query[:band_name] || "",
76
+ releaseTitle: query[:title] || "",
77
+ releaseYearFrom: query[:from_year] || "",
78
+ releaseMonthFrom: query[:from_month] || "",
79
+ releaseYearTo: query[:to_year] || "",
80
+ releaseMonthTo: query[:to_month] || "",
81
+ country: map_countries(query[:country]) || "",
82
+ location: query[:location] || "",
83
+ releaseLabelName: query[:label_name] || "",
84
+ releaseCatalogNumber: query[:catalog_id] || "",
85
+ releaseIdentifiers: query[:identifier] || "",
86
+ releaseRecordingInfo: query[:recording_info] || "",
87
+ releaseDescription: query[:version_description] || "",
88
+ releaseNotes: query[:notes] || "",
89
+ genre: query[:genre] || "",
90
+ releaseType: map_types(query[:types]),
91
+ releaseFormat: map_formats(query[:formats]),
88
92
  }
89
-
90
- params
91
93
  end
92
94
 
93
95
  ##
@@ -99,50 +101,56 @@ module MetalArchives
99
101
  # - rdoc-ref:MetalArchives::Errors::ParserError when parsing failed. Please report this error.
100
102
  #
101
103
  def parse_html(response)
102
- props = {}
104
+ # Set default props
105
+ props = {
106
+ title: nil,
107
+ type: nil,
108
+ date_released: nil,
109
+ catalog_id: nil,
110
+ identifier: nil,
111
+ version_description: nil,
112
+ format: nil,
113
+ limitation: nil,
114
+ }
115
+
103
116
  doc = Nokogiri::HTML response
104
117
 
105
- props[:title] = sanitize doc.css('#album_info .album_name a').first.content
118
+ props[:title] = sanitize doc.css("#album_info .album_name a").first.content
106
119
 
107
- doc.css('#album_info dl').each do |dl|
108
- dl.search('dt').each do |dt|
120
+ doc.css("#album_info dl").each do |dl|
121
+ dl.search("dt").each do |dt|
109
122
  content = sanitize dt.next_element.content
110
123
 
111
- next if content == 'N/A'
124
+ next if content == "N/A"
112
125
 
113
126
  case sanitize(dt.content)
114
- when 'Type:'
127
+ when "Type:"
115
128
  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:'
129
+ when "Release date:"
130
+ props[:date_released] = Parsers::Date.parse(content)
131
+ when "Catalog ID:"
124
132
  props[:catalog_id] = content
125
- when 'Identifier:'
133
+ when "Identifier:"
126
134
  props[:identifier] = content
127
- when 'Version desc.:'
135
+ when "Version desc.:"
128
136
  props[:version_description] = content
129
- when 'Label:'
137
+ when "Label:"
130
138
  # TODO: label
131
- when 'Format:'
139
+ when "Format:"
132
140
  props[:format] = map_format content
133
- when 'Limitation:'
141
+ when "Limitation:"
134
142
  props[:limitation] = content.to_i
135
- when 'Reviews:'
136
- next if content == 'None yet'
143
+ when "Reviews:"
144
+ next if content == "None yet"
137
145
  # TODO: reviews
138
146
  else
139
- raise MetalArchives::Errors::ParserError, "Unknown token: #{dt.content}"
147
+ raise Errors::ParserError, "Unknown token: #{dt.content}"
140
148
  end
141
149
  end
142
150
  end
143
151
 
144
152
  props
145
- rescue => e
153
+ rescue StandardError => e
146
154
  e.backtrace.each { |b| MetalArchives.config.logger.error b }
147
155
  raise Errors::ParserError, e
148
156
  end
@@ -158,7 +166,7 @@ module MetalArchives
158
166
  # +Array+ containing one or more +String+s
159
167
  #
160
168
  def map_countries(countries)
161
- countries && countries.map { |c| c.alpha2 }
169
+ countries&.map(&:alpha2)
162
170
  end
163
171
 
164
172
  ##
@@ -174,7 +182,7 @@ module MetalArchives
174
182
 
175
183
  types = []
176
184
  type_syms.each do |type|
177
- raise MetalArchives::Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_QUERY[type]
185
+ raise Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_QUERY[type]
178
186
 
179
187
  types << TYPE_TO_QUERY[type]
180
188
  end
@@ -188,7 +196,7 @@ module MetalArchives
188
196
  # Returns +Symbol+, see rdoc-ref:Release.type
189
197
  #
190
198
  def map_type(type)
191
- raise MetalArchives::Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_SYM[type]
199
+ raise Errors::ParserError, "Unknown type: #{type}" unless TYPE_TO_SYM[type]
192
200
 
193
201
  TYPE_TO_SYM[type]
194
202
  end
@@ -206,7 +214,7 @@ module MetalArchives
206
214
 
207
215
  formats = []
208
216
  format_syms.each do |format|
209
- raise MetalArchives::Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_QUERY[format]
217
+ raise Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_QUERY[format]
210
218
 
211
219
  formats << FORMAT_TO_QUERY[format]
212
220
  end
@@ -220,10 +228,11 @@ module MetalArchives
220
228
  # Returns +Symbol+, see rdoc-ref:Release.format
221
229
  #
222
230
  def map_format(format)
223
- return :vinyl if format =~ /[Vv]inyl/
224
- return :blu_ray if format =~ /[Bb]lu.?[Rr]ay/
231
+ return :cd if /CD/.match?(format)
232
+ return :vinyl if /[Vv]inyl/.match?(format)
233
+ return :blu_ray if /[Bb]lu.?[Rr]ay/.match?(format)
225
234
 
226
- raise MetalArchives::Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_SYM[format]
235
+ raise Errors::ParserError, "Unknown format: #{format}" unless FORMAT_TO_SYM[format]
227
236
 
228
237
  FORMAT_TO_SYM[format]
229
238
  end