rbrainz 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. data/CHANGES +31 -0
  2. data/LICENSE +1 -1
  3. data/README +3 -2
  4. data/Rakefile +40 -22
  5. data/TODO +6 -23
  6. data/doc/README.rdoc +50 -21
  7. data/examples/getartist.rb +6 -4
  8. data/examples/getuser.rb +30 -0
  9. data/examples/searchartists.rb +35 -0
  10. data/lib/rbrainz.rb +12 -7
  11. data/lib/rbrainz/core_ext.rb +8 -0
  12. data/lib/rbrainz/core_ext/mbid.rb +30 -0
  13. data/lib/rbrainz/core_ext/net_http_digest.rb +52 -0
  14. data/lib/rbrainz/core_ext/range.rb +28 -0
  15. data/lib/rbrainz/core_ext/range/equality.rb +232 -0
  16. data/lib/rbrainz/data/countrynames.rb +7 -5
  17. data/lib/rbrainz/data/languagenames.rb +8 -5
  18. data/lib/rbrainz/data/releasetypenames.rb +34 -0
  19. data/lib/rbrainz/data/scriptnames.rb +8 -5
  20. data/lib/rbrainz/model.rb +27 -35
  21. data/lib/rbrainz/model/alias.rb +31 -7
  22. data/lib/rbrainz/model/artist.rb +30 -41
  23. data/lib/rbrainz/model/collection.rb +102 -0
  24. data/lib/rbrainz/model/default_factory.rb +78 -0
  25. data/lib/rbrainz/model/disc.rb +45 -8
  26. data/lib/rbrainz/model/entity.rb +122 -53
  27. data/lib/rbrainz/model/incomplete_date.rb +31 -47
  28. data/lib/rbrainz/model/individual.rb +103 -0
  29. data/lib/rbrainz/model/label.rb +42 -33
  30. data/lib/rbrainz/model/mbid.rb +111 -40
  31. data/lib/rbrainz/model/relation.rb +78 -14
  32. data/lib/rbrainz/model/release.rb +119 -31
  33. data/lib/rbrainz/model/release_event.rb +38 -9
  34. data/lib/rbrainz/model/scored_collection.rb +99 -0
  35. data/lib/rbrainz/model/tag.rb +39 -0
  36. data/lib/rbrainz/model/track.rb +37 -13
  37. data/lib/rbrainz/model/user.rb +48 -0
  38. data/lib/rbrainz/utils.rb +9 -0
  39. data/lib/rbrainz/utils/data.rb +78 -0
  40. data/lib/rbrainz/utils/helper.rb +22 -0
  41. data/lib/rbrainz/version.rb +15 -0
  42. data/lib/rbrainz/webservice.rb +32 -6
  43. data/lib/rbrainz/webservice/filter.rb +124 -47
  44. data/lib/rbrainz/webservice/includes.rb +49 -10
  45. data/lib/rbrainz/webservice/mbxml.rb +228 -173
  46. data/lib/rbrainz/webservice/query.rb +312 -25
  47. data/lib/rbrainz/webservice/webservice.rb +164 -27
  48. data/test/lib/mock_webservice.rb +53 -0
  49. data/test/lib/test_entity.rb +27 -8
  50. data/test/lib/test_factory.rb +47 -0
  51. data/test/lib/testing_helper.rb +7 -5
  52. data/test/test-data/invalid/artist/tags_1.xml +6 -0
  53. data/test/test-data/valid/artist/Tchaikovsky-2.xml +12 -0
  54. data/test/test-data/valid/label/Atlantic_Records_2.xml +3 -0
  55. data/test/test-data/valid/label/Atlantic_Records_3.xml +11 -0
  56. data/test/test-data/valid/release/Highway_61_Revisited_2.xml +12 -0
  57. data/test/test-data/valid/track/Silent_All_These_Years_6.xml +8 -0
  58. data/test/test_alias.rb +13 -7
  59. data/test/test_artist.rb +26 -4
  60. data/test/test_artist_filter.rb +11 -6
  61. data/test/test_artist_includes.rb +11 -6
  62. data/test/test_collection.rb +66 -0
  63. data/test/test_default_factory.rb +75 -0
  64. data/test/test_disc.rb +9 -4
  65. data/test/test_incomplete_date.rb +21 -14
  66. data/test/test_label.rb +56 -18
  67. data/test/test_label_filter.rb +10 -5
  68. data/test/test_label_includes.rb +11 -6
  69. data/test/test_mbid.rb +34 -19
  70. data/test/test_mbxml.rb +242 -72
  71. data/test/test_query.rb +92 -7
  72. data/test/test_range_equality.rb +144 -0
  73. data/test/test_relation.rb +18 -7
  74. data/test/test_release.rb +15 -4
  75. data/test/test_release_event.rb +16 -4
  76. data/test/test_release_filter.rb +11 -5
  77. data/test/test_release_includes.rb +11 -6
  78. data/test/test_scored_collection.rb +86 -0
  79. data/test/test_tag.rb +39 -0
  80. data/test/test_track.rb +15 -4
  81. data/test/test_track_filter.rb +11 -5
  82. data/test/test_track_includes.rb +11 -6
  83. data/test/test_utils.rb +41 -0
  84. data/test/test_webservice.rb +16 -17
  85. metadata +93 -57
