tutorial phoenix framework v2

Post on 15-Feb-2017

88 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

TUTORIAL PHOENIX FRAMEWORKARTHUR BRAGA ALFREDO

TUTORIAL EM DUAS PARTES

PRIMEIRA PARTE

ELIXIR

▸ Conceitos de programação funcional

▸ IEx

▸ Mix

▸ Tipos de dados

▸ Operador Pipe

▸ Módulos e funções nomeadas

▸ Controles de fluxo

▸ Estruturas de repetição

SEGUNDA PARTE

PHOENIX FRAMEWORK

▸ Criação do projeto

▸ Estrutura de arquivos

▸ Rotas e pipelines

▸ Controllers e Models

▸ Templates e Views

▸ Channels

APLICAÇÃO DE CHAT EM PHOENIX

ELIXIRPRIMEIRA PARTE

ELIXIR

JOSÉ VALIM

▸ Brasileiro

▸ Fez parte do core team do rails

▸ Participou de vários projetos open source

▸ Decidiu criar o Elixir em 2011

OBJETIVO

Criar uma linguagem que possibilitasse alta performance, extensibilidade, produtividade e que rodasse na máquina virtual do Erlang(BEAM).

ELIXIR

PORQUE ERLANG?

▸ Criado 1986 para resolver problemas na área de telefonia

▸ Altamente tolerante a falhas

▸ Feito para concorrência e paralelismo.

ELIXIR

PORQUE ERLANG?

https://blog.whatsapp.com/196/1-million-is-so-2011

ELIXIR

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

O QUE É PROGRAMAÇÃO FUNCIONAL ?

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

É um paradigma de programação que trata a computação como uma avaliação de funções matemáticas e que evita estados ou dados mutáveis.

O QUE É PROGRAMAÇÃO FUNCIONAL?

IMUTABILIDADE

Uma vez que uma variável é criada, seu valor não pode mais ser alterado

IMUTABILIDADE

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Eshell V8.0.3

1> A = 10.102> A = 20. ** exception error: no match of right hand side value 20

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Interactive Elixir (1.3.2)

iex(1)> a = 1010iex(2)> a = 2020

IMUTÁVEL?

SINGLE MATCHING

A variável não pode mais ser reutilizada

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

Interactive Elixir (1.3.2)

iex(4)> a = 1010iex(5)> ^a = 20** (MatchError) no match of right hand side value: 20

REBINDING

O valor na memória continua imutável, mas a variável pode ser reutilizada

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

soma = 25

func_soma = fn -> "A soma é #{ soma }" end

soma = 100

func_soma.()"A soma é 25"

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

soma = 25

func_soma = -> { puts soma }

soma = 100

func_soma.()100

FUNÇÕES ANÔNIMAS

São funções que podem ser tratadas como valores e que podem ser manipuladas ou retornadas por outras funções.

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

FUNÇÕES ANÔNIMAS

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

soma10 = fn (x) -> x + 10 endsoma10.(20) => 30

multiplica = fn x,y -> x * y endmultiplica.(10,10) => 100

lista = [1,2,3,4,5]Enum.map(lista, soma10) => [11, 12, 13, 14, 15, 16]

FUNÇÕES PURAS

‣ Funções sem efeitos colaterais

‣ Não acessam banco

‣ Não acessam arquivos

‣ Sempre retornam os mesmos valores para os mesmo parâmetros

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

FUNÇÕES PURAS

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

FUNÇÕES PURAS

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

soma10 = fn (x) -> x + 10 endsoma10.(20) => 30

multiplica = fn x,y -> x * y endmultiplica.(10,10)=> 100

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

FUNÇÕES PURAS

HIGHER ORDER FUNCTIONS

São funções que recebem ou retornam outras funções

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

HIGHER ORDER FUNCTIONS

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

lista = [1,2,3,4,5][1, 2, 3, 4, 5]

Enum.map(lista, fn x -> x * x end)[1, 4, 9, 16, 25]

Enum.reduce(lista, 0, fn(x,y) -> x + y end)15

Enum.reduce(lista, 0, &(&1 + &2))15

Enum.filter(lista, fn x -> x > 2 end)[3, 4, 5]

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

add = fn x -> fn y -> x + y endend

increment = add.(1)increment.(3)=> 4

PATTERN MATCHING

O operador “=“ significa “Faça com que o lado esquerdo seja igual ao direito”

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

PATTERN MATCHING

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

PATTERN MATCHING

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

{a, b, c} = {:hello, "world", 42}

a:hello

b"world"

{a, _, c} = {:hello, "world", 42}

a:hello

c42

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

