I’m confused, to say the least! I’m setting up caches on objects using a
class variable. It all works well until I try to extract it out to a
module
to mixin to other objects:
module HostBasedCache
def setup_cache(method, &method_proc)
@@cache_method = method_proc if block_given?
class_eval <<-METHOD
def self.#{method}(param)
#some stuff not relevant
puts @@cache_method.call(param)
#some stuff not relevant
end
METHOD
end
end
class MyObject
extend HostBasedCache
setup_cache(:find_with_roles) do |id|
User.find_by_id(id, :select => “users.id, roles.id”, :include => [
:roles
])
end
end
Unfortunately, when calling find_with_roles I’m told that @@cache_method
isn’t defined. Setting @@cache_method explicitly in MyObject (rather
than the
setup_cache) call makes everything work. I must be missing some scoping
problem - can anyone explain this to me, please?
Thanks a lot,
Mark
On 6/19/07, Mark S. [email protected] wrote:
I’m confused, to say the least! I’m setting up caches on objects using a
class variable.
My rule of thumb is, Do Not Use Class Variables, use Class Instance
Variables
It all works well until I try to extract it out to a module
end
end
end
Unfortunately, when calling find_with_roles I’m told that @@cache_method
isn’t defined. Setting @@cache_method explicitly in MyObject (rather than the
setup_cache) call makes everything work. I must be missing some scoping
problem - can anyone explain this to me, please?
Look at this slightly adapted code just using Class Instance Variables.
Does this solve your problem?
-------------------------8<----------------------------
module HostBasedCache
def setup_cache(method, &method_proc)
@cache_method = method_proc if block_given?
class_eval <<-METHOD
def self.#{method}(param)
#some stuff not relevant
puts @cache_method.call(param)
#some stuff not relevant
end
METHOD
end
end
class MyObject
extend HostBasedCache
setup_cache(:find_with_roles) do |id|
User.find_by_id(id, :select => “users.id, roles.id”, :include => [
:roles ])
puts "Hi there " << id.to_s
end
end
MyObject.find_with_roles( 42 )
-------------------------8<----------------------------
Cheers
Robert
Hi –
On Tue, 19 Jun 2007, Mark S. wrote:
On Tue, Jun 19, 2007 at 09:05:38PM +0900, Robert D. wrote:
Look at this slightly adapted code just using Class Instance Variables.
Does this solve your problem?
It does! I wasn’t aware that there are class instance variables as well as
class variables.
Anything that can be ‘self’ can have instance variables
David
Is there a significant performance difference between these two ways to
call a method?
(a) Define the method in a module, then call it with
MODULE_NAME::METHOD_NAME
(b) Define the method in a class, then instantiate an object from the
class, then call the method with OBJECT_REFERENCE_VAR.METHOD_NAME
Purely for the convenience in naming methods, I’d love to do everything
in classes, but I can’t help suspecting that performance will suffer
somewhat if I instantiate objects when not really necessary.
On Tue, Jun 19, 2007 at 09:05:38PM +0900, Robert D. wrote:
Look at this slightly adapted code just using Class Instance Variables.
Does this solve your problem?
It does! I wasn’t aware that there are class instance variables as well
as
class variables.
Appreciated, thank you very much!
Mark
On Jun 23, 2007, at 10:28 AM, John Joyner wrote:
everything
in classes,
IMO that’s not a good reason. The main reason for grouping methods
into classes is to provide behavior to a set of objects where each
object maintains it own individual state. Another is that classes
support inheritance and modules don’t. In particular, every class you
define inherits great deal of commonly needed behavior from Object.
Also, I don’t see why naming is more convenient in classes than in
modules.
but I can’t help suspecting that performance will suffer
somewhat if I instantiate objects when not really necessary.
If you suspect this, test your hypothesis with the Benchmark library.
Apologies! I had meant to start a new thread.
Regards, Morton
On 6/22/07, John N. Joyner [email protected] wrote:
Is there a significant performance difference between these two ways to
call a method?
(a) Define the method in a module, then call it with
MODULE_NAME::METHOD_NAME
You don’t need to use ::, that’s mostly meant for constants and nested
class seperation.
Instead, do:
module MyModule
module_function
def whatever
end
end
you can also of course pass specific method names to module_function.
This lets you do:
MyModule.whatever
(b) Define the method in a class, then instantiate an object from the
class, then call the method with OBJECT_REFERENCE_VAR.METHOD_NAME
You can also make class methods.
class A
def self.whatever
end
end
A.whatever
This is useful when an object is stateful but doesn’t need to have
instances (or has behaviour at the class level and instance level)
Finally, to answer you question about performance, a big difference is
that modules can’t be instantiated. But I doubt that they will be
much less heavyweight than a class that you don’t create instances of,
or use just one instance. You’ll want to use profile memory usage to
be sure.
On 6/23/07, Robert D. [email protected] wrote:
extend M
…
C.my_fancy_method
--------------------- >8 -------------------
this might indeed be a useful pattern which is underused - citation David Black.
sure. It’s fairly OT from what was asked for though, but while we’re
here
I rarely find myself needing ‘just’ class methods, and I don’t like
doing a seperate call to mix them in, so i’d typically do something
like
module M
module ClassMethods
def whatever; end
end
def self.included(base)
base.extend(ClassMethods)
end
end
class C
include M
end
But if all you need is the class methods, and don’t mind using extend,
what you suggested works fine.
On 6/23/07, Gregory B. [email protected] wrote:
And to round up the picture and to keep David happy
--------------------- 8< ------------------
module M
def my_fancy_method
…
…
class C
extend M
…
C.my_fancy_method
--------------------- >8 -------------------
this might indeed be a useful pattern which is underused - citation
David Black.
Cheers
Robert