@@ -1,66 +1,136 @@
1
- # $Id: mbid.rb 17 2007-05-23 16:51:11Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: mbid.rb 146 2007-07-19 16:33:38Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
- require 'rbrainz/model'
8
+ require 'uri'
7
9
 
8
10
  module MusicBrainz
9
11
  module Model
10
12
 
13
+ # The format of a MusicBrainz identifier was wrong.
14
+ #
15
+ # See:: MBID
16
+ class InvalidMBIDError < Exception
17
+ end
18
+
19
+ # An unknown entity was encountered.
20
+ #
21
+ # Valid entities are only <tt>:artist</tt>, <tt>:release</tt>,
22
+ # <tt>:track</tt> and <tt>:label</tt>.
23
+ #
24
+ # See:: MBID
25
+ class UnknownEntityError < Exception
26
+ end
27
+
28
+ # The entity type of a MBID didn't match the type of the entity.
29
+ #
30
+ # See:: MBID
31
+ class EntityTypeNotMatchingError < Exception
32
+ end
33
+
11
34
  # Represents a MusicBrainz identifier.
12
35
  #
13
- # A MusicBrainz identifier is an URI identifying a resource like an artist or a track.
14
- # It consists of an URI prefix, the entity type it refers to and an UUID that
15
- # identifies the referenced entity.
36
+ # A MusicBrainz identifier is an URI identifying a resource like an artist
37
+ # or a track.
38
+ # It consists of an URI prefix, the entity type it refers to and an UUID
39
+ # that identifies the referenced entity.
16
40
  #
17
- # See http://musicbrainz.org/doc/MusicBrainzIdentifier.
41
+ # Example:
42
+ # http://musicbrainz.org/artist/6a2ca1ac-408d-49b0-a7f6-cd608f2f684f
18
43
  #
19
- # Example: http://musicbrainz.org/artist/6a2ca1ac-408d-49b0-a7f6-cd608f2f684f.
44
+ # See:: http://musicbrainz.org/doc/MusicBrainzIdentifier
20
45
  class MBID
21
46
 
22
- attr_reader :entity, :uuid
47
+ # The entity type (<tt>:artist</tt>, <tt>:label</tt>, <tt>:release</tt>,
48
+ # <tt>:track</tt>) this MBID references.
49
+ attr_reader :entity
23
50
 
24
- ENTITY_URI = 'http://musicbrainz.org/%s/%s'
25
- ENTITY_URI_REGEXP = /^http:\/\/musicbrainz.org\/(artist|release|track|label)\/([a-f0-9]{8}(-[a-f0-9]{4}){3}-[a-f0-9]{12})\/?$/
51
+ # The UUID of the referenced entity.
52
+ attr_reader :uuid
26
53
 
27
- # We make new private. Use from_uri or from_uuid instead.
28
- private_class_method :new
54
+ module PATTERN #:nodoc:
55
+ UUID = '([a-fA-F0-9]{8}(:?-[a-fA-F0-9]{4}){3}-[a-fA-F0-9]{12})'
56
+ ENTITY_TYPE = '(artist|release|track|label)'
57
+ ENTITY_URI = "http://musicbrainz\\.org/#{ENTITY_TYPE}/#{UUID}"
58
+ end
59
+
60
+ # A regular expression describing the format of a UUID.
61
+ UUID_REGEXP = Regexp.new('^' + PATTERN::UUID + '$')
62
+ # A regular expression to test if a string is a valid entity type.
63
+ ENTITY_TYPE_REGEXP = Regexp.new('^' + PATTERN::ENTITY_TYPE + '$')
64
+ # A regular expression describing a MusicBrainz identifier URI.
65
+ ENTITY_URI_REGEXP = Regexp.new('^' + PATTERN::ENTITY_URI + '$')
29
66
 