{a, b, c} = {:hello, “world"}

** (MatchError) no match of right hand side value: {:hello, "world"}

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

[head | tail] = [1, 2, 3][1, 2, 3]

head1

tail[2, 3]

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Math do def sum_list([head | tail], accumulator) do sum_list(tail, head + accumulator) end

def sum_list([], accumulator) do accumulator endend

IO.puts Math.sum_list([1, 2, 3], 0) 6

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Math do def sum_list([head (1) | tail ([2,3])], accumulator (0) ) do sum_list(tail([2,3]), head (1) + accumulator (0)) end

def sum_list([], accumulator) do accumulator endend

IO.puts Math.sum_list([1, 2, 3], 0) 6

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Math do def sum_list([head (2) | tail ([3])], accumulator (1) ) do sum_list(tail([3]), head (2) + accumulator (1)) end

def sum_list([], accumulator) do accumulator endend

IO.puts Math.sum_list([1, 2, 3], 0) 6

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Math do def sum_list([head (3) | tail ([])], accumulator (3) ) do sum_list(tail([]), head (3) + accumulator (3)) end

def sum_list([], accumulator) do accumulator endend

IO.puts Math.sum_list([1, 2, 3], 0) 6

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Math do def sum_list([head | tail], accumulator ) do sum_list(tail, head + accumulator) end

def sum_list([], accumulator (6) ) do accumulator (6) endend

IO.puts Math.sum_list([1, 2, 3], 0) 6

RECURSÃO

Funções recursivas são aquelas que chamam elas mesmas.

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

RECURSÃO

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Fatorial do def de(1), do: 1 def de(n) when n > 0 do n * de(n-1) endend

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

defmodule Fatorial do def de(1, acc), do: acc def de(n, acc) when n > 0 do de(n-1, acc * n) endend

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

SEM TAIL CALL OPTIMIZATION

CONCEITOS DE PROGRAMAÇÃO FUNCIONAL

COM TAIL CALL OPTIMIZATION

ELIXIR

IEX

Read evaluate print loop(REPL) para Elixir.

ELIXIR

IEX

MIX

É uma ferramenta que vem junto com o Elixir para criar tarefas, compilar código, testar, gerenciar dependências e muito mais.

ELIXIR

MIX

ELIXIR

CRIAÇÃO DE UM NOVO PROJETO› mix new teste

* creating README.md* creating .gitignore* creating mix.exs* creating config* creating config/config.exs* creating lib* creating lib/teste.ex* creating test* creating test/test_helper.exs* creating test/teste_test.exs

Your Mix project was created successfully.You can use "mix" to compile it, test it, and more:

cd teste mix test

Run "mix help" for more commands.

ELIXIR

BAIXAR DEPENDÊNCIAS› mix deps.get

Running dependency resolutionDependency resolution completed connection: 1.0.4 db_connection: 1.0.0 decimal: 1.2.0 postgrex: 0.12.1* Getting postgrex (Hex package) Checking package (https://repo.hex.pm/tarballs/postgrex-0.12.1.tar) Using locally cached package* Getting connection (Hex package) Checking package (https://repo.hex.pm/tarballs/connection-1.0.4.tar) Using locally cached package* Getting db_connection (Hex package) Checking package (https://repo.hex.pm/tarballs/db_connection-1.0.0.tar) Using locally cached package* Getting decimal (Hex package) Checking package (https://repo.hex.pm/tarballs/decimal-1.2.0.tar) Using locally cached package

ELIXIR

BUSCAR INFORMAÇÕES DE DEPENDÊNCIAS

› mix hex.info postgrexPostgreSQL driver for Elixir.

Config: {:postgrex, "~> 0.12.1"}Releases: 0.12.1, 0.12.0, 0.11.2, 0.11.1, 0.11.0, 0.10.0, 0.9.1, 0.9.0, 0.8.4, 0.8.3, ...

Maintainers: Eric Meadows-Jönsson, James FishLicenses: Apache 2.0Links: Github: https://github.com/elixir-ecto/postgrex

HEX

Repositório de pacotes do Elixir

ELIXIR

HEX

TIPOS DE DADOS

1 # integer0x1F # integer1.0 # floattrue # boolean:atom # atom / symbol"elixir" # string'elixir' # char list[1, 2, 3] # list{1, 2, 3} # tuple

ELIXIR

TIPOS DE DADOS

CONTROLES DE FLUXO

lang = "Elixir"

if lang do IO.puts langendElixir:ok

ELIXIR

IF

lang = "Phyton"

if lang == "Elixir" do IO.puts lang else IO.puts "Não é elixir"end Não é elixir:ok

ELIXIR

IF / ELSE

lang = "Elixir"

unless lang do IO.puts langendnil

lang = "Phyton"

unless lang == "Elixir" do IO.puts lang end "Python"

ELIXIR

UNLESS

cond do 2 + 2 == 5 -> "Falso" 2 * 2 == 3 -> "Falso" 1 + 1 == 2 -> "Verdadeiro" true -> "Se nada der certo chega aqui"end"Verdadeiro"

ELIXIR

COND

case {1, 2, 3} do {4, 5, 6} -> "Não vai dar match" {1, x, 3} -> "Vai dar match e o x vai receber o valor 2" _ -> "Essa clausula vai dar match em qualquer valor"end

"Vai dar match e o x vai receber o valor 2"

ELIXIR

CASE

case {1, 2, 3} do {4, 5, 6} -> "Não vai dar match" {1, ^x, 3} -> "Vai dar match e o x vai receber o valor 2" _ -> "Essa clausula vai dar match em qualquer valor"end

"Essa clausula vai dar match em qualquer valor"

ELIXIR

CASE

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 endend

calcular.({:+, 2 ,2})4calcular.({:-, 2 ,2})0calcular.({:/, 2 ,0})** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0)

ELIXIR

CASE

ESTRUTURAS DE REPETIÇÃO

lista = [1,2,3,4,5][1, 2, 3, 4, 5]

Enum.map(lista, fn x -> x * x end)[1, 4, 9, 16, 25]

Enum.reduce(lista, 0, fn(x,y) -> x + y end)15

Enum.reduce(lista, 0, &(&1 + &2))15

Enum.filter(lista, fn x -> x > 2 end)[3, 4, 5]

ELIXIR

ENUM

stream = 1..3|> Stream.map(&IO.inspect(&1))|> Stream.map(&(&1 * 2))|> Stream.map(&IO.inspect(&1))

Enum.to_list(stream)122436=> [2, 4, 6]

ELIXIR

STREAM

File.stream!("path/to/some/file")|> Flow.from_enumerable()|> Flow.flat_map(fn line -> for word <- String.split(" "), do: {word, 1} end)|> Flow.reduce_by_key(& &1 + &2)|> Enum.to_list()

ELIXIR

FLOW

MÓDULOS E FUNÇÕES

ELIXIR

CHAMANDO FUNÇÕES

Para chamar uma função nomeada, a sintaxe sempre é:

Modulo.funcao(parametro1, parametro2, ..)

defmodule Math do def sum(a, b) do a + b endend

Math.sum(1,2) => 3

ELIXIR

MÓDULOS

defmodule Math do def sum(a, b) do do_sum(a, b) end

defp do_sum(a, b) do a + b endend

IO.puts Math.sum(1, 2) => 3IO.puts Math.do_sum(1, 2) => ** (UndefinedFunctionError)

ELIXIR

FUNÇÕES

defmodule Math do def zero?(0), do: true def zero?(x) when is_integer(x), do: falseend

ELIXIR

FUNÇÕES

GUARD CLAUSES

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2 {:/, num1, num2} -> num1 / num2 endend

calcular.({:+, 2 ,2})4calcular.({:-, 2 ,2})0calcular.({:/, 2 ,0})** (ArithmeticError) bad argument in arithmetic expression :erlang./(2, 0)

ELIXIR

GUARD CLAUSES

calcular = fn expressao -> case expressao do {:+, num1, num2} -> num1 + num2 {:-, num1, num2} -> num1 - num2 {:*, num1, num2} -> num1 * num2

{:/, num1, num2} when num2 != 0 -> num1 / num2

{:/, num1, num2} when num2 == 0 -> IO.puts "Não é possível dividir por 0" endend

calcular.({:/, 2, 0})Não é possível dividir por 0:ok

calcular.({:/, 2, 1})2.0

ELIXIR

GUARD CLAUSES

PIPE OPERATOR ( |>)

Envia o retorno da função anterior como primeiro argumento da próxima função.

ELIXIR

PIPE OPERATOR (|>)

PIPE OPERATOR (|>)

foo( bar( baz( new_function( other_function()))))

ELIXIR

other_function() |> new_function() |> baz() |> bar() |> foo()

"Elixir rocks" |> String.upcase |> String.split["ELIXIR", "ROCKS"]

"elixir" |> String.ends_with?("ixir")true

ELIXIR

PHOENIXSEGUNDA PARTE

PHOENIX FRAMEWORK

CHRIS MCCORD

▸ Descobriu Elixir em 2013

▸ Desenvolveu uma biblioteca de websockets

▸ Viu a oportunidade de criar um framework com foco em produtividade no estilo do Rails.

TIMELINE

Dezembro de 2013: Início do desenvolvimento

Setembro de 2014: José Valim entra para o time

Agosto de 2015: Versão 1.0

Junho de 2016: Versão 1.2 com Phoenix Presence

Janeiro de 2017: Versão 1.3 sem models e pasta web

PHOENIX FRAMEWORK

LIVE CODING: CHAT COM PHOENIX

ONDE APRENDER MAIS

ONDE APRENDER MAIS

MUITO OBRIGADO

top related