Geoff Barnes wrote:
> foo = Klass.new
>  foo.legal_values = (4..10)
>
> foo.value = 5  # OK
> foo.value = 11 # ERROR - out of bounds, raise exception or something

Do you want the legal values to be different per instance, or set for
the whole class?
Here are two options:

class Klass
  class << self
    attr_accessor :legal_values
  end

  attr_reader :value
  def value=( new_value )
    if value_range = self.class.legal_values
      raise "Out of Range" unless value_range.include?( new_value )
    end
    @value = new_value
  end
end

foo = Klass.new
bar = Klass.new
Klass.legal_values = 4..10

foo.value = 8
puts foo.value  #=> 8

bar.value = 17  #=> RuntimeError: Out of Range


class Klass
  attr_accessor :legal_values
  attr_reader :value

  def value=( new_value )
    if @legal_values
      raise "Out of Range" unless @legal_values.include?( new_value )
    end
    @value = new_value
  end

  def legal_values=( new_range )
    raise "Value outside Range" if @value && !new_range.include?( value
)
    @legal_values = new_range
  end
end

foo = Klass.new
foo.legal_values = 4..10

foo.value = 8
puts foo.value           #=> 8

bar = Klass.new
bar.value = 200
puts bar.value           #=> 200

bar.legal_values = 1..10 #=> RuntimeError: Value outside Range



> Also, do I have to have an explicit method for the 'value', or can it
> operate like a "builtin" class, like this :
>
> foo = Klass.new
>  foo.legal_values = (4..10)
>
> foo = 5  # OK
> foo = 11 # ERROR - out of bounds, raise exception or something

No, you can't do this - there is no assignment method (=) that you can
override to do something different. "foo = 5" will always change the
local variable 'foo' to point to a Fixnum of 5.