Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Ruby > Iterating through class names using a block

Reply
Thread Tools

Iterating through class names using a block

 
 
Ge Bro
Guest
Posts: n/a
 
      11-24-2007
Hey all,
this is a total newbie question, i'm just starting to learn Ruby.

here's the thing: i've got a couple of arrays with several items in
each. I'd like to use a block to iterate through each array, and create
objects of the class that is named the same as the array.

This is supposed to populate a database where tables are named after
arrays, and each table contains 1 column called "item_name" with items
from the corresponding array.

allow me to illustrate:

###

some_item = ['foo', 'bar']
other_item = ['alpha', 'bravo', 'foxtrot', 'zebra']

['some_item', 'other_item'].each do |this_array|
array_length = 0
this_object = this_array.to_s.capitalize #<== here's the problem
until array_length == this_array.length
this_object.new(:item_name => this_array[array_length])
array_length += 1
end
end

###

the problem is, this_object becomes a string with the value of
|this_array|. How do I explain to the program that its value is not just
a string, but actually a name of the class, an instance of which i'm
trying to initialize?

Forgive the dumb question, but i'm just starting out. I've been banging
my head against this for hours.... any help would be appreciated...

thanks!
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
 
Phrogz
Guest
Posts: n/a
 
      11-24-2007
On Nov 23, 9:52 pm, Ge Bro <(E-Mail Removed)> wrote:
> this_object = this_array.to_s.capitalize #<== here's the problem


Search the archives (this is not just a forum on a website, but a
mailing list and newsgroup) for posts like string name to class. The
simple answer involves const_get. This is a FAQ.
 
Reply With Quote
 
 
 
 
Phrogz
Guest
Posts: n/a
 
      11-24-2007
On Nov 23, 10:07 pm, Phrogz <(E-Mail Removed)> wrote:
> On Nov 23, 9:52 pm, Ge Bro <(E-Mail Removed)> wrote:
>
> > this_object = this_array.to_s.capitalize #<== here's the problem

>
> Search the archives (this is not just a forum on a website, but a
> mailing list and newsgroup) for posts like string name to class. The
> simple answer involves const_get. This is a FAQ.


Oh, and...welcome to Ruby
 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      11-24-2007
Ge Bro wrote:
> ['some_item', 'other_item'].each do |this_array|
> ..
> this_object = this_array.to_s.capitalize #<== here's the problem


> the problem is, this_object becomes a string with the value of
> |this_array|.


This loop:

['some_item', 'other_item'].each do |this_array|

says to take each element in the array and stuff it in the variable
this_array. The array is that thing surrounded by brackets. Since each
element of the array is a string--that's what the quotes mean--those
strings get stuffed into the variable this_array in turn. For example,
the first time through the loop, the string 'some_item' will get stuffed
into the variable this_array.

Inside the loop, you tell ruby to convert the string stored in
this_array, which is 'some_item', into a string, but the string
'some_item' is already a string, so the to_s method call doesn't do
anything. Then you say to capitalize the string 'some_item', which
gives you: 'Some_item', and then you assign 'Some_item to this_object.

> the problem is, this_object becomes a string with the value of
> |this_array|. How do I explain to the program that its value is not just
> a string, but actually a name of the class


'Some_item' is the name of a class? Where is the 'Some_item' class
defined in your code? For that matter, where is any class defined in
your code?

--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
dusty
Guest
Posts: n/a
 
      11-24-2007
On Nov 23, 11:52 pm, Ge Bro <(E-Mail Removed)> wrote:
> Hey all,
> this is a total newbie question, i'm just starting to learn Ruby.
>
> here's the thing: i've got a couple of arrays with several items in
> each. I'd like to use a block to iterate through each array, and create
> objects of the class that is named the same as the array.
>
> This is supposed to populate a database where tables are named after
> arrays, and each table contains 1 column called "item_name" with items
> from the corresponding array.
>
> allow me to illustrate:
>
> ###
>
> some_item = ['foo', 'bar']
> other_item = ['alpha', 'bravo', 'foxtrot', 'zebra']
>
> ['some_item', 'other_item'].each do |this_array|
> array_length = 0
> this_object = this_array.to_s.capitalize #<== here's the problem
> until array_length == this_array.length
> this_object.new(:item_name => this_array[array_length])
> array_length += 1
> end
> end
>
> ###
>
> the problem is, this_object becomes a string with the value of
> |this_array|. How do I explain to the program that its value is not just
> a string, but actually a name of the class, an instance of which i'm
> trying to initialize?
>
> Forgive the dumb question, but i'm just starting out. I've been banging
> my head against this for hours.... any help would be appreciated...
>
> thanks!
> --
> Posted viahttp://www.ruby-forum.com/.


