lib/lotus/validations/attribute_definer.rb in lotus-validations-0.2.3 vs lib/lotus/validations/attribute_definer.rb in lotus-validations-0.2.4
- old
+ new
@@ -251,13 +251,18 @@
# signup = Signup.new(password: 'a-very-long-password')
# signup.valid? # => true
#
# signup = Signup.new(password: 'short')
# signup.valid? # => false
- def attribute(name, options = {})
- define_attribute(name, options)
- validates(name, options)
+ def attribute(name, options = {}, &block)
+ if block_given?
+ define_nested_attribute(name, options, &block)
+ validates(name, {})
+ else
+ define_attribute(name, options)
+ validates(name, options)
+ end
end
# Set of user defined attributes
#
# @return [Array<String>]
@@ -283,10 +288,20 @@
define_accessor(confirmation_accessor, type)
defined_attributes.add(confirmation_accessor)
end
end
+ # @since 0.2.4
+ # @api private
+ def define_nested_attribute(name, options, &block)
+ nested_class = build_validation_class(&block)
+ define_lazy_reader(name, nested_class)
+ define_coerced_writer(name, nested_class)
+ defined_attributes.add(name.to_s)
+ validates(name, nested: true)
+ end
+
# @since 0.2.2
# @api private
def define_accessor(name, type)
if type
define_reader(name)
@@ -317,9 +332,38 @@
# @api private
def define_reader(name)
define_method(name) do
@attributes.get(name)
end
+ end
+
+ # Defines a reader that will return a new instance of
+ # the given type if one is not already present
+ #
+ # @since 0.2.4
+ # @api private
+ def define_lazy_reader(name, type)
+ define_method(name) do
+ value = @attributes.get(name)
+ return value if value
+
+ type.new({}).tap do |val|
+ @attributes.set(name, val)
+ end
+ end
+ end
+
+ # Creates a validation class and configures it with the
+ # given block.
+ #
+ # @since 0.2.4
+ # @api private
+ def build_validation_class(&block)
+ kls = Class.new do
+ include Lotus::Validations
+ end
+ kls.class_eval(&block)
+ kls
end
end
# Support for `Lotus::Entity`
#