This library provides a way to ensure that object always satisfy a
specified set of constraints. An object that can be constrained must be
of kind <tt>Constraint::Shell</tt>. Constraints can be added to classes
and single objects. It is possible to define methods that handle
constraint violations and can make the object fit the demands.
Project:: http://rubyforge.org/projects/constraint/
Download:: http://rubyforge.org/frs/?group_id=748
Support:: http://rubyforge.org/forum/?group_id=748
In my experience, a certain type of errors in dynamically typed
languages are caused by pushing some wrong object to a collection type
of object. What makes this type of error so awkward is that they often
result in an exception in some totally different part of your program,
which is why it sometimes can be quite hard to track down what is
actually causing the problem. The goal of this library is to raise an
exception right where such a thing happens. While ruby is sometimes a
little bit hesitant in raising exceptions, this library tries to
counteract this tendency a little bit.
Be aware that this library introduces yet another level of indirection
and yet additional runtime checks what slows things down a little. If
you define CONSTRAINT_DISABLE before requiring the library, constraint
checks will be deactivated.
= Documentation
Constrained classes should inherit from <tt>Constraint::Shell</tt>. The
subclass should provide a way for defining new instances (by defining
#new_constrained) and redefine #process_constrained_value. The
@constrained_value instance variable contains the shell's actual values.
Examples:
class ConstrainedArray < Constraint::Shell
def new_constrained
[]
end
def process_constrained_value
@constrained_value.collect! {|e| yield e}
end
end
class NumericArray < ConstrainedArray
or_constraint("Numeric") {|e| e.kind_of?(Numeric)}
end
class EvenNumericArray < NumericArray
and_constraint("Even") {|e| e.modulo(2) == 0}
end
class EvenInteger < Constraint::Shell
and_constraint("Numeric") {|e| e.kind_of?(Integer)}
and_constraint("Even") {|e| e.modulo(2) == 0}
end
enum = EvenInteger.new(2)
enum.and_constraint("LT10") {|e| e < 10}
or:
class DuckPalace < ConstrainedArray
and_constraint('Quack') {|e| e.do_you_quack?}
and_constraint('Ticket') {|e| e.your_ticket_please == :valid}
end
whiteduckpalace = DuckPalace.new
whiteduckpalace.and_constraint('White') {|e| e.colour == 'white'}
class << whiteduckpalace
def handle_constraint_violation(contraint_name, object)
case contraint_name
when 'white'
return object.paint_me('white') if object.respond_to?(:paint_me)
end
return super
end
end
specified set of constraints. An object that can be constrained must be
of kind <tt>Constraint::Shell</tt>. Constraints can be added to classes
and single objects. It is possible to define methods that handle
constraint violations and can make the object fit the demands.
Project:: http://rubyforge.org/projects/constraint/
Download:: http://rubyforge.org/frs/?group_id=748
Support:: http://rubyforge.org/forum/?group_id=748
In my experience, a certain type of errors in dynamically typed
languages are caused by pushing some wrong object to a collection type
of object. What makes this type of error so awkward is that they often
result in an exception in some totally different part of your program,
which is why it sometimes can be quite hard to track down what is
actually causing the problem. The goal of this library is to raise an
exception right where such a thing happens. While ruby is sometimes a
little bit hesitant in raising exceptions, this library tries to
counteract this tendency a little bit.
Be aware that this library introduces yet another level of indirection
and yet additional runtime checks what slows things down a little. If
you define CONSTRAINT_DISABLE before requiring the library, constraint
checks will be deactivated.
= Documentation
Constrained classes should inherit from <tt>Constraint::Shell</tt>. The
subclass should provide a way for defining new instances (by defining
#new_constrained) and redefine #process_constrained_value. The
@constrained_value instance variable contains the shell's actual values.
Examples:
class ConstrainedArray < Constraint::Shell
def new_constrained
[]
end
def process_constrained_value
@constrained_value.collect! {|e| yield e}
end
end
class NumericArray < ConstrainedArray
or_constraint("Numeric") {|e| e.kind_of?(Numeric)}
end
class EvenNumericArray < NumericArray
and_constraint("Even") {|e| e.modulo(2) == 0}
end
class EvenInteger < Constraint::Shell
and_constraint("Numeric") {|e| e.kind_of?(Integer)}
and_constraint("Even") {|e| e.modulo(2) == 0}
end
enum = EvenInteger.new(2)
enum.and_constraint("LT10") {|e| e < 10}
or:
class DuckPalace < ConstrainedArray
and_constraint('Quack') {|e| e.do_you_quack?}
and_constraint('Ticket') {|e| e.your_ticket_please == :valid}
end
whiteduckpalace = DuckPalace.new
whiteduckpalace.and_constraint('White') {|e| e.colour == 'white'}
class << whiteduckpalace
def handle_constraint_violation(contraint_name, object)
case contraint_name
when 'white'
return object.paint_me('white') if object.respond_to?(:paint_me)
end
return super
end
end