introduction to yesod

35
Introduction to Yesod @bobjlong - Kats Conf 2015, Dublin

Upload: bobjlong

Post on 15-Apr-2017

700 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: Introduction to Yesod

Introduction to Yesod

@bobjlong - Kats Conf 2015, Dublin

Page 2: Introduction to Yesod

Brief overview + concepts

Composition

Builds and deployments

Page 3: Introduction to Yesod

About me

twitter.com/bobjlong

github.com/bobjflong

Page 4: Introduction to Yesod

Web development

Professional history of Rails

Late-night Haskell enthusiast

Page 5: Introduction to Yesod

Haskell web dev

Page 6: Introduction to Yesod

Rich types

Performance

Joy of discovery

Libraries

Error class elimination

Page 7: Introduction to Yesod

Everyday problems

Page 8: Introduction to Yesod

Wiring

Encoding issues

Safety (XSS)

Performance, concurrency

Page 9: Introduction to Yesod

What is Yesod?

Page 10: Introduction to Yesod

“Turn runtime bugs into compile-time errors”

http://www.yesodweb.com

Page 11: Introduction to Yesod

“A developer should be able to continue to productively write code as their application

grows and more team members join.”

“The key to achieving this is applying Haskell's type-safety to an otherwise

traditional MVC REST web framework.”

http://www.yesodweb.com/page/about

Page 12: Introduction to Yesod

Introducting Yesod ✨Concepts✨

Page 13: Introduction to Yesod

Routing & Handlers

DSLs

Composability

“Persistent”

- a safe and productive query interface

Familiarity

- conventions + scaffolding

Page 14: Introduction to Yesod

{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE QuasiQuotes #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-}

import Yesod

data HelloWorld = HelloWorld

mkYesod "HelloWorld" [parseRoutes| / HomeR GET |]

instance Yesod HelloWorld

getHomeR :: Handler Html getHomeR = defaultLayout [whamlet|Hello World!|]

main :: IO () main = warp 3000 HelloWorld

routing

handler

starting a web server

Page 15: Introduction to Yesod

Composition

Page 16: Introduction to Yesod

Case study: yesod-transloadit

Page 17: Introduction to Yesod

Transloadit

a webservice for handling file uploads, transformations, transcoding etc.

Page 18: Introduction to Yesod

jQuery dependency

transloadit.js

server-side scripting to compute HMAC

client-side scripting to “attach” transloadit

server-side scripting to handle response from Transloadit

where are client side assets loaded?

Page 19: Introduction to Yesod

getHomeR :: Handler Html getHomeR = defaultLayout $ do let now = UTCTime (ModifiedJulianDay 50000) (secondsToDiffTime 10)

ident <- newIdent

let expiry = addUTCTime 3600 now key = Key "my_key" template = Template "my_template" secret = Secret "my_secret" params = mkParams expiry key template ident secret

sig <- either (const $ error "nooo") transloadIt params

t <- tokenText

[whamlet| <form id="#{ident}" action=@{HomeR} method="POST"> <input type="hidden" name="_token" value="#{t}"> <input type="hidden" name="signature" value="#{sig}"> <input type="file" name="my_file"> <input type="submit" value="Upload"> |] return ()

Page 20: Introduction to Yesod

postHomeR :: Handler Html postHomeR = defaultLayout $ do results <- handleTransloadit

case nthStepResult 0 "cropped_thumb" results of Just s -> [whamlet| <img src="#{s ^. sslUrl}"/> |] _ -> [whamlet| No results :( |]

return ()

Page 21: Introduction to Yesod

How?

github.com/bobjflong/yesod-transloadit

Yesod has a generic WidgetT type that works for all web-apps

Typeclasses are used to enforce dependencies

Page 22: Introduction to Yesod

transloadIt :: (YesodJquery m, YesodTransloadit m) => TransloaditParams -> WidgetT m IO Signature

Page 23: Introduction to Yesod

data Test = Test

instance Yesod Test instance YesodJquery Test instance YesodTransloadit Test

— or

instance YesodTransloadit Test where transloaditRoot _ = “https://my_cdn.com/“

Page 24: Introduction to Yesod

Persistent

Page 25: Introduction to Yesod

share [mkPersist sqlSettings, mkMigrate “migrateAll”] [persistLowerCase| Person name String age Int Maybe deriving Show BlogPost title String authorId PersonId deriving Show |]

Page 26: Introduction to Yesod

johnId <- insert $ Person "John Doe" $ Just 35

oneJohnPost <- selectList [BlogPostAuthorId ==. johnId] [LimitTo 1]

Page 27: Introduction to Yesod

esqueleto

“esqueleto is a bare bones, type-safe EDSL for SQL queries that works with unmodified persistent SQL backends”

https://hackage.haskell.org/package/esqueleto

Page 28: Introduction to Yesod

E.selectSource $ E.from $ \(blog `E.InnerJoin` author) -> do E.on $ blog ^. BlogAuthor E.==. author ^. AuthorId return ( blog ^. BlogId , blog ^. BlogTitle , author ^. AuthorName )

Page 29: Introduction to Yesod

Building & deploying

Page 30: Introduction to Yesod

Cabal

Stack

Nix

Page 31: Introduction to Yesod

Quick intro to Nix

Page 32: Introduction to Yesod

Reproducible, stable builds

Binaries

Complete dependency graphs

Page 33: Introduction to Yesod

Immutable Infrastructure

Page 34: Introduction to Yesod

1. Pre-bake an AMI with a Nix environment

2. Build a new AMI per app version with Nix

3. Associate new instances with the ASG

http://bobjflong.co/posts/2015-08-22-yesod.html

Page 35: Introduction to Yesod

Questions?

@bobjlong

https://github.com/bitemyapp/learnhaskell http://www.yesodweb.com/book