module CouchPillow class Attribute attr_reader :name @required = false @type = nil @auto_convert = false @default_block = nil @check_value_message = nil @check_value_block = nil def initialize name @name = name.to_s.to_sym end # Directive to mark this Attribute as required. # def required @required = true self end def required? @required end # Directive to enforce the data type of this Attribute. # def type t @type = t self end # Attempts to auto convert values to the type specified by the {type} # directive if the value is not of the same type. # Has no effect if {type} is not specified. # def auto_convert @auto_convert = true self end # Directive to set the default value of this Attribute. Once specified, if # this Attribute does not exist during the Document initialization, whether # that's from {Document.get} or {Document#initialize}, the value of the # Attribute will be set to the value returned by the block. # # @yield Sets the value of this Attribute to the value returned by the # block. # def default &block @default_block = block self end def has_default? @default_block != nil end # Directive to perform a validation over the value of this Attribute. # # @param message Message when block passed fails. Optional. # @yield [v] Value of the Attribute. # # @example # content("Name must be John") { |v| v == "John" } # content { |v| v == "John" } # def content message = nil, &block @check_value_message = message @check_value_block = block self end # Check the default value. # # @param value The value of this attribute to validate. # def trigger_default_directive @default_block.call if has_default? end # Check value. # def trigger_content_directive value if @check_value_block raise ValidationError, @check_value_message unless @check_value_block.call(value) end value end # Check type. # def trigger_type_directive value if @type # Run auto-conversion first. value = trigger_auto_convert_directive(value) if @type == CouchPillow::Boolean raise ValidationError unless !!value == value else raise ValidationError unless value.is_a?(@type) end end value end # Auto convert the value # def trigger_auto_convert_directive value if @auto_convert if @type == Integer value = Integer(value) elsif @type == Float value = Float(value) elsif @type == String value = String(value) elsif @type == Array value = Array(value) elsif @type == Time && !value.is_a?(Time) value = Time.parse(value) elsif @type == CouchPillow::Boolean value = value == 0 || value.to_s.downcase == "false" || !value ? false : true end end value end # Run the validation directives, except required directive. # First it executes the {default} directive, then {auto_convert} to type, # then {type} validation, then finally the {content} directive. # # @return The final value after the validation. # def validate value value = trigger_default_directive if value.nil? trigger_content_directive(trigger_type_directive(value)) end end end