Problem Extracting Array Values

  • Thread starter Dustin Anderson
  • Start date
D

Dustin Anderson

Hi All,

I'm trying to iterate through an array and pull each value into a view
on my Rails app. The array is stored in a MySQL database.

The array is in a varchar (string) column named "blocks" with the value:
["journal", "about", "news"]

I'm trying to pull each value out one at a time.

If I try to access the array with something like this...:
<%= @blocks[0] %>

...the view returns a numeric value:
91

I'm totally confused as to why I can't extract the values out of the
array. It works fine in IRB:
irb(main):004:0> @blocks = ["journal", "about"]
=> ["journal", "about"]
irb(main):005:0> @blocks[0]
=> "journal"
irb(main):006:0>

Is there some reason why I can't get the "journal" string out of the
array?

Thanks in advance for your help!
Dustin
 
C

ChrisH

Hi All,

I'm trying to iterate through an array and pull each value into a view
on my Rails app. The array is stored in a MySQL database.

The array is in a varchar (string) column named "blocks" with the value:
["journal", "about", "news"]

I'm trying to pull each value out one at a time.

If I try to access the array with something like this...:
<%= @blocks[0] %>

..the view returns a numeric value:
91

I'm totally confused as to why I can't extract the values out of the
array. It works fine in IRB:
irb(main):004:0> @blocks = ["journal", "about"]
=> ["journal", "about"]
irb(main):005:0> @blocks[0]
=> "journal"
irb(main):006:0>

Is there some reason why I can't get the "journal" string out of the
array?

Thanks in advance for your help!
Dustin

As you say, its stored as a String, and String defines [] to return
the ASCII value of the character
at the given index. If you put 91.chr into IRB you'll see it is the
'[' character.

You need to convert your String into an actual array before you can
access each element.

Maybe:
eval(@blocks)[0]

Cheers
Chris
 
R

Ryan Leavengood

As you say, its stored as a String, and String defines [] to return
the ASCII value of the character
at the given index. If you put 91.chr into IRB you'll see it is the
'[' character.

You need to convert your String into an actual array before you can
access each element.

Maybe:
eval(@blocks)[0]

That is what I surmised as well. But in general it is a bad idea to be
evaling code from a database. Security and all that.

Dustin, why are you storing those values that way? Why not have a
normalized table with a row for each? In other words you create a
blocks table, define a Block model which belongs_to whatever model you
currently use the blocks column in, and then that model will have many
blocks. Then you could just do @model.blocks.each do |block| in your
view.

Ryan
 
I

Ilan Berci

Dustin said:
Hi All,

I'm trying to iterate through an array and pull each value into a view
on my Rails app. The array is stored in a MySQL database.

Dustin,

For future reference, could you please refer all rails related questions
to the rails forum.
The array is in a varchar (string) column named "blocks" with the value:
["journal", "about", "news"]

I'm trying to pull each value out one at a time.

If I try to access the array with something like this...:
<%= @blocks[0] %>

...the view returns a numeric value:
91

@blocks is not the type you think it is, I am taking a wild stab here
but 91 is the ascii code for "[" so I believe @blocks is a string:

irb(main):007:0> @blocks = "['journal', 'about']"
=> "['journal', 'about']"
irb(main):008:0> @blocks[0]
=> 91
irb(main):009:0>

hope this helps

ilan
 
D

Dustin Anderson

Dustin, why are you storing those values that way? Why not have a
normalized table with a row for each? In other words you create a
blocks table, define a Block model which belongs_to whatever model you
currently use the blocks column in, and then that model will have many
blocks. Then you could just do @model.blocks.each do |block| in your
view.

Ryan

Thanks Chris, ilan, Ryan for the help... You got it exactly correct.

Ryan - I think you're right - I was storing the value in the database
like that because it's a variable for a Javascript app. I'm writing an
app to allow users to store the state of the view (like Google
personalized homepage or netvibes) and the javascript that I'm using
requires a v to look like this:

value = ["block1_name", "block2_name", "block3_name"]

so, if I store "value" in the database like this, I can just read it
into my javascript. Otherwise, I'll need a helper to construct the
string to look like this.

thanks again.
Dustin

Ps. sorry ilan for posting in the Ruby forum - I thought it was just a
simple ruby array question, but obviously it does have something to do
with Rails.

For the record - the javascript app i'm using for drag/drop portal is
here:
http://aymanh.com/drag-drop-portal-interface-with-scriptaculous
 
A

ara.t.howard

Dustin, why are you storing those values that way? Why not have a
normalized table with a row for each? In other words you create a
blocks table, define a Block model which belongs_to whatever model you
currently use the blocks column in, and then that model will have many
blocks. Then you could just do @model.blocks.each do |block| in your
view.

Ryan

Thanks Chris, ilan, Ryan for the help... You got it exactly correct.

Ryan - I think you're right - I was storing the value in the database
like that because it's a variable for a Javascript app. I'm writing an
app to allow users to store the state of the view (like Google
personalized homepage or netvibes) and the javascript that I'm using
requires a v to look like this:

value = ["block1_name", "block2_name", "block3_name"]

so, if I store "value" in the database like this, I can just read it
into my javascript. Otherwise, I'll need a helper to construct the
string to look like this.

not really

