Class: Drum::Playlist

Inherits:
Struct
  • Object
show all
Defined in:
lib/drum/model/playlist.rb

Overview

A list of tracks with metadata.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializePlaylist

Returns a new instance of Playlist.



41
42
43
44
45
46
47
48
49
# File 'lib/drum/model/playlist.rb', line 41

def initialize(*)
  super
  self.description ||= ''
  self.path ||= []
  self.users ||= {}
  self.artists ||= {}
  self.albums ||= {}
  self.tracks ||= []
end

Instance Attribute Details

#albumsoptional, Hash<String, Album>

Returns A hash of ids to albums used somewhere in the playlist.

Returns:

  • (optional, Hash<String, Album>)

    A hash of ids to albums used somewhere in the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#applemusicoptional, PlaylistAppleMusic

Returns Apple Music-specific metadata.

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#artistsoptional, Hash<String, Artist>

Returns A hash of ids to artists used somewhere in the playlist.

Returns:

  • (optional, Hash<String, Artist>)

    A hash of ids to artists used somewhere in the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#author_idoptional, String

Returns The author id.

Returns:

  • (optional, String)

    The author id



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#descriptionoptional, String

Returns A description of the playlist.

Returns:

  • (optional, String)

    A description of the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#idString

Returns An internal id for the playlist.

Returns:

  • (String)

    An internal id for the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#nameString

Returns The name of the playlist.

Returns:

  • (String)

    The name of the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#pathoptional, Array<String>

Returns The path of parent 'folders' to this playlist.

Returns:

  • (optional, Array<String>)

    The path of parent 'folders' to this playlist.



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#spotifyoptional, PlaylistSpotify

Returns Spotify-specific metadata.

Returns:



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#tracksoptional, Array<Track>

Returns The list of tracks of the playlist, order matters here.

Returns:

  • (optional, Array<Track>)

    The list of tracks of the playlist, order matters here



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

#usersoptional, Hash<String, User>

Returns A hash of ids to users used somewhere in the playlist.

Returns:

  • (optional, Hash<String, User>)

    A hash of ids to users used somewhere in the playlist



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/drum/model/playlist.rb', line 33

class Playlist < Struct.new(
  :id, :name, :description,
  :path,
  :author_id,
  :users, :artists, :albums, :tracks,
  :spotify, :applemusic,
  keyword_init: true
)
  def initialize(*)
    super
    self.description ||= ''
    self.path ||= []
    self.users ||= {}
    self.artists ||= {}
    self.albums ||= {}
    self.tracks ||= []
  end

  # TODO: Handle merging in the store_x methods?

  # Stores a user if it does not exist already.
  #
  # @param [User] user The user to store.
  def store_user(user)
    unless self.users.key?(user.id)
      self.users[user.id] = user
    end
  end

  # Stores an artist if it does not exist already.
  #
  # @param [Artist] artist The artist to store.
  def store_artist(artist)
    unless self.artists.key?(artist.id)
      self.artists[artist.id] = artist
    end
  end

  # Stores an album if it does not exist already.
  #
  # @param [Album] album The album to store.
  def store_album(album)
    unless self.albums.key?(album.id)
      self.albums[album.id] = album
    end
  end

  # Stores a track.
  #
  # @param [Track] track The track to store.
  def store_track(track)
    self.tracks << track
  end

  # Describes a track in a way useful for song matching by search.
  #
  # @return [String] A short description of track name and artists
  def track_search_phrase(track)
    "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
  end

  # Parses a playlist from a nested Hash that uses string keys.
  #
  # @param [Hash<String, Object>] h The Hash to be parsed
  # @return [Playlist] The parsed playlist
  def self.deserialize(h)
    Playlist.new(
      id: h['id'],
      name: h['name'],
      description: h['description'],
      author_id: h['author_id'],
      path: h['path'],
      users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
      artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
      albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
      tracks: h['tracks']&.map { |t| Track.deserialize(t) },
      spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
      applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
    )
  end

  # Serializes the playlist to a nested Hash that uses string keys.
  #
  # @return [Hash<String, Object>] The serialized representation
  def serialize
    {
      'id' => self.id,
      'name' => self.name,
      'description' => (self.description unless self.description.empty?),
      'author_id' => self.author_id,
      'path' => (self.path unless self.path.empty?),
      'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
      'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
      'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
      'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
      'spotify' => self.spotify&.serialize,
      'applemusic' => self.applemusic&.serialize
    }.compact
  end
