I’m trying to define a static variable and methods in a module that will be extended/used by numerous classes. The following example demonstrates:
module Ammunition
def self.included(base)
base.class_eval("@@ammo = [bullets]")
end
def unload
p @@ammo #<-- doesn't work
end
end
class Tank
include Ammunition
@@a += [shells]
end
class Airplane
include Ammunition
@@a += [missiles, photon_torpedoes]
end
Tank.new.unload
Airplane.new.unload
This doesn’t work because ammunition doesn’t know how to evaluate @@ammo in the context of the class for some reason (I original thought the module would behave just like an include file). I would have to copy ‘unload’ to each class, which I’m doing right now, but I want to DRY it up b/c I have many other methods to add to the module.
Suggestions? The reasonable solution would be to evaluate ‘unload’ in the context of the class and not the module (but how to do this in Ruby?)
Thanks!
class variables can work strangely, and this use shows that off. What is the scope of
@@ammo?Ammunitionor doesTankhave its own copy of it? It turns out that@@ammois scoped by the module, and the classes that include it can simply access it.This produces:
When
Tankincludes the module, it sets@@ammofrom nil to an array with bullets in it. WhenAirplaneincludes the module, it overwrites the ammo value we just set.Here is what you want to do
Classes can have instance variables, and their scope is easier to understand. And separating your module into instance and class methods allow you to provide functionality to both. This snippet generates the following output