30
- # Creates a new MBID from a MBID URI, e.g.
31
- # http://musicbrainz.org/artist/6a2ca1ac-408d-49b0-a7f6-cd608f2f684f
32
- def self.from_uri(uri)
33
- if match = ENTITY_URI_REGEXP.match(uri)
34
- entity = match[1]
35
- uuid = match[2]
67
+ # The general format of a MusicBrainz identifier URI.
68
+ ENTITY_URI = 'http://musicbrainz.org/%s/%s'
69
+
70
+ # Tries to convert _str_ into a MBID using its to_mbid method.
71
+ #
72
+ # If _str_ does not respond to to_mbid a new MBID is created
73
+ # using the given parameters.
74
+ #
75
+ # See:: new
76
+ # See:: String#to_mbid, URI::HTTP#to_mbid
77
+ def self.parse(str, entity_type=nil)
78
+ if str.respond_to? :to_mbid
79
+ str.to_mbid(entity_type)
36
80
  else
37
- raise InvalidMBIDError.new(uri.inspect)
81
+ MBID.new(str, entity_type)
38
82
  end
39
- from_uuid(entity, uuid)
40
83
  end
41
84
 
42
- # Create a new MBID from the entity type and the UUID.
85
+ # Create a new MBID.
43
86
  #
44
- # The entity type must be <tt>:artist</tt>, <tt>:release</tt>,
45
- # <tt>:track</tt> or <tt>:label</tt>. The UUID is the last
46
- # part of the URI, e.g. <tt>6a2ca1ac-408d-49b0-a7f6-cd608f2f684f</tt>.
87
+ # _str_ can be either a complete identifier or just the UUID part of it.
88
+ # In the latter case the entity type (<tt>:artist</tt>, <tt>:label</tt>,
89
+ # <tt>:release</tt> or <tt>:track</tt>) has to be specified as well.
47
90
  #
48
- # Raises: +UnknownEntityError+, +InvalidUUIDError+
49
- def self.from_uuid(entity, uuid)
50
- if entity.nil? or entity == '' or
51
- not [:artist, :release, :track, :label].include? entity.to_sym
52
- raise UnknownEntityError.new(entity.to_s)
91
+ # Examples:
92
+ # require 'rbrainz'
93
+ # include MusicBrainz
94
+ # id = Model::MBID.new('http://musicbrainz.org/artist/10bf95b6-30e3-44f1-817f-45762cdc0de0')
95
+ # id = Model::MBID.new('10bf95b6-30e3-44f1-817f-45762cdc0de0', :artist)
96
+ #
97
+ # Raises:: UnknownEntityError, EntityTypeNotMatchingError,
98
+ # InvalidMBIDError
99
+ def initialize(str, entity_type=nil)
100
+ str = str.to_s if str.respond_to? :to_s
101
+ if entity_type && !(entity_type.to_s =~ ENTITY_TYPE_REGEXP )
102
+ raise UnknownEntityError, entity_type
53
103
  end
54
- unless uuid.is_a? String and uuid =~ UUID_REGEXP
55
- raise InvalidUUIDError.new(uuid.inspect)
104
+ entity_type = entity_type.to_sym if entity_type.respond_to? :to_sym
105
+
106
+ if str =~ ENTITY_URI_REGEXP
107
+ @entity = $1.to_sym
108
+ @uuid = $2.downcase
109
+ unless entity_type.nil? || @entity == entity_type
110
+ raise EntityTypeNotMatchingError, "#{@entity}, #{entity_type}"
111
+ end
112
+ elsif str =~ UUID_REGEXP
113
+ unless entity_type
114
+ raise UnknownEntityError, "nil is not a valid entity type"
115
+ end
116
+ @entity = entity_type
117
+ @uuid = str.downcase
118
+ else
119
+ raise InvalidMBIDError, str
56
120
  end
57
- new(entity.to_sym, uuid)
58
121
  end
59
122
 
60
- # Initialize the UUID given the entity type and an UUID.
61
- def initialize(entity, uuid) # :notnew:
62
- @entity = entity
63
- @uuid = uuid
123
+ # Returns self.
124
+ #
125
+ # If _entity_type_ is given it must match the entity type of the MBID
126
+ # or an EntityTypeNotMatchingError will be raised.
127
+ #
128
+ # Raises:: EntityTypeNotMatchingError
129
+ def to_mbid(entity_type=nil)
130
+ unless entity_type.nil? || @entity == entity_type
131
+ raise EntityTypeNotMatchingError, "#{self.entity}, #{entity_type}"
132
+ end
133
+ self
64
134
  end
