Reputation: 739
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
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
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
Reputation: 159095
There are a few things going on here.
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"
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.
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