# Controlling attribute setting in a Struct

**URL:** <https://www.ruby-forum.com/t/controlling-attribute-setting-in-a-struct/119913>\
**Category:** Ruby\
**Created:** [November 12, 2007, 5:15am UTC](https://www.ruby-forum.com/t/controlling-attribute-setting-in-a-struct/119913 "2007-11-12T05:15:37Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2007, 5:15am UTC](https://www.ruby-forum.com/t/controlling-attribute-setting-in-a-struct/119913/1 "2007-11-12T05:15:37Z")

</div>

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.

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2007, 6:30am UTC](https://www.ruby-forum.com/t/controlling-attribute-setting-in-a-struct/119913/2 "2007-11-12T06:30:49Z")

</div>

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

---

<div class="post-metadata">

**Author:** ![unknown](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/u/4bbf92/32.png) [@unknown](https://www.ruby-forum.com/u/unknown)\
**Post date:** [November 12, 2007, 6:40am UTC](https://www.ruby-forum.com/t/controlling-attribute-setting-in-a-struct/119913/3 "2007-11-12T06:40:27Z")

</div>

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
