2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 1/36
The Safest Headless Drupal 8 withThe Safest Headless Drupal 8 withElmElm
Amitai Burtein // @amitaibu
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 2/36
Amitai Burstein@amitaibu
Spent a whole day in rural Rwanda, watching - in action - an @elmlang web-app with a #Drupal backend we've built for @ihanganeproject.
No marketing landing pages, no sale funnels, no targeted ads. Just a web-app that helps provide a better health care to mothers and their babies
158 12:20 AM - Nov 15, 2019
45 people are talking about this
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 3/36
ElmElmGenerate JavaScript with great performance and no runtimeexceptions
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 4/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 5/36
module Counter exposing (..) import Html exposing (..) import Html.Attributes exposing (..) import Html.Events exposing (onClick) -- MODEL type alias Model = Int emptyModel : ModelemptyModel = 0 -- UPDATE type Msg = Decrement | Increment update : Msg -> Model -> ( Model, Cmd Msg ) update msg model =
case msg of
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 6/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 7/36
type alias Recipe = { title: String , image : String , preparationTime: Int }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 8/36
Types 101Types 101
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 9/36
type Bool = False | True
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 10/36
type DifficultyLevel = Easy | Normal | Hard type alias Recipe = { title: String , image : String , preparationTime: Int , difficultyLevel : DifficultyLevel }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 11/36
If something can go wrong, it willMurphy's law
type alias Recipe = { title: String , .. , isCarnivore : Bool , isVegetarian : Bool , isVegan : Bool } iAmConfused : RecipeiAmConfused = { title = "A vegan steak?!" , .. , isCarnivore = True , isVegetarian = False , isVegan = True }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 12/36
type DietaryRestriction = Carnivore | Vegetarian | Vegan type alias Recipe = { title: String , .. , dietaryRestriction : DietaryRestriction } thatIsBetter : RecipethatIsBetter = { title = "A vegan steak!" , .. , dietaryRestriction = Vegan }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 13/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 14/36
type alias Recipe = { title: String , .. , preparationTime : Int , cookingTime : ? }
{ title: "foo" , preparationTime: 10, , cookingTime: null }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 15/36
!empty ?!empty ?
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 16/36
type alias Recipe = { title: String , .. , preparationTime : Int , cookingTime : Maybe Int } iceCream : RecipeiceCream = { title = "Ice Cream" , .. , preparationTime = 10 , cookingTime = Nothing } pizza : Recipepizza = { title = "Pizza" , .. , preparationTime = 10 , cookingTime = Just 15 }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 17/36
type PreparationTimes = NoPreparation | Preparation Int (Maybe Int) type alias Recipe = { title: String , .. , preparationTimes : PreparationTimes } iceCreamFromRefrigerator : RecipeiceCreamFromRefrigerator = { title = "Ice Cream for lazy people" , .. , preparationTimes = NoPreparation } pizza : Recipepizza = { title = "Pizza" , .. , preparationTimes = Preparation 10 (Just 15) }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 18/36
type PreparationTimes = NoPreparation | Preparation Int (Maybe Int) viewPreparationTimes : Recipe -> Html msg viewPreparationTimes recipe = case recipe.preparationTimes of NoPreparation -> text "No preparation required" Preparation time Nothing -> text "Takes " ++ (String.fromInt time) ++ "minutes, but no cooking" Preparation time (Just cookingTime) -> text "Takes " ++ (String.fromInt time) ++ " minutes and " ++ (String.fromInt cookingTime " minutes for cooking"
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 19/36
How to model the states of an HTTP request?
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 20/36
type WebData a = NotAsked | Loading | Failure Http.Error | Success a type alias Recipe = { title: String , .. , preparationTimes : WebData PreparationTimes } viewPreparationTimes : Recipe -> Html msg viewPreparationTimes recipe = case recipe.preparationTimes of Failure error -> text "Error loading" Success preparationTimes -> case preparationTimes of NoPreparation -> text "No preparation required"
--
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 21/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 22/36
type alias Ingredient = { name: String , price : Int } type alias Recipe = { title: String , .. , ingredients : List Ingredient }
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 23/36
map & fold
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 24/36
viewIngredients : Recipe -> Html msg viewIngredients recipe = ul [] [ List.map ( \ingredient -> li [] [ text ingredient.name ] ) recipe.ingredients ] viewTotalPrice : Recipe -> Html msg viewTotalPrice recipe = List.foldl ( \ingredient accum -> accum + ingredient.price ) 0 recipe.ingredients
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 25/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 26/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 27/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 28/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 29/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 30/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 31/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 32/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 33/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 34/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 35/36
2019/12/25 Gizra
https://gizra-presentations.github.io/drupalcamp-tokyo-2019/#/ 36/36