65
135
 
66
136
  # Returns the string representation of the MBID (that is the complete URI).
@@ -73,10 +143,11 @@ module MusicBrainz
73
143
  # Two MBIDs are considered equal if both their entity
74
144
  # type and their UUID are equal.
75
145
  def ==(other)
146
+ other = other.to_mbid if other.respond_to? :to_mbid
76
147
  self.entity == other.entity and self.uuid == other.uuid
77
148
  end
78
149
 
79
150
  end
80
151
 
81
152
  end
82
- end
153
+ end
@@ -1,36 +1,93 @@
1
- # $Id: relation.rb 33 2007-05-29 14:48:47Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: relation.rb 145 2007-07-19 13:11:44Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
8
  module MusicBrainz
7
9
  module Model
8
10
 
9
- # Relationship class.
11
+ ##
12
+ # Represents a relation between two Entities.
13
+ #
14
+ # There may be an arbitrary number of relations between all first
15
+ # class objects in MusicBrainz. The Relation itself has multiple
16
+ # attributes, which may or may not be used for a given relation
17
+ # type.
18
+ #
19
+ # Note that a Relation object only contains the target but not
20
+ # the source end of the relation.
21
+ #
22
+ # TODO:: Add some examples.
23
+ #
10
24
  class Relation
11
25
 
26
+ # Relation reading direction is from target to source.
12
27
  DIR_BACKWARD = :backward
28
+ # Relation reading direction is from source to target.
13
29
  DIR_FORWARD = :forward
30
+ # Relation reading direction doesn't matter.
14
31
  DIR_BOTH = :both
15
32
 
33
+ # Identifies relations linking to an artist.
16
34
  TO_ARTIST = NS_REL_1 + 'Artist'
35
+ # Identifies relations linking to a release.
17
36
  TO_RELEASE = NS_REL_1 + 'Release'
37
+ # Identifies relations linking to a track.
18
38
  TO_TRACK = NS_REL_1 + 'Track'
39
+ # Identifies relations linking to a label.
19
40
  TO_LABEL = NS_REL_1 + 'Label'
41
+ # Identifies relations linking to an URL.
20
42
  TO_URL = NS_REL_1 + 'Url'
21
43
 
22
- attr_accessor :type, :direction
44
+ # The relation's type.
45
+ attr_accessor :type
23
46
 
24
- attr_reader :target, :begin_date, :end_date, :attributes
47
+ # The reading direction.
48
+ #
49
+ # The direction may be one of DIR_FORWARD, DIR_BACKWARD, or DIR_BOTH,
50
+ # depending on how the relation should be read. For example,
51
+ # if direction is DIR_FORWARD for a cover relation,
52
+ # it is read as "X is a cover of Y". Some relations are
53
+ # bidirectional, like marriages. In these cases, the direction
54
+ # is Relation.DIR_BOTH.
55
+ attr_accessor :direction
25
56
 
26
- def initialize
27
- @attributes = Array.new
28
- @target = nil
57
+ # The relation's target object.
58
+ attr_reader :target
59
+
60
+ # The list of attributes describing this relation.
61
+ #
62
+ # The attributes permitted depend on the relation type.
63
+ attr_reader :attributes
64
+
65
+ # The begin date.
66
+ #
67
+ # The definition depends on the relation's type. It may for
68
+ # example be the day of a marriage or the year an artist
69
+ # joined a band. For other relation types this may be
70
+ # undefined.
71
+ attr_reader :begin_date
72
+
73
+ # The end date.
74
+ #
75
+ # As with the begin date, the definition depends on the
76
+ # relation's type. Depending on the relation type, this may
77
+ # or may not be defined.
78
+ attr_reader :end_date
79
+
80
+ def initialize(type=nil, target=nil, direction=nil)
81
+ @target = nil
82
+ @attributes = Array.new
83
+ self.type = type
84
+ self.target = target if target
85
+ self.direction = direction
29
86
  end
30
87
 
31
88
  # Set the target of this relation.
32
89
  #
33
- # The target can either be a object of the type Model::Entity
90
+ # The _target_ can either be a object of the type Model::Entity
34
91
  # or a URL.
35
92
  def target=(target)
36
93
  if target.is_a? Entity
@@ -40,7 +97,14 @@ module MusicBrainz
40
97
  end
