Controlling attribute setting in a Struct

I’m using a bunch of Struct classes in a program; they’re a perfect
way for me to bundle and access attributes. But in one of my
subclasses of Struct, I’m trying to control setting attributes so that
setting an attribute above a certain value causes an effect, like
this:

All attributes are integers.

MyMaximumBoundedStruct <
Struct.new(:life, :strength, :charisma, :weapon)
@maximum = 1000

def what_happens_when_an_attribute_is_set(attribute_name, new_value)
if new_value <= @maximum
super(attribute, new_value)
else
raise ArgumentError, “#{attribute_name} set above maximum”
end
end

end

rabbit_stats = MyMaximumBoundedStruct.new
rabbit_stats.life = 128 # okay, normal behavior
rabbit_stats.life = 1001 # raises an exception

Is there some method I can override to get this sort of behavior? Or
is this impossible or impractical using Structs (which would make me
sad, because they’re otherwise perfect for me)?

Thank you all in advance.

unknown wrote:

I’m using a bunch of Struct classes in a program; they’re a perfect
way for me to bundle and access attributes. But in one of my
subclasses of Struct, I’m trying to control setting attributes so that
setting an attribute above a certain value causes an effect

You just need to redefine the setter attribute; we can automate the
production of the setter attributes as follows (I assume that the
maximum has the same value for all attributes, else this would need to
be modified a bit):

class MyMaxBoundedStruct < Struct.new(:life, :strength, :charisma,
:weapon)

class variable (depending on Spec, a Constant could be used)

@@maximum = 1000

arr = %w[life strength charisma weapon]

arr.each do |m|
define_method("#{m}=") do |val|
if val < @@maximum
super(val)
else
raise ArgumentError, “#{m} set above maximum”
end
end
end

end

rabbit = MyMaxBoundedStruct.new

rabbit.life = 999
rabbit.weapon = 10
p rabbit.life # => 999

rabbit.life = 1000 # => ArgumentError: life set above maximum

Uups, I treated the maximum as the “first invalid value”; correction:

class MyMaxBoundedStruct < Struct.new(:life, :strength, :charisma,
:weapon)

class variable (depending on Spec, a Constant could be used)

@@maximum = 1000

arr = %w[life strength charisma weapon]

arr.each do |m|
define_method("#{m}=") do |val|
if val <= @@maximum
super(val)
else
raise ArgumentError, “#{m} set above maximum”
end
end
end
end # class

rabbit = MyMaxBoundedStruct.new

rabbit.strength = 1000 # ok
rabbit.strength = 1001 # Argument: strength set above maximum