winterwolff
winterwolff

Reputation: 135

How to access a class variable from the outside in ruby?

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

Answers (5)

Mike S
Mike S

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

Peter Camilleri
Peter Camilleri

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

peter
peter

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

Ilya
Ilya

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

user6225298
user6225298

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

Related Questions