41
98
  end
42
99
 
43
- # Get the target type.
100
+ # The type of target this relation points to.
101
+ #
102
+ # For MusicBrainz data, the following target types are defined:
103
+ # - artists: #TO_ARTIST
104
+ # - labels: #TO_LABEL
105
+ # - releases: #TO_RELEASE
106
+ # - tracks: #TO_TRACK
107
+ # - urls: #TO_URL
44
108
  def target_type
45
109
  if @target.is_a? Model::Entity
46
110
  case @target.entity_type
@@ -58,7 +122,7 @@ module MusicBrainz
58
122
  end
59
123
  end
60
124
 
61
- # Set the begin date of this relation.
125
+ # Set the begin date of this relation to _date_.
62
126
  #
63
127
  # Should be an IncompleteDate object or
64
128
  # a date string, which will get converted
@@ -68,7 +132,7 @@ module MusicBrainz
68
132
  @begin_date = date
69
133
  end
70
134
 
71
- # Set the end date of this relation.
135
+ # Set the end date of this relation to _date_.
72
136
  #
73
137
  # Should be an IncompleteDate object or
74
138
  # a date string, which will get converted
@@ -1,7 +1,9 @@
1
- # $Id: release.rb 30 2007-05-29 02:12:33Z phw $
2
- # Copyright (c) 2007, Philipp Wolfer
3
- # All rights reserved.
4
- # See LICENSE for permissions.
1
+ # $Id: release.rb 145 2007-07-19 13:11:44Z phw $
2
+ #
3
+ # Author:: Philipp Wolfer (mailto:phw@rubyforge.org)
4
+ # Copyright:: Copyright (c) 2007, Nigel Graham, Philipp Wolfer
5
+ # License:: RBrainz is free software distributed under a BSD style license.
6
+ # See LICENSE[file:../LICENSE.html] for permissions.
5
7
 
6
8
  require 'rbrainz/model/entity'
7
9
  require 'rbrainz/model/release_event'
@@ -10,39 +12,125 @@ require 'rbrainz/model/disc'
10
12
  module MusicBrainz
11
13
  module Model
12
14
 
15
+ #
13
16
  # A release in the MusicBrainz DB.
14
- #
15
- # See http://musicbrainz.org/doc/Release.
17
+ #
18
+ # A release within MusicBrainz is an Entity which contains Track
19
+ # objects. Releases may be of more than one type: There can be albums,
20
+ # singles, compilations, live recordings, official releases, bootlegs
21
+ # etc.
22
+ #
23
+ # See:: http://musicbrainz.org/doc/Release.
24
+ # Note:: The current MusicBrainz server implementation supports only a
25
+ # limited set of types.
26
+ #
16
27
  class Release < Entity
17
28
 
18
- TYPE_ALBUM = NS_MMD_1 + 'Album'
19
- TYPE_AUDIOBOOK = NS_MMD_1 + 'Audiobook'
20
- TYPE_BOOTLEG = NS_MMD_1 + 'Bootleg'
21
- TYPE_COMPILATION = NS_MMD_1 + 'Compilation'
22
- TYPE_EP = NS_MMD_1 + 'EP'
23
- TYPE_INTERVIEW = NS_MMD_1 + 'Interview'
24
- TYPE_LIVE = NS_MMD_1 + 'Live'
25
- TYPE_NONE = NS_MMD_1 + 'None'
26
- TYPE_OFFICIAL = NS_MMD_1 + 'Official'
27
- TYPE_OTHER = NS_MMD_1 + 'Other'
28
- TYPE_PROMOTION = NS_MMD_1 + 'Promotion'
29
- TYPE_PSEUDO_RELEASE = NS_MMD_1 + 'Pseudo-Release'
30
- TYPE_REMIX = NS_MMD_1 + 'Remix'
31
- TYPE_SINGLE = NS_MMD_1 + 'Single'
32
- TYPE_SOUNDTRACK = NS_MMD_1 + 'Soundtrack'
33
- TYPE_SPOKENWORD = NS_MMD_1 + 'Spokenword'
29
+ TYPE_ALBUM = NS_MMD_1 + 'Album'
30
+ TYPE_AUDIOBOOK = NS_MMD_1 + 'Audiobook'
31
+ TYPE_BOOTLEG = NS_MMD_1 + 'Bootleg'
32
+ TYPE_COMPILATION = NS_MMD_1 + 'Compilation'
33
+ TYPE_EP = NS_MMD_1 + 'EP'
34
+ TYPE_INTERVIEW = NS_MMD_1 + 'Interview'
35
+ TYPE_LIVE = NS_MMD_1 + 'Live'
36
+ TYPE_NONE = NS_MMD_1 + 'None'
37
+ TYPE_OFFICIAL = NS_MMD_1 + 'Official'
38
+ TYPE_OTHER = NS_MMD_1 + 'Other'
39
+ TYPE_PROMOTION = NS_MMD_1 + 'Promotion'
40
+ TYPE_PSEUDO_RELEASE = NS_MMD_1 + 'Pseudo-Release'
41
+ TYPE_REMIX = NS_MMD_1 + 'Remix'
42
+ TYPE_SINGLE = NS_MMD_1 + 'Single'
43
+ TYPE_SOUNDTRACK = NS_MMD_1 + 'Soundtrack'
44
+ TYPE_SPOKENWORD = NS_MMD_1 + 'Spokenword'
34
45
 
