2. Linguagem Ruby
Foi criada com o intuito de parecer natural, não
necessariamente simples.
Seu idealizador buscou o equilíbrio entre programação
funcional e programação imperativa.
"O Ruby é simples na aparência, mas muito complexo no
interior, tal como o corpo humano." - Yukishiro 'Matz' Matsumoto
3. Linguagem Ruby
Parte de sua naturalidade vem do fato de Ruby utilizar
tipagem dinâmica.
Outras propriedades interessantes:
● Compilação just-in-time (tradução dinâmica)
● Garbage Collector
● Tipagem forte
● E o mais interessante...
4. Linguagem Ruby
Tudo em Ruby é um objeto.
Ou seja, cada pedaço de informação em um código Ruby
pode possuir suas próprias propriedades e métodos.
Lembrando: em programação orientada a objetos,
chamamos propriedades de variáveis de instância e ações
de métodos. Veremos isso melhor mais adiante.
5. IRB
Grande recurso para os desenvolvedores Ruby é o console
interativo Ruby, ou IRB.
7. Strings
São delimitadas por aspas simples ou duplas. Aspas simples
não comportam interpolação.
Strings são mutáveis. Através do operador '<<', por
exemplo, a string é modificada na mesma instancia
8. Strings (primeira convenção)
O método capitalize transforma a primeira letra de uma
String em maiúscula.
Quantos outros métodos uma String possui?
9. Tipos e operações básicas
Como era de se esperar o Ruby consegue lidar com
expressões matemáticas.
Possui 3 tipos numéricos básicos: Fixnum, Bignum e Float
10. Tipos e operações básicas
+: Soma
-: Subtração
*: Multiplicação
/: Divisão
%: Mod (vulgo resto)
**: Potência
11. Tipos e operações básicas (Range)
Range: Maneira simples de se trabalhar com sequências.
(1..9): Sequência de 1 a 9
('a'..'z'): Sequência de a a z minúsculo
(0...5): Sequência de 0 a 4
12. Tipos e operações básicas (Symbol)
Symbol: São textos como as Strings.
São imutáveis e compartilhados; por conta disso, são
usados como identificadores e nomenclatura.
13. Operações booleanas
Ruby possui operações booleanas como qualquer outra
linguagem.
São elas: <, >, <=, >=, ==.
Estas operações ainda podem ser combinadas com &&
(and) e || (or)
16. Arrays
São delimitados por colchetes [ ] e podem guardar qualquer
objeto. Por padrão, seu tamanho não é definido. Vejamos:
alunos = Array.new ou alunos = []
Quando tentamos acessar um índice não existente do array,
ele nos retorna nil: alunos[0] ou alunos[1000000].
17. Arrays
Para recebermos algum erro ao tentar acessar um índice
inexistente de um Array, devemos utilizar o método fetch.
alunos.fetch(100)
Para retornar uma mensagem padrão ao invés do
IndexError: alunos.fetch(100, "Não temos tantos alunos.")
18. Arrays
Vamos iterar por nosso array.
alunos.each do |aluno|
puts aluno + " sobrenome"
end
Ao invés de puts aluno, tentem aluno = aluno + "
sobrenome".
19. Arrays
O método map pode ser usado para criarmos um novo
array a partir do nosso.
alunos.map do |aluno|
aluno = aluno + " sobrenome"
end
E se usarmos map! ao invés de map ?
20. Hashes (~= Arrays associativos)
São delimitados por chaves {} e representam uma estrutura
de chave-valor. Podemos usar qualquer tipo de chave e
qualquer tipo de valor (por convenção, usamos symbols
como chaves).
idades_alunos = {} ou idades_alunos = Hash.new
Quando tentamos acessar o valor de uma chave não
existente, ele nos retorna nil: idade_alunos["workshop"]
21. Leitura do input
Equivalente ao cin de C++, temos o gets em Ruby.
meu_nome = gets.chomp
Porque chomp?
22. Declaração de função
def minha_funcao(param1, param2 = [])
param2[0] = param1
end
minha_funcao("Matheus", alunos)
Porque retornou "Matheus"? Chequem alunos
23. Exercício: troco mínimo (+-)
Queremos uma função que devolva um determinado troco
com o menor número de moedas possível, dado um
conjunto de moedas.
Mais do que isso, queremos um programa que leia o valor
do troco e também o valor das moedas que estarão no tal
conjunto. Para o conjunto de moedas brasileiras (50, 25, 10,
5, 1), a solução precisa estar correta (mas não precisa ser
ótima :P).
25. Ruby OO
Ruby é considerada uma linguagem puramente orientada à
objetos.
Como foi dito antes, em Ruby tudo é objeto.
● Classe Aberta: Hmm?
● Herança: como funciona em Ruby?
26. Atributos e Propriedades
Atributos, ou variáveis de instancia, são sempre privados e
começam com @.
Para alterá-los precisamos usar métodos do objeto
(Encapsulamento).
27. Atributos e Propriedades
É comum que precise de algum código a ser executado ao
criar um objeto. Para isto usamos o método initiliaze.
Initializers são métodos privados, ou seja, não podem ser
chamados fora da classe.
28. Atributos e Propriedades
Nos nossos exemplos utilizamos os nomes get e set para
resgatar e modificar alguma variável de instancia.
Em Ruby esses métodos são definidos como
'nome_atributo' para o 'get' e 'nome_atributo='
29. Atributos e Propriedades
Como criar um método set e um get para cada um dos
atributos pode ser muito trabalhoso, a linguagem ruby
disponibiliza um método para fazer isto automaticamente:
attr_accessor
31. Hashes
Além de guardar vários valores em uma variável de forma
legível, hashes podem ser usados para passar opções a
métodos.
32. Blocks
Em ruby também podemos passar bloco de código como
parâmetro em algum método.
33. Blocks
Podemos com isso deixar nossos métodos mais genéricos.
No exemplo, temos uma função que precisa ser alterada
para imprimir as somas parciais, mas não queremos que
isto influencie em outros lugares onde este método é
chamado nem duplicar código.
34. Blocks
Podemos até melhorar a legibilidade da chamada do block
utilizando o yield.
Yield é uma palavra reservada do ruby e substitui a
expressão block.call.
35. Tratamento de exceções
Exceções são tipos particulares de objetos, instanciados ou
entendidos da classe Exception.
Assim como em Java, lançar uma exceção significa que algo
não esperado aconteceu. Com isso é preciso passar um
bloco para ser chamado se algo ocorrer.
36. Tratamento de exceções
Seguem as exceções mais utilizadas no ruby (todas filhas de
Exception):
RuntimeError: Exceção padrão, lançada pelo método
raise.
NoMethodError: Como o nome já diz é lançada quando
o objeto recebe um método que não pode ser encontrado.
37. Tratamento de exceções
NameError: Lançada quando o interpretador não
encontra uma variável ou método com o nome passado.
IOError: É lançada ao tentar ler um stream que foi
fechado ou escrever em um arquivo read-only.
TypeError: É lançada quando um método recebe como
argumento algo que não pode tratar.
38. Tratamento de exceções
ArgumentError: É lançada quando foi passado um
número errado de argumentos à um método.
40. Métodos de classe
Como já falamos, tudo em Ruby é objeto, até mesmo as
classes.
Sabendo disso é natural que possamos adicionar métodos
ao objeto que representa a classe.
41. Métodos de classe
O mais usual é definirmos os métodos de classe na própria
classe, mas como?
42. Singleton Classes
Mas e se nossa classe tiver muitos métodos de classe,
vamos ter que colocar self. antes de cada método?
43. Singleton Classes
Todo objeto em ruby possui duas classes.
1- A class do objeto instanciado;
2- A sua singleton class.
44. Singleton Classes
Singleton classes guardam os singleton methods.
Aquele método que criamos para um objeto é um singleton
method.
45. Singleton Classes
Os singleton methods são definidos na singleton class.
Possui uma sintaxe própria.
46. Singleton Classes
Utilizando esta sintaxe conseguimos definir os métodos de
classe sem precisar colocar o self. antes de cada método. =)
47. Convenções
O ruby permite que seus métodos possuam caracteres como
"?" e "!"
De olho nisto foram criadas convenções para métodos que
retornam booleanos (?) e que alterem o estado do objeto(!).
48. Convenções
Comparações entre objetos são feitas com o método "==".
A versão original deste apenas verifica se as referências são
iguais. Se precisarmos é só definí-lo na classe que estamos
usando.
50. Polimorfismo
Em ruby a tipagem é implicita, então precisamos declarar
quais os tipos dos atributos.
Assim basta que o objeto saiba como "faz_barulho"
seguindo nosso exemplo.
51. Duck Typing
"If it walks like a duck and quacks like a duck, I would call it
a duck."
Traduzindo: Para que a classe PatoDoente responda como
Pato, só precisamos implementar os métodos da classe
Pato. (Ruby não precisa de Interface)
53. Módulos
Em ruby podemos definir módulos, servem como
namespaces.
54. Módulos
Ou também podem guardar um conjunto de métodos que
serão inclusos em alguma classe.
55. Metaprogramação
Hoje nós modificamos vários objetos, adicionamos métodos
a eles em tempo de execução, passamos blocos de código
como parâmtro dentre outras coisas. Tudo isso é
Metaprogramação.
56. Metaprogramação
Metaprogramação é uma grande vantagem das linguagens
interpretadas.
Podemos levar a metaprogramação ao extremo quando
criamos um método que cria métodos.
58. Metaprogramação
A definição de métodos de acesso a atributos em ruby é
feita através de metaprogramação.
Utilizamos o método de classe attr_accessor.
Qual seria a possível implementação deste método de
classe? (dica: class_eval ou )
59. Metaprogramação
Outro exemplo são os métodos de classe 'private', 'public' e
'protected'.
Estes métodos alteram a visibilidade do método. Não existe
palavra reservada para isto em Ruby.
60. Metaprogramação
A visibilidade de métodos em ruby lembra um pouco C++
que possui regiões de visibilidade dentro da classe.
Um método privado no Ruby só pode ser chamado por
objeto self implícito. Ou seja, a expressão
self.vai_ao_banheiro, causaria um erro.
61. Metaprogramação
Caso precise, podemos fazer com que a visiblidade dos
métodos a baixo de private sejam publicos novamente com
a palavra public.
62. Metaprogramação
Outro modificador de visibilidade em ruby é o protected.
protected, diferente do private, permite que utilize os
métodos através do metodo self implícito ou explícito.
67. Um pouco de história
Ruby on Rails foi criado por David Heinemeier
Hansson, mais conhecido como DHH, para ser
usado em um dos projetos da 37signals, o
Basecamp.
68. Um pouco de história
Rails foi anunciado oficialmente em setembro
de 2004.
Teve sua versão 1.0 lançada em dezembro de
2005.
69. Um pouco de história
Foi criado pensando na praticidade que
proporcionaria ao escrever os aplicativos web.
Além disso, comparado aos outros, o Rails
permite que as funcionalidades do sistema
possam ser implementadas de forma
incremental.
70. Um pouco de história
Por isto o Rails é bastante usado em projetos e
empresas que adotam metodologias ágeis de
gerencia de projeto e desenvolvimento.
Principais pilares: CoC, DRY e KISS
71. Um pouco de história
CoC: Convention over Configuration.
DRY: Don't Repeat Yourself.
KISS: Keep It Simple, Stupid.
72. MVC
Model: Classes que representam as entidades
no banco de dados e outras que ajudam na
busca e armazenamento dos dados.
73. MVC
View: Responsavel por apresentar os dados.
Também chamada de camada de apresentação.
74. MVC
Controller: Responsavel por tratar as
requisições e seus parâmetros e direcioná-las
para as respectivas camadas.
Notes de l'éditeur
O quê é programação funcional? Programação a partir de expressões, de funções. O output de um método vai depender sempre unicamente dos parâmetros passados para ele. Dar exemplo.
soma = 0
array.each do |e|
soma += e
end
soma
O quê é programação imperativa? Assim como o modo imperativo da língua portuguesa expressa comandos de ação, uma programação imperativa expressa uma sequência de comandos para o computador executar. Dar exemplo.
Como assim natural? O código ruby precisa ser expressivo, ou seja, legível. Veremos adiante que é muito fácil entender o código (assemelha-se ao inglês).
Tipagem dinâmica? Em Java, C e outras linguagens nós precisaríamos informar que uma variável é do tipo inteiro antes de lhe atribuir um valor. Ou seja, são linguagens de tipagem estática. E em Ruby?
Compilação just-in-time? Compilação de um programa em tempo de execução.
Vantagens: não compila todo o código antes de subir a aplicação, podemos alterar o código e ver a alteração sem reiniciar o servidor, etc. ;
Desvantagens: permite execução com código errado, a execução é mais lenta.. Alguém sabe de alguma outra?
Garbage Collector? Não precisamos nos preocupar em limpar o lixo da memória.. Mas se por algum motivo precisarmos, nós podemos fazer isso manualmente. Que beleza!!
Tipagem forte? Os tipos são "fortes", ou seja, não podemos fazer certas operações com objetos de tipos diferentes.. Linguagens com tipagem fraca, como PHP e Javascript, permitem que eu realize por exemplo 1 + "1"
irb
nome = "Joao"
soma_nome = nome + 1
TypeError: no implicit conversion of Fixnum into String
multiplicacao_nome = 4*nome
=> TypeError: String can't be coerced into Fixnum
Ahá: Linguagem dinâmica, tipagem forte.
Mas olha que legal
nome_repetido = nome*4=> "JoaoJoaoJoaoJoao"
Exemplo:
nome = "Joao"
quantidade = 4
"quantas vezes a palavra #{nome} aparece? R: #{quantidade}"
=> "quantas vezes a palavra joao aparece? R: 4"
> 'quantas vezes a palavra #{nome} aparece? R: #{quantidade}'
=> 'quantas vezes a palavra #{nome} aparece? R: #{quantidade}'
> mensagem = "Oi, "
> mensagem << "tudo bem?"
> mensagem
=> "Oi, tudo bem?"
Exemplo:
> nome = "joao"
> nome.methods
Oooolha, quantos métodos
> nome.capitalize
=> "Joao"
> nome
=> "joao"
Ué, porque?
> nome.capitalize!
=> "Joao"
> nome
=> "Joao"
Hmmm.. O que essa exclamação significa?
Exemplo:
Verificando no irb com .class
123.class
=> Fixnum
123123123123123123123123123123123123.class
=> Bignum
12.3.class
=> Float
Imutáveis: Se precisar de um novo valor, precisa ser criado outro objeto Symbol
Compartilhados: Com o mesmo valor, mesmo que em locais diferentes do códico, compartilham o mesmo objeto.
Exemplo:
> :simbolo.class
=> Symbol
Exemplo:
nil e false são os únicos valores falsos do Ruby.
a = nil
if (a)
puts "Só imprime variavel diferente de nil"
end
# nil se comporta como false em ruby. Assim os únicos valores false são false: Boolean e nil: NilClass
if (3 == 3 )
puts "3 é igual a 3"
end
def worlcup_country(year)
case year
when 1895..2005
puts "Don't know..."
when 2006
puts "Germany"
when 2010
puts "South Africa"
when 2014
puts "Brazil"
end
end
for i in 1..9
puts i
end
soma = 0
while soma < 10
soma = soma + 1
puts soma
end
Aqui, modificamos a classe Fixnum e sobrescrevemos (override) o método '+' para diminuir ao invés de somar.
Demonstrar no Terminal.> Fixnum
> Fixnum.methods
> Fixnum.class
PERIGO
> class Fixnum
> def +(other)
> self - other
> end
Mostrar o caso da herança
class Mamifero
def respirar
puts "Estou respirando"
end
end
class Cachorro < Mamifero
def latir
puts "Woof woof!"
end
end
lion = Cachorro.new
lion.latir
lion.respirar
Exemplo:
class Pessoa
def set_nome(nome)
@nome = nome
end
end
Exemplo:
class Pessoa
def initialize(nome)
@nome = nome
end
def get_nome
@nome
end
end
Exemplo:
class Pessoa
def nome
@nome
end
def nome=(nome)
@nome = nome
end
end
class Pessoa
attr_accessor :nome, :sobrenome, :idade
end
class Pessoa
attr_accessor :nome, :sobrenome, :idade
def imprimir_nome_e_sobrenome
puts self.nome + " " + self.sobrenome
end
def nome_falso(nome)
puts "Meu nome eh #{self.nome}, nao #{nome}"
end
end
exemplo:
class Banco
def transferir(valor, opções = {})
...
end
end
exemplo:
def metodo(&block)
puts "aqui podemos passar um bloco"
block.call
end
metodo do
puts "meu bloco"
end
metodo { puts "meu bloco" }
Exemplo
# Método original
def soma(array)
soma = 0
for i in 0..(array.length-1)
soma += array[i]
end
soma
end
# adicionamos o bloco de código, mas este método irá afetar o resultado em outros lugares
def soma(array, &block)
soma = 0
for i in 0..(array.length-1)
soma += array[i]
block.call(soma)
end
soma
end
# usando o block_given? só chamamos o bloco caso ele tenha sido passado
def soma(array, &block)
soma = 0
for i in 0..(array.length-1)
soma += array[i]
if block_given?
block.call(soma)
end
end
soma
end
Exemplo:
def soma(array, &block)
soma = 0
for i in 0..(array.length-1)
soma += array[i]
if block_given?
yield(soma)
end
end
soma
end
Exemplo:
valor = 0
begin
divisao = 100/valor
rescue ZeroDivisionError => e
puts "Ooooolha o erro: #{e}"
end
Exemplo:
class Pessoa
def fala
"falei!"
end
end
p = Pessoa.new
p.fala
=> "falei!"
def Pessoa.fala_especie
"Homo Sapiens!!"
end
Pessoa.fala_mais
=> "Homo Sapiens!!"
Exemplo:
class Pessoa
def fala
"falei!"
end
# Método self aponta para a própria classe.
def self.fala_especie
"Homo Sapiens!!"
end
end
Exemplo:
# Pra relembrar
a = Array.new
def a.outro_metodo
"hahaah singleton method"
end
a.outro_metodo
Exemplo:
# Singleton Class da classe Pessoa
class << Pessoa
...
end
class Pessoa
def fala
"falei!"
end
# Método self aponta para a própria classe.
# class << self é a singleton class do objeto Pessoa
class << self
def fala_especie
"Homo Sapiens!!"
end
def outro_metodo_de_classe
"outro"
end
end
end
exemplo:
class Pessoa
def ==(outra)
self.cpf == outra.cpf
end
end
exemplo:
class Animal
def come
"comendo"
end
end
class Pato < Animal
def faz_barulho
"quack!"
end
end
pato = Pato.new
pato.come
=> "comendo"
pato.faz_barulho
=> "quack!"
Exemplo:
class PatoDoente
def faz_barulho
"queeeeeeeeeeck!"
end
end
class CriadorMau
def castiga(pato)
pato.faz_barulho
end
end
pato_normal = Pato.new
pato_doente = PatoDoente.new
criador = CriadorMau.new
criador.castiga(pato_normal)
=> "quack!"
criador.castiga(pato_doente)
=> "queeeeeeeeeeck!"
class Ave
def voa
raise "Implement This Method"
end
end
Exemplo:
module Rails
module Validacoes
class ValidacaoCPF
...
end
class ValidacaoCNPJ
...
end
end
end
Rails::Validacoes::ValidacaoCPF.valida(cpf)
Exemplo:
module Comentavel
def escrever_comentario
...
end
def receber_comentario
...
end
end
class Revista
include Comentavel
end
class Blog
include Comentavel
end
revista = Revista.new
blog = Blog.new
revista.methods - Object.methods
=> [:receber_comentario, :escrever_comentario]
Exemplo:
class Aluno
end
class Professor
def ensina(aluno)
def aluno.ler
"acabei de ler"
end
end
end
aluno = Aluno.new
professor = Professor.new
aluno.respond_to? :ler
=> false
professor.ensina aluno
aluno.respond_to? :ler
=> true
aluno.ler
=> "acabei de ler"
Exemplo:
[:metodo1, :metodo2, :metodo3].each do |metodo|
define_method metodo do
"novo metodo #{metodo}"
end
end
metodo1
=> "novo metodo metodo1"
metodo2
=> "novo metodo metodo2"
metodo3
=> "novo metodo metodo3"
Exemplo:
class Pessoa
attr_accessor :nome
end
pessoa = Pessoa.new
pessoa.methods - Object.methods
=> [:nome, :nome=]
# resposta:
class Class #firstly, the * decoration on the parameter variable #indicates that the parameters should come in as an array #of whatever was sent def mikeys_attr_accessor(*args) #We simply iterate through each passed in argument... args.each do |arg| #Here's the getter self.class_eval("def #{arg};@#{arg};end") #Here's the setter self.class_eval("def #{arg}=(val);@#{arg}=val;end") end endend
Exemplo:
class Pessoa
# Por padrão todos os métodos em ruby são public
…
private
def vai_ao_banheiro
...
end
end
class Pessoa
# Por padrão todos os métodos em ruby são public
def metodo_publico
...
end
private
def vai_ao_banheiro
...
end
public
def outro_metodo_publico
...
end
end
CoC: Permite escrever menos código utilizando as convenções.
DRY: Incentiva a reutilização de código.
KISS: Seguindo os dois últimos temos uma aplicação simples com pouco ( ou de preferência nenhum) código desnecessário, fácil de manter.