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

Minicurso Ruby/Sinatra - UDESC Ceplan

Avatar for Andrey Nering 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)

Avatar for Andrey Nering

Andrey Nering

September 03, 2016
Tweet

More Decks by Andrey Nering

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