Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Minicurso Ruby/Sinatra - UDESC Ceplan

Andrey Nering
September 03, 2016

Minicurso Ruby/Sinatra - UDESC Ceplan

Slides do minicurso da linguagem Ruby + Sinatra, com duração de cerca de 8 horas, realizado no segundo semestre de 2016 na UDESC, Campus São Bento do Sul (CEPLAN)

Andrey Nering

September 03, 2016
Tweet

Other Decks in Programming

Transcript

  1. Sobre a linguagem Ruby • Criado pelo Japonês Yukihiro "Matz"

    Matsumoto em 1995 • Foi pouco conhecida até 2003, com o lançamento do framework Ruby on Rails • A grande maioria dos projetos Ruby usam o Rails 2
  2. Características da linguagem Ruby • Interpretada (JIT Compiler) • Tipagem

    dinâmica (variáveis e parâmetros de função não tem tipo definido) • Pensada para ter um código enxuto e ser de fácil leitura ◦ O código se parece mais com o inglês escrito, e possui menos símbolos como parênteses, chaves, etc. 3
  3. Características da linguagem Ruby • No Ruby, tudo é um

    objeto, até mesmo números, strings, booleanos e mesmo "nil" • Há várias maneiras de se fazer uma mesma coisa • Entrevista com o criador: ◦ http://www.artima.com/intv/ruby.html 4
  4. Críticas à linguagem Ruby • Lenta para aplicações de alto

    tráfego • Suporta concorrência mas não paralelismo • Suporte ruim ao Windows ◦ Lentidão ◦ Sem suporte a certas bibliotecas 5
  5. Instalação do Ruby no Linux com o rbenv (https://github.com/rbenv/rbenv): •

    sudo apt-get install git build-essential • git clone https://github.com/rbenv/rbenv.git ~/.rbenv • echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc • echo 'eval "$(rbenv init -)"' >> ~/.bashrc • git clone https://github.com/rbenv/ruby-build.git ~/.rbenv/plugins/ruby-build • rbenv install --list • rbenv install 2.3.1 • rbenv global 2.3.1 6
  6. Comandos do Ruby • irb (Interactive Ruby Shell): ◦ Interpretador

    interativo do Ruby • ruby: ◦ Executa um arquivo .rb: ◦ Exemplo: ruby arquivo.rb • gem: ◦ Gerenciador de pacotes do Ruby 8
  7. Links úteis • Documentação: ◦ http://ruby-doc.org/ • Guia de estilo

    ◦ https://github.com/bbatsov/ruby-style-gu ide • Tutorial interativo no navegador: ◦ http://tryruby.org/ 9
  8. Imprimindo • O "puts" imprime um conteúdo no console, mais

    o caractere de quebra de linha ("\n") puts 'Olá,' puts 'mundo!' => Olá, => mundo • O "print" imprime sem a quebra de linha print 'Olá, ';print 'mundo!' => Olá, mundo! 10
  9. Strings • Strings podem ter aspas simples ou duplas •

    Strings com aspas duplas suportam interpolação nome = "Mundo" puts 'Olá, '+nome+'!' => Olá, Mundo! puts "Olá, #{nome}!" => Olá, Mundo! 11
  10. Strings • Caracteres especiais como quebra de linha ("\n") e

    tabulação ("\t") só funcionam com aspas duplas puts 'Olá\nmundo' => Olá\nmundo puts "Olá\nmundo" => Olá => mundo puts "Olá\\nmundo" => Olá\nmundo 12
  11. Strings • Com [] é possível fatiar uma string str

    = "ruby" puts str[0] => r puts str[1] => u puts str[1..3] => uby 13
  12. Strings • Alguns métodos úteis: puts "olá mundo".capitalize => Olá

    mundo puts "olá mundo".upcase => OLÁ MUNDO puts "OLÁ MUNDO".downcase => olá mundo 14
  13. Strings • Alguns métodos possuem uma variação com "!" ao

    final, que modifica a string ao invés de retornar uma nova string lang = 'ruby' lang.upcase puts lang => ruby lang.upcase! puts lang => RUBY 15
  14. If num = 5 if num >= 3 puts "Maior

    que 2" end if num == 5 puts "É 5" else puts "Não é 5" end 16
  15. If num = 5 if num < 5 puts "Menor

    que 5" elseif num == 5 puts "Igual a 5" elseif num == 6 puts "Igual a 6" else puts "Maior que 6" end 17
  16. If • Unless (a menos que) unless num == 5

    puts "Não é 5" end • Forma inline (na mesma linha) puts "Igual a 5" if num == 5 puts "Não é 5" unless num == 5 18
  17. Números • Os métodos "even?" e "odd?" retornam se um

    número é par ou ímpar, respectivamente puts 1.even? => false puts 1.odd? => true puts 2.even? => true puts 2.odd? => false 19
  18. Números • O método "to_s" converte um número para uma

    string 123.to_s # "123" • "to_i" converte uma string para inteiro "567".to_i # 567 20
  19. Números • Com o método "times" é possível criar um

    laço de repetição 5.times do |i| # faça algo 5 vezes print i print ',' end => 0,1,2,3,4, 3.times {|i| print i.to_s+',' } => 0,1,2, 21
  20. Nil • O nil representa ausência de um valor •

    Com o método "nil?" é possível se uma variável é nula variavel = nil puts variavel.nil? => true variavel = "string" puts variavel.nil? => false 22
  21. Arrays • Arrays no Ruby são dinâmicos (não possuem tamanho

    fixo) arr = ["joão", "maria", "josé"] puts arr[0] => joão puts arr.first => joão puts arr.last => josé puts arr[1..2] => ["maria", "josé"] 23
  22. Arrays • "length" (alias "size" ou "count") retorna o tamanho

    do array arr = ["joão", "maria", "josé"] puts arr.length => 3 • "push" adiciona um item ao final. "pop" remove do final arr.push "pedro" => ["joão", "maria", "josé", "pedro"] arr.pop => ["joão", "maria", "josé"] 24
  23. Arrays • O uso do "[]" retorna "nil" se a

    posição não existe. Use "fetch" se quiser uma exceção para um posição inexistente arr = ["joão", "maria", "josé"] puts arr[10] => nil puts arr.fetch(10) => IndexError: index 10 out of array bounds 25
  24. Arrays • "include?" informa se o array contém um elemento

    arr = [1, 2, 3] puts arr.include? 2 => true puts arr.include? 6 => false 26
  25. Arrays • "reverse" inverte um array. "sort" o ordena arr

    = [5, 7, 3, 8, 1] arr.reverse! puts arr => [1, 8, 3, 7, 5] arr.sort! puts arr => [1, 3, 5, 7, 8] 27
  26. Arrays • Com o "each" é possível percorrer um array

    arr = ["Ruby", "Python", "Go"] arr.each do |lang| puts "Linguagem #{lang}" end => Linguagem Ruby => Linguagem Python => Linguagem Go 28
  27. Arrays • O "map" (alias "collect") retorna um novo array

    com o conteúdo retornado pelo bloco para cada iteração arr = [1, 2, 3, 4, 5] dobros = arr.map do |num| num * 2 end puts dobros => [2, 4, 6, 8, 10] 29
  28. Arrays • Encadeamento de métodos puts "hello world!" .upcase #

    convertendo para caixa alta .reverse # revertendo a string .chars # para array de chars .reject {|char| char == '!'} # rejeitando "!" .reverse # revertendo o array .join('-') # juntando chars com "-" .sub(' ', '=') # substituindo espaço com "=" => H-E-L-L-O-=-W-O-R-L-D puts "hello".upcase.chars.push('!').join => HELLO! 30
  29. Symbols • Symbols são como strings, mas imutáveis "ruby" #

    string :ruby # symbol • Symbol para string :symbol.to_s # "symbol" • String para symbol "string".to_sym # :string 31
  30. Hashes • Hash é um array associativo (ou dicionário) estados

    = { :pr => 'Paraná', :sc => 'Santa Catarina' } estados[:rs] = 'Rio Grande do Sul' puts estados[:sc] => Santa Catarina 32
  31. Hashes • Percorrendo um hash estados = { pr: 'Paraná',

    sc: 'Santa Catarina', rs: 'Rio Grande do Sul' } estados.each do |chave, valor| puts "#{chave.to_s.upcase} - #{valor}" end 33
  32. Expressões regulares • Expressões regulares são nativas no Ruby •

    Elas servem, por exemplo, para validar se uma string bate com um determinado padrão /\A[a-z]+\z/.match "string" #contém apenas letras minúsculas /\A[A-z]+\z/.match "string" #contém apenas letras # CPF /\A\d\d\d\.\d\d\d\.\d\d\d\-\d\d\z/.match "000.000.000-00" # E-mail /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.[a-z]+\z/i 34
  33. Arquivos • Escrevendo em arquivos f = File.open "arquivo.txt", "w"

    f.write "Olá, mundo!" f.close # ou File.open "arquivo.txt", "w" do |f| f << "Olá, mundo!" end # ou File.write "arquivo.txt", "Olá, mundo!" 35
  34. Arquivos • Lendo arquivos File.open "arquivo.txt", "r" do |f| puts

    f.read end # ou File.read "arquivo.txt" # lendo linhas File.open "arquivo.txt", "r" do |f| puts f.readlines # ["linhas", "do", "arquivo"] end 36
  35. Funções/métodos def diga_ola(nome) puts "Olá, #{nome}" end diga_ola "mundo" =>

    Olá, mundo • Parênteses são opcionais diga_ola("mundo") => Olá, mundo 37
  36. Funções/métodos • O "return" é opcional ao final do método

    def dobro(num) return num * 2 end def metade(num) num / 2 end 38
  37. Funções/métodos • Com o "yield" é possível receber um bloco

    na função def faca_algo puts "Antes" yield "Olá" yield "mundo" puts "Depois" end faca_algo do |parametro| puts parametro end => Antes => Olá => mundo => Depois 39
  38. Classes • Declarando uma classe class Pessoa def diga_ola puts

    "Olá" end end pessoa = Pessoa.new pessoa.diga_ola => Olá 40
  39. Classes • "initialize" é o construtor • "@" aloca um

    atributo class Pessoa def initialize(nome, idade) @nome = nome @idade = idade end def debug "#{@nome} tem #{@idade} anos" end end pessoa = Pessoa.new "João", 20 puts pessoa.debug => João tem 20 anos 42
  40. Classes • Não é possível tornar atributos públicos diretamente. É

    necessário criar métodos para acessar e modificar os valores (getter e setter). class Pessoa def nome=(novo_nome) @nome = novo_nome end def nome @nome end end pessoa = Pessoa.new pessoa.nome = "Pedro" puts pessoa.nome => Pedro 43
  41. Classes • "attr_reader" cria um getter • "attr_writer" cria um

    setter • "attr_accessor" cria tanto um getter como setter class Pessoa # getter attr_reader :nome # setter attr_writer :nome # getter e setter attr_accessor :idade end pessoa = Pessoa.new pessoa.nome = "Pedro" pessoa.idade = 20 44
  42. Classes - Herança class Pessoa attr_accessor :nome def tipo_documento "?"

    end end class PessoaFisica < Pessoa def tipo_documento "CNPJ" end end class PessoaJuridica < Pessoa def tipo_documento "CPF" end end 45
  43. Classes - Herança - Super class Animal attr_accessor :especie def

    initialize(especie) @especie = especie end end class Cao < Animal attr_accessor :raca def initialize(especie, raca) super especie @raca = raca end end c = Cao.new "Cão", "Vira-lata" puts c.especie # "Cão" puts c.raca # "Vira-lata" 46
  44. Open Classes • É possível modificar uma classe já declarada,

    inclusive as nativas do Ruby class String def adiciona_exclamacao! self << '!!!' end end str = 'Funciona' str.adiciona_exclamacao! puts str => "Funciona!!!" 47
  45. Operator Overloading (Sobrecarga de operadores) • É possível declarar métodos

    para os seguintes operadores: ◦ Matemáticos: ▪ + - * / ** ◦ Comparação ▪ == === <= >= ◦ Shift ▪ << >> ◦ Lista ▪ [] []= ◦ Outros 48
  46. Operator Overloading (Sobrecarga de operadores) class Pessoa attr_accessor :nome def

    initialize(nome) @nome = nome end def ==(outra_pessoa) @nome == outra_pessoa.nome end end john = Pessoa.new "John" outro_john = Pessoa.new "John" puts john == outro_john => true 49
  47. Metaprogramação / Metaclasses • No Ruby, classes também são objetos,

    instâncias da classe "Class" nil.class.to_s # "NilClass" true.class.to_s # "TrueClass" "".class.to_s # "String" 1.class.to_s # "Fixnum" /[A-z]/.class.to_s # "Regexp" (1..5).class.to_s # "Range" "".class.class.to_s # "Class" 51
  48. Reflexão • Reflexão permite manipular uma classe depois que ela

    foi definida Pessoa = Class.new # equivalente à "class Pessoa;end" # retorna métodos da classe puts Pessoa.instance_methods # definindo um método Pessoa.class_eval do define_method :ola do |nome| puts "Olá, #{nome}" end end # chamando um método Pessoa.new.send :ola, "Fulano" # equivalente à Pessoa.new.ola("Fulano") 52
  49. Módulos - Mixins • Módulos podem conter métodos que são

    importadas em classes module Somador def somar(a, b) a + b end end class Calculadora include Somador end puts Calculadora.new.somar 2, 3 => 5 53
  50. Módulos • Módulos também são muito usados para agrupar classes

    module Concessionaria class Carro end class Gol < Carro end end gol = Concessionaria::Gol.new gol.algum_metodo 54
  51. Exceções - Try/Catch • "raise" lança uma exceção • "rescue"

    recupera uma exceção begin raise 'Lançando uma exceção' rescue puts 'Se recuperando de um erro' end begin num = 5 / 0 rescue ZeroDivisionError => e puts "Houve um erro: #{e}" end 55
  52. Exceções - Finally • "ensure" garante que algo é executado

    begin # … ensure puts "Isso roda sempre" end begin # … rescue => e # … ensure puts "Isso roda sempre" end 56
  53. Exceções • Dentro de uma função def uma_funcao # …

    rescue => e # … ensure # … end 57
  54. Exceções • Classe personalizada class MinhaExcesao < Exception end raise

    MinhaExcesao.new('Um erro ocorreu...') # ou raise MinhaExcesao, 'Um erro ocorreu...' 58
  55. Chamando outro arquivo • Incluindo uma biblioteca require 'biblioteca' •

    Incluindo um arquivo local require_relative 'arquivo' require_relative 'pasta/arquivo' 59
  56. Sinatra • É um microframework para criar pequenas aplicações web

    ◦ http://www.sinatrarb.com/ ◦ http://www.sinatrarb.com/intro.html • Instalação ◦ gem install sinatra --no-ri --no-rdoc 60
  57. Sinatra • Um servidor web simples, acessível de: ◦ http://localhost:4567/

    require 'sinatra' get '/' do "Uma página <i>web</i>" end 61
  58. Sinatra • Parâmetros de URL require 'sinatra' get '/usuario/:nome' do

    |nome| "Bem vindo, #{nome.capitalize}" end # http://localhost:4567/usuario/john 62
  59. Sinatra • Parâmetros query ficam disponíveis dentro do hash "params"

    require 'sinatra' get '/soma' do c = params['a'].to_i + params['b'].to_i c.to_s end # http://localhost:4567/soma?a=3&b=2 63
  60. Sinatra • Gerando HTML com ERB ◦ ERB é uma

    biblioteca nativa para gerar HTML a partir do Ruby ◦ Como convenção do Sinatra, os arquivos .erb ficam na pasta "/views" /app /app/app_sinatra.rb /app/views/ /app/views/pagina1.erb /app/views/pagina2.erb 65
  61. Sinatra • Chamando um arquivo .erb • "locals" contém as

    variáveis acessíveis de dentro do template require 'sinatra' get '/' do # chama arquivo "um_template.erb" erb :um_template, locals: { uma_variavel: "...", outra_variavel: "..." } end 66
  62. Sinatra • <% codigo_ruby %> ◦ Executa código Ruby mas

    não imprime retorno ◦ Exemplo: if, loop, etc • <%= codigo_ruby %> ◦ Imprime retorno da expressão no HTML 67
  63. Sinatra • Exemplo de ERB • Variáveis ◦ nome =

    "João" ◦ idade = 20 <div> <p><%= nome %> tem <%= idade %> anos.</p> </div> • Resultado <div> <p>João tem 20 anos.</p> </div> 68
  64. Sinatra • ERB com if • Variáveis ◦ condicao =

    true <% if condicao %> <p>Condição verdadeira</p> <% else %> <p>Condição falsa</p> <% end %> • Resultado <p>Condição verdadeira</p> 69
  65. Sinatra • ERB com loop • Variáveis ◦ lista =

    [10, 20, 30, 40, 50] <ul> <% lista.each do |valor| %> <li><%= valor %></li> <% end %> </ul> • Resultado <ul> <li>10</li><li>20</li><li>30</li>... </ul> 70
  66. Sinatra • Formulário com sinatra (1/3) require 'sinatra' get '/login'

    do # executa views/form_login.erb erb :form_login end post '/login' do login_correto = false if params['usuario'] == 'fulano' && params['senha'] == 'abc123' login_correto = true end erb :login, locals: {login_correto: login_correto} end 71
  67. Sinatra • Formulário com sinatra (2/3) • form_login.erb <form method="post">

    <p>Usuário</p> <p><input name="usuario" /></p> <p>Senha</p> <p><input type="password" name="senha" /></p> </form> 72
  68. Sinatra • Formulário com sinatra (3/3) • login.erb <% if

    login_correto %> <p>Bem vindo, <%= params['usuario'] %></p> <% else %> <p>Usuário ou senha incorretos</p> <p><a href="/login">Voltar</a></p> <% end %> 73
  69. Sinatra • Se houver um arquivo "layout.erb", ele é usado

    como base: <!doctype html> <html> <head> <meta charset="utf-8"> <title>Meu App</title> <link rel="stylesheet" href="/app.css"> </head> <body> <%= yield %> </body> </html> 74
  70. Sinatra • Os arquivos jogados na pasta /public ficam disponíveis

    aos usuários /app/public/imagem.jpg /app/public/estilo.css /app/public/script.js <img src="/imagem.jpg" /> <link rel="stylesheet" href="/estilo.css"> <script src="/script.js"></script> 75
  71. Sinatra • Enviando um arquivo de uma rota require 'sinatra'

    get '/arquivo' do send_file 'public/arquivo.jpg' end 76
  72. Sinatra • O "not_found" é executado quando a página não

    é encontrada require 'sinatra' # ... not_found do "<p>Página não encontrada!</p>" end 77
  73. Sinatra • Sessão ◦ Serve para guardar informações, como o

    usuário que está logado, um carrinho de compras de um e-commerce, etc require 'sinatra' enable :sessions post '/login' do if params['usuario'] = 'x' && params['senha'] == 'y' session['usuario_logado'] = params['usuario'] end end # ERB <% if session['usuario_logado'] %> <p>Bem vindo, <%= session['usuario_logado'] %></p> <% end %> 78