Undefined method 'name' for []: Array (NoMethodError) - ruby

I am creating a program that reads tracks and albums from a given file. So I have created the following code.
# Task 6.1 T - use the code from last week's tasks to complete this:
# eg: 5.1T, 5.2T
module Genre
POP, CLASSIC, JAZZ, ROCK = *1..4
end
$genre_names = ['Null', 'Pop', 'Classic', 'Jazz', 'Rock']
class Album
# NB: you will need to add tracks to the following and the initialize()
attr_accessor :title, :artist, :genre, :tracks
# complete the missing code:
def initialize (title, artist, genre, tracks)
#title = title
#artist = artist
#genre = genre
#tracks = tracks
end
end
class Track
attr_accessor :name, :location
def initialize (name, location)
#name = name
#location = location
end
end
# Returns an array of tracks read from the given file
def read_tracks (music_file)
tracks = Array.new
count = music_file.gets().to_i
index = 0
while index < count
track = read_track(music_file)
tracks << track
index = index + 1
end
tracks
end
# Reads in and returns a single track from the given file
def read_track (music_file)
track_name = music_file.gets
track_location = music_file.gets
track = Track.new(track_name, track_location)
end
# Takes an array of tracks and prints them to the terminal
def print_tracks (tracks)
index = 0
while (index < tracks.length)
puts 'Track Number ' + index.to_s + ' is:'
print_track(tracks[index])
index = index + 1
tracks
end
end
# Reads in and returns a single album from the given file, with all its tracks
def read_album (music_file)
# read in all the Album's fields/attributes including all the tracks
# complete the missing code
album_artist = music_file.gets
album_title = music_file.gets
album_genre = music_file.gets
tracks = music_file.gets
album = Album.new(album_title, album_artist, album_genre, tracks)
album
end
# Takes a single album and prints it to the terminal along with all its tracks
def print_album (album, tracks)
# print out all the albums fields/attributes
# Complete the missing code.
puts 'Album title is ' + album.title.to_s
puts 'Album artist is ' + album.artist.to_s
puts 'Genre is ' + album.genre.to_s
puts $genre_names[album.genre.to_i]
# print out the tracks
puts 'Tracks are ' + print_track(tracks).to_s
end
# Takes a single track and prints it to the terminal
def print_track (track)
# This is the line where the error is directing me
puts('Track title is: ' + track.name.to_s)
puts('Track file location is: ' + track.location.to_s)
end
# Reads in an album from a file and then print the album to the terminal
def main
music_file = File.new("album.txt", "r")
album = read_album(music_file)
tracks = read_tracks(music_file)
read_tracks(music_file)
print_album(album, tracks)
print_tracks(tracks)
end
main
The program is supposed to read the tracks from the given file, yet I am given the error:
C:/Users/Harry/Desktop/6.1T/album_file_handling.rb:104:in `print_track': undefined method `name' for []:Array (NoMethodError)
Why is this happening?

Five lines above you pass an array of tracks to the method print_track:
puts 'Tracks are ' + print_track(tracks).to_s
And inside the method itself, you expect the single track there. You need to iterate over tracks and print each of them. Somewhat like this would do:
def print_track(tracks)
tracks.each do |track|
puts('Track title is: ' + track.name.to_s)
puts('Track file location is: ' + track.location.to_s)
end
end
Sidenote: never ever put a space between a method declaration/call and the parenthesis opening the list of arguments in ruby. It might result in unpredicted errors.

The problem is you are passing an array(tracks) to the print_track in print_album def.
def print_album (album, tracks)
puts 'Album title is ' + album.title.to_s
puts 'Album artist is ' + album.artist.to_s
puts 'Genre is ' + album.genre.to_s
puts $genre_names[album.genre.to_i]
tracks.each do |track|
puts 'Tracks are '
print_track(track).to_s
end
end

Related

Ruby input failed