Something like this will work.

class Foo; end
class Bar; end
arr = ['foo','bar','bad']
out = arr.collect {|a| Object.const_get(a.capitalize) rescue nil }
out.compact!

See http://www.ruby-doc.org/core/classes/Array.html

Look for collect and compact! to see what I'm doing there.

 
Reply With Quote
 
dusty
Guest
Posts: n/a
 
      11-24-2007
On Nov 24, 12:27 pm, dusty <(E-Mail Removed)> wrote:
> On Nov 23, 11:52 pm, Ge Bro <(E-Mail Removed)> wrote:
>
>
>
> > Hey all,
> > this is a total newbie question, i'm just starting to learn Ruby.

>
> > here's the thing: i've got a couple of arrays with several items in
> > each. I'd like to use a block to iterate through each array, and create
> > objects of the class that is named the same as the array.

>
> > This is supposed to populate a database where tables are named after
> > arrays, and each table contains 1 column called "item_name" with items
> > from the corresponding array.

>
> > allow me to illustrate:

>
> > ###

>
> > some_item = ['foo', 'bar']
> > other_item = ['alpha', 'bravo', 'foxtrot', 'zebra']

>
> > ['some_item', 'other_item'].each do |this_array|
> > array_length = 0
> > this_object = this_array.to_s.capitalize #<== here's the problem
> > until array_length == this_array.length
> > this_object.new(:item_name => this_array[array_length])
> > array_length += 1
> > end
> > end

>
> > ###

>
> > the problem is, this_object becomes a string with the value of
> > |this_array|. How do I explain to the program that its value is not just
> > a string, but actually a name of the class, an instance of which i'm
> > trying to initialize?

>
> > Forgive the dumb question, but i'm just starting out. I've been banging
> > my head against this for hours.... any help would be appreciated...

>
> > thanks!
> > --
> > Posted viahttp://www.ruby-forum.com/.

>
> Something like this will work.
>
> class Foo; end
> class Bar; end
> arr = ['foo','bar','bad']
> out = arr.collect {|a| Object.const_get(a.capitalize) rescue nil }
> out.compact!
>
> Seehttp://www.ruby-doc.org/core/classes/Array.html
>
> Look for collect and compact! to see what I'm doing there.


Sorry, forgot to instantiate the objects. Should have been.

class Foo; end
class Bar; end
arr = ['foo','bar','bad']
out = arr.collect {|a| Object.const_get(a.capitalize).new rescue nil }
out.compact!

 
Reply With Quote
 
Ge Bro
Guest
Posts: n/a
 
      11-24-2007
Great, so with everyone's help this is what I ended up doing in the end:

foo = [1foo, 2foo, 3foo]
bar = [abar, bbar]

['foo', 'bar'].each do |this_array|
length = 0
this_obj = this_array.to_s.capitalize.constantize
until length == eval(this_array).length
this_obj.create(:word => eval(this_array)[length])
length += 1
end

the trick was to use the .constantize method to turn 'foo' and 'bar'
into classes Foo and Bar, and then to use eval() to use the array's
names instead of its contents.

I came across .constantize after searching for const_get as phrogz
suggested.

7stud, my classes are defined in their corresponding controllers - this
is a part of a Rails exercise

dusty, your method using collect and compact looks interesting, I'll
play with it too.

Thanks everyone for help. I haven't been excited about programming for
the last 15 years, but Ruby is changing that rapidly


--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
Ge Bro
Guest
Posts: n/a
 
      11-24-2007
Ge Bro wrote:
> Great, so with everyone's help this is what I ended up doing in the end:
>
> foo = [1foo, 2foo, 3foo]
> bar = [abar, bbar]
>
> ['foo', 'bar'].each do |this_array|
> length = 0
> this_obj = this_array.to_s.capitalize.constantize
> until length == eval(this_array).length
> this_obj.create(:word => eval(this_array)[length])
> length += 1
> end
>
> the trick was to use the .constantize method to turn 'foo' and 'bar'
> into classes Foo and Bar, and then to use eval() to use the array's
> names instead of its contents.
>
> I came across .constantize after searching for const_get as phrogz
> suggested.
>
> 7stud, my classes are defined in their corresponding controllers - this
> is a part of a Rails exercise
>
> dusty, your method using collect and compact looks interesting, I'll
> play with it too.
>
> Thanks everyone for help. I haven't been excited about programming for
> the last 15 years, but Ruby is changing that rapidly



btw, i do have to admit that i have no clear idea of why eval() works
here and what it's actually supposed to do. Just reading about it now
and trying to make sense of it.
--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      11-24-2007
Ge Bro wrote:
> Great, so with everyone's help this is what I ended up doing in the end:


