examples: annotate examples
[nit.git] / lib / popcorn / pop_validation.nit
index aebbc93..c3eee92 100644 (file)
 #
 # ~~~
 # import popcorn
+# import popcorn::pop_json
 # import serialization
 #
 # # Serializable book representation.
 # class Book
-#      super Jsonable
+#      super Serializable
 #
 #      # Book ISBN
 #      var isbn: String
@@ -61,7 +62,7 @@
 #      redef fun post(req, res) do
 #              var validator = new BookValidator
 #              if not validator.validate(req.body) then
-#                      res.json_error(validator.validation, 400)
+#                      res.json(validator.validation, 400)
 #                      return
 #              end
 #              # TODO data persistence
@@ -95,10 +96,8 @@ end
 #
 # Errors messages are grouped into *scopes*. A scope is a string that specify wich
 # field or document the error message is related to.
-#
-# See `HttpResponse::json_error`.
 class ValidationResult
-       super Jsonable
+       super Serializable
 
        # Object parsed during validation
        #
@@ -140,20 +139,15 @@ class ValidationResult
        # Does `self` contains `errors`?
        fun has_error: Bool do return errors.not_empty
 
-       # Render self as a JsonObject
-       fun json: JsonObject do
-               var obj = new JsonObject
-               obj["has_error"] = has_error
-               var e = new JsonObject
-               for k, v in errors do
-                       e[k] = new JsonArray.from(v)
+       redef fun core_serialize_to(v) do
+               var errors = new JsonObject
+               for k, e in self.errors do
+                       errors[k] = new JsonArray.from(e)
                end
-               obj["errors"] = e
-               return obj
+               v.serialize_attribute("has_error", has_error)
+               v.serialize_attribute("errors", errors)
        end
 
-       redef fun serialize_to(v) do json.serialize_to(v)
-
        # Returns the validation result as a pretty formated string
        fun to_pretty_string: String do
                var b = new Buffer
@@ -199,8 +193,8 @@ class ObjectValidator
                return validate_json(json)
        end
 
-       # Validate a Jsonable input
-       fun validate_json(json: Jsonable): Bool do
+       # Validate a Serializable input
+       fun validate_json(json: Serializable): Bool do
                if not json isa JsonObject then
                        validation.add_error("document", "Expected JsonObject got `{json.class_name}`")
                        return false
@@ -251,8 +245,8 @@ class ArrayValidator
                return validate_json(json)
        end
 
-       # Validate a Jsonable input
-       fun validate_json(json: Jsonable): Bool do
+       # Validate a Serializable input
+       fun validate_json(json: Serializable): Bool do
                if not json isa JsonArray then
                        validation.add_error("document", "Expected JsonArray got `{json.class_name}`")
                        return false
@@ -523,6 +517,52 @@ class FloatField
        end
 end
 
+# Check if a field is a Bool
+#
+# ~~~
+# var validator = new ObjectValidator
+# validator.add new BoolField("field", required=false)
+# assert validator.validate("""{}""")
+# assert validator.validate("""{ "field": true }""")
+# assert validator.validate("""{ "field": false }""")
+# assert not validator.validate("""{ "field": "foo" }""")
+#
+# validator = new ObjectValidator
+# validator.add new BoolField("field")
+# assert not validator.validate("""{}""")
+# assert validator.validate("""{ "field": true }""")
+# assert validator.validate("""{ "field": false }""")
+# assert not validator.validate("""{ "field": "foo" }""")
+# ~~~
+#
+# No type conversion is applied on the input value:
+# ~~~
+# assert not validator.validate("""{ "field": "true" }""")
+# assert not validator.validate("""{ "field": 1 }""")
+# assert not validator.validate("""{ "field": [true] }""")
+# ~~~
+class BoolField
+       super RequiredField
+
+       redef fun validate_field(v, obj) do
+               if not super then return false
+               var val = obj.get_or_null(field)
+               if val == null then
+                       if required == null or required == true then
+                               v.validation.add_error(field, "Expected Bool got `null`")
+                               return false
+                       else
+                               return true
+                       end
+               end
+               if not val isa Bool then
+                       v.validation.add_error(field, "Expected Bool got `{val.class_name}`")
+                       return false
+               end
+               return true
+       end
+end
+
 # Check that a field is a JsonObject
 #
 # ~~~