here is my code. I've encountered the bug that said: test.rb:101:in <main>': undefined method location' for nil:NilClass (NoMethodError)
although i've defined the method tracks above. I've tried to debug and got the result that nothing was pushed into the tracks variable. Please help me in this stage.
puts albums[0].tracks[0].location
`
class Album
attr_accessor :author, :name, :year, :genre, :cover, :count, :tracks
def initialize (author, name, year, genre, cover, count, tracks)
#author = author
#name = name
#year = year
#genre = genre
#cover = cover
#count = count
#tracks = tracks
end
end
class Track
attr_accessor :name, :location
def initialize (name, location)
#name = name
#location = location
end
end
def read_track(pineapple_music)
song = pineapple_music.gets
file = pineapple_music.gets
t = Track.new(song, file)
return t
end
def read_tracks(pineapple_music, count)
tracks = Array.new
trackcount = count
while trackcount < count
track = read_track(pineapple_music)
tracks << track
trackcount += 1
end
return tracks
end
def read_album(music_file)
album_author = music_file.gets.chomp
album_name = music_file.gets.chomp
album_year = music_file.gets.chomp.to_i
album_genre = music_file.gets.chomp.to_i
cover = music_file.gets.chomp
count = music_file.gets.chomp.to_i
tracks = read_tracks(music_file, count)
album = Album.new(album_author, album_name, album_year, album_genre, cover, count, tracks)
return album
end
def read_albums(pineapple_music)
count = pineapple_music.gets.to_i
albums = Array.new
albumcount = 0
while albumcount < count
album = read_album(pineapple_music)
albums << album
albumcount += 1
end
return albums
end
def read_file(pineapple_music)
music_file = File.new(pineapple_music, "r")
albums = read_albums(music_file)
music_file.close()
return albums
end
def read_number_albums(pineapple_music)
music_file = File.new(pineapple_music, "r")
count = music_file.gets.to_i
music_file.close()
return count
end
`
I've tried some methods like try to output in every function to see what happened. I'm expecting the file name in the library to be loaded in the program, but nothing was loaded and the output was nil afterall.

Undefined method .split for Nil class Ruby