You didn't learn your lessons very well. Look up what the method to_s
does. Does calling to_s on a string do anything? Experiment.

> 7stud, my classes are defined in their corresponding controllers - this
> is a part of a Rails exercise


This isn't a Rails forum.

> I came across .constantize after searching for const_get as phrogz
> suggested.


If you are discarding the ruby solutions that were proffered in favor of
rails specific solutions, then why not just go to the rails forum?

In any case, if you look at the definition of the constantize method, it
just calls the ruby method module_eval, and module_eval seems to act
like const_get in your situation, although module_eval can also do some
other things.


> btw, i do have to admit that i have no clear idea of why eval() works
> here and what it's actually supposed to do.


You don't seem to understand the difference between a variable name and
a string. The most obvious difference is that a string has quotes
around it. Look at this example:

arr = [1, 2, 3, 4, 5, 6, 7]

puts 'arr'.length
puts arr.length

Can you guess what the output will be? Run the code and see if you are
correct.

Now try this:

puts 'arr'[0, 1]
puts arr[0, 1]

Those lines say get the elements starting at position 0 and stopping at
position 1(which does not include the stopping position). Can you
guess the output?

A string and a variable name are different animals.

The eval method says to treat a string as if it is ruby code. If your
string looks like this:

str = "num = 10; puts num"

and you eval() that string then ruby will treat the string as code and
execute it. Essentially, eval removes the quotes around a string and
then treats what's left as code. As a result, when you ask ruby to eval
a string like:

"name"

that becomes:

name

and to ruby that looks like a variable name or a method call. Try this
program:

eval("name")

--output:---
r5test.rb:1: undefined local variable or method `name' for main:Object
(NameError)

ruby can't find a variable named name nor a method named name, so ruby
produces the error message. Now try this:

def name
puts 'Jon'
end

name

The output should be obvious. Now using eval:

def name
puts 'Jon'
end

eval("name")

Why is that useful? Why not just use the previous example's code?
Because sometimes you have a method name as a string, and you want to
execute the method, e.g.:

puts "What method do you want to execute: "
input = gets
input = input.strip

def hi
puts 'hello'
end

def bye
puts 'goodbye'
end

eval(input)

--output:--
What method do you want to execute:
hi
hello

However, you should avoid using eval whenever possible. First, it's
slow. Second, someone could enter a string that contains a command to
erase your hard drive. When you eval that string, poof!







--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
7stud --
Guest
Posts: n/a
 
      11-24-2007
Ge Bro wrote:
> Hey all,
> this is a total newbie question, i'm just starting to learn Ruby.
>
> here's the thing: i've got a couple of arrays with several items in
> each. I'd like to use a block to iterate through each array, and create
> objects of the class that is named the same as the array.
>
> This is supposed to populate a database where tables are named after
> arrays, and each table contains 1 column called "item_name" with items
> from the corresponding array.
>
> allow me to illustrate:
>
> ###
>
> some_item = ['foo', 'bar']
> other_item = ['alpha', 'bravo', 'foxtrot', 'zebra']
>
> ['some_item', 'other_item'].each do |this_array|
> array_length = 0
> this_object = this_array.to_s.capitalize #<== here's the problem
> until array_length == this_array.length
> this_object.new(:item_name => this_array[array_length])
> array_length += 1
> end
> end
>
> ###
>
> the problem is, this_object becomes a string with the value of
> |this_array|. How do I explain to the program that its value is not just
> a string, but actually a name of the class, an instance of which i'm
> trying to initialize?
>
> Forgive the dumb question, but i'm just starting out. I've been banging
> my head against this for hours.... any help would be appreciated...
>
> thanks!


By the way, are you aware that your arrays can contain the class objects
themselves rather than strings:

class Dog
def id
puts "I'm a Dog"
end
end

class Flower
def id
puts "I'm a Flower"
end
end

class Circle
def id
puts "I'm a Circle"
end
end

arr = [Dog, Flower, Circle]

arr.each do |a_class|
obj = a_class.new
obj.id
end

--output:--
I'm a Dog
I'm a Flower
I'm a Circle



--
Posted via http://www.ruby-forum.com/.

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Iterating a std::vector vs iterating a std::map? carl C++ 5 11-25-2009 09:55 AM
Iterating Through Variable Names digital.pardoe@gmail.com C Programming 7 06-04-2008 02:47 PM
iterating through a block; declaring an index/counter within that block Thufir Ruby 1 10-20-2007 03:28 AM
Fo:Block can you check to see if a block contains any text by using the block id? morrell XML 1 10-10-2006 07:18 PM



Advertisments