values = ["block1_name", "block2_name", "block3_name"]

javascript = "value = #{ values.inspect }"

fyi.

-a
 
D

Dustin Anderson

unknown said:
Thanks Chris, ilan, Ryan for the help... You got it exactly correct.
into my javascript. Otherwise, I'll need a helper to construct the
string to look like this.

not really

values = ["block1_name", "block2_name", "block3_name"]

javascript = "value = #{ values.inspect }"

fyi.

-a

is there a simple way in ruby to build an array from a string like this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]

Thanks
 
J

James Edward Gray II

unknown said:
Thanks Chris, ilan, Ryan for the help... You got it exactly correct.
into my javascript. Otherwise, I'll need a helper to construct the
string to look like this.

not really

values = ["block1_name", "block2_name", "block3_name"]

javascript = "value = #{ values.inspect }"

fyi.

-a

is there a simple way in ruby to build an array from a string like
this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]
Sure:
"block1,block2,block3".split(",")
=> ["block1", "block2", "block3"]

James Edward Gray II
 
B

Brian Candler

is there a simple way in ruby to build an array from a string like this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?
 
A

Alex Young

Brian said:
is there a simple way in ruby to build an array from a string like this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?
For the basic types, eval will do it to a tolerable degree. For
everything else, there's YAML...
 
P

Phrogz

is there a simple way in ruby to build an array from a string like this:
block1,block2,block3 to an array that is like this:
["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?

irb(main):001:0> a1 = ["foo",/bar/,42,false,nil]
=> ["foo", /bar/, 42, false, nil]
irb(main):002:0> s = a1.inspect
=> "[\"foo\", /bar/, 42, false, nil]"
irb(main):003:0> a2 = eval(s)
=> ["foo", /bar/, 42, false, nil]
irb(main):004:0> a1 == a2
=> true

So:

class String
def uninspect
eval(self)
end
end

:)
 
A

ara.t.howard

is there a simple way in ruby to build an array from a string like this:
block1,block2,block3 to an array that is like this:
["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?

irb(main):001:0> a1 = ["foo",/bar/,42,false,nil]
=> ["foo", /bar/, 42, false, nil]
irb(main):002:0> s = a1.inspect
=> "[\"foo\", /bar/, 42, false, nil]"
irb(main):003:0> a2 = eval(s)
=> ["foo", /bar/, 42, false, nil]
irb(main):004:0> a1 == a2
=> true

So:

class String
def uninspect
eval(self)
end
end

yeah. maybe

class String
def uninspect
Thread.new {
$SAFE=4
begin
eval self
rescue Exception => e
e
end
}
end
end

though.

-a
 
P

Phrogz

yeah. maybe

class String
def uninspect
Thread.new {
$SAFE=4
begin
eval self
rescue Exception => e
e
end
}
end
end

though.

I think you failed to properly read my final ":)" as "But of course
you'd be a fool to really use this when so much can go disastrously
wrong by naively running eval() on a String".

Easy to miss the extra whitespace between the eyes and the grin that
implied that. ;)
 
B

Brian Candler

Brian said:
is there a simple way in ruby to build an array from a string like this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?
For the basic types, eval will do it to a tolerable degree.

No, that's not what I meant.

Firstly, eval is more dangerous than is wanted. For example, "[3, 4]" can
deserialise as [3, 4], but "3 + 4" should give an error as it would never be
the output of foo.inspect

Secondly, it should also handle regular objects with instance variables. For
example,

irb(main):001:0> class Foo; attr_accessor :a, :b, :c; end
=> nil
irb(main):002:0> obj = Foo.new; obj.a="one"; obj.b="two"; obj.c="three"; obj.inspect
=> "#<Foo:0xb7cd6f70 @c=\"three\", @b=\"two\", @a=\"one\">"

That last string would allow an object of class Foo to be reconstructed
(obviously with a different object_id)

Clearly it won't work for graph-like constructs:

irb(main):001:0> a = nil
=> nil
irb(main):002:0> a = [1, 2]
=> [1, 2]
irb(main):003:0> b = [a, a]
=> [[1, 2], [1, 2]]
irb(main):004:0> a << b
=> [1, 2, [[...], [...]]]
irb(main):005:0> b.inspect
=> "[[1, 2, [...]], [1, 2, [...]]]"
irb(main):006:0>

YAML does all that of course, but it's not inspect.

I just think that using 'inspect' would allow basic objects (with simple
nesting) to be stuffed into a database column in a simple and obvious way,
if there were a safe way to reconstruct them from it.

nil
123
"123\n"
[123, "456"]
{"foo"=>["bar","baz"]}
#<Foo: @var="val">

Regards,

Brian.
 
J

Joel VanderWerf

Brian said:
is there a simple way in ruby to build an array from a string like this:

block1,block2,block3 to an array that is like this:

["block1", "block2", "block3"]

I always thought that Object#inspect could be considered as a (crude) form
of object serialisation, and it would be really useful to have a reverse
"uninspect" operation to recreate the object from it again. Has anyone
written such a parser?

There was amarshal (on raa)

http://raa.ruby-lang.org/project/amarshal/

but it may have required you to use eval to go the other way.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,239
Messages
2,571,200
Members
47,840
Latest member
Tiffany471

Latest Threads

Top