# Module Global Hash

**URL:** <https://www.ruby-forum.com/t/module-global-hash/127315>\
**Category:** Ruby\
**Created:** [January 28, 2008, 6:06am UTC](https://www.ruby-forum.com/t/module-global-hash/127315 "2008-01-28T06:06:17Z")\
**Posts on this page:** 9\
**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 28, 2008, 6:06am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/1 "2008-01-28T06:06:17Z")

</div>

#!/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

I’ve also tried putting both a @ and @@ infront of user\_hash but irb  
comes up with the same error.

---

<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 28, 2008, 6:20am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/2 "2008-01-28T06:20:31Z")

</div>

On Jan 28, 12:06 am, Ryan L. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> ```
> end
> 
> ```
> 
> Posted viahttp://www.ruby-forum.com/.  
> Remember that in Ruby, everything is an object and objects communicate  
> by passing messages (calling methods). So you can’t get to variables  
> of an object (such as user\_hash). You can only call methods that an  
> object responds to.

---

<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 28, 2008, 6:28am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/3 "2008-01-28T06:28:08Z")

</div>

On Jan 28, 12:17 am, Wyatt G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> > ```
> > self.password = pw
> > 
> > ```
> > 
> > end
> 
> > ## I’ve also tried putting both a @ and @@ infront of user\_hash but irb comes up with the same error.
> > 
> > Posted viahttp://www.ruby-forum.com/.
> 
> Remember that in Ruby, everything is an object and objects communicate  
> by passing messages (calling methods). So you can’t get to variables  
> of an object (such as user\_hash). You can only call methods that an  
> object responds to.

I think what’s going on here is that when the parser gets to the line  
that says

user\_hash = {}

it looks for a method called user\_hash to execute. It doesn’t realize  
that you’re trying to instantiate a variable. Maybe you should  
consider turning the Users module into a class and trying @@user\_hash  
= {} again.

---

<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 28, 2008, 6:35am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/4 "2008-01-28T06:35:53Z")

</div>

Wyatt G. wrote:

> On Jan 28, 12:17 am, Wyatt G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:
> 
> > > ```
> > > self.password = pw
> > > 
> > > ```
> > > 
> > > end
> > 
> > > ## I’ve also tried putting both a @ and @@ infront of user\_hash but irb comes up with the same error.
> > > 
> > > Posted viahttp://www.ruby-forum.com/.
> > 
> > Remember that in Ruby, everything is an object and objects communicate  
> > by passing messages (calling methods). So you can’t get to variables  
> > of an object (such as user\_hash). You can only call methods that an  
> > object responds to.
> 
> I think what’s going on here is that when the parser gets to the line  
> that says
> 
> user\_hash = {}
> 
> it looks for a method called user\_hash to execute. It doesn’t realize  
> that you’re trying to instantiate a variable. Maybe you should  
> consider turning the Users module into a class and trying @@user\_hash  
> = {} again.

I thought of this, but I’m going to be using a system with many many  
users and each time I would call Users, I would crate two classes,  
taking up twice as much memory.

Should I just drop the module and just keep it in a Users.rb file to  
call it later?

---

<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 28, 2008, 6:58am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/5 "2008-01-28T06:58:00Z")

</div>

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

> ```
> 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   
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

---

<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 28, 2008, 11:19am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/6 "2008-01-28T11:19:05Z")

</div>

2008/1/28, Gary W. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> On Jan 28, 2008, at 12:06 AM, Ryan L. wrote:
> 
> > #!/usr/bin/env ruby  
> > module Users  
> > class User \< Struct.new(:screenname, :password, :dob, :join\_date,  
> > :age)

You do not need to inherit from the new struct class, instead you can do

User = Struct.new(:screenname, :password, :dob, :join\_date, :age)  
class User  
…  
end

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

Note though that this approach will prevent any User instance from  
being garbage collected. This might or might not be what you want. I  
do not know the use case but there is another option: you can traverse  
all User instances via ObjectSpace.

Ah, and another remark: the implementations show so far will also  
allow to create two users with the same name but only one of them will  
be accessible via the Hash.

Kind regards

robert

---

<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 28, 2008, 2:23pm UTC](https://www.ruby-forum.com/t/module-global-hash/127315/7 "2008-01-28T14:23:03Z")

</div>

On Jan 28, 2008, at 4:18 AM, Robert K. wrote:

> can do
> 
> User = Struct.new(:screenname, :password, :dob, :join\_date, :age)  
> class User  
> …  
> end
> 
> >

I like:

User = Struct.new(…) do

end

James Edward G. II

---

<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 28, 2008, 7:10am UTC](https://www.ruby-forum.com/t/module-global-hash/127315/8 "2008-01-28T07:10:35Z")

</div>

Gary W. wrote:

> class \<\<self

Hey, thanks man. I was thinking about defining [] and []=, but I didnt  
know about \<\<self.

---

<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 28, 2008, 2:55pm UTC](https://www.ruby-forum.com/t/module-global-hash/127315/9 "2008-01-28T14:55:00Z")

</div>

2008/1/28, James G. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid):

> > 
> 
> User = Struct.new(…) do

Of course. Unfortunately it does not work with class constants  
properly. I should have mentioned that. (In my experiments I wanted  
to use User::USERS.)

Thanks for pointing it out!

Kind regards

robert