35
- attr_accessor :title, :asin, :artist,
36
- :text_language, :text_script
46
+ # See Entity::ENTITY_TYPE.
47
+ ENTITY_TYPE = :release # :nodoc:
48
+
49
+ # The title of this release.
50
+ attr_accessor :title
51
+
52
+ # The amazon shop identifier.
53
+ #
54
+ # The ASIN is a 10-letter code (except for books) assigned
55
+ # by Amazon, which looks like 'B000002IT2' or 'B00006I4YD'.
56
+ attr_accessor :asin
57
+
58
+ # The main artist of this release.
59
+ attr_accessor :artist
60
+
61
+ # The language used in release and track titles.
62
+ #
63
+ # To represent the language, the ISO-639-2/T standard is used,
64
+ # which provides three-letter terminological language codes like
65
+ # 'ENG', 'DEU', 'JPN', 'KOR', 'ZHO' or 'YID'.
66
+ #
67
+ # Note that this refers to release and track <i>titles</i>, not
68
+ # lyrics.
69
+ #
70
+ # See:: Utils#get_language_name
71
+ attr_accessor :text_language
72
+
73
+ # The script used in release and track titles.
74
+ #
75
+ # To represent the script, ISO-15924 script codes are used.
76
+ # Valid codes are, among others: 'Latn', 'Cyrl', 'Hans', 'Hebr'
77
+ #
78
+ # Note that this refers to release and track <i>titles</i>, not
79
+ # lyrics.
80
+ #
81
+ # See:: Utils#get_script_name
82
+ attr_accessor :text_script
37
83
 
38
- attr_reader :tracks, :release_events, :discs, :types
84
+ # The list of tracks.
85
+ attr_reader :tracks
86
+
87
+ # The list of release events.
88
+ #
89
+ # A Release may contain a list of so-called release events,
90
+ # each represented using a ReleaseEvent object. Release
91
+ # events specify where and when this release was, well, released.
92
+ attr_reader :release_events
93
+
94
+ # The list of associated discs.
95
+ #
96
+ # Note that under rare circumstances (identical TOCs), a
97
+ # Disc could be associated with more than one release.
98
+ attr_reader :discs
99
+
100
+ # The list of types for this release.
101
+ #
102
+ # To test for release types, you can use the constants
103
+ # TYPE_ALBUM, TYPE_SINGLE, etc.
104
+ attr_reader :types
39
105
 
40
- def initialize
41
- super
42
- @tracks = Array.new
43
- @release_events = Array.new
44
- @discs = Array.new
45
- @types = Array.new
106
+ def initialize(id=nil, title=nil)
107
+ super id
108
+ self.title = title
109
+ @tracks = Collection.new
110
+ @release_events = Collection.new
111
+ @discs = Collection.new
112
+ @types = Array.new
113
+ end
114
+
115
+ #
116
+ # Checks if this is a single artist's release.
117
+ #
118
+ # Returns +true+ if the release's main artist (#artist) is
119
+ # also the main artist for all of the tracks. This is checked by
120
+ # comparing the artist IDs.
121
+ #
122
+ # Note that the release's artist has to be set (see #artist=)
123
+ # for this. The track artists may be unset.
124
+ def single_artist_release?
125
+ raise 'Release Artist may not be None!' unless artist
126
+ tracks.all {|track| !track.artist || track.artist.id == artist.id }
127
+ end
128
+
129
+ # Returns the string representation for this release.
130
+ #
131
+ # Returns #title converted into a string.
132
+ def to_s
133
+ title.to_s
46
134
  end
47
135
 
48
136
  end