create an adjustable playlist with ruby - 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.

Related

How to display multiple items using puts?

I have written a Travel App with Tour Items and I'm trying to display the order at the end.
When I use puts #order_items I get {"SevendaySurfSportTour"=>2} for two tours.
I would like it to display
2 SevendaySurfSportTour at the end. But I don't know how, any help would be good?
class TourOrder
def initialize
#order_items = Hash.new(0)
end
def add_item(name, quantity)
#order_items[name] += quantity
end
def get_items
return #order_items
end
def display
puts "Thank you for coming!"
puts #order_items
end
end
#order_items is a hash and what has printed out if the string representation of such a hash. When you want to format the output differently, then you have to implement that on your own – for example like this:
def display
puts "Thank you for coming!"
#order_items.each do |name, quantity|
puts "#{quantity} #{name}"
end
end
Below code works for you
class TourOrder
def initialize
#order_items = Hash.new(0)
end
def add_item(name, quantity)
#order_items[name] += quantity
end
def get_items
#order_items
end
def display
puts "Thank you for coming!"
puts items
end
def items
#order_items.collect{ |k, v| "#{v} #{k}"}
end
end
t = TourOrder.new
t.add_item('SevendaySurfSportTour', 2)
t.add_item('Foo', 4)
t.add_item('Bar', 1)
t.display
=> Thank you for coming!
2 SevendaySurfSportTour
4 Foo
1 Bar

Can someone point to me to the right direction but leading me with questions to ask myself to solve this error for my hw

