Module Global Hash

R

Ryan Lewis

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

Wyatt Greene

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

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

Wyatt Greene

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

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

Ryan Lewis

Wyatt said:
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?
 
G

Gary Wright

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

Robert Klemme

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

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
 
J

James Gray

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

User =3D Struct.new:)screenname, :password, :dob, :join_date, :age)
class User
...
end

I like:

User =3D Struct.new(=85) do

end

James Edward Gray II=
 
R

Robert Klemme

2008/1/28 said:
I like:

User =3D Struct.new(=85) 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

--=20
use.inject do |as, often| as.you_can - without end
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,777
Messages
2,569,604
Members
45,214
Latest member
JFrancisDavis

Latest Threads

Top