user7736482
user7736482

Reputation:

Creating a class based on user input

I am new to Ruby and just had a quick question when writing a program that asks a user to create a playlist of their favorite songs!

class Playlist

array_songs = Array.new
print "How many songs do you want to add to your playlist? "
songs = gets.to_i

for i in 1..songs
    print "Enter song #{i}: "
    song = gets.chomp

    print "Enter genre for song #{i}: "
    genre = gets.chomp

    print "Enter artist of song #{i}: "
    artist = gets.to_i

    p = playlist.new
    p.set_song(song)
    p.set_genre(genre)
    p.set_artist(artist)
    array_songs << p
end
end 

puts "This is your current playlist: "

for song in array_songs
    puts "#{song.get_song} #{song.get_genre} #{song.get_artist}" 
end

So basically every time I run this, it won't work, saying I have undefined methods and such... Just want a few tips on how to make this work so that at the end of a user entering the songs, the result of all the songs will be printed! Thanks!

Upvotes: 0

Views: 1089

Answers (1)

Sekalf Nroc
Sekalf Nroc

Reputation: 467

You appear to have a misunderstanding of what a class is, or at least, how to use them well.

A class is a type of object which represents a distinct concept or item in the internal universe of the application.

The internal universe of an application like Stack Overflow consists of (amongst other things) User, Question and Answer objects. Therefore, these are some of the classes you might find in the source code.

An individual Answer, like this one, or an individual User, like you, is an instance of the class. It has its own distinct data, which is different to that of another User or Answer, but it shares the same behaviour, such as delete or edit.

You have a class called Playlist. Logically, this should be a list of Songs. As a Song is a separate concept, with its own data and behaviour, it should be a separate class.

Because a Playlist does not do anything at the moment, it's probably best to use an Array object. So that you can change this in the future, you can do something like this:

Playlist = Array

And later:

class Playlist
  # extra behaviour when needed
end

A Song has three pieces of data:

  • name
  • genre
  • artist

In Ruby, we can use attr_accessor to handle the setters and getters.

class Song
  attr_accessor :name, :genre, :artist
end

Notice the case sensitivity on the class and variable names. You made that mistake with p = playlist.new.

Here is the fully adapted version of the code. I have changed some of the variable names to improve readability.

I have also changed your for loop to Ruby's .times method, which I feel is easier to read.

Finally, I have changed the gets.to_i for artist to gets.chomp, as I presumed it was supposed to be a String like the others. Just change it back if I was wrong about this.

Playlist = Array

class Song
  attr_accessor :name, :genre, :artist
end

songs = Playlist.new
print "How many songs do you want to add to your playlist? "
number_of_songs = gets.to_i

number_of_songs.times do |i|
  song_number = i + 1

  print "Enter song #{song_number}: "
  name = gets.chomp

  print "Enter genre for song #{song_number}: "
  genre = gets.chomp

  print "Enter artist of song #{song_number}: "
  artist = gets.chomp

  s = Song.new
  s.name   = name
  s.genre  = genre
  s.artist = artist

  songs << s
end

puts "This is your current playlist: "

songs.each do |song|
  puts "#{song.name} #{song.genre} #{song.artist}"
end

Lastly, I know that this does not apply to your case, but I feel it is important to learn if you did not know already: you can use def to add behaviour to a class. attr_accessor does this implicitly.

class Duck
  attr_accessor :name

  def quack
    "QUACK! My name is #{name}."
  end
end

a_duck = Duck.new
a_duck.name = "Mr. Duck"
puts a_duck.quack
#=> QUACK! My name is Mr. Duck.

Good luck.

Upvotes: 2

Related Questions