So when I run my lab i am getting the following error:
Associations — Song and Artist: Artist #add_song adds the song to the current artist's 'songs' collection
Failure/Error: expect(artist.songs).to include(song)
expected ["In the Aeroplane Over the Sea"] to include #<Song:0x0000000001496e88 #name="In the Aeroplane Over the Sea", #artist=#<Artist:0x0000000001496f50 #name="Neutral Milk Hotel", #songs=["In the Aeroplane Over the Sea"]>>
Diff:
## -1,2 +1,2 ##
-[#<Song:0x0000000001496e88 #name="In the Aeroplane Over the Sea", #artist=#<Artist:0x0000000001496f50 #name="Neutral Milk Hotel", #songs=["In the Aeroplane Over the Sea"]>>]
+["In the Aeroplane Over the Sea"]
But when I run my code through pry, I can see the song added into the array of the instance variable, #songs. I am working with two classes, a song class and artist class.
class Artist
attr_accessor :name
attr_reader :songs
##all = []
def initialize(name)
#name = name
save
#songs = []
end
def self.all
##all
end
def save
##all << self
end
def self.destroy_all
##all.clear
end
def self.create(name)
self.new(name)
end
def add_song(song)
if song.artist == nil
song.artist = self
end
#checks if the same song has already been added, otherwise adds new song
if #songs.include?(song.name) == false
#songs << song.name
end
binding.pry
end
end
class Song
attr_accessor :name, :artist
##all =[]
def initialize(name, artist = nil)
#name = name
#artist = artist
save
end
def self. all
##all
end
def save
##all << self
end
def self.destroy_all
##all.clear
end
def self.create(name)
self.new(name)
end
end
Your tests are expecting an aray of Song instances. But what they find is an array of strings.
To fix it you'd just need to change #songs << song.name to #songs << song.
I am sorry if I just gave you the answer instead of hinting you along to solve it yourself, but this isn't really the right platform for that kind of thing. Every question on StackOverflow can be searched by users and we want to keep things helpful to them by getting straight to the point.
However, I can give some advice. Practice reading errors. Try and understand what the error is telling you.

Array Method that only outputs the name without instances

When I run the command I get
all the song names and then the instances following it. How do I only
get the names?
class Song
##all = []
attr_accessor :name
def initialize(name)
#name = name
##all << self
end
def self.all
##all
end
def self.print_all_song_names
##all.each do |song|
puts song.name
end
end
end
hotline_bling = Song.new("Hotline Bling")
thriller = Song.new("Thriller")
ninety_nine_problems = Song.new("99 Problems")
thriller = Song.new("Thriller")
puts Song.print_all_song_names
Which outputs:
Hotline Bling
Thriller
99 Problems
Thriller
#<Song:0x00000000058ced30>
#<Song:0x00000000058cecb8>
#<Song:0x00000000058cebc8>
#<Song:0x00000000058ceb50>
The issue with your code is your calling puts here and there.
The code already calls puts in print_all_song_names, and after you call puts Song.print_all_song_names which roughly means call the method and print the value returned.
each returns a receiver, which means print_all_song_names returns the value of ##all class variable. Which gets printed again.
To fix it, just don’t call puts in the last line; Song.print_all_song_names already prints out everything needed.
Song.print_all_song_names # voilà

undefined method `[]' for nil:NilClass (NoMethodError) in tic-tac-toe game

I am building a Tic-Tac-Toe game to be played on the command line.
module TicTacToe
class Player
attr_accessor :symbol
def initialize(symbol)
#symbol = symbol
end
end
class Board
attr_reader :spaces
def initialize
#spaces = Array.new(9)
end
def to_s
output = ""
0.upto(8) do |position|
output << "#{#spaces[position] || position}"
case position % 3
when 0, 1 then output << " | "
when 2 then output << "\n-----------\n" unless position == 8
end
end
output
end
def space_available(cell, sym)
if spaces[cell].nil?
spaces[cell] = sym
else
puts "Space unavailable"
end
end
end
class Game < Board
attr_reader :player1, :player2
def initialize
play_game
end
def play_game
#player1 = Player.new("X")
#player2 = Player.new("O")
puts Board.new
#current_turn = 1
turn
end
def move(player)
while victory != true
puts "Where would you like to move?"
choice = gets.chomp.to_i
space_available(choice, player.symbol)
puts Board
#current_turn += 1
turn
end
end
def turn
#current_turn.even? ? move(#player2) : move(#player1)
end
def victory
#still working on this
end
end
end
puts TicTacToe::Game.new
The method that is to take a user's cell choice (space_available) and alter the array with their piece ('X' or 'O') is giving me an error. I can't find why my code is throwing this particular error.
The problem is that you don't call the parent constructor in your Game class, therefore #spaces is not initialized.
Your hierarchy decision is questionable, but to make it work, you can simply change the Game constructor to:
def initialize
super
play_game
end
You are calling spaces[cell]. The error is telling you that you are calling [] on nil, which means that spaces must be nil.
Perhaps you mean #spaces? Otherwise - you need to tell the program how spaces is defined and how it is initialized. A simple spaces = {} unless spaces would work
Another way of initialising your spaces variable would be to call super when you initialize the Game:
class Game < Board
attr_reader :player1, :player2
def initialize
super
play_game
end
...

How to run a method from another class in Ruby

Hi I try to make my first game in ruby :)
I have two files:
#"game.rb" with code:
class Game
attr_accessor :imie, :klasa, :honor
def initialize(start_scena)
#start = start_scena
end
def name()
puts "Some text"
exit(0)
end
end
and second file
#"game_engine.rb"
require_relative 'game.rb'
class Start
def initialize
#game = Game.new(:name)
end
def play()
next_scena = #start
while true
puts "\n---------"
scena = method(next_scena)
next_scena = scena.call()
end
end
end
go = Start.new()
go.play()
The question is, how can I call class Game.name method from Start.play() class. The game goes deeper, and insted of 'exit(0)' it returns :symbol of another method from "Game" class that should work.
Make start readable for the Game class. DO NOT call exit(0) in your code unless it's really necessary. Instead, use some conditions to make sure the program runs to the end of script.
#"game.rb" with code:
class Game
attr_accessor :imie, :klasa, :honor
attr_reader :start
def initialize(start_scena)
#start = start_scena
end
def name()
puts "Some text"
:round2
end
def round2
puts "round2"
nil
end
end
Use instance#method(...) to get a bounded method to that instance.
#"game_engine.rb"
require_relative 'game.rb'
class Start
def initialize
#game = Game.new(:name)
end
def play()
next_scene = #game.start
while next_scene
puts "\n---------"
scene = #game.method(next_scene)
next_scene = scene.call()
end
end
end
go = Start.new()
go.play()

Resources