C
Chuck Remes
I have a class that I would like to "freeze" when it reaches a particular state so that it becomes read-only. I do *not* want to use the existing #freeze method because it raises an exception when there is an attempted mutation on a frozen object and I want the attempt to be silent. It appears that the best way to enforce this (state machine pattern) is by redefining the accessors and other methods that cause mutations to be no ops.
What is the preferred practice for doing that?
Here's an example of my approach:
class Foo
attr_accessor :bar, :baz, :quxxo
def freeze!
do_nothing = Proc.new {|val| nil}
recreate_methodbar=, do_nothing)
recreate_methodbaz=, do_nothing)
recreate_methodquxxo=, do_nothing)
end
private
def recreate_method name, meth
self.class.senddefine_method, name, meth)
nil
end
end
ruby-1.9.2-p0 > f=Foo.new
=> #<Foo:0x0000010185f7d0>
ruby-1.9.2-p0 > f.bar=2
=> 2
ruby-1.9.2-p0 > f.baz=9
=> 9
ruby-1.9.2-p0 > f.freeze!
=> nil
ruby-1.9.2-p0 > f.inspect
=> "#<Foo:0x0000010185f7d0 @bar=2, @baz=9>"
ruby-1.9.2-p0 > f.bar=3
=> 3
ruby-1.9.2-p0 > f.inspect
=> "#<Foo:0x0000010185f7d0 @bar=2, @baz=9>"
Is that reasonable or is there a more idiomatic way of accomplishing this task?
cr
What is the preferred practice for doing that?
Here's an example of my approach:
class Foo
attr_accessor :bar, :baz, :quxxo
def freeze!
do_nothing = Proc.new {|val| nil}
recreate_methodbar=, do_nothing)
recreate_methodbaz=, do_nothing)
recreate_methodquxxo=, do_nothing)
end
private
def recreate_method name, meth
self.class.senddefine_method, name, meth)
nil
end
end
ruby-1.9.2-p0 > f=Foo.new
=> #<Foo:0x0000010185f7d0>
ruby-1.9.2-p0 > f.bar=2
=> 2
ruby-1.9.2-p0 > f.baz=9
=> 9
ruby-1.9.2-p0 > f.freeze!
=> nil
ruby-1.9.2-p0 > f.inspect
=> "#<Foo:0x0000010185f7d0 @bar=2, @baz=9>"
ruby-1.9.2-p0 > f.bar=3
=> 3
ruby-1.9.2-p0 > f.inspect
=> "#<Foo:0x0000010185f7d0 @bar=2, @baz=9>"
Is that reasonable or is there a more idiomatic way of accomplishing this task?
cr