Reputation: 135
I'm trying to access a class variable from a method outside of the class.
This is my class:
class Book
@@bookCount = 0
@@allBooks = []
def self.allBooks
@@allBooks
end
def self.bookCount
@@bookCount
end
attr_accessor :name,:author,:date,:genre,:rating
def initialize(name, author, date, genre, rating)
@name = name
@author = author
@date = date
@genre = genre
@rating = rating
@@bookCount += 1
@@allBooks << self
end
end
This is the method trying to access the class variable @@bookCount
def seeBookShelf
if @@bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have " + @bookCount + " books in your bookshelf:"
puts allBooks
end
end
When I try to execute the method I get this:
undefined local variable or method `bookCount' for main:Object (NameError)
How can I access bookCount from the outside?
Upvotes: 11
Views: 14783
Reputation: 11409
You can use class_eval
to evaluate a block of code within the scope of a specific class:
class Book
@@bookCount = 1
end
Book.class_eval '@@bookCount'
# => 1
And just for fun... you can actually do all kinds of trickery with class_eval
such as define a new method in the class without monkey patching:
Book.class_eval { @@bookCount = 5 }
Book.class_eval '@@bookCount'
# => 5
Book.class_eval do
def self.hey_look_a_new_method
return "wow"
end
end
Book.hey_look_a_new_method
# => "wow"
Upvotes: 3
Reputation: 1902
For most cases, class instance variables are preferred to class variables. The latter are prone to all manner of strange behaviour when used with inheritance.
Consider:
class Book
@book_count = 0
@all_books = []
class << self
attr_reader :book_count
attr_reader :all_books
end
# further code omitted.
end
With this code Book.book_count and Book.all_books get the expected data.
Upvotes: 3
Reputation: 42182
You need a getter to access the class variable, try this code. See http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/ for an explanation. You are also better to use string interpolation otherwise you get a Type error, also it is more Rubyesque.
class Book
@@bookCount = 0
def self.bookCount
@@bookCount
end
end
def seeBookShelf
if Book.bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have #{Book.bookCount} books in your bookshelf:"
end
end
seeBookShelf # Your bookshelf is empty.
Upvotes: 1
Reputation: 13477
Use class_variable_get
to access a class variable outside of a class:
class Foo
@@a = 1
end
Foo.class_variable_get(:@@a)
=> 1
Upvotes: 15
Reputation:
You have to specify the Class of the variable :
def seeBookShelf
if Book.bookCount == 0
puts "Your bookshelf is empty."
else
puts "You have " + Book.bookCount + " books in your bookshelf:"
puts Book.allBooks
end
end
Upvotes: 0