Undefined method for nil:Nilclass
In a class, a method counts the number of words in a paragraph.An error occurs when a method is called(1). I can’t understand how to pass the argument methods using send.
If I remove the class and put the def calc_1(paragraph) method into the loop, then everything works, I start calling the select method. It turns out he does not see my books variable with text, when there is a class.
#books = "You can use this knowledge to create small tools that might help."
class Filecalculation
def select
loop do
puts "# Will we search : сounting words in text File(1)".cyan
print "\n>>>>>> "
input = gets.chomp
search_method = "calc_#{input}".to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
end
end
end
def calc_1 paragraph
word_count = paragraph.split.length
puts "#{word_count} words"
end
end
Filecalculation.new.select
If replaced by search_method = "calc_#{input}".to_sym also works.
Helped add def initialize #books end.
Instead of contents = send (search_method, #books) you can use send (search_method, #books).
require "colorize"
class Filecalculation
def initialize
#books = "You can use this knowledge to create small tools that might help you."
end
def calc_1 paragraph
word_count = paragraph.strip.squeeze(' ').count(' ') + 1
puts "#{word_count} words"
end
def select
loop do
puts "# Will we search : Calculation_lines paragraph(1)".cyan
print "\n>>>>>> ".yellow
input = gets.chomp
search_method = "calc_#{input}" #.to_sym
if (respond_to?(search_method))
contents = send(search_method, #books)
else
puts "exit "
exit
end
end
end
end
Filecalculation.new.select

Unable to extract information from a file

My program is designed to intake the "Album title", "Album artist", "Album Genre", and "tracks" from a .txt file. It puts these tracks into an array and then prints that array to the terminal.
Everything works fine, except the array that is being printed is empty "[]"
The Ruby Code
module Genre
POP, CLASSIC, JAZZ, ROCK = *1..4
end
$genre_names = ['Null', 'Pop', 'Classic', 'Jazz', 'Rock']
class Album
# NB: you will need to add tracks to the following and the initialize()
attr_accessor :title, :artist, :genre, :tracks
# complete the missing code:
def initialize (title, artist, genre, tracks)
#title = title
#artist = artist
#genre = genre
#tracks = tracks
end
end
class Track
attr_accessor :name, :location
def initialize (name, location)
#name = name
#location = location
end
end
# Returns an array of tracks read from the given file
def read_tracks(music_file)
tracks = Array.new
count = music_file.gets().to_i
index = 0
while index < count
track = read_track(music_file)
tracks << track
index = index + 1
end
tracks
end
# Reads in and returns a single track from the given file
def read_track(music_file)
track_name = music_file.gets
track_location = music_file.gets
track = Track.new(track_name, track_location)
end
# Takes an array of tracks and prints them to the terminal
def print_tracks(tracks)
index = 0
while (index < tracks.length)
puts 'Track Number ' + index.to_s + ' is:'
print_track(tracks[index])
index = index + 1
end
tracks
end
# Reads in and returns a single album from the given file, with all its tracks
def read_album(music_file)
# read in all the Album's fields/attributes including all the tracks
# complete the missing code
album_artist = music_file.gets
album_title = music_file.gets
album_genre = music_file.gets
tracks = read_tracks(music_file)
album = Album.new(album_title, album_artist, album_genre, tracks)
album
end
# Takes a single album and prints it to the terminal along with all its tracks
def print_album(album, tracks)
# print out all the albums fields/attributes
# Complete the missing code.
puts 'Album title is ' + album.title.to_s
puts 'Album artist is ' + album.artist.to_s
puts 'Genre is ' + album.genre.to_s
puts $genre_names[album.genre.to_i]
# print out the tracks
puts 'Tracks are: ' + print_tracks(tracks).to_s
end
# Takes a single track and prints it to the terminal
def print_track(tracks)
tracks.each do |track|
puts('Track title is: ' + track.name.to_s)
puts('Track file location is: ' + track.location.to_s)
end
end
# Reads in an album from a file and then print the album to the terminal
def main
music_file = File.new("album.txt", "r")
if music_file
album = read_album(music_file)
tracks = read_tracks(music_file)
music_file.close
else
puts "unable to read"
end
print_album(album, tracks)
end
main
This is what the .txt file contains
Neil Diamond
Greatest Hits
1
3
Crackling Rose
sounds/01-Cracklin-rose.wav
Soolaimon
sounds/06-Soolaimon.wav
Sweet Caroline
sounds/20-Sweet_Caroline.wav
I receive an ouput of:
Album title is Greatest Hits
Album artist is Neil Diamond
Genre is 1
Pop
Tracks are: []
when the tracks array should print out the different tracks, their name and their file location
Here your solution))) It was a few little mistakes. Firstly, you had empty tracks because you read the end of the file. You have been called read_tracks the first time in read_album and the second time in main.
Also, you have an exception when you in print_track tried to call the loop on Track object.
module Genre
POP, CLASSIC, JAZZ, ROCK = *1..4
end
$genre_names = ['Null', 'Pop', 'Classic', 'Jazz', 'Rock']
class Album
# NB: you will need to add tracks to the following and the initialize()
attr_accessor :title, :artist, :genre, :tracks
# complete the missing code:
def initialize (title, artist, genre)
#title = title
#artist = artist
#genre = genre
end
end
class Track
attr_accessor :name, :location
def initialize (name, location)
#name = name
#location = location
end
end
# Returns an array of tracks read from the given file
def read_tracks(music_file)
tracks = Array.new
count = music_file.gets.to_i
index = 0
while index < count
tracks << read_track(music_file)
index += 1
end
tracks
end
# Reads in and returns a single track from the given file
def read_track(music_file)
track_name = music_file.gets
track_location = music_file.gets
track = Track.new(track_name, track_location)
end
# Takes an array of tracks and prints them to the terminal
def print_tracks(tracks)
index = 0
while (index < tracks.length)
puts 'Track Number ' + index.to_s + ' is:'
print_track(tracks[index])
index += 1
end
tracks
end
# Reads in and returns a single album from the given file, with all its tracks
def read_album(music_file)
# read in all the Album's fields/attributes including all the tracks
# complete the missing code
album_artist = music_file.gets
album_title = music_file.gets
album_genre = music_file.gets
album = Album.new(album_title, album_artist, album_genre)
album
end
# Takes a single album and prints it to the terminal along with all its tracks
def print_album(album)
# print out all the albums fields/attributes
# Complete the missing code.
puts 'Album title is ' + album.title.to_s
puts 'Album artist is ' + album.artist.to_s
puts 'Genre is ' + album.genre.to_s
puts $genre_names[album.genre.to_i]
# print out the tracks
puts 'Tracks are: ' + print_tracks(album.tracks).to_s
end
# Takes a single track and prints it to the terminal
def print_track(track)
puts('Track title is: ' + track.name.to_s)
puts('Track file location is: ' + track.location.to_s)
end
# Reads in an album from a file and then print the album to the terminal
def main
music_file = File.new("album.txt", "r")
if music_file
album = read_album(music_file)
album.tracks = read_tracks(music_file)
music_file.close
else
puts "unable to read"
end
print_album(album)
end
main

