We are kind of getting away from the subject a bit, so I’m breaking this off to a “Struct-like” discussion thread.
I had to go look up Struct again because I always avoid using it, and never suggest it. I needed to refresh my memory as to why.
Otherwise, the name of this struct will appear as a constant in class Struct , so it must be unique for all Struct s in the system …
This is why in a shared environment I avoid them. The identifier name for Struct classes is added to the Struct class itself, as a local constant.
This means my Window struct can clash with Nat’s.
It not that it is a limitation, because it an be avoided by omitting a first String argument, but the potential for creating clashing constants by newbs is so great, that I’d only recommend it to more advanced coders.
But remember that Struct is just a factory class that generates data classes. By the time a coder is experienced enough to understand proper use of Struct in a shared environment, they’re talented enough to write their own wrapper or factory classes themselves.
As an exercise in writing a custom class factory similar to Struct in pure Ruby.
Code a factory (class of module) that creates data attribute classes.
Difference it from Struct that will not create constant identifier(s) in a shared namespace.
Instead, write it so the coder must assign the returned class object to a reference within
their own namespace(s).
Just like the Struct class, pass symbols attribute names to the factory method that create full accessor attributes. (Both getter and setter methods.)
The factory needs to set up the constructor method (initialize) in the generated classes that will accept constructor values to assign to the attributes. Any attribute values not passed into the constructor must assign a nil value to the attribute.
… Good luck
Click to view, to see Dan's version ...
module Author::SomeLibrary
# A factory library module that creates data attribute classes.
# It can be used by qualification or as a mixin module. This is an
# exercise in writing a custom class factory similar to Struct in
# pure Ruby. The main difference with Struct is that it will not
# create constant identifier(s) in a shared namespace. Instead, the
# coder must assign the returned class object to a reference within
# their own namespace(s).
module DataForge
extend self
def new(*args)
# check if all args are symbols
nas = args.find {|arg| !arg.is_a?(Symbol) }
if nas # not a symbol ...
fail(
ArgumentError,
"argument (#{args.index(nas)}) is not a Symbol.",
caller
)
end
klass = Class.new
# For each symbol name in the args array, create
# an attribute with getter and setter method ...
klass.class_eval {
attr_accessor( *args )
define_method(:initialize) { | *params |
args.each_with_index do | arg, i |
instance_variable_set( "@#{arg.to_s}".to_sym, params[i] )
end
}
}
#
return klass
end
end # DataForge module
end # module Author::SomeLibrary
Example of use …
# From within some plugin namespace (module or class) ...
include Author::SomeLibrary
Person = DataForge.new(:name,:gender,:age,:occupation,:iq)
# Person is now a class with the named attributes.
smarty = Person.new("Albert Einstein","Male",76,"Physicist",160)
smarty.iq #=> 160
smarty.age > 50 #=> true
LICENSE (Declared as a Public Domain Example)
Feel free to use the example within your own namespace hierarchy without limitation nor compensation.
However, … RENAME the mixin module names so it is within YOUR namespace.
(Your may also rename the DataForge module if you can think of something you like better.)