On Jan 28, 2008, at 12:06 AM, Ryan Lewis wrote:

> #!/usr/bin/env ruby
> module Users
>   class User < Struct.new(:screenname, :password, :dob, :join_date,
> :age)
>     def initialize(sn, pw, dob)
>       self.screenname = sn
>       self.password   = pw
>       self.dob        = Time.parse(dob)
>       self.join_date  = Time.now
>       self.age        = Time.now.year - Time.parse(dob).year
>     end
>   end
>   #########################################
>   user_hash = {}
>
>   def new(sn, pw, dob)
>     Users::user_hash[sn] = User.new(sn, pw, dob)
>   end
>   #########################################
>   module_function :new
> end
>
> I'm trying to make it so when I call:
>    Users::new("screenname", "pass", "1/15/91")
>
> it adds a new instance of the User class into user_hash, but when I
> execute the above code in IRB I get a NoMethodError for user_hash for
> the Users:module

The way you've used it, user_hash is a local variable for the module  
Users block.  It disappears when the block ends.

You don't need a separate enclosing module. You've already got User.

In the following code, I used an instance variable of User,  
@user_hash, to store the instances by name, User#initialize adds the  
entry, and for added ease of use, I defined User.[] and User.[]= as a  
way to access @user_hash.

require 'time'
class User < Struct.new(:screenname, :password, :dob, :join_date, :age)

   class <<self
     def [](u)
       user_hash[u]
     end
     def []=(name, struct)
       user_hash[name] = struct
     end
     def user_hash
       @user_hash ||= {}
     end
   end

   def initialize(sn, pw, dob)
     self.screenname = sn
     self.password   = pw
     self.dob        = Time.parse(dob)
     self.join_date  = Time.now
     self.age        = Time.now.year - Time.parse(dob).year
     self.class[sn] = self
   end
end

User.new('bob', 'pw', '1/1/01')

p User['bob']
p User.user_hash