[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

included module and scope confusion

jOhn

1/10/2006 7:12:00 PM

I am confused about modules and scope.

Here is a module:

module Crumbs
MAX_CRUMBS = 10

def self.included(mod)
def cookies
return @cookies == nil ? Hash.new : @cookies
end
end

def crumb_new( controller, action, params )
cstr = controller + "^" + action
if params != nil && params.keys != nil
params.keys.each {|p|
if params[p] != nil
cstr << "^" << p << "^" << params[p]
end
}
end
return cstr
end

def crumb_add( bite )
cbs = @cookies
puts cbs.class
cbs = cbs[:rdf_crumbs]
if cbs == nil
puts "crumb_add::cbs is nil!"
cbs =[bite]
else
puts "crumb_add::cbs is OK!"
cbs = cbs.split("|")
#don't add a redundant
if cbs.last == bite
return
end
# add to
cbs << bite
# cap the cookie queue at 5 using fifo
if cbs.length > @@MAX_CRUMBS
cbs.delete_at(0)
end
end
crumbs_set( cbs )
end

def crumbs_set( mouthful )
cr = ""
mouthful.each { |m|
if cr == ""
cr = m
else
cr << "|" << m
end
}
puts cookies.class
cookies[:rdf_crumbs] = cr
end

def get_crumbs()
crs = @cookies["rdf_crumbs"]
if crs == nil
return []
else
return crs.split("|")
end
end

end
==================================

Here is a unit test:
==================================
class Bread
include Crumbs
def initialize
@cookies = Hash.new
end
end

class CrumbTest < Test::Unit::TestCase

attr :bread

def setup
@bread = Bread.new
end

def test_crumbs_simple
@params = Hash.new
bite =bread.crumb_new( "test1", "test_action", @params )
bread.crumb_add(bite)
puts bite
bite =bread.crumb_new( "test2", "test_action_2", @params )
bread.crumb_add(bite)
puts bite
bite =bread.crumb_new( "test3", "test_action_3", @params )
bread.crumb_add(bite)
puts bite
assert bite == "test3^test_action_3"
bites =bread.get_crumbs()
puts bites.class
assert_equal bites.length, 3
end
end

Here is the output:
------------------------------------------
test cookies! on Bread
Hash
crumb_add::cbs is nil!
sets Hash with test1^test_action
has 1
test1^test_action
Hash
crumb_add::cbs is nil!
sets Hash with test2^test_action_2
has 1
test2^test_action_2
Hash
crumb_add::cbs is nil!
sets Hash with test3^test_action_3
has 1
test3^test_action_3
------------------------------------------

And:
------------------------------------------
Test::Unit::AssertionFailedError: <1> expected but was <3>.
test/unit/crumbs_test.rb:62:in `test_crumbs_simple'
------------------------------------------

I have tried different ways, but can't get the Correct Way to have a module
insert a variable into the Class that includes it. In this case it should
inject a @cookies hash, but in tests @cookies always gets reset to
Hash.new...

Excuse the inconsistencies in the code (towards @cookies) b/c I can't seem
to figure out the proper way.

So how do you add instance vars to a class from a module and how to
reference that attribute? Or is this not the Right Ruby Way?

I have a lot of confusion about modules... suppose its my java funk :/

Please point me to any more docs on modules besides the ruby-lang snippet.

-netcam
3 Answers

jOhn

1/10/2006 7:25:00 PM

0

Before I was mixing (include) Crumbs on the unit test class and I think
there was a name collision with the rails test_helper.rb file and @cookies
hence it got me all confused.

Ok here is what I did, and it seems simple. But a better way it seems would
to do it transparently to the subclass on the module, so if anyone knows
how, divulge. I don't want to have to declare the attr_reader :cookies on
the Class.

class Bread
include Crumbs

attr_reader :cookies

def initialize
@cookies = Hash.new
end
end

module Crumbs

# def self.included(mod)
# puts "test cookies! on #{mod}"
# def mod.cookies
# if @cookies == nil
# @cookies = Hash.new
# end
# return @cookies
# end
# end

#----------------------------------------
#--------------begin/ cookie crumbs mixin
#----------------------------------------
MAX_CRUMBS = 10

def crumbs_clear
if @cookies != nil and @cookies["rdf_crumbs"] != nil
@cookies.delete "rdf_crumbs"
end
end

def crumb_new( controller, action, params )
cstr = controller + "^" + action
if params != nil && params.keys != nil
params.keys.each {|p|
if params[p] != nil
cstr << "^" << p << "^" << params[p]
end
}
end
return cstr
end

def crumb_add( bite )
cbs = @cookies
puts cbs.class
cbs = cbs["rdf_crumbs"]
if cbs == nil
puts "crumb_add::cbs is nil!"
cbs =[bite]
else
puts "crumb_add::cbs is OK!"
cbs = cbs.split("|")
#don't add a redundant
if cbs.last == bite
return
end
# add to
cbs << bite
# cap the cookie queue at 5 using fifo
if cbs.length > MAX_CRUMBS
cbs.delete_at(0)
end
end

crumbs_set( cbs )
end

def crumbs_set( mouthful )
cr = ""
mouthful.each { |m|
if cr == ""
cr = m
else
cr << "|" << m
end
}
puts "sets #{@cookies.class} with #{cr}"
if @cookies == nil
@cookies = Hash.new
end
@cookies["rdf_crumbs"]=cr
puts "has #{@cookies.keys.length}"
end

def crumb_del( bite )
crs = cookies[:rdf_crumbs]
if crs != nil
crs = crumbs.split("|")
c2 =""
crs.each { |c|
if crs[c] != bite
if c2 == ""
c2 = c
else
c2 << "|" << c
end
end
}
cookies[:rdf_crumbs] =c2
end
end

def get_crumbs()
crs = @cookies["rdf_crumbs"]
if crs == nil
return []
else
return crs.split("|")
end
end

#----------------------------------------
#--------------end/ cookie crumbs mixin
#----------------------------------------
end

jOhn

1/10/2006 9:46:00 PM

0

Ok here is the final version...

Unit Test:
===============================
class Bread
include Crumbs
def cookies
@cookies ||= Hash.new
end
def initialize
@cookies = Hash.new
end
end

class CrumbTest < Test::Unit::TestCase

attr :bread

def setup
@bread = Bread.new
end

# Simple add/delete/clear tests
def test_crumbs_simples
@params = Hash.new
bite =bread.crumb_new( "test1", "test_action", @params )
bread.crumb_add(bite)
bite =bread.crumb_new( "test2", "test_action_2", @params )
bread.crumb_add(bite)
bite =bread.crumb_new( "test3", "test_action_3", @params )
bread.crumb_add(bite)
assert bite == "test3^test_action_3"
bites =bread.get_crumbs()
assert_equal bites.length, 3
bread.crumbs_clear()
bites =bread.get_crumbs()
assert_equal bites.length, 0
bite =bread.crumb_new( "test1", "test_action", @params )
bread.crumb_add(bite)
bread.crumb_del(bite)
bites =bread.get_crumbs()
assert_equal bites.length, 0
end

def test_crumbs_params
bite =bread.crumb_new( "test1", "test_action",
{"filter"=>"s`divx:divx"})
bread.crumb_add(bite)
bites =bread.get_crumbs()
assert_equal bites[0], bite
end
end


And the crumbs module:
===============================

module Crumbs
#----------------------------------------
#--------------begin/ cookie crumbs mixin
#----------------------------------------
MAX_CRUMBS = 10

public
def crumbs_clear
if cookies != nil and cookies[:rdf_crumbs] != nil
cookies.delete :rdf_crumbs
end
end

def crumb_new( controller, action, params )
cstr = controller + "^" + action
if params != nil && params.keys != nil
params.keys.each {|p|
if params[p] != nil
cstr << "^" << p << "^" << params[p]
end
}
end
return cstr
end

def crumb_add( bite )
cbs = cookies[:rdf_crumbs]
if (cbs == nil or cbs == "") or (cbs.instance_of? Array and cbslength==0)
cbs =[bite]
else
cbs = cbs.split("|")
#don't add a redundant
if cbs.last == bite
return
end
# add to
cbs << bite
# cap the cookie queue at 5 using fifo
if cbs.length > MAX_CRUMBS
cbs.delete_at(0)
end
end

crumbs_set( cbs )
end

def crumbs_set( mouthful )
cr = ""
mouthful.each { |m|
if cr == ""
cr = m
else
cr << "|" << m
end
}
cookies[:rdf_crumbs]=cr
end

def crumb_del( bite )
crs = cookies[:rdf_crumbs]
if crs != nil
crs = crs.split("|")
c2 =""
crs.each { |c|
if c != bite
if c2 == ""
c2 = c
else
c2 << "|" << c
end
end
}
cookies[:rdf_crumbs] =c2
end
end

def get_crumbs()
crs = cookies[:rdf_crumbs]
if crs == nil
return []
else
return crs.split("|")
end
end

#----------------------------------------
#--------------end/ cookie crumbs mixin
#----------------------------------------
end

Robert Klemme

1/11/2006 9:48:00 AM

0

hmmm wrote:

</snip>

> I have tried different ways, but can't get the Correct Way to have a
> module insert a variable into the Class that includes it. In this
> case it should inject a @cookies hash, but in tests @cookies always
> gets reset to Hash.new...

Of course because you assign it in initialize.

Two options:

1 Lazy init: You need to define cookies differently and access it always
through the getter method (attachment ex1.rb)

2 Init during constructor: you need to define #initialize in the module
and either leave initialize out of Bread or use super (attachment ex2.rb)

Module#included is completely wrong here as you do not want to do anything
to the class that uses the mod.

> Excuse the inconsistencies in the code (towards @cookies) b/c I can't
> seem to figure out the proper way.
>
> So how do you add instance vars to a class from a module and how to
> reference that attribute? Or is this not the Right Ruby Way?
>
> I have a lot of confusion about modules... suppose its my java funk :/

Apparently. :-)

> Please point me to any more docs on modules besides the ruby-lang
> snippet.



HTH

Kind regards

robert