musicbrainz 0.6.0 → 0.7.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.
- data/Contributors +4 -0
- data/README.md +19 -4
- data/Rakefile +5 -0
- data/lib/deprecated.rb +20 -7
- data/lib/musicbrainz.rb +20 -11
- data/lib/musicbrainz/artist.rb +61 -65
- data/lib/musicbrainz/base.rb +61 -7
- data/lib/musicbrainz/release.rb +32 -31
- data/lib/musicbrainz/release_group.rb +30 -30
- data/lib/musicbrainz/track.rb +16 -14
- data/lib/parsers/artist.rb +49 -0
- data/lib/parsers/base.rb +41 -0
- data/lib/parsers/release.rb +28 -0
- data/lib/parsers/release_group.rb +27 -0
- data/lib/parsers/track.rb +18 -0
- data/lib/tools/cache.rb +34 -31
- data/lib/tools/proxy.rb +54 -46
- data/lib/version.rb +2 -1
- data/musicbrainz.gemspec +1 -0
- data/spec/fixtures/kasabian.xml +1 -0
- data/spec/misc/deprecated_spec.rb +38 -0
- data/spec/requests/artist_spec.rb +4 -2
- data/spec/requests/release_group_spec.rb +2 -0
- data/spec/requests/release_spec.rb +2 -0
- data/spec/requests/track_spec.rb +2 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/tools/cache_spec.rb +8 -20
- metadata +41 -11
data/Contributors
ADDED
data/README.md
CHANGED
|
@@ -4,16 +4,21 @@
|
|
|
4
4
|
```bash
|
|
5
5
|
gem install musicbrainz
|
|
6
6
|
```
|
|
7
|
+
or add this line to your Gemfile
|
|
8
|
+
```ruby
|
|
9
|
+
gem "musicbrainz"
|
|
10
|
+
```
|
|
11
|
+
|
|
7
12
|
### Usage
|
|
8
13
|
```ruby
|
|
9
|
-
require
|
|
14
|
+
require "musicbrainz"
|
|
10
15
|
|
|
11
16
|
# Search for artists
|
|
12
|
-
@suggestions = MusicBrainz::Artist.search(
|
|
17
|
+
@suggestions = MusicBrainz::Artist.search("Jet")
|
|
13
18
|
|
|
14
19
|
# Find artist by name or mbid
|
|
15
|
-
@foo_fighters = MusicBrainz::Artist.find_by_name(
|
|
16
|
-
@kasabian = MusicBrainz::Artist.find(
|
|
20
|
+
@foo_fighters = MusicBrainz::Artist.find_by_name("Foo Fighters")
|
|
21
|
+
@kasabian = MusicBrainz::Artist.find("69b39eab-6577-46a4-a9f5-817839092033")
|
|
17
22
|
|
|
18
23
|
# Use them like ActiveRecord models
|
|
19
24
|
@empire_tracks = @kasabian.release_groups[8].releases.first.tracks
|
|
@@ -71,6 +76,16 @@ MusicBrainz::Track
|
|
|
71
76
|
@track.length
|
|
72
77
|
```
|
|
73
78
|
|
|
79
|
+
### Testing
|
|
80
|
+
```bash
|
|
81
|
+
bundle rake spec
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Debug console
|
|
85
|
+
```bash
|
|
86
|
+
bundle rake console
|
|
87
|
+
```
|
|
88
|
+
|
|
74
89
|
### Contributing
|
|
75
90
|
|
|
76
91
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
data/Rakefile
CHANGED
data/lib/deprecated.rb
CHANGED
|
@@ -1,12 +1,25 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
class << self
|
|
5
|
+
def query_interval
|
|
6
|
+
$stdout.send :puts, "WARNING! MusicBrainz.query_interval is deprecated. Use MusicBrainz::Tools::Proxy.query_interval"
|
|
7
|
+
MusicBrainz::Tools::Proxy.query_interval
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def query_interval=(sec)
|
|
11
|
+
$stdout.send :puts, "WARNING! MusicBrainz.query_interval= is deprecated. Use MusicBrainz::Tools::Proxy.query_interval"
|
|
12
|
+
MusicBrainz::Tools::Proxy.query_interval = sec
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def cache_path
|
|
16
|
+
$stdout.send :puts, "WARNING! MusicBrainz.cache_path is deprecated. Use MusicBrainz::Tools::Cache.cache_path"
|
|
17
|
+
MusicBrainz::Tools::Cache.cache_path
|
|
18
|
+
end
|
|
7
19
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
def cache_path=(path)
|
|
21
|
+
$stdout.send :puts, "WARNING! MusicBrainz.cache_path= is deprecated. Use MusicBrainz::Tools::Cache.cache_path"
|
|
22
|
+
MusicBrainz::Tools::Cache.cache_path = path
|
|
23
|
+
end
|
|
11
24
|
end
|
|
12
25
|
end
|
data/lib/musicbrainz.rb
CHANGED
|
@@ -1,20 +1,29 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
require "open-uri"
|
|
3
4
|
require "socket"
|
|
4
5
|
require "nokogiri"
|
|
5
6
|
require "cgi"
|
|
6
7
|
|
|
8
|
+
module MusicBrainz
|
|
9
|
+
module Tools; end
|
|
10
|
+
module Parsers; end
|
|
11
|
+
end
|
|
12
|
+
|
|
7
13
|
require "version"
|
|
14
|
+
require "deprecated"
|
|
8
15
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
autoload :Track, "musicbrainz/track"
|
|
16
|
+
require "musicbrainz/base"
|
|
17
|
+
require "musicbrainz/artist"
|
|
18
|
+
require "musicbrainz/release_group"
|
|
19
|
+
require "musicbrainz/release"
|
|
20
|
+
require "musicbrainz/track"
|
|
15
21
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
require "tools/cache"
|
|
23
|
+
require "tools/proxy"
|
|
24
|
+
|
|
25
|
+
require "parsers/base"
|
|
26
|
+
require "parsers/artist"
|
|
27
|
+
require "parsers/release_group"
|
|
28
|
+
require "parsers/release"
|
|
29
|
+
require "parsers/track"
|
data/lib/musicbrainz/artist.rb
CHANGED
|
@@ -1,81 +1,77 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
2
|
|
|
3
3
|
module MusicBrainz
|
|
4
|
-
class Artist <
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
class Artist < Base
|
|
5
|
+
|
|
6
|
+
field :id, String
|
|
7
|
+
field :type, String
|
|
8
|
+
field :name, String
|
|
9
|
+
field :country, String
|
|
10
|
+
field :date_begin, Time
|
|
11
|
+
field :date_end, Time
|
|
12
|
+
field :urls, Hash
|
|
7
13
|
|
|
8
14
|
def release_groups
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
@release_groups ||= nil
|
|
16
|
+
if @release_groups.nil? and !id.nil?
|
|
17
|
+
@release_groups = self.class.load({
|
|
18
|
+
:parser => :artist_release_groups,
|
|
19
|
+
:create_models => MusicBrainz::ReleaseGroup
|
|
20
|
+
}, {
|
|
21
|
+
:resource => :release_group,
|
|
22
|
+
:artist => id
|
|
23
|
+
})
|
|
24
|
+
@release_groups.sort!{ |a, b| a.first_release_date <=> b.first_release_date }
|
|
14
25
|
end
|
|
15
|
-
@release_groups
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def self.find mbid
|
|
19
|
-
res = self.load :artist, :id => mbid, :inc => [:url_rels]
|
|
20
|
-
return nil if res.nil?
|
|
21
|
-
@artist = self.parse_xml(Nokogiri::XML(res))
|
|
26
|
+
@release_groups
|
|
22
27
|
end
|
|
23
28
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@artist.urls[rel.attr('type').downcase.split(' ').join('_').to_sym] = rel.css('target').text
|
|
29
|
+
class << self
|
|
30
|
+
def find(mbid)
|
|
31
|
+
load({
|
|
32
|
+
:parser => :artist_model,
|
|
33
|
+
:create_model => MusicBrainz::Artist
|
|
34
|
+
}, {
|
|
35
|
+
:resource => :artist,
|
|
36
|
+
:id => mbid,
|
|
37
|
+
:inc => [:url_rels]
|
|
38
|
+
})
|
|
35
39
|
end
|
|
36
|
-
@artist
|
|
37
|
-
end
|
|
38
40
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
def search(name)
|
|
42
|
+
artists = load({
|
|
43
|
+
:parser => :artist_search
|
|
44
|
+
}, {
|
|
45
|
+
:resource => :artist,
|
|
46
|
+
:query => CGI.escape(name).gsub(/\!/, '\!') + '~',
|
|
47
|
+
:limit => 50
|
|
48
|
+
})
|
|
49
|
+
artists.each { |artist|
|
|
50
|
+
if artist[:name].downcase == name.downcase
|
|
51
|
+
artist[:weight] += 80
|
|
52
|
+
elsif artist[:name].downcase.gsub(/\s/, "") == name.downcase.gsub(/\s/, "")
|
|
53
|
+
artist[:weight] += 25
|
|
54
|
+
elsif artist[:aliases].include? name
|
|
55
|
+
artist[:weight] += 20
|
|
56
|
+
elsif artist[:aliases].map { |item| item.downcase }.include?(name.downcase)
|
|
57
|
+
artist[:weight] += 10
|
|
58
|
+
elsif artist[:aliases].map { |item| item.downcase.gsub(/\s/, "") }.include?(name.downcase.gsub(/\s/, ""))
|
|
59
|
+
artist[:weight] += 5
|
|
60
|
+
end
|
|
61
|
+
}
|
|
62
|
+
artists.sort{ |a, b| b[:weight] <=> a[:weight] }.take(10)
|
|
63
|
+
end
|
|
44
64
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
65
|
+
def discography(mbid)
|
|
66
|
+
artist = find(mbid)
|
|
67
|
+
artist.release_groups.each { |rg| rg.releases.each { |r| r.tracks } }
|
|
68
|
+
artist
|
|
69
|
+
end
|
|
49
70
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
xml.css('artist-list > artist').each do |a|
|
|
54
|
-
artist = {
|
|
55
|
-
:name => a.first_element_child.text.gsub(/[`’]/, "'"),
|
|
56
|
-
:sort_name => self.safe_get_value(a, 'sort-name').gsub(/[`’]/, "'"),
|
|
57
|
-
:weight => 0,
|
|
58
|
-
:desc => self.safe_get_value(a, 'disambiguation'),
|
|
59
|
-
:type => self.safe_get_attr(a, nil, 'type'),
|
|
60
|
-
:mbid => self.safe_get_attr(a, nil, 'id')
|
|
61
|
-
}
|
|
62
|
-
aliases = a.css('alias-list > alias').map{ |item| item.text }
|
|
63
|
-
if artist[:name] == name
|
|
64
|
-
artist[:weight] += 100
|
|
65
|
-
elsif artist[:name].downcase == name.downcase
|
|
66
|
-
artist[:weight] += 50
|
|
67
|
-
elsif artist[:name].downcase.gsub(/\s/, '') == name.downcase.gsub(/\s/, '')
|
|
68
|
-
artist[:weight] += 25
|
|
69
|
-
elsif aliases.include? name
|
|
70
|
-
artist[:weight] += 20
|
|
71
|
-
elsif aliases.map{ |item| item.downcase }.include? name.downcase
|
|
72
|
-
artist[:weight] += 10
|
|
73
|
-
elsif aliases.map{ |item| item.downcase.gsub(/\s/, '') }.include? name.downcase.gsub(/\s/, '')
|
|
74
|
-
artist[:weight] += 5
|
|
75
|
-
end
|
|
76
|
-
artists << artist
|
|
71
|
+
def find_by_name(name)
|
|
72
|
+
matches = search(name)
|
|
73
|
+
matches.length.zero? ? nil : find(matches.first[:mbid])
|
|
77
74
|
end
|
|
78
|
-
artists.sort{ |a, b| b[:weight] <=> a[:weight] }.take(10)
|
|
79
75
|
end
|
|
80
76
|
end
|
|
81
77
|
end
|
data/lib/musicbrainz/base.rb
CHANGED
|
@@ -1,17 +1,71 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
4
|
class Base
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
class << self
|
|
6
|
+
def field(name, type)
|
|
7
|
+
@fields ||= {}
|
|
8
|
+
@fields[name] = type
|
|
9
|
+
|
|
10
|
+
define_method(name) {
|
|
11
|
+
instance_variable_get("@#{name}")
|
|
12
|
+
}
|
|
13
|
+
define_method("#{name}=") { |val|
|
|
14
|
+
instance_variable_set("@#{name}", validate_type(val, type))
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def load(params, query)
|
|
19
|
+
parser = MusicBrainz::Parsers.get_by_name(params[:parser])
|
|
20
|
+
xml = MusicBrainz::Tools::Proxy.query(query)
|
|
21
|
+
result = parser[:const].send(parser[:method], Nokogiri::XML(xml))
|
|
22
|
+
if params[:create_model]
|
|
23
|
+
result_model = params[:create_model].new
|
|
24
|
+
result.each { |field, value|
|
|
25
|
+
result_model.send("#{field}=".to_sym, value)
|
|
26
|
+
}
|
|
27
|
+
result_model
|
|
28
|
+
elsif params[:create_models]
|
|
29
|
+
result_models = []
|
|
30
|
+
result.each { |item|
|
|
31
|
+
result_model = params[:create_models].new
|
|
32
|
+
item.each { |field, value|
|
|
33
|
+
result_model.send("#{field}=".to_sym, value)
|
|
34
|
+
}
|
|
35
|
+
result_models << result_model
|
|
36
|
+
}
|
|
37
|
+
result_models
|
|
38
|
+
else
|
|
39
|
+
result
|
|
40
|
+
end
|
|
41
|
+
end
|
|
7
42
|
end
|
|
8
43
|
|
|
9
|
-
def
|
|
10
|
-
|
|
44
|
+
def initialize
|
|
45
|
+
self.class.instance_variable_get("@fields").each { |name, type|
|
|
46
|
+
instance_variable_set("@#{name}", nil)
|
|
47
|
+
}
|
|
11
48
|
end
|
|
12
49
|
|
|
13
|
-
def
|
|
14
|
-
|
|
50
|
+
def validate_type(val, type)
|
|
51
|
+
if type == Integer
|
|
52
|
+
val.to_i
|
|
53
|
+
elsif type == Float
|
|
54
|
+
val.to_f
|
|
55
|
+
elsif type == String
|
|
56
|
+
val.to_s
|
|
57
|
+
elsif type == Time
|
|
58
|
+
if val.nil? or val == ""
|
|
59
|
+
val = "2030-12-31"
|
|
60
|
+
elsif val.split("-").length == 1
|
|
61
|
+
val << "-12-31"
|
|
62
|
+
elsif val.split("-").length == 2
|
|
63
|
+
val << "-31"
|
|
64
|
+
end
|
|
65
|
+
Time.utc(*val.split("-"))
|
|
66
|
+
else
|
|
67
|
+
val
|
|
68
|
+
end
|
|
15
69
|
end
|
|
16
70
|
end
|
|
17
71
|
end
|
data/lib/musicbrainz/release.rb
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
|
-
class Release <
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
class Release < Base
|
|
5
|
+
|
|
6
|
+
field :id, String
|
|
7
|
+
field :title, String
|
|
8
|
+
field :status, String
|
|
9
|
+
field :format, String
|
|
10
|
+
field :date, Time
|
|
11
|
+
field :country, String
|
|
6
12
|
|
|
7
13
|
def tracks
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
@tracks ||= nil
|
|
15
|
+
if @tracks.nil? and !id.nil?
|
|
16
|
+
@tracks = self.class.load({
|
|
17
|
+
:parser => :release_tracks,
|
|
18
|
+
:create_models => MusicBrainz::Track
|
|
19
|
+
}, {
|
|
20
|
+
:resource => :release,
|
|
21
|
+
:id => id,
|
|
22
|
+
:inc => [:recordings, :media],
|
|
23
|
+
:limit => 100
|
|
24
|
+
})
|
|
25
|
+
@tracks.sort{ |a, b| a.position <=> b.position }
|
|
13
26
|
end
|
|
14
|
-
@tracks
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.find mbid
|
|
18
|
-
xml = Nokogiri::XML(self.load(:release, :id => mbid, :inc => [:media])).css('release').first
|
|
19
|
-
self.parse_xml(xml) unless xml.nil?
|
|
27
|
+
@tracks
|
|
20
28
|
end
|
|
21
29
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
date += '-12-31'
|
|
33
|
-
elsif date.length == 7
|
|
34
|
-
date += '-31'
|
|
30
|
+
class << self
|
|
31
|
+
def find(mbid)
|
|
32
|
+
load({
|
|
33
|
+
:parser => :release_model,
|
|
34
|
+
:create_model => MusicBrainz::Release
|
|
35
|
+
}, {
|
|
36
|
+
:resource => :release,
|
|
37
|
+
:id => mbid,
|
|
38
|
+
:inc => [:media]
|
|
39
|
+
})
|
|
35
40
|
end
|
|
36
|
-
date = date.split('-')
|
|
37
|
-
@release.date = Time.utc(date[0], date[1], date[2])
|
|
38
|
-
@release.country = self.safe_get_value(xml, 'country')
|
|
39
|
-
@release
|
|
40
41
|
end
|
|
41
42
|
end
|
|
42
43
|
end
|
|
@@ -1,41 +1,41 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
|
-
class ReleaseGroup <
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
class ReleaseGroup < Base
|
|
5
|
+
|
|
6
|
+
field :id, String
|
|
7
|
+
field :type, String
|
|
8
|
+
field :title, String
|
|
9
|
+
field :disambiguation, String
|
|
10
|
+
field :first_release_date, Time
|
|
6
11
|
|
|
7
12
|
def releases
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
+
@releases ||= nil
|
|
14
|
+
if @releases.nil? and !id.nil?
|
|
15
|
+
@releases = self.class.load({
|
|
16
|
+
:parser => :release_group_releases,
|
|
17
|
+
:create_models => MusicBrainz::Release
|
|
18
|
+
}, {
|
|
19
|
+
:resource => :release,
|
|
20
|
+
:release_group => self.id,
|
|
21
|
+
:inc => [:media],
|
|
22
|
+
:limit => 100
|
|
23
|
+
})
|
|
24
|
+
@releases.sort!{ |a, b| a.date <=> b.date }
|
|
13
25
|
end
|
|
14
|
-
@releases
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def self.find mbid
|
|
18
|
-
xml = Nokogiri::XML(self.load(:release_group, :id => mbid)).css('release-group').first
|
|
19
|
-
self.parse_xml(xml) unless xml.nil?
|
|
26
|
+
@releases
|
|
20
27
|
end
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
elsif date.length == 4
|
|
32
|
-
date += '-12-31'
|
|
33
|
-
elsif date.length == 7
|
|
34
|
-
date += '-31'
|
|
29
|
+
class << self
|
|
30
|
+
def find(mbid)
|
|
31
|
+
load({
|
|
32
|
+
:parser => :release_group_model,
|
|
33
|
+
:create_model => MusicBrainz::ReleaseGroup
|
|
34
|
+
}, {
|
|
35
|
+
:resource => :release_group,
|
|
36
|
+
:id => mbid
|
|
37
|
+
})
|
|
35
38
|
end
|
|
36
|
-
date = date.split('-')
|
|
37
|
-
@release_group.first_release_date = Time.utc(date[0], date[1], date[2])
|
|
38
|
-
@release_group
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
data/lib/musicbrainz/track.rb
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
|
-
class Track <
|
|
4
|
-
attr_accessor :position, :recording_id, :title, :length
|
|
4
|
+
class Track < Base
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
field :position, Integer
|
|
7
|
+
field :recording_id, String
|
|
8
|
+
field :title, String
|
|
9
|
+
field :length, Integer
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
11
|
+
class << self
|
|
12
|
+
def find(mbid)
|
|
13
|
+
load({
|
|
14
|
+
:parser => :track_model,
|
|
15
|
+
:create_model => MusicBrainz::Track
|
|
16
|
+
}, {
|
|
17
|
+
:resource => :recording,
|
|
18
|
+
:id => mbid
|
|
19
|
+
})
|
|
20
|
+
end
|
|
19
21
|
end
|
|
20
22
|
end
|
|
21
23
|
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module MusicBrainz
|
|
4
|
+
module Parsers
|
|
5
|
+
class Artist < Base
|
|
6
|
+
class << self
|
|
7
|
+
def model(xml)
|
|
8
|
+
res = {
|
|
9
|
+
:id => safe_get_attr(xml, "artist", "id"),
|
|
10
|
+
:type => safe_get_attr(xml, "artist", "type"),
|
|
11
|
+
:name => safe_get_value(xml, "artist > name").gsub(/[`’]/, "'"),
|
|
12
|
+
:country => safe_get_value(xml, "artist > country"),
|
|
13
|
+
:date_begin => safe_get_value(xml, "artist > life-span > begin"),
|
|
14
|
+
:date_end => safe_get_value(xml, "artist > life-span > end"),
|
|
15
|
+
:urls => {}
|
|
16
|
+
}
|
|
17
|
+
xml.css("relation-list[target-type='url'] > relation").each { |rel|
|
|
18
|
+
res[:urls][rel.attr("type").downcase.split(" ").join("_").to_sym] = rel.css("target").text
|
|
19
|
+
}
|
|
20
|
+
res
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def search(xml)
|
|
24
|
+
artists = []
|
|
25
|
+
xml.css("artist-list > artist").each do |a|
|
|
26
|
+
artists << {
|
|
27
|
+
:name => a.first_element_child.text.gsub(/[`’]/, "'"),
|
|
28
|
+
:sort_name => safe_get_value(a, "sort-name").gsub(/[`’]/, "'"),
|
|
29
|
+
:weight => 0,
|
|
30
|
+
:desc => safe_get_value(a, "disambiguation"),
|
|
31
|
+
:type => safe_get_attr(a, nil, "type"),
|
|
32
|
+
:mbid => safe_get_attr(a, nil, "id"),
|
|
33
|
+
:aliases => a.css("alias-list > alias").map { |item| item.text }
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
artists
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def release_groups(xml)
|
|
40
|
+
release_groups = []
|
|
41
|
+
xml.css("release-group").each do |rg|
|
|
42
|
+
release_groups << MusicBrainz::Parsers::ReleaseGroup.model(rg)
|
|
43
|
+
end
|
|
44
|
+
release_groups
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
data/lib/parsers/base.rb
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module MusicBrainz
|
|
4
|
+
module Parsers
|
|
5
|
+
class << self
|
|
6
|
+
def get_by_name(name)
|
|
7
|
+
case name
|
|
8
|
+
when :artist_model
|
|
9
|
+
{ :const => MusicBrainz::Parsers::Artist, :method => :model }
|
|
10
|
+
when :artist_search
|
|
11
|
+
{ :const => MusicBrainz::Parsers::Artist, :method => :search }
|
|
12
|
+
when :artist_release_groups
|
|
13
|
+
{ :const => MusicBrainz::Parsers::Artist, :method => :release_groups }
|
|
14
|
+
when :release_group_model
|
|
15
|
+
{ :const => MusicBrainz::Parsers::ReleaseGroup, :method => :model }
|
|
16
|
+
when :release_group_releases
|
|
17
|
+
{ :const => MusicBrainz::Parsers::ReleaseGroup, :method => :releases }
|
|
18
|
+
when :release_model
|
|
19
|
+
{ :const => MusicBrainz::Parsers::Release, :method => :model }
|
|
20
|
+
when :release_tracks
|
|
21
|
+
{ :const => MusicBrainz::Parsers::Release, :method => :tracks }
|
|
22
|
+
when :track_model
|
|
23
|
+
{ :const => MusicBrainz::Parsers::Track, :method => :model }
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
class Base
|
|
29
|
+
class << self
|
|
30
|
+
def safe_get_attr(xml, path, name)
|
|
31
|
+
node = path.nil? ? xml : (xml.css(path).first unless xml.css(path).empty?)
|
|
32
|
+
node.attr(name) unless node.nil? or node.attr(name).nil?
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def safe_get_value(xml, path)
|
|
36
|
+
xml.css(path).first.text unless xml.css(path).empty?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module MusicBrainz
|
|
4
|
+
module Parsers
|
|
5
|
+
class Release < Base
|
|
6
|
+
class << self
|
|
7
|
+
def model(xml)
|
|
8
|
+
{
|
|
9
|
+
:id => safe_get_attr(xml, nil, "id") || safe_get_attr(xml, "release", "id"),
|
|
10
|
+
:title => safe_get_value(xml, "title"),
|
|
11
|
+
:status => safe_get_value(xml, "status"),
|
|
12
|
+
:country => safe_get_value(xml, "country"),
|
|
13
|
+
:format => safe_get_value(xml, "medium-list > medium > format"),
|
|
14
|
+
:date => safe_get_value(xml, "date")
|
|
15
|
+
}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def tracks(xml)
|
|
19
|
+
tracks = []
|
|
20
|
+
xml.css("medium-list > medium > track-list > track").each do |r|
|
|
21
|
+
tracks << MusicBrainz::Parsers::Track.model(r)
|
|
22
|
+
end
|
|
23
|
+
tracks
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module MusicBrainz
|
|
4
|
+
module Parsers
|
|
5
|
+
class ReleaseGroup < Base
|
|
6
|
+
class << self
|
|
7
|
+
def model(xml)
|
|
8
|
+
{
|
|
9
|
+
:id => safe_get_attr(xml, nil, "id") || safe_get_attr(xml, "release-group", "id"),
|
|
10
|
+
:type => safe_get_attr(xml, nil, "type") || safe_get_attr(xml, "release-group", "type"),
|
|
11
|
+
:title => safe_get_value(xml, "title"),
|
|
12
|
+
:disambiguation => safe_get_value(xml, "disambiguation"),
|
|
13
|
+
:first_release_date => safe_get_value(xml, "first-release-date")
|
|
14
|
+
}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def releases(xml)
|
|
18
|
+
releases = []
|
|
19
|
+
xml.css("release").each do |r|
|
|
20
|
+
releases << MusicBrainz::Parsers::Release.model(r)
|
|
21
|
+
end
|
|
22
|
+
releases
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
module MusicBrainz
|
|
4
|
+
module Parsers
|
|
5
|
+
class Track < Base
|
|
6
|
+
class << self
|
|
7
|
+
def model(xml)
|
|
8
|
+
{
|
|
9
|
+
:position => safe_get_value(xml, "position"),
|
|
10
|
+
:recording_id => safe_get_attr(xml, "recording", "id"),
|
|
11
|
+
:title => safe_get_value(xml, "recording > title"),
|
|
12
|
+
:length => safe_get_value(xml, "length") || safe_get_value(xml, "recording > length")
|
|
13
|
+
}
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
data/lib/tools/cache.rb
CHANGED
|
@@ -1,44 +1,47 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
4
|
module Tools
|
|
4
5
|
class Cache
|
|
5
|
-
|
|
6
|
+
class << self
|
|
7
|
+
@@cache_path = nil
|
|
6
8
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
def cache_path=(path)
|
|
10
|
+
@@cache_path = path
|
|
11
|
+
end
|
|
10
12
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
def cache_path
|
|
14
|
+
@@cache_path
|
|
15
|
+
end
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
def clear_cache
|
|
18
|
+
FileUtils.rm_r(@@cache_path) if @@cache_path && File.exist?(@@cache_path)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def cache_contents(url)
|
|
22
|
+
response = nil
|
|
23
|
+
url_parts = url.split('/')
|
|
24
|
+
file_name = url_parts.pop
|
|
25
|
+
directory = url_parts.pop
|
|
26
|
+
file_path = @@cache_path ? "#{@@cache_path}/#{directory}/#{file_name}" : nil
|
|
27
|
+
|
|
28
|
+
if file_path && File.exist?(file_path)
|
|
29
|
+
response = File.open(file_path).gets
|
|
30
|
+
else
|
|
31
|
+
response = yield
|
|
18
32
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
response = File.open(file_path).gets
|
|
28
|
-
else
|
|
29
|
-
response = yield
|
|
30
|
-
|
|
31
|
-
unless response.nil? or file_path.nil?
|
|
32
|
-
FileUtils.mkdir_p file_path.split('/')[0..-2].join('/')
|
|
33
|
-
file = File.new(file_path, 'w')
|
|
34
|
-
file.puts(response.gets) # .force_encoding('UTF-8')
|
|
35
|
-
file.chmod(0755)
|
|
36
|
-
file.close
|
|
37
|
-
response.rewind
|
|
33
|
+
unless response.nil? or file_path.nil?
|
|
34
|
+
FileUtils.mkdir_p file_path.split('/')[0..-2].join('/')
|
|
35
|
+
file = File.new(file_path, 'w')
|
|
36
|
+
file.puts(response.gets) # .force_encoding('UTF-8')
|
|
37
|
+
file.chmod(0755)
|
|
38
|
+
file.close
|
|
39
|
+
response.rewind
|
|
40
|
+
end
|
|
38
41
|
end
|
|
39
|
-
end
|
|
40
42
|
|
|
41
|
-
|
|
43
|
+
response
|
|
44
|
+
end
|
|
42
45
|
end
|
|
43
46
|
end
|
|
44
47
|
end
|
data/lib/tools/proxy.rb
CHANGED
|
@@ -1,53 +1,61 @@
|
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
2
3
|
module MusicBrainz
|
|
3
4
|
module Tools
|
|
4
5
|
class Proxy
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
6
|
+
class << self
|
|
7
|
+
@@last_query_time = 0
|
|
8
|
+
@@query_interval = 1.5 # Min: 1.0 Safe: 1.5
|
|
9
|
+
@@tries_limit = 5
|
|
10
|
+
|
|
11
|
+
WEB_SERVICE_URL = 'http://musicbrainz.org/ws/2/'
|
|
12
|
+
USER_AGENT = "gem musicbrainz (https://github.com/magnolia-fan/musicbrainz) @ " + Socket.gethostname
|
|
13
|
+
|
|
14
|
+
def query_interval=(sec)
|
|
15
|
+
@@query_interval = sec.to_f
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def query_interval
|
|
19
|
+
@@query_interval
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def tries_limit=(num)
|
|
23
|
+
@@tries_limit = num.to_i
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def query(params = {})
|
|
27
|
+
url = WEB_SERVICE_URL + params[:resource].to_s.gsub('_', '-') + '/' + (params[:id].to_s || '')
|
|
28
|
+
params.delete(:resource)
|
|
29
|
+
params.delete(:id) unless params[:id].nil?
|
|
30
|
+
url << '?' + params.map{ |k, v|
|
|
31
|
+
k = k.to_s.gsub('_', '-')
|
|
32
|
+
v = (v.is_a?(Array) ? v.map{ |_| _.to_s.gsub('_', '-') }.join('+') : v.to_s)
|
|
33
|
+
k + '=' + v
|
|
34
|
+
}.join('&') unless params.empty?
|
|
35
|
+
MusicBrainz::Tools::Cache.cache_contents(url) {
|
|
36
|
+
get_contents url
|
|
37
|
+
}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def get_contents(url)
|
|
41
|
+
response = nil
|
|
42
|
+
|
|
43
|
+
@@tries_limit.times {
|
|
44
|
+
time_passed = Time.now.to_f - @@last_query_time
|
|
45
|
+
sleep(@@query_interval - time_passed) if time_passed < @@query_interval
|
|
46
|
+
|
|
47
|
+
begin
|
|
48
|
+
response = open(url, "User-Agent" => USER_AGENT)
|
|
49
|
+
@@last_query_time = Time.now.to_f
|
|
50
|
+
rescue => e
|
|
51
|
+
response = nil if e.io.status[0].to_i == 404
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
break unless response.nil?
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
response
|
|
58
|
+
end
|
|
51
59
|
end
|
|
52
60
|
end
|
|
53
61
|
end
|
data/lib/version.rb
CHANGED
data/musicbrainz.gemspec
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?><metadata xmlns="http://musicbrainz.org/ns/mmd-2.0#"><artist type="Group" id="69b39eab-6577-46a4-a9f5-817839092033"><name>Kasabian</name><sort-name>Kasabian</sort-name><country>GB</country><life-span><begin>1999</begin></life-span><relation-list target-type="url"><relation type="allmusic"><target>http://allmusic.com/artist/p678134</target></relation><relation type="wikipedia"><target>http://en.wikipedia.org/wiki/Kasabian</target></relation><relation type="microblog"><target>http://twitter.com/kasabianhq</target></relation><relation type="BBC Music page"><target>http://www.bbc.co.uk/music/artists/69b39eab-6577-46a4-a9f5-817839092033</target></relation><relation type="discogs"><target>http://www.discogs.com/artist/Kasabian</target></relation><relation type="social network"><target>http://www.facebook.com/kasabian</target></relation><relation type="IMDb"><target>http://www.imdb.com/name/nm1868442/</target></relation><relation type="official homepage"><target>http://www.kasabian.co.uk/</target></relation><relation type="myspace"><target>http://www.myspace.com/kasabian</target></relation><relation type="youtube"><target>http://www.youtube.com/kasabianvevo</target></relation><relation type="youtube"><target>http://www.youtube.com/user/KasabianTour</target></relation></relation-list></artist></metadata>
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
3
|
+
require "spec_helper"
|
|
4
|
+
|
|
5
|
+
describe MusicBrainz do
|
|
6
|
+
before(:all) {
|
|
7
|
+
@old_cache_path = MusicBrainz::Tools::Cache.cache_path
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
before(:each) {
|
|
11
|
+
$stdout.stub!(:puts)
|
|
12
|
+
MusicBrainz::Tools::Cache.cache_path = nil
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
after(:all) {
|
|
16
|
+
MusicBrainz::Tools::Cache.cache_path = @old_cache_path
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
it "allows deprecated use of cache_path" do
|
|
20
|
+
MusicBrainz::Tools::Cache.cache_path = "some/path"
|
|
21
|
+
MusicBrainz::cache_path.should == "some/path"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "allows deprecated use of cache_path=" do
|
|
25
|
+
MusicBrainz.cache_path = "some/path"
|
|
26
|
+
MusicBrainz::Tools::Cache.cache_path.should == "some/path"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "allows deprecated use of query_interval" do
|
|
30
|
+
MusicBrainz::Tools::Proxy.query_interval = 2
|
|
31
|
+
MusicBrainz::query_interval.should == 2
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "allows deprecated use of query_interval=" do
|
|
35
|
+
MusicBrainz.query_interval = 2
|
|
36
|
+
MusicBrainz::Tools::Proxy.query_interval.should == 2
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
1
3
|
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
describe MusicBrainz::Artist do
|
|
@@ -21,7 +23,7 @@ describe MusicBrainz::Artist do
|
|
|
21
23
|
it "finds name first than alias" do
|
|
22
24
|
matches = MusicBrainz::Artist.search('Chris Martin')
|
|
23
25
|
matches.length.should be > 0
|
|
24
|
-
matches.first[:
|
|
26
|
+
matches.first[:mbid].should == "af2ab893-3212-4226-9e73-73a1660b6952"
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
it "gets correct result by name" do
|
|
@@ -35,7 +37,7 @@ describe MusicBrainz::Artist do
|
|
|
35
37
|
artist.type.should == "Group"
|
|
36
38
|
artist.name.should == "Kasabian"
|
|
37
39
|
artist.country.should == "GB"
|
|
38
|
-
artist.date_begin.should ==
|
|
40
|
+
artist.date_begin.year.should == 1999
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
it "gets correct artist's release groups" do
|
data/spec/requests/track_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/tools/cache_spec.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
|
|
1
3
|
require "spec_helper"
|
|
2
4
|
|
|
3
5
|
describe MusicBrainz::Tools::Cache do
|
|
@@ -11,32 +13,17 @@ describe MusicBrainz::Tools::Cache do
|
|
|
11
13
|
end
|
|
12
14
|
|
|
13
15
|
before(:each) do
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
'<artist type="Group" id="69b39eab-6577-46a4-a9f5-817839092033">'+
|
|
17
|
-
'<name>Kasabian</name><sort-name>Kasabian</sort-name><country>GB</country>'+
|
|
18
|
-
'<life-span><begin>1999</begin></life-span><relation-list target-type="url">'+
|
|
19
|
-
'<relation type="allmusic"><target>http://allmusic.com/artist/p678134</target>'+
|
|
20
|
-
'</relation><relation type="wikipedia"><target>http://en.wikipedia.org/wiki/Kasabian</target>'+
|
|
21
|
-
'</relation><relation type="microblog"><target>http://twitter.com/kasabianhq</target>'+
|
|
22
|
-
'</relation><relation type="BBC Music page"><target>'+
|
|
23
|
-
'http://www.bbc.co.uk/music/artists/69b39eab-6577-46a4-a9f5-817839092033</target></relation>'+
|
|
24
|
-
'<relation type="discogs"><target>http://www.discogs.com/artist/Kasabian</target></relation>'+
|
|
25
|
-
'<relation type="social network"><target>http://www.facebook.com/kasabian</target></relation>'+
|
|
26
|
-
'<relation type="IMDb"><target>http://www.imdb.com/name/nm1868442/</target></relation>'+
|
|
27
|
-
'<relation type="official homepage"><target>http://www.kasabian.co.uk/</target></relation>'+
|
|
28
|
-
'<relation type="myspace"><target>http://www.myspace.com/kasabian</target></relation>'+
|
|
29
|
-
'<relation type="youtube"><target>http://www.youtube.com/kasabianvevo</target></relation>'+
|
|
30
|
-
'<relation type="youtube"><target>http://www.youtube.com/user/KasabianTour</target></relation>'+
|
|
31
|
-
'</relation-list></artist></metadata>')
|
|
16
|
+
file_path = File.join(File.dirname(__FILE__), "../fixtures/kasabian.xml")
|
|
17
|
+
@test_response = ::StringIO.new(File.open(file_path).gets)
|
|
32
18
|
end
|
|
33
19
|
|
|
34
20
|
context "with cache enabled" do
|
|
35
21
|
it "calls get contents only once when requesting the resource twice" do
|
|
36
22
|
MusicBrainz::Tools::Cache.cache_path = @tmp_cache_path
|
|
23
|
+
mbid = "69b39eab-6577-46a4-a9f5-817839092033"
|
|
24
|
+
|
|
37
25
|
MusicBrainz::Tools::Proxy.stub(:get_contents).and_return(@test_response)
|
|
38
26
|
MusicBrainz::Tools::Proxy.should_receive(:get_contents).once
|
|
39
|
-
mbid = "69b39eab-6577-46a4-a9f5-817839092033"
|
|
40
27
|
|
|
41
28
|
File.exist?("#{@tmp_cache_path}/artist/#{mbid}?inc=url-rels").should be_false
|
|
42
29
|
artist = MusicBrainz::Artist.find(mbid)
|
|
@@ -53,9 +40,10 @@ describe MusicBrainz::Tools::Cache do
|
|
|
53
40
|
context "with cache disabled" do
|
|
54
41
|
it "calls get contents twice when requesting the resource twice" do
|
|
55
42
|
MusicBrainz::Tools::Cache.cache_path = nil
|
|
43
|
+
mbid = "69b39eab-6577-46a4-a9f5-817839092033"
|
|
44
|
+
|
|
56
45
|
MusicBrainz::Tools::Proxy.stub(:get_contents).and_return(@test_response)
|
|
57
46
|
MusicBrainz::Tools::Proxy.should_receive(:get_contents).twice
|
|
58
|
-
mbid = "69b39eab-6577-46a4-a9f5-817839092033"
|
|
59
47
|
|
|
60
48
|
File.exist?("#{@tmp_cache_path}/artist/#{mbid}?inc=url-rels").should be_false
|
|
61
49
|
artist = MusicBrainz::Artist.find(mbid)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: musicbrainz
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.7.0
|
|
5
5
|
prerelease:
|
|
6
6
|
platform: ruby
|
|
7
7
|
authors:
|
|
@@ -9,11 +9,11 @@ authors:
|
|
|
9
9
|
autorequire:
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
|
-
date: 2012-07-
|
|
12
|
+
date: 2012-07-08 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
|
14
14
|
- !ruby/object:Gem::Dependency
|
|
15
15
|
name: nokogiri
|
|
16
|
-
requirement:
|
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
|
17
17
|
none: false
|
|
18
18
|
requirements:
|
|
19
19
|
- - ! '>='
|
|
@@ -21,10 +21,15 @@ dependencies:
|
|
|
21
21
|
version: '0'
|
|
22
22
|
type: :runtime
|
|
23
23
|
prerelease: false
|
|
24
|
-
version_requirements:
|
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
25
|
+
none: false
|
|
26
|
+
requirements:
|
|
27
|
+
- - ! '>='
|
|
28
|
+
- !ruby/object:Gem::Version
|
|
29
|
+
version: '0'
|
|
25
30
|
- !ruby/object:Gem::Dependency
|
|
26
31
|
name: rake
|
|
27
|
-
requirement:
|
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
|
28
33
|
none: false
|
|
29
34
|
requirements:
|
|
30
35
|
- - ! '>='
|
|
@@ -32,10 +37,15 @@ dependencies:
|
|
|
32
37
|
version: '0'
|
|
33
38
|
type: :development
|
|
34
39
|
prerelease: false
|
|
35
|
-
version_requirements:
|
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
41
|
+
none: false
|
|
42
|
+
requirements:
|
|
43
|
+
- - ! '>='
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
36
46
|
- !ruby/object:Gem::Dependency
|
|
37
47
|
name: awesome_print
|
|
38
|
-
requirement:
|
|
48
|
+
requirement: !ruby/object:Gem::Requirement
|
|
39
49
|
none: false
|
|
40
50
|
requirements:
|
|
41
51
|
- - ! '>='
|
|
@@ -43,10 +53,15 @@ dependencies:
|
|
|
43
53
|
version: '0'
|
|
44
54
|
type: :development
|
|
45
55
|
prerelease: false
|
|
46
|
-
version_requirements:
|
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
57
|
+
none: false
|
|
58
|
+
requirements:
|
|
59
|
+
- - ! '>='
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
47
62
|
- !ruby/object:Gem::Dependency
|
|
48
63
|
name: rspec
|
|
49
|
-
requirement:
|
|
64
|
+
requirement: !ruby/object:Gem::Requirement
|
|
50
65
|
none: false
|
|
51
66
|
requirements:
|
|
52
67
|
- - ! '>='
|
|
@@ -54,7 +69,12 @@ dependencies:
|
|
|
54
69
|
version: '0'
|
|
55
70
|
type: :development
|
|
56
71
|
prerelease: false
|
|
57
|
-
version_requirements:
|
|
72
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
73
|
+
none: false
|
|
74
|
+
requirements:
|
|
75
|
+
- - ! '>='
|
|
76
|
+
- !ruby/object:Gem::Version
|
|
77
|
+
version: '0'
|
|
58
78
|
description:
|
|
59
79
|
email:
|
|
60
80
|
- magnolia_fan@me.com
|
|
@@ -65,6 +85,7 @@ files:
|
|
|
65
85
|
- .gitignore
|
|
66
86
|
- .rspec
|
|
67
87
|
- .travis.yml
|
|
88
|
+
- Contributors
|
|
68
89
|
- Gemfile
|
|
69
90
|
- LICENSE
|
|
70
91
|
- README.md
|
|
@@ -76,10 +97,17 @@ files:
|
|
|
76
97
|
- lib/musicbrainz/release.rb
|
|
77
98
|
- lib/musicbrainz/release_group.rb
|
|
78
99
|
- lib/musicbrainz/track.rb
|
|
100
|
+
- lib/parsers/artist.rb
|
|
101
|
+
- lib/parsers/base.rb
|
|
102
|
+
- lib/parsers/release.rb
|
|
103
|
+
- lib/parsers/release_group.rb
|
|
104
|
+
- lib/parsers/track.rb
|
|
79
105
|
- lib/tools/cache.rb
|
|
80
106
|
- lib/tools/proxy.rb
|
|
81
107
|
- lib/version.rb
|
|
82
108
|
- musicbrainz.gemspec
|
|
109
|
+
- spec/fixtures/kasabian.xml
|
|
110
|
+
- spec/misc/deprecated_spec.rb
|
|
83
111
|
- spec/requests/artist_spec.rb
|
|
84
112
|
- spec/requests/release_group_spec.rb
|
|
85
113
|
- spec/requests/release_spec.rb
|
|
@@ -107,11 +135,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
107
135
|
version: '0'
|
|
108
136
|
requirements: []
|
|
109
137
|
rubyforge_project:
|
|
110
|
-
rubygems_version: 1.8.
|
|
138
|
+
rubygems_version: 1.8.23
|
|
111
139
|
signing_key:
|
|
112
140
|
specification_version: 3
|
|
113
141
|
summary: MusicBrainz Web Service wrapper with ActiveRecord-style models
|
|
114
142
|
test_files:
|
|
143
|
+
- spec/fixtures/kasabian.xml
|
|
144
|
+
- spec/misc/deprecated_spec.rb
|
|
115
145
|
- spec/requests/artist_spec.rb
|
|
116
146
|
- spec/requests/release_group_spec.rb
|
|
117
147
|
- spec/requests/release_spec.rb
|