Returning with methods

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?

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.

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

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