end

Class Method Details

.deserialize(h) ⇒ Playlist

Parses a playlist from a nested Hash that uses string keys.

Parameters:

Returns:



98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/drum/model/playlist.rb', line 98

def self.deserialize(h)
  Playlist.new(
    id: h['id'],
    name: h['name'],
    description: h['description'],
    author_id: h['author_id'],
    path: h['path'],
    users: h['users']&.map { |u| User.deserialize(u) }&.to_h_by_id,
    artists: h['artists']&.map { |a| Artist.deserialize(a) }&.to_h_by_id,
    albums: h['albums']&.map { |a| Album.deserialize(a) }&.to_h_by_id,
    tracks: h['tracks']&.map { |t| Track.deserialize(t) },
    spotify: h['spotify'].try { |s| PlaylistSpotify.deserialize(s) },
    applemusic: h['applemusic'].try { |a| PlaylistAppleMusic.deserialize(a) }
  )
end

Instance Method Details

#serializeHash<String, Object>

Serializes the playlist to a nested Hash that uses string keys.

Returns:



117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/drum/model/playlist.rb', line 117

def serialize
  {
    'id' => self.id,
    'name' => self.name,
    'description' => (self.description unless self.description.empty?),
    'author_id' => self.author_id,
    'path' => (self.path unless self.path.empty?),
    'users' => (self.users.each_value.map { |u| u.serialize } unless self.users.empty?),
    'artists' => (self.artists.each_value.map { |a| a.serialize } unless self.artists.empty?),
    'albums' => (self.albums.each_value.map { |a| a.serialize } unless self.albums.empty?),
    'tracks' => (self.tracks.map { |t| t.serialize } unless self.tracks.empty?),
    'spotify' => self.spotify&.serialize,
    'applemusic' => self.applemusic&.serialize
  }.compact
end

#store_album(album) ⇒ Object

Stores an album if it does not exist already.

Parameters:

  • album (Album)

    The album to store.



74
75
76
77
78
# File 'lib/drum/model/playlist.rb', line 74

def store_album(album)
  unless self.albums.key?(album.id)
    self.albums[album.id] = album
  end
end

#store_artist(artist) ⇒ Object

Stores an artist if it does not exist already.

Parameters:

  • artist (Artist)

    The artist to store.



65
66
67
68
69
# File 'lib/drum/model/playlist.rb', line 65

def store_artist(artist)
  unless self.artists.key?(artist.id)
    self.artists[artist.id] = artist
  end
end

#store_track(track) ⇒ Object

Stores a track.

Parameters:

  • track (Track)

    The track to store.



83
84
85
# File 'lib/drum/model/playlist.rb', line 83

def store_track(track)
  self.tracks << track
end

#store_user(user) ⇒ Object

Stores a user if it does not exist already.

Parameters:

  • user (User)

    The user to store.



56
57
58
59
60
# File 'lib/drum/model/playlist.rb', line 56

def store_user(user)
  unless self.users.key?(user.id)
    self.users[user.id] = user
  end
end

#track_search_phrase(track) ⇒ String

Describes a track in a way useful for song matching by search.

Returns:

  • (String)

    A short description of track name and artists



90
91
92
# File 'lib/drum/model/playlist.rb', line 90

def track_search_phrase(track)
  "#{track.name} #{track.artist_ids.filter_map { |i| self.artists[i]&.name }.join(' ')}"
end