Riptyde4
Riptyde4

Reputation: 5460

Instance variable in model can not be accessed from within method

I'm working on a Rails app, and I've run into a small issue, but I can't seem to find any information pertaining to my certain case.

I'm getting an undefined method error '[]' for NilClass when calling the add_user method in an instance of the class below.

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  @user_info = Hash.new

  def add_user(user_id)
    new_info = OpenStruct.new
    new_info.score1 = 0
    new_info.score2 = 0
    @user_info[user_id] = new_info
  end

  ...

end

Why is this happening and how can I fix it? In a C++, Java program the equivalent would work fine but I guess Ruby works a bit differently.

Upvotes: 0

Views: 468

Answers (2)

Aetherus
Aetherus

Reputation: 8888

Since your class is a subclass of ActiveRecord::Base, you probably should not override the constructor. You can do the initialization in the after_initialize hook:

class Group < ActiveRecord::Base
  after_initialize do
    @user_info = {}
  end

  # Other stuff here
end

BTW, there's a huge difference between ruby and other languages: The instance variables defined directly in the class belong to the class itself, not its instances. Only those instance variables defined in the instance methods belong to that class's instances.

Upvotes: -1

drhining
drhining

Reputation: 221

When you use @user_info = Hash.new in the body of Group's class definition, the scoping rules of Ruby dictate that @user_info is an instance variable of the Group instance of the class Class. It is accessible only when self is Group, not when self is an instance of Group.

You can give yourself access to the class-level instance variable by defining a singleton method on Group.

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
  @user_info = Hash.new

  def self.user_info
    @user_info
  end

  def add_user(user_id)
    new_info = OpenStruct.new
    new_info.score1 = 0
    new_info.score2 = 0

    self.class.user_info[user_id] = new_info
    # OR: Group.user_info[user_id] = new_info
  end
end

Upvotes: 0

Related Questions