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` #