Today I learned about @@class_variables
which are accessible to the entire class. For the assignment to help me learn this, I was given the task to create the class Song and keep track of the name, artist, genre, and counts all song instances.
First things first, creating the class and creating my class variables which would hold all the data about all the instances.
class Song
@@count=0
@@genres=[]
@@artists=[]
@@count
is going to be used to create a counter for everytime a song instance is born. @@genres
is going to house all of the genres in this now empty array. Keep in mind that this will be storing duplicates if there is more than one song in each genre. @@artists
is going to store all of the artists just like @@genres
.
Now to create the variables/attributes that all the song will be born with. Which means using my favorite attr_acessor
. Then creating the initialize method that will run on creation of each instance to give it all the attributes required. This includes pushing data into the previously created arrays and assigning instance variables.
attr_accessor :name, :artist, :genre
def initialize(name, artist, genre)
@name = name
@artist = artist
@genre = genre
@@count += 1
@@genres << genre
@@artists << artist
end
With all of this I also learned about self, which just means referring to the class. It is pretty self explanatory...yes, time to roll your eyes at my lame joke. Now the task is to create class methods that will allow me to access the class variables outside of the method. Also to create unique arrays of the artist and genre arrays so there are no repeats using the handy .uniq
. I first made the mistake of using the bang operator and then remembered that I don't want to change my array because I need both arrays for one of the later tasks.
def self.count
@@count
end
def self.genres
@@genres.uniq
end
def self.artists
@@artists.uniq
end
Everything was going great up until now. No major issues and then the last task threw me off and it took me a long time to figure it out. The last task was to return a hash with the keys set to the genres and artists and the values to be the count of each. Ex. {"rap" => 3, "pop" => 5, "metal" => 1}
. I knew the first thing was to create an empty array and I would need to return the array. I also knew that I needed to do some iterating. Great... but the rest was lost to me.
def self.genre_count
genre_hash= {}
self.genres.each do |genre|
genre_hash[genre] = @@genres.count{|g| g == genre}
end
genre_hash
end
def self.artist_count
artist_hash={}
self.artists.each do |artist|
artist_hash[artist] = @@artists.count{|a| a == artist}
end
artist_hash
end
end
The solution was to iterate through the self.genres
aka the unique array of genres. Then set the key in the hash equal to genre via genre_hash[genre]
. Now to set the value which is a count. As I mentioned earlier, I initially still had the bang operator in my self.genres
method. Which meant there was nothing to count. Once I fixed that then it became clearer to use the initial @@genres
array that had the duplicates and .count
. The great thing about .count
that I didn't know before was that it could take a block of code. In the block of code I set a local variable of |g|
as to not overwrite the genre variable. I set g == genre
. For every time this returns true, the count will increase! How cool is that? Then I just applied the same thing to artist and viola! Lab was passed.
Top comments (0)