Here's a function similar to attr_accessor, except it takes a block,
which is used to validate assignments to the attribute, and substitute
in a string value to be used as a key to the hash inside class_eval.

It's just ugly having to use a hash to store the block. class_eval and
friends should support saving parameters into global variables for the
duration? Or is there an obvious way of doing this that I've missed?
I removed some checking for simplicity.

Clifford Heath.

def validated_attr(*names, &block)
    begin
        Thread.critical = true
        $__VALIDATOR_BLOCK ||= {}
        while $__VALIDATOR_BLOCK.has_key?([r = (rand*16777216).to_i]); end
        $__VALIDATOR_BLOCK[r] = block
    ensure
        Thread.critical = false
    end

    names.each{|name|
        class_eval <<-END
            def #{name}
                @#{name}
            end
            def #{name}=(__val)
                if !$__VALIDATOR_BLOCK[#{r.to_s}.to_i].call(__val)
                    throw "Invalid assignment of \#{__val.inspect} to #{name}"
                end
                @#{name} = __val
            end
        END
    }
end

class Foo
    validated_attr(:bar) {|v| v.kind_of?(Integer) && (0..14).include?(v)}
end

f = Foo.new

begin
    f.bar = 2       # Ok
rescue => e
    puts e.to_s
end

begin
    f.bar = 15      # Not ok
rescue => e
    puts e.to_s
end

begin
    f.bar = "Hi there"  # Not ok
rescue => e
    puts e.to_s
end