# Returning with methods

**URL:** <https://rubytalk.org/t/returning-with-methods/43805>\
**Category:** ruby-talk\
**Created:** [16 January 2008 04:14 UTC](https://rubytalk.org/t/returning-with-methods/43805 "2008-01-16T04:14:34Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![Ryan\_Lewis](https://avatars.discourse-cdn.com/v4/letter/r/c4cdca/32.png) [@Ryan\_Lewis](https://rubytalk.org/u/Ryan_Lewis)\
**Post date:** [16 January 2008 04:14 UTC](https://rubytalk.org/t/returning-with-methods/43805/1 "2008-01-16T04:14:34Z")

</div>

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

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

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

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/](http://www.ruby-forum.com/).

---

<div class="post-metadata">

**Author:** ![Gary\_Wright](https://avatars.discourse-cdn.com/v4/letter/g/58956e/32.png) [@Gary\_Wright](https://rubytalk.org/u/Gary_Wright)\
**Post date:** [16 January 2008 05:43 UTC](https://rubytalk.org/t/returning-with-methods/43805/2 "2008-01-16T05:43:12Z")

</div>

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 Wright

> **···**
>
> On Jan 15, 2008, at 11:14 PM, Ryan Lewis wrote:
> 
> > Now, why doesn't the inspect method return as an array?

---

<div class="post-metadata">

**Author:** ![Ryan\_Lewis](https://avatars.discourse-cdn.com/v4/letter/r/c4cdca/32.png) [@Ryan\_Lewis](https://rubytalk.org/u/Ryan_Lewis)\
**Post date:** [16 January 2008 06:02 UTC](https://rubytalk.org/t/returning-with-methods/43805/3 "2008-01-16T06:02:00Z")

</div>

Gary Wright 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 Wright

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

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

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

> **···**
>
> --  
> Posted via [http://www.ruby-forum.com/\](http://www.ruby-forum.com/%5C).

---

<div class="post-metadata">

**Author:** ![Stefano\_Crocco](https://avatars.discourse-cdn.com/v4/letter/s/5f9b8f/32.png) [@Stefano\_Crocco](https://rubytalk.org/u/Stefano_Crocco)\
**Post date:** [16 January 2008 08:45 UTC](https://rubytalk.org/t/returning-with-methods/43805/4 "2008-01-16T08:45:44Z")

</div>

> Well, what I'm basically trying to figure out is how to change the a  
> class into another class. Heres my new struct.rb:  
> &nbsp;&nbsp;#!/usr/bin/env ruby  
> &nbsp;&nbsp;class Hash  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;def to\_struct(struct\_name)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Struct.new(struct\_name,\*keys).new(\*values)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;&nbsp;end
> 
> &nbsp;&nbsp;class User  
> &nbsp;&nbsp;&nbsp;&nbsp;def initialize(sn, pw, dob)  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;vars = {:screenname =\> sn,
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:password =\> pw,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:dob =\> Time.parse(dob),  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:join\_date =\> Time.now,  
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:age =\> Time.now.year - Time.parse(dob).year}
> 
> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return vars.to\_struct("User")  
> &nbsp;&nbsp;&nbsp;&nbsp;end  
> &nbsp;&nbsp;end
> 
> 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

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

&nbsp;&nbsp;def initialize var  
&nbsp;&nbsp;&nbsp;&nbsp;@var = var  
&nbsp;&nbsp;&nbsp;&nbsp;@var \* 2  
&nbsp;&nbsp;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  
&nbsp;&nbsp;def to\_struct  
&nbsp;&nbsp;&nbsp;&nbsp;OpenStruct.new self  
&nbsp;&nbsp;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  
&nbsp;&nbsp;def to\_struct name  
&nbsp;&nbsp;&nbsp;&nbsp;cls = Struct.const\_get(name) rescue Struct.new( name, \*keys)  
&nbsp;&nbsp;&nbsp;&nbsp;cls.new \*values  
&nbsp;&nbsp;end  
end

I hope this helps

Stefano