Using a variable across classes in Ruby

I have this class:
class Player
attr_accessor :card_pile, :name
def initialize
#name = name
#bust = false
#card_pile = []
end
def bust?
return #cards.inject(:+) > 21
end
end
I also have this as the beginning of another class
def playing_game
puts "How many players are playing? "
players_amount = gets.chomp.to_i
(0...players_amount).each do
puts ("What is the players name? ")
#name = gets.chomp
#players.push(#name)
end
#players.each do |each_player|
#name = Player.new
while true
while #name.card_pile.length < 2 do
new_card = Card.new
#name.card_pile.push(new_card.value)
end
puts(#name.card_pile)
print #name, "'s turn" "\n"
At the moment this will print out #<Player:0x007fc14984a4b0>'s turn instead of Rich's turn
Why is this happening? I thought I had made an instance variable in the Player class and then instantiated this class #name = Player.new and then could reference it from here on out??
This will help
def playing_game
puts 'How many players are playing?'
players_amount = gets.chomp.to_i
players_names = (0...players_amount).map do
puts ("What is the players name? ")
gets.chomp
end
players_names.each do |player_name|
player = Player.new(player_name)
while player.card_pile.length < 2 do
new_card = Card.new
player.card_pile.push(new_card.value)
end
puts player.card_pile
puts "#{player.name}'s turn"
end
end
UPD:
You don't need instance variables (like #name and #players inside single method).
In this code you iterate over players names
#players.each do |each_player|
=>
players_names.each do |player_name|
In context of
#name = Player.new
name is a Player instance
to create player with given name pass it to initializer:
player = Player.new(player_name)
then call name on Player instance, that you create earlier
puts "#{player.name}'s turn"

create an adjustable playlist with ruby

I'm not sure why my code will not pass the corresponding test. Each time I try the code, the following error is reported: "rb:60:in <main>': undefined local variable or methodtrack' for main:Object (NameError)." What can I do without editing the tests? Thanks! Open to another approach...thanks!
strong text
class Song
attr_reader :song
def initialize(song, artist)
#song = song
#artist = artist
end
def play
puts "#{#song}by #{#artist}"
end
end
class Playlist
def initialize(player_list)
#player_list = player_list
end
def add(add_song)
add_song.each do |song|
#player_list << song
end
end
def track_number
#player_list.length
end
def remove(remove_song)
remove_song.each do |song|
#player_list.delete(song)
end
end
def includes?(from_list)
i = 0
from_list.each do |song|
if #player_list.include?(song)
i+=1
end
end
if i==from_list.length
true
else
false
end
end
def play_all
#player_list.each do |song|
song.play
end
end
def display
#player_list.each do |song|
puts song.song
end
end
end
one_by_one = Song.new("One by One", "Sirenia")
world_so_cold = Song.new("World So Cold", "Three Days Grace")
going_under = Song.new("Going Under", "Evanescence")
my_playlist = Playlist.new(one_by_one, world_so_cold, going_under)
lying_from_you = Song.new("Lying From You", "Linkin Park")
angels = Song.new("Angels", "Within Temptation")
my_playlist.add(lying_from_you, angels)
p my_playlist.track_number == 5
going_under.play
my_playlist.remove(angels)
p my_playlist.includes?(lying_from_you) == true
my_playlist.play_all
my_playlist.display
When you call the "add" method for PlayList, it is expecting a single Song. However, the "add" method is trying to call .each() which would work for an array of Songs but not for a single song.
The best solution, without changing your test code, would be to remove the ".each" calls in the "add", "remove" and "includes?" methods for PlayList. Have them each add, remove or check for a single song at a time.

Resources