rbrainz 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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