VersĂculo chave: "Consagre ao Senhor tudo o que vocĂŞ faz, e os seus planos serĂŁo bem-sucedidos." - ProvĂ©rbios 16:3
💎 Preparação: Para este conteúdo, o aluno deverá dispor de um computador com acesso à internet, um web browser com suporte a HTML 5 (Google Chrome, Mozilla Firefox, Microsoft Edge, Safari, Opera etc.), um editor de texto ou IDE (VSCode etc.) e o software Ruby, com a versão mais recente, instalado na sua máquina local.
Sou um especialista em desenvolvimento de software com foco no ecossistema Ruby, utilizando frameworks como Ruby on Rails, Sinatra e Hanami. Tenho experiĂŞncia sĂłlida na aplicação de boas práticas como SOLID, DRY, KISS, TDA e SoC, alĂ©m do uso de design patterns (criacionais, estruturais e comportamentais) e adoção dos princĂpios de Clean Code e Clean Architecture, visando legibilidade, manutenibilidade e escalabilidade das soluções desenvolvidas.
No front-end, atuo em projetos com SPAs (React, Vue, Angular) integradas a back-ends Ruby via APIs REST ou GraphQL, e aplicações SSR com Rails (utilizando Hotwire, Turbo, Stimulus ou ERB). Domino o uso de HTML/CSS, Flexbox, CSS Grid e padrões de design responsivo, seguindo protótipos de UI/UX elaborados no Figma.
No back-end, desenvolvo APIs RESTful e GraphQL com Rails ou Sinatra (utilizando graphql-ruby), com domĂnio de Git e atuação colaborativa por meio de pipelines CI/CD (GitHub Actions, GitLab CI, CircleCI). Utilizo ferramentas de análise estática e linting como RuboCop, StandardRB e Reek, alĂ©m de realizar testes unitários e de integração com RSpec, Minitest e Capybara. Tenho experiĂŞncia em arquiteturas baseadas em microsserviços, com monitoramento de performance usando Prometheus e Grafana, e rastreamento de erros com logs estruturados via Lograge, Rails Logger ou Honeybadger.
TambĂ©m implemento ferramentas de analytics como Google Analytics 4 e Segment para análise de comportamento do usuário e acompanhamento das principais interações nas interfaces. Em relação Ă entrega de software, atuo com deploy contĂnuo em ambientes PaaS como Heroku, Render e Fly.io, alĂ©m do uso de recursos em nuvens como AWS (EC2, S3, RDS, Fargate), Azure e Google Cloud Platform.
- https://exercism.org/tracks/ruby
- https://guides.rubyonrails.org/v3.2/getting_started.html#getting-up-and-running-quickly-with-scaffolding
- https://gorails.com/
- https://www.ruby-toolbox.com/
- https://rspec.info/
O Ruby foi uma linguagem de programação criada em 1995 por Matz, no Japão. É uma linguagem de programação interpretada e multi-paradigma com foco em simplicidade. Possui uma popularidade em 2001 após o livro "Programming Ruby". É uma linguagem dinâmica, open source, com foco na simplicidade e na produtividade. Tem uma sintaxe elegante de leitura natural e fácil escrita. Além disso, tudo no Ruby é tratado como objeto da mesma forma como é na linguagem JavaScript, diferente da linguagem Java e C# que possui classes, métodos e atributos.
class Hello
def initialize (nome):
@nome = nome.capitalize
end
def falar
puts "Olá #{@nome}"
end
end
# Criar um objeto
h = Hello.new("mundo")
# saĂda: "Olá, mundo!"
g.falarPossui uma tipagem dinâmica e forte, se assemelhando a linguagem de programação Python.
puts "Hello World!" # mais comum
puts ("Hello World!")
p "Hello, World!"
print "Hello, World!"
printf "Hello, World!"Evento:
nome = "Isaac"
mensagem = "Bem vindo #{nome}"
puts mensagemHeredoc:
mensagem = <<~TXT
Essa Ă© minha mensagem
TXTColocando prompt:
puts "Digite o seu nome: "
nome = gets
puts "Seu nome é #(nome)"# comentário de uma linhaComo faz para capturar um input da tela padrão do computador, existe um método chamado gets, ele possibilita fazer um prompt da entrada padrão. Assim, que a gente entrar um valor na entrada padrão, esse valor vai ser acessado pra que a gente consiga acessa-lo depois.
gets()
# ou
getsSintaxe
nome = gets
nome
puts nome
nome.chomp() # Tira o Ăşltimo caractere social, no caso, o \n
# ou
nome = nome.chomp
# ou
nome = gets.chompO gerenciamento de versão se refere ao processo de planejamento, desenvolvimento, agendamento, testes, implantação e controle de versões de software. Ele garante que as equipes de versão entreguem com eficiência os aplicativos e os upgrades exigidos pelas empresas e preservem, ao mesmo tempo, a integridade do ambiente de produção existente. Vamos utiliza-lo no ambiente de desenvolvimento para gerenciar as versões do Ruby.
No mundo competitivo, dinâmico e fluĂdo dos negĂłcios e da TI, as versões prematuras sĂŁo a Ăşltima coisa de que vocĂŞ precisa. A empresa moderna Ă© um ambiente verdadeiramente dinâmico, e nem todas essas alterações ocorrem no mesmo ritmo. As organizações de TI precisam de um jeito para orquestrar essa grande quantidade de alterações. É aĂ que as soluções Release Control e Deployment Automation entram em cena. Elas ajudam a facilitar a transição para a entrega contĂnua, e trabalham com a transformação digital, uma versĂŁo de cada vez. Essa Ă© a nova normalidade da TI.
Existe alguns tipos de gerenciadores de versĂŁo indicados:
- RVM (Mais popular)
- rbenv
- asdf (Mais recomendável)
Vou usar o asdf, você pode usar ele nos sistemas operacionais Linux ou no macOS, além dos interpretadores de comando UNIX, como Bash, ZSH ou Fish.
Comandos utilizados para iniciar o asdf:
asdf version
asdf plugin-add ruby
asdf install ruby 2.7.1
ruby -v
asdf list ruby
asdf local ruby 2.7.1
asdf list nodejsSĂŁo bibliotecas de cĂłdigo escritas em Ruby compartilhadas entre a comunidade, entĂŁo basicamente o gem Ă© um gerenciador de pacotes (package manager) imbutido na linguagem Ruby. VocĂŞ consegue fazer o download de uma biblioteca Ruby fazendo: gem install nomeDaBiblioteca, um exemplo de gem Ă© o prĂłprio Rails. Existe um site em que vocĂŞ pode encontrar essas gems: https://rubygems.org/?locale=pt-BR
Comando para listar todas as gems locais:
gem listTraduzido do inglĂŞs-O Interactive Ruby Shell Ă© um REPL (Um loop read-eval-print ( REPL ), tambĂ©m chamado de toplevel interativo ou shell de linguagem , Ă© um ambiente de programação de computador interativo simples que recebe entradas de um Ăşnico usuário, as executa e retorna o resultado para o usuário; um programa escrito em um ambiente REPL Ă© executado por partes. O termo geralmente se refere a interfaces de programação semelhantes ao ambiente interativo clássico de máquina Lisp . Exemplos comuns incluem shells de linha de comando e ambientes semelhantes para linguagens de programação , e a tĂ©cnica Ă© muito caracterĂstica de linguagens de script).
Esse REPL serve para programação na linguagem de script orientada a objetos Ruby. A abreviação irb é um portmanteau da palavra "interativo" e a extensão do nome de arquivo para arquivos Ruby, .rb.
O programa é iniciado a partir de uma linha de comando ( CLI - Command Line Interface ) e permite a execução de comandos Ruby com resposta imediata, experimentando em tempo real. Possui histórico de comandos , recursos de edição de linha e controle de tarefas , e é capaz de se comunicar diretamente como um script de shell pela Internet e interagir com um servidor ativo. Foi desenvolvido por Keiju Ishitsuka .
(Input) Entrada:
irb
7.times { puts "Hello, World!" }
exit()A saĂda será o "Hello, World!" impresso 7 vezes em cada linha.
(Output) SaĂda:
Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World! Hello, World!
(Input) Entrada:
nome = Isaac
nome(Output) SaĂda:
Isaac
Linguagem de tipagem dinâmica que pode trocar a tipagem a qualquer momento. Como Ă© de costume e padrĂŁo, sempre o Ăşltimo valor atribuĂdo Ă© o que conta!
(Input) Entrada:
nome = 7
nome(Output) SaĂda:
7
Verificando objetos
(Input) Entrada:
nome.object_id(Output) SaĂda:
21
(Input) Entrada:
nome.class(Output) SaĂda:
Integer
(Input) Entrada:
nil.object_idnil = valor nulo
(Output) SaĂda:
8
(Input) Entrada:
nil.class(Output) SaĂda:
NilClass
(Input) Entrada:
NilClass.object_id(Output) SaĂda:
40
(Input) Entrada:
NilClass.superclass(Output) SaĂda:
Object
Definindo funções:
(Input) Entrada:
def somar (x,y)
puts "Outra coisa..."
x+y
end
somar (1, 2)(Output) SaĂda:
Outra coisa... 3
Atribuição de uma função
(Input) Entrada:
soma = somar (10, 5)
soma(Output) SaĂda:
15
Array (Listas)
(Input) Entrada:
lista = ["Isaac", 7, "DevOps", true, nil, 7.77, "Ruby"]
lista
lista.class
lista.length(Output) SaĂda:
["Isaac", 7, "DevOps", true, nil, 7.77, "Ruby"] Array 7
Executando o Ruby pelo interpretador no terminal
(Input) Entrada:
ruby main.rb(Output) SaĂda:
Hello World
Executando um cĂłdigo-fonte:
Strings são tipos de dados tratados como escrita ou texto, podem ser definidas entre aspas duplas ("") ou apóstrofos, também conhecida como aspas simples ('').
Exemplo:
nome = "Isaac"
nome = 'Isaac'
nome = %q(meu texto)Caracteres de escape com Aspas ("")
Nova linha:
\nTab:
\tAspas:
\"CĂłdigo-fonte main.rb:
nome = "Isaac"
mensagem = "Bem vindo #{nome}"
mensagemErrada = 'Bem vindo #{nome}'
soma = "O valor da soma de 1 + 2 = #{1 + 2}"
outraMensagem = "Bem vindo" + nome
puts nome
puts mensagem
puts mensagemErrada
puts soma
puts outraMensagem
#{}não serve somente para strings, mas sim para interpolação de código. Os apóstrofos se inseridos em conjunto com o delimitador de manipulação de variável retornarão o mesmo código inserido.
(Input) Entrada:
ruby main.rb(Output) SaĂda:
Isaac
Bem vindo Isaac
Bem vindo #{nome}
O valor da soma de 1 + 2 = 3
Bem vindo Isaac
CĂłdigo-fonte mensagem.rb:
nome = "Isaac"
mensagem = <<-MENSAGEM
Olá #{nome}
Bem vindo(a) ao meu programa!
Obrigado
MENSAGEM
puts mensagem(Input) Entrada:
ruby mensagem.rb(Output) SaĂda:
Olá Isaac Bem vindo(a) ao meu programa! Obrigado
CĂłdigo-fonte mensagem.rb:
mensagem = %q(Bem vindo ao meu programa)
mensagemErrada = %q(Bem vindo ao meu programa #{nome})
puts mensagem
puts mensagemErrada(Input) Entrada:
ruby mensagem.rb(Output) SaĂda:
Bem vindo ao meu programa
Bem vindo ao meu programa #{nome}
Caso queira interpolar com o delimitador de manipulação de variável
%q, é necessário usar o%Q.
CĂłdigo-fonte mensagem.rb:
nome = "Isaac"
mensagem = %Q(Bem vindo ao meu programa #{nome})
puts mensagem(Input) Entrada:
ruby mensagem.rb(Output) SaĂda:
Bem vindo ao meu programa Isaac
CĂłdigo-fonte public-methods.rb:
nome = "Isaac"
mensagem = %Q(Bem vindo ao meu programa #{nome})
puts mensagem.public_methods
puts mensagemEsse comando, atributo
public_methods, vai imprimir os métodos públicos do Ruby que possui nessa string para ser utilizado.
(Input) Entrada:
ruby public-methods.rb(Output) SaĂda:
unicode_normalized? encode! unicode_normalize ascii_only? unicode_normalize! to_r to_c encode include? % * + unpack unpack1 count partition +@ -@ <=> << sum == === next =~ [] []= empty? casecmp eql? insert casecmp? match? bytesize match next! succ! index upto replace rindex chr clear byteslice getbyte setbyte freeze scrub scrub! dump inspect intern upcase downcase capitalize swapcase upcase! undump length size downcase! succ swapcase! hex capitalize! split chars oct grapheme_clusters concat codepoints lines bytes to_str end_with? start_with? reverse reverse! sub to_s to_i to_f rjust center prepend crypt ord chomp strip to_sym ljust delete_prefix delete_suffix lstrip gsub scan chomp! sub! gsub! rstrip delete_prefix! chop lstrip! rstrip! chop! delete_suffix! strip! tr_s delete squeeze tr! tr delete! squeeze! each_line each_byte tr_s! each_codepoint each_grapheme_cluster slice slice! each_char encoding force_encoding b valid_encoding? rpartition hash between? clamp <= >= < > singleton_class dup itself taint tainted? untaint untrust untrusted? trust methods singleton_methods protected_methods private_methods public_methods instance_variables instance_variable_get instance_variable_set instance_variable_defined? remove_instance_variable instance_of? kind_of? is_a? display class frozen? tap then yield_self public_send extend clone method public_method singleton_method define_singleton_method !~ nil? respond_to? object_id send to_enum enum_for __send__ ! instance_eval instance_exec != equal? __id__ Bem vindo ao meu programa Isaac
CĂłdigo-fonte mensagem.rb:
nome = "Isaac"
mensagem = %Q(Bem vindo ao meu programa #{nome})
puts "O tamanho da minha string Ă©: #{mensagem.length()}"(Input) Entrada:
ruby mensagem.rb(Output) SaĂda:
O tamanho da minha string Ă©: 30
Operações com Strings:
Pegar um caracter da String
# 01234
"Isaac"[0] # "I"Todos os caracteres da string como array
"Isaac".chars # ["I", "s", "a", "a", "c"]Substring
"Isaac"[0,3] # "Isa"Multiplicação de Strings
"-" * 10 # "----------"Multiplicação de Strings
" mensagem ".strip # "mensagem"MaiĂşsculo/MinĂşsculo
"isaac".upcase # upcase
"ISAAC".downcase # downcasePrimeira letra maĂuscula
"isaac".capitalizeDividir
"cadu teste outra_nome".split
"cadu-teste-outro_nome".split("-")Brincando com manipulação de variáveis e operações de Strings
o comando
pimprime a string da sua forma natural inserida pelo programador, diferente do comando
nome = "Isaac"
nomes = "isaac matheus janaina alexandre jurema fábio cauã gabriela jade nemo marlim fanny jajá azul".split(",")
numero = 7
mensagem = "minha mensagem"
puts ["A", "B", "C"]
print ["A", "B", "C"]
p ["A", "B", "C"]
p "quebra automaticamente\"" # quebra de linha
p nome
p nome[0]
p nome[nome.length - 1]
p nome[-1]
p nome.chars
p nome.chars.length
p nome[0,3]
# multiplicação de strings
puts "Cabeçalho"
puts "---------"
puts "texto de informação"
puts "-" * 10
puts "O nĂşmero Ă© %05d" % numero
puts "*" * 10
puts mensagem.capitalize
# gsub
puts mensagem.gsub("mensagem","mulher")
p nomes(Input) Entrada:
ruby main.rb(Output) SaĂda:
A B C ["A", "B", "C"]["A", "B", "C"] "quebra automaticamente\"" "Isaac" "I" "c" ["I","s","a","a","c"] 5 "Isa" Cabeçalho --------- texto de informação --------- O número é 00007 Minha mulher
(Input) Entrada
irb
7.class
7.7.class(Output) SaĂda
Integer Float
(Input) Entrada
puts 123_500(Output) SaĂda
123500
(Input) Entrada
# soma um inteiro com um ponto flutuante
soma = 3 + 4.77
p soma(Output) SaĂda
7.77
Os sĂmbolos sĂŁo tipos especiais de objeto que sĂŁo criados com o : no inĂcio do identificador. Eles sĂŁo Ăşnicos globalmente e imutáveis, entĂŁo quando vocĂŞ utilizar um sĂmbolo no Ruby ele vai usar aquele objeto na memĂłria e vai usar o nome, por exemplo Isaac`, o Ruby vai usar esse objeto na memĂłria a primeira vez e quando eu reutilizar esse sĂmbolo ele vai reutilizar esse mesmo objeto.
SĂŁo Ăłtimos substitutos para strings quando vocĂŞ for usado como label / chaves.
(Input) Entrada
irb
variavel = "isaac"
variavel.object_id
variavel = "isaac"
variavel.object_id(Output) SaĂda
"isaac" 28420 "isaac" 35380
Toda vez que reutilizamos uma string, elas são imutáveis, ela vai gerar um novo objeto na memória. Então, toda vez que usar a string, o Ruby vai usar a memória do computador e vai referenciar ela, portanto vai ser criada várias posições na memória dependendo do uso.
(Input) Entrada
irb
:"isaac"
:isaac # posso fazer desse modo, sem especificar a string com aspas duplas
:isaac.object_id
:isaac.object_id(Output) SaĂda
:isaac :isaac 2290588 2290588
Note que ele nĂŁo muda o id do objeto, ou seja, toda vez ele vai gerar o mesmo objeto.
(Input) Entrada
irb
1.send("+", 2) # o sĂmbolo + está sendo usado na memĂłria, nĂŁo reutilizada
1.send(:+, 2) # o sĂmbolo + está sendo usado na memĂłria, sendo reutilizado(Output) SaĂda
3 3
Em algumas linguagens de programação o Hash Ă© chamado de Hash-Map ou dicionário (Ă© uma estrutura de chave-valor). O Hash permite vocĂŞ acessar qualquer Ăndice diretamente na memĂłria do computador.
Para iniciar um Hash:
hash = {}
# ou
hash = Hash.newSintaxe do Hash:
hash = {
chave => valor,
chave => valor,
}Um hash pode ser qualquer tipo primitivo de dados, pode ser um nĂşmero, uma string ou um sĂmbolo.
i = {} # hash i vazio
h = {} # hash h vazio
i.class
a.class
i = { "nome" => "Isaac", "idade" => 21 } # Strings e nĂşmeros
h = { :nome => "Isaac", :idade => 21 } # SĂmbolos
h[:nome] # acessando um hash
h[:nome] = "Novo nome" # Alterando um hash
h[77] = "New value" # Adicionando um novo item no hashAo acessar o hash, note que Ă© bem parecido com array, porĂ©m nele vocĂŞ está acessando o Ăndice pelo prĂłprio nome dele.
Alguns atributos e métodos para o hash
hash.keys # retorna um array com as chaves
hash.values # retorna um array com os valores
hash.empty? # verifica se o hash está vazio(Input) Entrada
irb
dicionario = {}
dicionario["isaac"] = "7"
dicionario["isaac"]
dicionario[:isaac] = "7"
dicionario[:isaac](Output) SaĂda
"7" "7" "7" "7"
Entretanto, toda vez que eu acessar esse Hash, ele está criando na memĂłria. Portanto, Ă© muito perfomático criar sĂmbolos do que texto na memĂłria toda vez.
Arrays ou listas sĂŁo listas de valores separados por vĂrgula.
lista = []
lista = Array.newOs arrays no Ruby, assim como na maioria das linguagens de programação de alto-nĂvel, podem ser de diferentes tipos.
(Input) Entrada
lista = [1, 2.7, "3", "isaac", true] # elementos do tipo int, float, string e boolean (TrueClass)
lista[1] # Acessando um item da lista no Ăndice 1 = 2.7
p lista[1](Output) SaĂda
2.7
Incluir um novo elemento na lista:
lista = [1, 2.7, "3", "isaac", true] # elementos do tipo int, float, string e boolean (TrueClass)
lista << "novo item 1"
# ou
lista.append("novo item 2")
p lista(Output) SaĂda
[1, 2.7, "3", "isaac", true, "novo item 1", "novo item 2"]
Outros métodos para manipular Arrays:
lista.length # tamanho do array
lista.empty? # verifica se o array está vazio
lista.first # pegar o primeiro valor
lista.last # pegar o Ăşltimo valor
lista.include?(1) # verifica se algum item da lista inclui o valor especĂficoSomando listas com o Ruby:
(Input) Entrada
lista_1 = [0, 1, 2, 3]
lista_2 = [4, 5, 6, 7]
resultado = lista_1 + lista_2
p resultado(Output) SaĂda
[0, 1, 2, 3, 4, 5, 6, 7]
Operadores relacionais
== # igualdade
!= # diferente
> # maior que
>= # maior ou igual a
< # menor que
<= # menor ou igual a Operadores lĂłgicos
! # Negação
&& # And
|| # Or Sintaxe
if condicao
faca_algo
else
faca_outra_coisa
endEstrutura condicional com operadores relacionais
valor = 20
if valor > 50
puts "Eu sou maior que 50"
else
puts "Eu sou menor que 50"
endEstrutura condicional com operadores relacionais && lĂłgicos
valor = 65
if valor >= 50 && valor <= 100
puts "Estou entre 50 e 100"
endEstrutura condicional com elsif (senĂŁo se)
valor = 20
if valor > 50
puts "Eu sou maior que 50"
elsif valor == 50
puts "Eu sou igual a 50"
else # nesse caso, o else sempre vem por Ăşltimo, depois do elsif
puts "Eu sou menor que 50"
endApenas
nilefalsesão avaliados como falso, se por acaso tiver um parênteses vazio será do valor lógico true.
Estrutura condicional com uma linha de condição:
valor = 20
puts "Eu sou maior que 50" if valor > 50 unless Se a condição não for verdadeira, ele iá executar o bloco de código dentro dela (faca_isso).
Sintaxe:
unless condicao
faca_isso
endOperador ternário Usado para estruturas condicionais de pequeno porte.
valor > 50 ? puts "Eu sou maior que 50" : puts "Eu sou menor que 50"
# if valor > 50
# puts "Eu sou maior que 50"
# else
# puts "Eu sou menor que 50"Switch case
linguagem = "ruby"
case linguagem
when "ruby"
puts "bem vindo ao curso de ruby"
when "golang"
puts "curso nĂŁo disponĂvel"
else
puts "não conheço essa linguagem"
endExemplo estrutura de condicional: Entrada (Input):
valor gets.chomp.to_i # conversor para inteiro
p valor.class # String
p valor
if valor > 20
puts "Esse valor Ă© maior que 20"
elsif valor == 20
puts "Esse valor Ă© igual a 20"
else
puts "Esse valor Ă© menor que 20"
endSaĂda (Output):
50 Integer 50 Esse valor Ă© maior que 20
Exemplo estrutura de condicional: Entrada (Input):
puts "Digitar um valor: "
valor = gets.chomp.to_i
if valor >= 50 && valor <= 100
puts "Estou entre 50 e 100"
else
puts "Eu nĂŁo estou entre 50 e 100"
endSaĂda (Output):
Exemplo 2 - estrutura de condicional: Entrada (Input):
valor = ""
if valor
puts "Eu tenho alguma coisa" # true = vazio
else
puts "Eu nĂŁo tenho nada"
endSaĂda (Output):
Eu tenho alguma coisa
O resultado se torna verdadeiro devido ao tipo do código inserido, para ele declarar falso, é preciso especificar uma negação na primeira condição
Entrada (Input):
valor = ""
if !valor.empty? # se valor nĂŁo Ă© vazio
puts "Eu tenho alguma coisa" # true = vazio
else
puts "Eu nĂŁo tenho nada"
endSaĂda (Output):
Eu nĂŁo tenho nada
O mesmo pode ser feito com
unless
Entrada (Input):
valor = ""
unless valor # se valor nĂŁo Ă© vazio
puts "Eu tenho alguma coisa"
else
puts "Eu nĂŁo tenho nada"
endSaĂda (Output):
Eu nĂŁo tenho nada
Os laços ou loops, são formas de executar repetitivamente uma operação a fim de obedecer a uma estrutura condicional.
O while significa repetir enquanto a condição for verdadeira.
Entrada (Input)
valor = 5 # imprimindo de 5 até 1
while valor > 0 # true
puts valor
valor = valor - 1 # Outra forma: valor -= 1
end # quando parar em 0, irá retornar em `false`, a execução será encerradaSaĂda (Output)
5 4 3 2 1
Entrada (Input)
valor = 5
while valor > 0
puts valor
valor = valor - 0
endSaĂda (Output)
`looping infinito do valor`
For Funciona semelhante ao while, porém você declara uma variável em uma lista de objetos.
for i in [1, 2, 3, 4, 5] # para i em algum array, hash ou objeto que corresponde ao `.each`
puts "O nĂşmero Ă© #{i}"
endUntil Semelhante ao while, a diferença está na condição, que assim quando executar a condição for falsa.
valor = 0
until valor == 10
puts valor
valor += 1
end Alguns comandos usados em laços
break # sair do laço
return # sair do laço e do método onde o laço está contido
next # vai imediatamente para a próxima iteração
redo # repete o laço do inĂcio (a condição nĂŁo será reavaliada)Exemplo 1: Imprimir de 0 atĂ© 9 Entrada (Input):
valor = 0
while (valor < 10)
puts "O valor Ă© #{valor}"
valor += 1
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7 O valor Ă© 8 O valor Ă© 9
Exemplo 1: Imprimir de 0 até 5 Entrada (Input):
valor = 0
while (valor < 10)
puts "O valor Ă© #{valor}"
break if valor == 5
valor += 1
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5
Exemplo 1: Imprimir de 0 até 5 Entrada (Input):
valor = 0
while (valor < 10)
puts "O valor Ă© #{valor}"
break if valor == 5
valor += 1
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5
Exemplo 2: For Entrada (Input):
for meu_valor in [0,1,2,3,4,5,6,7]
puts "Meu valor Ă© #{meu_valor}"
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7
Exemplo 2: Range For Entrada (Input):
range = 0..7
for meu_valor in range
puts "Meu valor Ă© #{meu_valor}"
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7
Exemplo 2: For Range Entrada (Input):
for meu_valor in 0..7
puts "Meu valor Ă© #{meu_valor}"
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7
Exemplo 2: For para Arrays Entrada (Input):
lista = [0,1,2,3,4,5,6,7]
for meu_valor in lista
puts "Meu valor Ă© #{meu_valor}"
endSaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7
Exemplo 2: Each Entrada (Input):
lista = [0,1,2,3,4,5,6,7]
lista.each do |meu_valor|
puts "O valor Ă© #{meu_valor}"
endEm JavaScript, podemos fazer algo parecido com o comando
for each.
SaĂda (Output):
O valor Ă© 0 O valor Ă© 1 O valor Ă© 2 O valor Ă© 3 O valor Ă© 4 O valor Ă© 5 O valor Ă© 6 O valor Ă© 7
Exemplo 2: Each com hash Entrada (Input):
hash = {nome: Isaac, idade: 21}
lista.each do |chave, valor|
puts "Meu nome Ă© #{chave} e tenho #{valor} anos"
endSaĂda (Output):
Meu nome Ă© Isaac e tenho 21 anos
Agora, iremos aprender sobre o paradigma orientado a objetos em Ruby, se você tiver o mesmo conhecimento em teorias e lógicas sobre este paradigma é bem mais fácil, basta somente usar com a semântica do Ruby.
A diferença entre Classes x Objetos:
Na imagem acima, conseguimos ter uma boa ideia do que seria uma classe e objetos. A classe, ou class, é como se fosse uma planta ou esboço de um objeto ou partes de um objeto.
Um objeto, ou object, é a construção daquela classe (planta ou esboço) na memória do computador, portanto, chamamos essa construção de instância.
Então, podemos obter vários objetos na memória do computador a partir dessa classe (desenho técnico) como referência (como esboço).
Sintaxe para classe:
class NomeDaClasse
endSintaxe para objeto:
obj NomeDaClasse.newInstanciando uma classe pelo objeto:
class MinhaClasse
end
objeto = MinhaClasse.new
p objeto.object_idirb
nome = "isaac"
nome.object_id
outra_variável = "outro_nome"
outra_variável.object_id
outro_nome = nome
nome
outro_nome
nome.object_id
outro_nome.object_id
nome.upcase
nome
nome.upcase!
nome
outro_nome=> "isaac" => 180 => "outro_nome" => 200 => "isaac" => "isaac" => "isaac" => 180 => 180 => "ISAAC" => "isaac" => "ISAAC" => "ISAAC" => "ISAAC"
def meu_metodo
puts "meu_metodo foi executado"
enddef meu_metodo(parametro1, parametro2)
puts "meu_metodo foi executado com #{parametro1} e #{parametro2}"
enda palavra
returné opcional. O ruby sempre retorna o resultado da execução da última linha.
Exemplo:
def soma (a, b)
return a + b
end
# Ă© igual
def soma(a, b)
a + b
endExemplo 2:
Entrada (Input):
def soma (valor1, valor2 = 0) # valor1 = 10 e valor2 = 0
puts "Estou somando #{valor1} e #{valor2}"
valor1 + valor2
end
puts "Vou executar a soma"
puts soma(10) # valor1SaĂda (Output):
Vou executar a soma Estou somando 10 e 0 10
Exemplo 3:
Entrada (Input):
def soma (valor1, valor2 = 0) # valor1 = 10 e valor2 = 0
puts "Estou somando #{valor1} e #{valor2}"
valor1 + valor2
end
def soma_com_parametros_nomeados(valor1:,valor2:)
soma(valor1, valor2)
end
puts "Vou executar a soma"
puts soma_com_parametros_nomeados(valor1: 5)SaĂda (Output):
Vou executar a soma Estou somando 5 e 0 5
variavel = nil
variavel = "Algum valor" if variavel.nil?variavel = nil
variavel = "Algum valor" unless variavelvariavel ||= "Valor"Exemplo:
variavel = 10
variavel ||= 20
variavel
variavel = nil
variavel
variavel ||= 20
variavel
nova_variavel ||= 100
nova_variavelExercĂcio 01: Análise de PalĂndromo
PalĂndromo: SĂŁo palavras que sĂŁo iguais quando lidas de frente para trás e de trás para frente.
Exemplos:
Ovo Osso Radar Pop Bob ...
Objetivo:
- Definir um mĂ©todo que verifica se Ă© palĂndromo
- Usar gets para pedir input de dados e chamar o método
- Imprimir se Ă© palĂndromo ou nĂŁo
Resolução:
Entrada (Input)
puts "Digite alguma palavra ou nĂşmero:"
palavra = gets.chomp
def palindromo?(palavra)
palavra.downcase == palavra.downcase.reverse
end
puts palindromo?(palavra)SaĂda (Output)
Digite alguma palavra ou nĂşmero: Isaac false Digite alguma palavra ou nĂşmero: Pop true Digite alguma palavra ou nĂşmero: 7 true
Foi feita uma classe chamada NomeDaClasse, porém essa está em branco (BLANK).
Sintaxe de uma classe em Ruby:
class NomeDaClasse
endVamos criar um comportamento pra ela:
class NomeDaClasse
def imprimir_ola(nome)
puts "Olá #{nome}"
end
end
objeto = NomeDaClasse.new # instância para o objeto NomeDaClasse
objeto.imprimir_ola("isaac")Cujo o método (verbo) é imprimir_ola com um argumento (parâmetro) que se chama nome.
Portanto, estamos instanciando essa classe (cujo é o esboço do objeto) com a instância de classe
.new, e assim criando esse objeto chamadoNomeDaClasse.
Na Ăşltima linha, estamos imprimindo o nome desse objeto com o argumento "isaac".
class NomeDaClasse
def imprimir_ola(nome)
@nome = nome
puts "Olá #{@nome}"
end
endO diferencial dessa estrutura Ă© o @nome, isso, pois a nossa variável nome irá ficar disponĂvel durante todo o ciclo de vida enquanto estiver na memĂłria. SĂł que nĂŁo podemos acessar essa variável antes da classe.
Nós somente podemos corrigir essa variável dentro da classe.
Se eu criar outro método, chamado imprimir_tchau(), logo eu não preciso receber como argumento mais, pois eu consigo pegar essa variável nome que está dentro do objeto. Então, a gente cria um método e essa variável retorna pra gente no mundo exterior.
Na parte de
Olá #{@nome}oOlá #nĂŁo será exibido na saĂda do cĂłdigo, apena o@nome.
class NomeDaClasse
def imprimir_ola(nome)
@nome = nome
puts "Olá #{@nome}"
end
def nome
@nome
end
end
isaac = NomeDaClasse.new
isaac.imprimir_ola("isaac")
isaac.nomeQuando o mĂ©todo Ă© pĂşblico a gente sĂł pega e delega a palavra, ou seja, esse mĂ©todo sĂł vai retornar a palavra de instância. Portanto, essa variável vai ficar disponĂvel durante todo o ciclo de vida do objeto na memĂłria e possuĂmos um mĂ©todo que retorna essa variável.
class NomeDaClasse
def initialize(nome)
@nome = nome
end
def imprimir_ola(nome)
puts "Olá #{@nome}"
end
def nome
@nome
end
end
pessoa = NomeDaClasse.new("isaac")
pessoa.nome = "Foo"
pessoa.nomeNo entanto, somente estamos imprimindo o nome no imprimir_ola, então para a gente alterar o nome, precisamos imprimir_ola novamente. Então, eu quero passar o estado inicial para o método inicial e a partir desse conceito entra o método construtor. Em Ruby, o método construtor se chama initialize, então para inicializar um método, você precisa utiliza-lo e passamos o @nome como argumento.
Podemos criar um objeto a partir da classe, no nosso initialize podemos usar o nome como parâmetro. Então, no nosso new devemos passar um nome, então nas 3 últimas linhas, estamos criando um objeto pessoa e passo o nome "isaac", então essa variável vai ser inserida no @nome e quando eu quiser o nome.
Entretanto, e se eu quiser alterar o nome dessa variável? Eu posso criar um método que altera o nome dessa variável.
class NomeDaClasse
def initialize(nome)
@nome = nome
end
def imprimir_ola(nome)
puts "Olá #{@nome}"
end
def nome # retorna a variável de instância
@nome
end
def nome=(novo_nome) # troca o valor da instância
@nome = novo_nome
end
end
pessoa = NomeDaClasse.new("isaac")
pessoa.nome = "Foo"
pessoa.nomePara getters e setters em Ruby, utilizamos o método attr_accessor para uma variável :nome. Dessa forma, faz o objeto se comportar da mesma forma como anteriormente, ou seja, a gente cria um objeto e a gente troca esse objeto com o atributo (variável) :nome e a gente retorna esse objeto.
class NomeDaClasse
attr_accessor :nome # getter e setter
# attr_reader :nome # apenas getter
# attr_writter :nome # apenas setter
def initialize(nome)
@nome = nome
end
def imprimir_ola(nome)
puts "Olá #{@nome}"
end
end
pessoa = NomeDaClasse.new("isaac")
pessoa.nome = Foo
pessoa.nomeSe for o caso de criar somente um getter podemos usar o attr_reader e se for o caso de apenas um setter podemos usar o att_writter.
class Pessoa
def initialize(nome)
@nome = nome
end
end
pessoa = Pessoa.new("isaac")
p pessoa#<Pessoa:0x000000000304c2e0 @nome="isaac">
Analisando o código com o método
p, esse método retorna a inspeção do métodopessoa, ou seja, daria o mesmo resultado se fizessemos da seguinte forma:
class Pessoa
def initialize(nome)
@nome = nome
end
end
pessoa = Pessoa.new("isaac")
p pessoa.inspect # o inspect é um parâmetro de inspeção cujo podemos ver todas as variáveis na memória do objeto, que no caso é @nome="isaac"E se fizermos outro objeto para uma nova pessoa?
class Pessoa
def initialize(nome)
@nome = nome
end
end
pessoa = Pessoa.new("isaac")
pessoa2 = Pessoa.new("matheus")
p pessoa, pessoa2#<Pessoa:0x000000000313c2b8 @nome="isaac">
#<Pessoa:0x000000000313c268 @nome="matheus">EntĂŁo, todo objeto tem a sua entidade na memĂłria e cada um tem um nome diferente.
Em seguida, criamos um método chamado imprimir_ola:
class Pessoa
def initialize(nome)
@nome = nome
end
def imprimir_ola
puts "Olá, #{@nome}"
end
end
pessoa = Pessoa.new("isaac")
pessoa2 = Pessoa.new("matheus")
pessoa.imprimir_ola
pessoa2.imprimir_olaOlá, isaac Olá, matheus
E se eu colocar um novo nome:
class Pessoa
def initialize(nome)
@nome = nome
end
def imprimir_ola
puts "Olá, #{@nome}"
end
def nome(novo_nome)
@nome = novo_nome
end
end
pessoa = Pessoa.new("isaac")
pessoa.imprimir_ola
pessoa.nome('Foo')
pessoa.imprimir_olaDessa forma, podemos trocar os valores de objetos no Ruby.
Olá, isaac Olá, Foo
Podemos também fazer o mesmo com uma linha só utilizando getters e setters:
class Pessoa
attr_writer :nome
def initialize(nome)
@nome = nome
end
def imprimir_ola
puts "Olá, #{@nome}"
end
end
pessoa = Pessoa.new("isaac")
pessoa.imprimir_ola
pessoa.nome='Foo'
pessoa.imprimir_olaOlá, isaac Olá, Foo
Podemos fazer o Poo Ruby também com o irb:
irb
class MinhaClasse
def initialize(nome)
@nome = nome
end
end
objeto = MinhaClasse.new("isaac"):initialize
=> #<MinhaClasse:0x000000000351e020 @nome="isaac">
Podemos pegar a variável de instância pelo irb, da seguinte forma:
objeto.instance_variable_get(:@nome)
=> "isaac"
Imagine a seguinte estrutura de diretĂłrios:
├── classes | ├── carro.rb | └── pessoa.rb └── principal.rb
Na seguinte hierarquia, possuimos o nosso código principal, onde chamará as suas classes pelos arquivos localizados na pasta chamada classes.
# arquivo: classes/pessoa.rb
class Pessoa
def initialize(nome)
@nome = nome
end
end# arquivo: classes/carro.rb
class Carro
def initialize(modelo,dono)
@modelo = modelo
@dono = dono
end
end# arquivo: principal.rb
require "./classes/pessoa"
require "./classes/carro"
foo = Pessoa.new("Foo")
carro = Carro.new("carro", foo)Chamamos outro arquivo ruby pelo método de importação require juntamente com o caminho do diretório.
Agora, vamos instalar uma biblioteca do Ruby chamada awesome_print.
gem install awesome_printDepois que instalamos essa biblioteca, também devemos importá-la no arquivo utilizando o require.
# arquivo: principal.rb
require "awesome_print" # importando a biblioteca
require "./classes/pessoa"
require "./classes/carro"
foo = Pessoa.new("Foo")
carro = Carro.new("carro", foo)
ap foo # método da biblioteca importadaO conceito de herança é quando uma classe precisa herdar as funcionalidades de outra classe.
Em Ruby, o conceito de herança somente pode uma classe herdar de uma outra classe, portanto, heranças múltiplas não serão permitidas, como é o caso das outras linguagens de programação.
Exemplo: A classe Filho herda os comportamentos da classe Pai.
Outro exemplo é a classe Cachorro herdar o comportamento da classe Animal, o comportamento no caso é o método, como por exemplo: Respirar(), então isso será passado para a classe Cachorro.
Se a gente não especifica qual a classe a gente deve herdar, essa classe herdará da classe object (não confunda com o objeto) que é uma classe trazida pelo próprio Ruby.
Quando chamamos um método, o Ruby vai avisar se esse método existe na classe do objeto, senão ele começa a analisar a hierarquia de classes procurando um método com aquele nome, senão ele vai avisar que esse método não existe.
Exemplo:
class Sensor
def iniciar
# iniciar o sensor
end
def coletar
# fazer uma coleta genérica
end
end
class SensorSolo < Sensor
def coletar
# coletar métricas no solo
end
end
class SensorTemperatura < Sensor
def coletar
# coletar métricas de temperatura
end
endPodemos também fazer o mesmo em arquivos separados e importando a
classe Sensorpara cada um deles, onde o arquivo principal conterá toda a manipulação dessas classes dos sensores.
Você pode utilizar também um método que foi sobrescrito na super classe base chamada
super. Então, vamos supor que você escreve todo o comportamento para o sensor genérico, então ele irá fazer umas coisas antes que o sensor de solo irá coletar e fazer isso em passos (passo 1, passo 2 e passo 3, cujo o passo 3 é o sensor regular, onde será chamado osuper).
super # executa o método sobrescrito da super classeHerança é para reuso de funcionalidades.
Exemplo em somente um arquivo com todas as classes:
class Sensor
def instalar
# instala o sensor
puts "Sensor instalado"
end
def iniciar
# inicia o sensor
puts "Sensor iniciado"
end
def coletar_metricas
# coleta as métricas
puts "Métricas analisadas e coletadas"
puts "Métricas analisadas e coletadas novamente"
end
end
class SensorTemperatura < Sensor
# Sem nada dentro pode inicializar o SensorTemperatura herdando todos os métodos da classe Sensor
# Com algo dentro, podemos fazer algo mais exĂłtico, como abaixo:
def coletar_metricas
# inicializar componentes de temperatura
puts "Métricas de temperatura coletadas"
super # Logo, ao rodar a aplicação ela irá rodar a mensagem acima na impressão de sensor.coletar_metricas primeiro e posteriormente os da classe Sensor
end
# Logo, ao rodar a aplicação ela irá rodar a mensagem acima na impressão de sensor.coletar_metricas
end
sensor = SensorTemperatura.new # Sensor.new # Sensor.new = imprimir apenas os métodos da classe Sensor
sensor.instalar
sensor.iniciar
sensor.coletar_metricasSensor instalado Sensor iniciado Métricas de temperatura coletadas Métricas analisadas e coletadas Métricas analisadas e coletadas novamente
AtĂ© entĂŁo foram feitos mĂ©todos de classe como Pessoa.new que gerava uma nova classe a ser usada, mas tambĂ©m podemos definir as nossas prĂłprias classes e esses mĂ©todos sĂŁo chamados na classe, bem diferente daqueles que eram instâncias da classe para criação de um objeto especĂfico.
Pessoa.gerarOs mĂ©todos de classe sĂŁo Ăşteis quando possuĂmos uma funcionalidade que nĂŁo Ă© tĂŁo dependente do estado do objeto.
Sintaxe dos métodos de classe: Para definirmos os métodos de classe basta somente inserir o prefixo self.nome_do_método, isso é claro depois de ser inserido o def da função do nosso método.
class Pessoa
def self.gerar
puts "Estou gerando uma nova pessoa partir do método de classe"
end
endCom isso, esse mĂ©todo de classe vai se tornar disponĂvel apenas para a classe e nĂŁo para as instâncias do objeto. Se vocĂŞ tentar executar esse mĂ©todo de classe em um objeto vai ocorrer um erro. Os mĂ©todos de classe nĂŁo usam o estado inicial de um objeto, mas vocĂŞ pode abordar um estado se vocĂŞ quiser.
class Pessoa
@@variavel_da_classe_pessoa = 100
def self.valor_da_variável
@@variavel_da_classe_pessoa
end
def self.incrementar_valor_variavel
@@variavel_da_classe_pessoa += 1
end
endQuando definimos
@@estamos definindo variáveis (atributos) de classe e os mĂ©todos definidos comselfconseguem acessar e gravar nessas variáveis, onde possuĂmos dois mĂ©todos, cujo o primeiro funciona como um getter e o outro Ă© um incremento dessa variável.
class Pessoa
@@numero_de_pessoas = 0
def self.gerar
@@numero_de_pessoas += 1
puts "vou fazer antes"
Pessoa.new
end
end
pessoa = Pessoa.new # instânciando o objeto Pessoa
pessoa = Pessoa.gerar # instânciando a classe com o método de classe gerar
p pessoa AtĂ© agora, todos os mĂ©todos que utilizamos na classe sĂŁo pĂşblicos, porque Ă© o padrĂŁo, isso quer dizer que eles sĂŁo acessĂveis em qualquer outro lugar no nosso cĂłdigo.
class MinhaClasse
def m1
puts "Método 1"
m2
m3
end
def m2
puts "Método 2"
end
def m3
puts "Método 3"
end
endO método
m1imprime:Método 1,m2em3. Portanto, esses métodos são públicos.
Vamos supor que nĂŁo queremos o m2 e o m3 acessĂveis a qualquer mĂ©todo, entĂŁo podemos deixar eles private (privado). Para isso basta inseri-lo da seguinte forma:
class MinhaClasse
def m1
puts "Método 1"
m2
m3
end
private
def m2
puts "Método 2"
end
def m3
puts "Método 3"
end
endTudo abaixo da palavra
privatefica privado, portanto om2e om3estĂŁo privados.
Os métodos privados podem também serem chamados por uma subclasse.
class MinhaSubClasse < MinhaClasse
def m4
puts "Método m4 - subclass"
m3
end
endExistem 3 tipos de acessibilidade de métodos no Ruby:
public(padrĂŁo) podem ser acessados por qualquer mĂ©todo em qualquer objeto.privatesĂł podem ser chamados dentro de sua prĂłpria instância. NĂŁo Ă© possĂvel acessar MĂ©todos privados de outras instâncias, apenas pode ser chamada por uma subclasse.protectedpodem ser chamados por qualquer instância se for da mesma Classe/SuperClasse.
Somente os métodos públicos podem ser ações para os controllers!
Vamos testar esses modos de acessibilidade de métodos!
Todos os métodos ficaram públicos.
class MinhaClasse
def m1
puts "Método 1"
m2
m3
end
def m2
puts "Método 2"
end
def m3
puts "Método 3"
end
end
### a partir daqui, Ă© um outro contexto
obj = MinhaClasse.new
obj.m1
obj.m2
obj.m3Método 1 Método 2 Método 3
Todos os métodos ficaram privados.
class MinhaClasse
private
def m1
puts "Método 1"
m2
m3
end
def m2
puts "Método 2"
end
def m3
puts "Método 3"
end
end
### a partir daqui, Ă© um outro contexto
obj = MinhaClasse.new
obj.m1
obj.m2
obj.m3c:/Users/ipinheiro/Desktop/MinhaClasse.rb:23:in `': private method `m1' called for # (NoMethodError)
Como privatizar um mĂ©todo especĂfico:
m1será o único método privado da Classe.
class MinhaClasse
private def m1
puts "Método 1"
m2
m3
end
def m2
puts "Método 2"
end
def m3
puts "Método 3"
end
end
### a partir daqui, Ă© um outro contexto
obj = MinhaClasse.new
obj.m1
obj.m2
obj.m3Todavia, na saĂda do cĂłdigo, o
m1será o primeiro a ser executado, gerando a finalização dele por ser privado.
c:/Users/ipinheiro/Desktop/MinhaClasse.rb:23:in `': private method `m1' called for # (NoMethodError)
A diferença entre o
privatee oprotected, oprotectednão funciona inline com o método e, além disso, oprotectedserve para poder chamar outros métodos dentro de outros objetos, diferente doprivateque é para privatizar o nosso objeto principal.
class MinhaClasse
def m1
puts "Método 1"
m2
m3
end
private
def m2
puts "Método 2"
end
def m3
puts "Método 3 privado"
end
protected # Tudo aqui em baixo Ă© PROTECTED!
def m5
puts "Método 5"
end
end
class MinhaSubClasse < MinhaClasse
def m4
m3
outro_obj = MinhaClasse.new
puts "Método 4"
outro_obj.m5
end
end
# a partir daqui, Ă© um outro contexto
obj = MinhaSubClasse.new
obj.m4
obj.m5c:/Users/ipinheiro/Desktop/MinhaClasse.rb:38:in `': protected method `m5' called for # (NoMethodError) Método 3 privado Método 4 Método 5
No Ruby, possuĂmos algumas propriedades que podem acessar os mĂ©todos privados, como por exemplo o mĂ©todo
send(:método da classe).
irb
class Pessoa
private def falar
puts "Estou falando"
end
end
pessoa = Pessoa.new
pessoa.send(:falar)ExercĂcio 02: Conta bancária
Desafio:
- Criar uma classe responsável para representar Contas Bancárias.
- Criar um método que me permita transferir valor entre contas usando: "conta1.transferir(conta2,100)" onde 100 é o valor que eu desejo transferir.
- Plus: Criar um tipo de conta em que existe uma tarifa para se transferir dinheiro
Solução:
Estrutura de arquivos
├── classes | └── conta_bancaria.rb └── principal.rb
# principal.rb
require "./classes/conta_bancaria"
conta_cadu = ContaBancaria.new("cadu", 100)
conta_pessoa2 = ContaBancaria.new("pessoa2", 200)
conta_cadu.transferir(conta_pessoa2, 50)
p "Conta Cadu"
p conta_cadu.saldo # 50
p "Conta Pessoa 2"
p conta_cadu.saldo # 250
# caso de teste de conta sem saldo
conta_cadu.transferir(conta_pessoa2, 60) # falhar
p "Conta Cadu"
p conta_cadu.saldo # 50
p "Conta Pessoa 2"
p conta_pessoa2.saldo # 250class ContaBancaria
def initialize(proprietario, valor_inicial)
@proprietario = proprietario
@valor = valor_inicial
end
def transferir(outra_conta, valor)
# logica de transferĂŞncia
if saldo >= valor
# consigo
debitar(valor)
outra_conta.depositar(valor)
else
# não consigo (não faço nada)
raise "NĂŁo consegui transferir! Saldo insuficiente."
end
end
def saldo
@valor
end
private
def debitar(valor_para_debitar)
@valor -= valor
@valor = valor_para_debitar
end
protected
def depositar(valor_para_depositar)
@valor += valor_para_depositar
end
endPlus: Taxa na transferĂŞncia
Estrutura de arquivos
├── classes | ├── conta_com_taxa.rb | └── conta_bancaria.rb └── principal.rb
# conta_com_taxa.rb
class ContaComTaxa < ContaBancaria
def transferir(outra_conta, valor)
if saldo >= valor
debitar(2)
super
end
end
end# principal.rb
require "./classes/conta_bancaria"
require "./classes/conta_com_taxa"
conta_cadu = ContaComTaxa.new("cadu", 100)
conta_pessoa2 = ContaBancaria.new("pessoa2", 200)
conta_cadu.transferir(conta_pessoa2, 50)
p "Conta Cadu"
p conta_cadu.saldo # 50
p "Conta Pessoa 2"
p conta_cadu.saldo # 250
# caso de teste de conta sem saldo
begin
conta_cadu.transferir()
conta_cadu.transferir(conta_pessoa2, 60) # falhar
# o codigo abaixo nĂŁo foi executado, pois a linha acima gerou um erro.
p "Conta Cadu"
p conta_cadu.saldo # 50
p "Conta Pessoa 2"
p conta_pessoa2.saldo # 250O Rails Ă© um framework/biblioteca para fazer aplicações web escritas na linguagem Ruby, ele foi criado em 2004 por David Heinemeier Hanson (DHH) e foi extraĂdo pelo software Basecamp, da empresa do DHH, cujo era um software de gerenciamento de tarefas. A biblioteca Rails trabalha mais especificamente com um padrĂŁo de arquitetura de software chamado MVC (Model View Controller) que separa a representação da informação da interação do usuário.
Existem várias maneiras de instalar o Rails, a mais famosa consiste na instalação a partir da gem oficial liberada pelo RubyGems.
gem install railsO comando abaixo mostra as seguintes opções que temos para criar um projeto RubyOnRails:
rails new -hLogo, podemos criar o nosso primeiro projeto utilizando o Rails:
rails new meu_projetoApĂłs isso, vai ser criado o seguinte diretĂłrio do projeto com os seguintes arquivos:
/meu_projeto ├── app │ ├── assets │ │ ├── config │ │ ├── images │ │ └── stylesheets │ ├── channels │ ├── controllers │ └── views ├── bin ├── config ├── db | ├── │ └── seeds.rb ├── lib │ ├── assets │ └── tasks ├── log │ ├── .keep │ └── development.log ├── public ├── storage ├── test ├── tmp ├── vendor │ ├── javascript | | └── .keep │ └── .keep ├── .gitattributes ├── .gitattributes ├── .gitignore ├── .ruby.version ├── config.ru ├── Gemfile ├── Gemfile.lock ├── Rakefile └── README.md
O Gemfile é um arquivo onde instalamos todas as gems que iremos usar no projeto, se você for incluir alguma, é só copiar e colar o nome e a versão da gem, disponibilizada no RubyGems, no arquivo e após salvá-lo basta somente rodar o comando bundle install que ele irá instalar essa nova gem.
Já o arquivo Gemfile.lock é um arquivo que nem deve ser alterado, pois é gerado após a instalação do bundle.
O Gemfile Ă© similar ao package.json.
Resumidamente, o conjunto de comandos para iniciar uma aplicação em RubyOnRails é:
# rails new -h
rails new meu_projeto
cd meu_projeto
bundle install
# bundle update
rails server # rails sO banco de dados padrão para o desenvolvimento em Rails é o SQLite. No entanto, geralmente, em alguns ambientes esse banco funciona apenas para a etapa de desenvolvimento e testes, não servindo para produção. Portanto, utilize outro banco de dados para produção como o MySQL ou PostgreSQL.
O comando abaixo permite vocĂŞ definir, no inĂcio do seu projeto, o banco de dados necessário:
rails new meu_projeto -d postgresqlCaso se não for especificado, você irá utilizar o SQLite.
Você pode editar essas configurações instalando uma gem e configurando em config/database.yml. E, também vale ressaltar, que ao criar e migrar o banco de dados do PostgreSQL, o arquivo do banco de dados não irá aparecer no diretório db, como é o caso do SQLite. Então é necessário a instalação do banco de dados PostgreSQL (com acesso ao pgAdmin ou psql).
Com isso, a sua aplicação RoR irá se conectar ao banco de dados do PostgreSQL no endereço: http://localhost:5432
Além disso, você pode consultar os dados pelo console do Rails ou pelo próprio banco utilizando uma ferramenta como o DBeaver, na qual é só definir o caminho do banco de dados e gerenciar o banco de dados pela ferramenta.
Com o projeto criado, projeto mvc_test, iremos utilizar o scaffold (traduzido no inglês como "andaime"), ele é uma extensão do Rails que permite criar um CRUD rapidamente somente a partir dos comandos de declaração do Model.
rails g scaffold User name:string email:stringO comando acima serve para gerar (g = generate) um scaffold com User onde name e email recebem o valor string.
A partir da versĂŁo 5 do Rails nĂŁo Ă© preciso inserir o tipo
string. Portanto o comando ficará dessa forma:rails g scaffold User name email
Comando para desfazer o CRUD: O comando abaixo serve para excluir as tabelas criadas para fazer o CRUD, com isso o CRUD será desfeito.
rails db:rollbackComando para deletar o scaffold: O comando abaixo deleta tudo relacionado ao scaffold criado.
rails d scaffold ProductCriando um banco de dados e migrando para o banco: Após o diretório da aplicação Rails funcionar, no diretório ./db/ foi criado uma pasta ./migrate/ onde possui um model para a criação da tabela proposta.
rails db:migrate db:createPortanto, rodar o comando acima: rails db:create irá instanciar a ação do model em criar um banco de dados e o outro comando: db:migrate para criação daquela tabela.
Um controller é simplesmente uma classe que é definida para herdar do ApplicationController. É dentro dessa classe que você vai definir as ações por este controller. Aquelas ações vão performar as operações do CRUD nos posts.
Gerando um model com Rails:
rails generate model Post title:string body:textDessa forma, ele vai gerar um model com tĂtulo e corpo automaticamente, sem precisarmos escrever isso no cĂłdigo.
Criando as tabelas no banco de dados com o Rails:
rails db:migrateDessa forma, serão criadas as tabelas no banco de dados juntamente com os models e uma pasta chamada migrate onde está o model de criação da tabela, como mostrado abaixo:
class CreatePosts < ActiveRecord::Migration[7.0]
def change
create_table :posts do |t|
t.string :title, null: false
t.text :body, null: false
t.timestamps
end
end
endO comando
null: falsesignifica que o dado não será aceito ser ele conter o valornull(nulo).
Comando para acessar o console do Rails:
rails consoleVamos dizer que eu queira acessar a classe Posts:
irb(main):003:0> Post => Post (call 'Post.connection' to establish a connection) irb(main):004:0>
Para contar quantos posts tem na tabela:
irb(main):004:0> Post.count() (2.4ms) SELECT sqlite_version(*) Post Count (0.3ms) SELECT COUNT(*) FROM "posts" => 0 irb(main):005:0>
Para criar um post na tabela diretamente pelo console:
irb(main):005:0> post = Post.create(title: "Isaac", body: "lindo")
TRANSACTION (0.1ms) begin transaction
Post Create (1.4ms) INSERT INTO "posts" ("title", "body", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["title", "Isaac"], ["body", "lindo"], ["created_at", "2022-07-12 18:56:22.030795"], ["updated_at", "2022-07-12 18:56:22.030795"]]
TRANSACTION (4.0ms) commit transaction
=>
Para contar todos os itens da tabela do maior ao menor:
irb(main):021:0> Post.last Post Load (0.3ms) SELECT "posts".* FROM "posts" ORDER BY "posts"."id" DESC LIMIT ? [["LIMIT", 1]] => # irb(main):022:0>
Para consultar o post:
irb(main):022:0> post
=>
#<Post:0x0000026fa2a5bd60
id: 1,
title: "Isaac",
body: "lindo",
created_at: Tue, 12 Jul 2022 18:56:22.030795000 UTC +00:00,
updated_at: Tue, 12 Jul 2022 18:56:22.030795000 UTC +00:00>
irb(main):023:0>
Depois que fizemos todo aquele processo anterior, o Rails gera todo o MVC com as rotas prontas pra criação do CRUD com o seguinte resource: resources :users.
- Endereço para saber informações sobre as rotas da aplicação: http://localhost:3000/rails/info/routes
E agora, vamos aprender a criar as nossas rotas para um projeto RoR:
Rails.application.routes.draw do
resources :users
get 'usuarios', to: 'users#index'
# Define your application routes per the DSL in https://guides.rubyonrails.org/routing.html
# Defines the root path route ("/")
# root "articles#index"
endDessa forma, com o método HTTP get mirando em 'usuarios', onde to: 'users#index' que irá criar uma nova rota e nela conter as mesmas funcionalidades da rota users, o que é interessante caso o cliente queira acessar essa rota e insire errado, então ele irá acessar rota certa já que foi configurado na aplicação.
Para mais detalhes de como inserir o bootstrap numa aplicação RoR: https://gorails.com/forum/install-bootstrap-with-webpack-with-rails-6-beta
Para saber mais acesse: https://docs.docker.com/samples/rails/
O RSpec é uma ferramenta de teste de comportamento para o framework Ruby on Rails. Ele permite que os desenvolvedores escrevam testes que descrevem o comportamento esperado do código, em vez de apenas testar se o código funciona corretamente. O RSpec é baseado na abordagem Behavior-Driven Development (BDD), que enfatiza a colaboração entre desenvolvedores, gerentes de produto e outros stakeholders para definir o comportamento esperado do software. Em resumo, o RSpec é uma ferramenta poderosa para testar o comportamento do código Ruby on Rails, e é amplamente utilizada na comunidade de desenvolvimento de software.
Com o RSpec, os desenvolvedores podem escrever testes que descrevem o comportamento esperado do cĂłdigo, usando uma linguagem natural e fácil de entender. Isso ajuda a garantir que o cĂłdigo esteja funcionando corretamente e atendendo aos requisitos do projeto. Algumas das principais caracterĂsticas do RSpec incluem:
- Descrição de comportamento: O RSpec permite que os desenvolvedores descrevam o comportamento esperado do código, em vez de apenas testar se o código funciona corretamente.
- Testes de unidade: O RSpec pode ser usado para escrever testes de unidade, que verificam se as unidades de código (como métodos ou funções) estão funcionando corretamente.
- Testes de integração: O RSpec também pode ser usado para escrever testes de integração, que verificam se as diferentes unidades de código estão funcionando corretamente juntas.
- RelatĂłrios de teste: O RSpec fornece relatĂłrios de teste detalhados, que mostram quais testes passaram ou falharam, e por quĂŞ.
Ruby + Cucumber + Capybara é uma combinação de ferramentas para desenvolvimento de software que visa facilitar a criação de testes automatizados de aceitação, também conhecidos como testes de comportamento. A combinação Ruby + Cucumber + Capybara é amplamente utilizada em projetos de desenvolvimento de software, especialmente aqueles que utilizam o framework Ruby on Rails.
Cucumber é uma ferramenta de teste de comportamento que permite que os desenvolvedores escrevam testes em uma linguagem natural. É baseada na abordagem Behavior-Driven Development (BDD). Cucumber é frequentemente usado para testar a interface do usuário e o comportamento do sistema.
Capybara é uma ferramenta de teste de aceitação que simula a interação do usuário com a aplicação web. É projetada para ser usada com Cucumber. Capybara fornece uma API simples para interagir com a aplicação web, como clicar em botões, preencher formulários, etc.
Juntas, essas ferramentas permitem que os desenvolvedores criem testes automatizados de aceitação que simulam a interação do usuário com a aplicação web. Isso ajuda a garantir que a aplicação esteja funcionando corretamente e atendendo aos requisitos do projeto.












