Skip to content

Instantly share code, notes, and snippets.

@h3h
Last active December 18, 2016 06:22
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save h3h/5953a0657f0040fe66ce098fc7e0c247 to your computer and use it in GitHub Desktop.
Save h3h/5953a0657f0040fe66ce098fc7e0c247 to your computer and use it in GitHub Desktop.
Evolving Elm Validation Code
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import List
import Regex exposing (regex)
main =
Html.beginnerProgram
{ model = model
, view = view
, update = update
}
-- MODEL
type alias Model =
{ name : String
, age : String
, password : String
, passwordAgain : String
}
model : Model
model =
Model "" "" "" ""
-- UPDATE
type Msg
= Name String
| Age String
| Password String
| PasswordAgain String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Age age ->
{ model | age = age }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ type_ "text", placeholder "Name", onInput Name ] []
, input [ type_ "text", placeholder "Age", onInput Age ] []
, input [ type_ "password", placeholder "Password", onInput Password ] []
, input [ type_ "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
, viewValidation model
]
viewValidation : Model -> Html msg
viewValidation model =
let
errors = List.filterMap (\fn -> fn model) modelValidations
in
if List.isEmpty errors then
div [ style [("color", "green")] ] [ text "Great password!" ]
else
ul [ style [("color", "red")] ] (List.map (\msg -> li [] [ text (msg) ]) errors)
modelValidations =
[ validatePasswordsMatch
, validatePasswordLength
, validatePasswordChars
, validateAge
]
validatePasswordChars : Model -> Maybe String
validatePasswordChars {password} =
if not (Regex.contains (regex "[a-z]") password) ||
not (Regex.contains (regex "[A-Z]") password) ||
not (Regex.contains (regex "[0-9]") password) then
Just "Your password must contain lowercase and uppercase letters and a number."
else
Nothing
validatePasswordLength : Model -> Maybe String
validatePasswordLength {password} =
if String.length password < 8 then
Just "Your password must be at least 8 characters long."
else
Nothing
validatePasswordsMatch : Model -> Maybe String
validatePasswordsMatch {password, passwordAgain} =
if password /= passwordAgain then
Just "Your passwords don't match."
else
Nothing
validateAge : Model -> Maybe String
validateAge {age} =
if not (Regex.contains (regex "^[0-9]+$") age) then
Just "Your age must be a positive integer number."
else
Nothing
module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import List
import Regex
main =
Html.beginnerProgram
{ model = model
, view = view
, update = update
}
-- MODEL
type alias Model =
{ name : String
, age : String
, password : String
, passwordAgain : String
}
model : Model
model =
Model "" "" "" ""
-- UPDATE
type Msg
= Name String
| Age String
| Password String
| PasswordAgain String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Age age ->
{ model | age = age }
Password password ->
{ model | password = password }
PasswordAgain password ->
{ model | passwordAgain = password }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ type_ "text", placeholder "Name", onInput Name ] []
, input [ type_ "text", placeholder "Age", onInput Age ] []
, input [ type_ "password", placeholder "Password", onInput Password ] []
, input [ type_ "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
, viewValidation model
]
viewValidation : Model -> Html msg
viewValidation model =
let
errors : List String
errors =
List.filterMap (\fn -> fn model) modelValidations
in
if List.isEmpty errors then
div [ style [ ( "color", "green" ) ] ] [ text "Great password!" ]
else
ul [ style [ ( "color", "red" ) ] ] (List.map (\msg -> li [] [ text (msg) ]) errors)
modelValidations =
[ validatePasswordsMatch
, validatePasswordLength
, validatePasswordChars
, validateAge
]
validatePasswordChars : Model -> Maybe String
validatePasswordChars { password } =
if
List.any (\pattern -> not <| Regex.contains (Regex.regex pattern) password)
[ "[a-z]"
, "[A-Z]"
, "[0-9]"
]
then
Just "Your password must contain lowercase and uppercase letters and a number."
else
Nothing
validatePasswordLength : Model -> Maybe String
validatePasswordLength { password } =
if String.length password < 8 then
Just "Your password must be at least 8 characters long."
else
Nothing
validatePasswordsMatch : Model -> Maybe String
validatePasswordsMatch { password, passwordAgain } =
if password /= passwordAgain then
Just "Your passwords don't match."
else
Nothing
validateAge : Model -> Maybe String
validateAge { age } =
if not (Regex.contains (Regex.regex "^[0-9]+$") age) then
Just "Your age must be a positive integer number."
else
Nothing
module Main exposing (..)
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import List
import Regex
main : Program Never Model Msg
main =
Html.beginnerProgram
{ model = model
, view = view
, update = update
}
-- MODEL
type alias Model =
{ name : String
, age : String
, password : String
, passwordAgain : String
}
model : Model
model =
Model "" "" "" ""
-- UPDATE
type Msg
= Name String
| Age String
| Password String
| PasswordAgain String
update : Msg -> Model -> Model
update msg model =
case msg of
Name name ->
{ model | name = name }
Age age ->
{ model | age = age }
Password password ->
{ model | password = password }
PasswordAgain passwordAgain ->
{ model | passwordAgain = passwordAgain }
-- VIEW
view : Model -> Html Msg
view model =
div []
[ input [ type_ "text", placeholder "Name", onInput Name ] []
, input [ type_ "text", placeholder "Age", onInput Age ] []
, input [ type_ "password", placeholder "Password", onInput Password ] []
, input [ type_ "password", placeholder "Re-enter Password", onInput PasswordAgain ] []
, viewValidation model
]
viewValidation : Model -> Html msg
viewValidation model =
let
errors : List String
errors =
List.filterMap (\fn -> fn model) modelValidations
in
if List.isEmpty errors then
div [ style [ ( "color", "green" ) ] ] [ text "Great password!" ]
else
ul [ style [ ( "color", "red" ) ] ] (List.map (\msg -> li [] [ text (msg) ]) errors)
modelValidations : List (Model -> Maybe String)
modelValidations =
[ modelValidator
( (\{ password, passwordAgain } -> password /= passwordAgain)
, "Your passwords don't match."
)
, modelValidator
( (\{ password } -> String.length password < 8)
, "Your password must be at least 8 characters long."
)
, modelValidator
( validatePasswordChars
, "Your password must contain lowercase and uppercase letters and a number."
)
, modelValidator
( (\{ age } -> not <| simpleRegexMatches "^[0-9]+$" age)
, "Your age must be a positive integer number."
)
]
modelValidator : ( Model -> Bool, String ) -> (Model -> Maybe String)
modelValidator ( fnValidator, errorMsg ) =
(\model ->
if fnValidator model then
Just errorMsg
else
Nothing
)
simpleRegexMatches : String -> String -> Bool
simpleRegexMatches pattern string =
Regex.contains (Regex.regex pattern) string
validatePasswordChars : Model -> Bool
validatePasswordChars { password } =
List.any
(\pattern -> not <| simpleRegexMatches pattern password)
[ "[a-z]"
, "[A-Z]"
, "[0-9]"
]
--- 01.elm 2016-12-18 00:19:28.000000000 -0600
+++ 02.elm 2016-12-18 00:19:28.000000000 -0600
@@ -1,8 +1,10 @@
+module Main exposing (..)
+
import Html exposing (..)
import Html.Attributes exposing (..)
import Html.Events exposing (onInput)
import List
-import Regex exposing (regex)
+import Regex
main =
@@ -71,16 +73,20 @@
, viewValidation model
]
+
viewValidation : Model -> Html msg
viewValidation model =
let
- errors = List.filterMap (\fn -> fn model) modelValidations
+ errors : List String
+ errors =
+ List.filterMap (\fn -> fn model) modelValidations
in
if List.isEmpty errors then
div [ style [("color", "green")] ] [ text "Great password!" ]
else
ul [ style [("color", "red")] ] (List.map (\msg -> li [] [ text (msg) ]) errors)
+
modelValidations =
[ validatePasswordsMatch
, validatePasswordLength
@@ -88,15 +94,21 @@
, validateAge
]
+
validatePasswordChars : Model -> Maybe String
validatePasswordChars {password} =
- if not (Regex.contains (regex "[a-z]") password) ||
- not (Regex.contains (regex "[A-Z]") password) ||
- not (Regex.contains (regex "[0-9]") password) then
+ if
+ List.any (\pattern -> not <| Regex.contains (Regex.regex pattern) password)
+ [ "[a-z]"
+ , "[A-Z]"
+ , "[0-9]"
+ ]
+ then
Just "Your password must contain lowercase and uppercase letters and a number."
else
Nothing
+
validatePasswordLength : Model -> Maybe String
validatePasswordLength {password} =
if String.length password < 8 then
@@ -104,6 +116,7 @@
else
Nothing
+
validatePasswordsMatch : Model -> Maybe String
validatePasswordsMatch {password, passwordAgain} =
if password /= passwordAgain then
@@ -111,9 +124,10 @@
else
Nothing
+
validateAge : Model -> Maybe String
validateAge {age} =
- if not (Regex.contains (regex "^[0-9]+$") age) then
+ if not (Regex.contains (Regex.regex "^[0-9]+$") age) then
Just "Your age must be a positive integer number."
else
Nothing
--- 02.elm 2016-12-18 00:19:28.000000000 -0600
+++ 03.elm 2016-12-18 00:19:28.000000000 -0600
@@ -7,6 +7,7 @@
import Regex
+main : Program Never Model Msg
main =
Html.beginnerProgram
{ model = model
@@ -55,8 +56,8 @@
Password password ->
{ model | password = password }
- PasswordAgain password ->
- { model | passwordAgain = password }
+ PasswordAgain passwordAgain ->
+ { model | passwordAgain = passwordAgain }
@@ -87,47 +88,47 @@
ul [ style [ ( "color", "red" ) ] ] (List.map (\msg -> li [] [ text (msg) ]) errors)
+modelValidations : List (Model -> Maybe String)
modelValidations =
- [ validatePasswordsMatch
- , validatePasswordLength
- , validatePasswordChars
- , validateAge
+ [ modelValidator
+ ( (\{ password, passwordAgain } -> password /= passwordAgain)
+ , "Your passwords don't match."
+ )
+ , modelValidator
+ ( (\{ password } -> String.length password < 8)
+ , "Your password must be at least 8 characters long."
+ )
+ , modelValidator
+ ( validatePasswordChars
+ , "Your password must contain lowercase and uppercase letters and a number."
+ )
+ , modelValidator
+ ( (\{ age } -> not <| simpleRegexMatches "^[0-9]+$" age)
+ , "Your age must be a positive integer number."
+ )
]
-validatePasswordChars : Model -> Maybe String
-validatePasswordChars { password } =
- if
- List.any (\pattern -> not <| Regex.contains (Regex.regex pattern) password)
- [ "[a-z]"
- , "[A-Z]"
- , "[0-9]"
- ]
- then
- Just "Your password must contain lowercase and uppercase letters and a number."
- else
- Nothing
-
-
-validatePasswordLength : Model -> Maybe String
-validatePasswordLength { password } =
- if String.length password < 8 then
- Just "Your password must be at least 8 characters long."
+modelValidator : ( Model -> Bool, String ) -> (Model -> Maybe String)
+modelValidator ( fnValidator, errorMsg ) =
+ (\model ->
+ if fnValidator model then
+ Just errorMsg
else
Nothing
+ )
-validatePasswordsMatch : Model -> Maybe String
-validatePasswordsMatch { password, passwordAgain } =
- if password /= passwordAgain then
- Just "Your passwords don't match."
- else
- Nothing
+simpleRegexMatches : String -> String -> Bool
+simpleRegexMatches pattern string =
+ Regex.contains (Regex.regex pattern) string
-validateAge : Model -> Maybe String
-validateAge { age } =
- if not (Regex.contains (Regex.regex "^[0-9]+$") age) then
- Just "Your age must be a positive integer number."
- else
- Nothing
+validatePasswordChars : Model -> Bool
+validatePasswordChars { password } =
+ List.any
+ (\pattern -> not <| simpleRegexMatches pattern password)
+ [ "[a-z]"
+ , "[A-Z]"
+ , "[0-9]"
+ ]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment