Selah
Selah

Reputation: 8064

Instance Variables in Rails Model

I want to initialize an instance variable within my Rails model that will hold an array and I want to access this variable in other methods within my model. I tried this:

class Participant < ActiveRecord::Base

  @possible_statuses = [
    'exists',
    'paired',
    'quiz_finished',
    'quiz_results_seen',
    'money_sent'
  ]

  def statuses
    @possible_statuses
  end

But when I tried the following using rails console:

 Participant.first.statuses

I am returned nil :(

Why does this happen? Is there a way to accomplish what I am trying to accomplish?

Upvotes: 6

Views: 17941

Answers (4)

Selah
Selah

Reputation: 8064

The best answer for me was to create a class variable, not an instance variable:

@@possible_statuses = [
    'exists',
    'paired',
    'chat1_ready',
    'chat1_complete'
]

I could then freely access it in methods of the class:

  def status=(new_status)
    self.status_data = @@possible_statuses.index(new_status)
  end

Upvotes: 2

Kenny Bania
Kenny Bania

Reputation: 637

The instance variable will only exist when you create the model, since it is not being stored in a database anywhere. You will want to make it a constant as per Nobita's suggestion. Alternatively, you could make it a module like...

module Status
  EXISTS = "exists"
  PAIRED = "paired"
  QUIZ_FINISHED = "quiz_finished"
  QUIZ_RESULTS_SEEN = "quiz_results_seen"
  MONEY_SENT = "money_sent"

  def self.all
    [EXISTS, PAIRED, QUIZ_FINISHED, QUIZ_RESULTS_SEEN, MONEY_SENT]
  end
end

This gives you a bit more control and flexibility, IMO. You would include this code nested in your model.

Upvotes: 0

user1454117
user1454117

Reputation:

In your example, @possible_statuses is a variable on the class rather than on each instance of the object. Here is a rather verbose example of how you might accomplish this:

class Participant < ActiveRecord::Base

  @possible_statuses = [
    'exists',
    'paired',
    'quiz_finished',
    'quiz_results_seen',
    'money_sent'
  ]

  def self.possible_statuses
    @possible_statuses
  end

  def possible_statuses
    self.class.possible_statuses
  end

  def statuses
    possible_statuses
  end

end

As mentioned in other answers, if that list of statuses never changes, you should use a constant rather than a variable.

Upvotes: 2

Nobita
Nobita

Reputation: 23713

I would recommend using a constant for this kind of cases:

class Participant < ActiveRecord::Base

  STATUSES = [
    'exists',
    'paired',
    'quiz_finished',
    'quiz_results_seen',
    'money_sent'
  ]

If you want to access that array from the inside class, just do STATUSES, and from the outside class use Participant::STATUSES

Upvotes: 14

Related Questions