# Returning with methods

**URL:** <https://www.ruby-forum.com/t/returning-with-methods/126186>\
**Category:** Ruby\
**Created:** [January 16, 2008, 5:14am UTC](https://www.ruby-forum.com/t/returning-with-methods/126186 "2008-01-16T05:14:39Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![lazukars](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/eb9ed0/32.png) [@lazukars](https://www.ruby-forum.com/u/lazukars)\
**Post date:** [January 16, 2008, 5:14am UTC](https://www.ruby-forum.com/t/returning-with-methods/126186/1 "2008-01-16T05:14:39Z")

</div>

struct.rb:  
#!/usr/bin/env ruby  
class User \< Struct.new(:screenname, :password)  
def initialize(sn, pw)  
self.screenname = sn  
self.password = pw  
end  
def inspect  
self.values  
end  
end

in IRB:  
Ruby\> irb -r struct.rb  
irb(main):001:0\> myusr = User.new “c00lryguy”, “pass”  
=\> c00lryguypass #Returns as an array as a string  
irb(main):002:0\> myusr.values  
=\> [“c00lryguy”, “pass”] #Returns as an array  
irb(main):003:0\> myusr  
=\> c00lryguypass #Again, returns as an array as a string

Now, why doesn’t the inspect method return as an array?

---

<div class="post-metadata">

**Author:** ![lazukars](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/eb9ed0/32.png) [@lazukars](https://www.ruby-forum.com/u/lazukars)\
**Post date:** [January 16, 2008, 6:44am UTC](https://www.ruby-forum.com/t/returning-with-methods/126186/2 "2008-01-16T06:44:48Z")

</div>

On Jan 15, 2008, at 11:14 PM, Ryan L. wrote:

> Now, why doesn’t the inspect method return as an array?

It does. Try

myusr.inspect.class

The problem is that IRB has to write that object to stdout so  
Array#to\_s gets called on the array returned by inspect.

It is probably a bad idea to break the convention that inspect  
returns a string.

Gary W.

---

<div class="post-metadata">

**Author:** ![lazukars](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/eb9ed0/32.png) [@lazukars](https://www.ruby-forum.com/u/lazukars)\
**Post date:** [January 16, 2008, 7:02am UTC](https://www.ruby-forum.com/t/returning-with-methods/126186/3 "2008-01-16T07:02:06Z")

</div>

Gary W. wrote:

> It does. Try
> 
> myusr.inspect.class
> 
> The problem is that IRB has to write that object to stdout so  
> Array#to\_s gets called on the array returned by inspect.
> 
> It is probably a bad idea to break the convention that inspect  
> returns a string.
> 
> Gary W.

Well, what I’m basically trying to figure out is how to change the a  
class into another class. Heres my new struct.rb:  
#!/usr/bin/env ruby  
class Hash  
def to\_struct(struct\_name)  
Struct.new(struct\_name,\*keys).new(\*values)  
end  
end

class User  
def initialize(sn, pw, dob)  
vars = {:screenname =\> sn,  
:password =\> pw,  
:dob =\> Time.parse(dob),  
:join\_date =\> Time.now,  
:age =\> Time.now.year - Time.parse(dob).year}  
return vars.to\_struct(“User”)  
end  
end

Now when I call User.new, I want it to turn the User class into the  
‘vars’ Structure

---

<div class="post-metadata">

**Author:** ![lazukars](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/l/eb9ed0/32.png) [@lazukars](https://www.ruby-forum.com/u/lazukars)\
**Post date:** [January 16, 2008, 9:46am UTC](https://www.ruby-forum.com/t/returning-with-methods/126186/4 "2008-01-16T09:46:32Z")

</div>

> ```
> def initialize(sn, pw, dob)
> 
> ```
> 
> Now when I call User.new, I want it to turn the User class into the  
> ‘vars’ Structure

I’m not sure whether your approach will do what you want (if I  
understand you  
correctly), for several reasons:

1. your to\_struct method will attempt to create a new class called  
struct\_name  
every time it is called. This will produce a warning about redefining a  
constant if it is called more than once with the same parameter.
2. the to\_struct method will return an instance of class Struct::User  
(the  
name of the class is struct\_name), which is just another class, only  
with the  
[] method added.
3. the return value of the initialize method is always ignored. If you  
wanted  
User.new to return the value returned by User#initialize, you need to  
redefine User.new. If you do, though, you won’t be able to access the  
new  
user object. Look at this:

class C

def C.new(var)  
obj = allocate  
return obj.send(:initialize, var) #initialize is private  
end

def initialize var  
@var = var  
@var \* 2  
end

end

c = C.new(3)  
puts c  
=\> 6

Now, you have no variable containing the instance of C you just created.

I think you can use an OpenStruct instead of a Struct. OpenStruct is  
like a  
hash, but you can access items using method notation. Since OpenStruct  
can be  
initialized with a hash, you can define your to\_struct method like this:

require ‘ostruct’

class Hash  
def to\_struct  
OpenStruct.new self  
end  
end

If you truly need to use a Struct, you should first check whether a  
class with  
that name is already defined, and create it only if it isn’t. For  
instance:

class Hash  
def to\_struct name  
cls = Struct.const\_get(name) rescue Struct.new( name, \*keys)  
cls.new \*values  
end  
end

I hope this helps

Stefano
