class Card
attr_accessor :number, :suit
def initialize(number, suit)
#number = number
#suit = suit
end
def to_s
"#{#number} of #{#suit}"
end
end
I'm assuming this creates a new array correct?
But why the use of the AT symbol? When should I use it and not use it?
#stack_of_cards = []
#stack << Card.new("A", "Spades")
puts #stack
# => BlackjackGame.rb:17: undefined method `<<' for nil:NilClass (NoMethodError)
Any ideas why this error is firing?
Exactly as it says in error: variable #stack is not defined (or nil).
Did you mean #stack_of_cards << .. instead?
If you had warnings on (ruby -W2 script_name.rb), you would have got a warning that #stack is not merely nil, but undefined. See How do I debug Ruby scripts? for more hints on how to debug.
Related
The following Ruby code raises the confusing error "no id given" shown at the end. How do I avoid this problem?
class Asset; end
class Proxy < Asset
def initialize(asset)
#asset
end
def method_missing(property,*args)
property = property.to_s
property.sub!(/=$/,'') if property.end_with?('=')
if #asset.respond_to?(property)
# irrelevant code here
else
super
end
end
end
Proxy.new(42).foobar
#=> /Users/phrogz/test.rb:13:in `method_missing': no id given (ArgumentError)
#=> from /Users/phrogz/test.rb:13:in `method_missing'
#=> from /Users/phrogz/test.rb:19:in `<main>'
The core of this problem can be shown with this simple test:
def method_missing(a,*b)
a = 17
super
end
foobar #=> `method_missing': no id given (ArgumentError)
This error arises when you call super inside method_missing after changing the value of the first parameter to something other than a symbol. The fix? Don't do that. For example, the method from the original question can be rewritten as:
def method_missing(property,*args)
name = property.to_s
name.sub!(/=$/,'') if name.end_with?('=')
if #asset.respond_to?(name)
# irrelevant code here
else
super
end
end
Alternatively, be sure to explicitly pass a symbol as the first parameter to super:
def method_missing(property,*args)
property = property.to_s
# ...
if #asset.respond_to?(property)
# ...
else
super( property.to_sym, *args )
end
end
trying to pick up ruby through this programming ruby site and i'm stuck on this syntax
class SongList
def initialize
#songs = Array.new
end
def append(aSong)
#songs.push(aSong)
self
end
def deleteFirst
#songs.shift
end
def deleteLast
#songs.pop
end
end
When i go to add a song...
list = SongList.new
list.append(Song.new('title1', 'artist1', 1))
I get this error message:
NameError: uninitialized constant Song ...Programming Ruby
I saw that i need to require the variable Song, but I'm not sure where to do it within the SongList class....
You can use Ruby Struct class :
A Struct is a convenient way to bundle a number of attributes together, using accessor methods, without having to write an explicit class.
class SongList
def initialize
#songs = [] # use [] instead of Array.new
end
def append(aSong)
#songs.push(aSong)
self
end
def delete_first
#songs.shift
end
def delete_last
#songs.pop
end
end
Song = Struct.new(:song_name, :singer, :var)
list = SongList.new
list.append(Song.new('title1', 'artist1', 1))
# => #<SongList:0x9763870
# #songs=[#<struct Song song_name="title1", singer="artist1", var=1>]> var=1>]>
I am experiencing strange behaviour when using ERB and implementing #to_s - example:
require "erb"
TEMPLATE = "<%= not_here %>"
class A
def to_s
"class <A>"
end
def to_str
to_s
end
def render
begin
ERB.new(TEMPLATE, nil, '-').result(binding)
rescue Exception => e
print e.to_s
end
end
end
A.new().render
On ruby 1.9.3 this prints undefined local variable or method 'not_here' for class <A>:A
On ruby 2.0.0 this prints undefined local variable or method 'not_here' for #<A:0x007f98a29a88b8>
Can somebody explain why that is the case and what to do about it in order to get the same output on both ruby versions.
The printed string #<A:0x007f98a29a88b8> comes from a call to inspect and not from to_s.
To get a different output for that part, implement the inspect method.
class A
def inspect
'class <A>'
end
end
class Deck
attr_accessor :all
def initialize
#all = [1,2,3]
end
end
newdeck = Deck.new
puts newdeck.all
class Testdeck
attr_accessor :cards
def initialize
#cards = []
counter = 0
['H','C', 'S', 'D'].product(['2','3','4','5','6','7','8','9','10','J','K','Q','A']).each do |arr|
#cards << Card.new(arr[0], arr[1])
end
end
end
zen = Testdeck.new
puts zen.cards.pop
This code is giving me: 'block in initialize' uninitialized constant Testdeck NameError
All help is appreciated.
This code has no clue what a Card is; the error message you're getting is not an uninitialized constant Testdeck error but an uninitialized constant Testdeck::Card error, where the :: indicates that Ruby is looking inside the Testdeck class for the Card class (not that you need to put it there, Ruby just looks there first).
You need to define the Card class somewhere, and make its constructor take in a string and an integer.
I'm trying to learn ruby more in depth before I move on to rails dev, but I'm having some issues learning classes. I can't seem to understand why the following doesn't work.
#point.rb
class Point
attr_accessor :x, :y
def initialize(p = [0,0])
#x = p[0]
#y = p[1]
end
end
#shape.rb
require_relative 'point.rb'
class Shape
attr_accessor :points
def initialize *the_points
for p in the_points
#points.append Point.new(p)
end
end
end
s = Shape.new([3,2])
puts s.points
When I call the function I get a no method error for NilClass, which I'm assuming is referring to #point.append.
First, try this:
def initialize *the_points
#points = []
for p in the_points
#points << Point.new(p)
end
end
You get NilClass error because #points instance variable is Nil, and NilClass, which does not have append() method.
Better than creating an array and populating it in a loop would be to initialize it like so:
class Shape
attr_accessor :points
def initialize *the_points
#points = the_points.map{ |p| Point.new(p) }
end
end
If you had warnings on (ruby -w or $VERBOSE = true), it'd warn you that #points didn't exist.
See some other debugging tips in How do I debug Ruby scripts?
You need to initialize #points to be a new array. It starts off as nil.
def initialize *the_points
#points = [];
for p in the_points
#points.append Point.new(p)
end
end