Mariam
Mariam

Reputation: 739

How do I define and reference multi-dimensional arrays in Ruby?

I have a global definition in my controller for a multi-dimensional array as follows:

def ch
  @ch = Array.new(1){[]}
  @ch[0][0] = "Option 1"
  @ch[0][1] = "Option 2"
end

(I'm not sure if this is the best to do the array but I found an example online to do it this way)

in my controller action called "test", I am not able to print the values of the array appropriately.

def test
  logger.debug ch
  logger.debug ch[0]
  logger.debug ch[1]
  logger.debug ch[0][0]
  logger.debug ch[0][1]
end

stdout shows the following for the 5 logger statements respectively

Option 2
79
112
1
1

Why do the integers show? Any idea how I get the array values Option 1 and Option 2 to show?

If I define the array in the action itself (not doing it globally outside the action), I get the expected results i.e. ch[0][0] shows Option 1 and ch[0][1] shows Option 2. Eventually, I want to have access to the array in my view. There may be a better way to do this.

Upvotes: 0

Views: 684

Answers (3)

Szymon Jeż
Szymon Jeż

Reputation: 8449

Why do the integers show?

Because the ch method return a "Option 2" string and calling the [] method on a string will return the integer value (ASCII code) of the letter at the index you wanted to get (i.e. ch[1] returns the int value of the "p" character).

Any idea how I get the array values Option 1 and Option 2 to show?

Define the ch method as:

def ch
  ch = Array.new(1){[]}
  ch[0][0] = "Option 1"
  ch[0][1] = "Option 2"
  return ch
end

Or leave it as is and modivie the test method:

def test
  ch # initialize the @ch instance variable
  logger.debug @ch
  logger.debug @ch[0]
  logger.debug @ch[1]
  logger.debug @ch[0][0]
  logger.debug @ch[0][1]
end

I think this will be helpful. Cheers.

Upvotes: 2

Vojislav Stojkovic
Vojislav Stojkovic

Reputation: 8153

You're confusing methods and variables. When you do

def ch
...
end

you're defining a method and that method returns the last thing that was evaluated in it. In this case, the last thing you did in the method is:

@ch[0][1] = "Option 2" 

which evaluates to "Option 2". Therefore, when you call your method ch it will return "Option 2". That's why

logger.debug ch

logs "Option 2".

Now, inside your method ch you're creating an instance variable @ch. To log the values the way you wanted to, you would have to change your logging code like this:

logger.debug @ch
logger.debug @ch[0]
logger.debug @ch[1]
logger.debug @ch[0][0]
logger.debug @ch[0][1]

But, for this to work, you have to ensure that the code which creates the @ch instance variable has been executed before executing the test method. One way to do this is by having your ch method called using before_filter:

class YourControllerClassName
  before_filter :ch

Upvotes: 2

Michelle Tilley
Michelle Tilley

Reputation: 159095

There are a few things going on here.

  1. In Ruby, the last line of a method is that method's return value; so the return value of ch is "Option 2". Let's verify this on IRB, the Ruby REPL:

    [BinaryMuse ~]: irb
    ruby-1.9.2-p136 :001 > def ch
    ruby-1.9.2-p136 :002?>   ary = Array.new(1){[]}
    ruby-1.9.2-p136 :003?>   ary[0][0] = "Option 1"
    ruby-1.9.2-p136 :004?>   ary[0][1] = "Option 2"
    ruby-1.9.2-p136 :005?>   end
     => nil 
    ruby-1.9.2-p136 :006 > ch
     => "Option 2"
    
  2. In test, you are calling the ch method rather than referencing the @ch variable. logger.debug ch is thus equivalent to logger.debug "Option 2", and thus ch[0] is the first character of "Option 2", which is "O", which has the ASCII code 79. The same goes for ch[1], which is "p", with the ASCII code 112. ch[0][0] returns the least significant bit of 79, which is 1, and so on.

  3. Even if you change test to use @ch instead of calling the ch method, @ch still isn't defined since you haven't yet called ch to set up the @ch variable during your request. You can do this via a before_filter in your controller:

    class WhateverController
      before_filter :ch
    
      def ch
        # your code
      end
    
      def test
        logger.deubg @ch
        # etc.
      end
    end
    

Upvotes: 4

Related Questions