Skip to content

IsaacAlves7/ruby

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Versículo chave: "Consagre ao Senhor tudo o que você faz, e os seus planos serão bem-sucedidos." - Provérbios 16:3

It's a repository of Ruby language đź’Ž

💎 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.

đź’Ž Linguagem Ruby

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.

.RB

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.falar

Possui uma tipagem dinâmica e forte, se assemelhando a linguagem de programação Python.

[Ruby] Hello, World!

.RB

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 mensagem

Heredoc:

mensagem = <<~TXT
  Essa Ă© minha mensagem
TXT

Colocando prompt:

puts "Digite o seu nome: "
nome = gets
puts "Seu nome Ă© #(nome)"

[Ruby] Comentário

# comentário de uma linha

[Ruby] Entrada de dados

Como 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
gets

Sintaxe

nome = gets
nome
puts nome
nome.chomp() # Tira o Ăşltimo caractere social, no caso, o \n
# ou
nome = nome.chomp
# ou
nome = gets.chomp

💎 [Ruby] Gerenciadores de versões

O 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 nodejs

📦 gem - RubyGems

SĂŁ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 list

đź’Ž [Ruby] irb - Interactive Ruby

Traduzido 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_id

nil = 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

đź’Ž [Ruby] Procedural

Executando um cĂłdigo-fonte:

đź’Ž [Ruby] Tipos de dados

[Ruby] Strings

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:

\n

Tab:

\t

Aspas:

\"

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 mensagem

Esse 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 # downcase

Primeira letra maĂ­uscula

"isaac".capitalize

Dividir

"cadu teste outra_nome".split
"cadu-teste-outro_nome".split("-")

Brincando com manipulação de variáveis e operações de Strings

o comando p imprime a string da sua forma natural inserida pelo programador, diferente do comando print que imprime com valor nulo.

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

[Ruby] Tipos numéricos

(Input) Entrada

irb
7.class
7.7.class

(Output) SaĂ­da

Integer
Float

[Ruby] Int - Inteiros

(Input) Entrada

puts 123_500

(Output) SaĂ­da

123500

[Ruby] Float - Flutuante

(Input) Entrada

# soma um inteiro com um ponto flutuante
soma = 3 + 4.77
p soma

(Output) SaĂ­da

7.77

[Ruby] SĂ­mbolos

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

[Ruby] Dicionários

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.new

Sintaxe 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 hash

Ao 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.

đź’Ž [Ruby] Arrays (listas)

Arrays ou listas sĂŁo listas de valores separados por vĂ­rgula.

lista = []
lista = Array.new

Os 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Ă­fico

Somando 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]

💎 [Ruby] Operadores e expressões

Operadores relacionais

== # igualdade
!= # diferente
> # maior que
>= # maior ou igual a 
< # menor que
<= # menor ou igual a 

Operadores lĂłgicos

! # Negação
&& # And
|| # Or 

💎 [Ruby] Estruturas de programação

[Ruby] Estruturas Condicionais

Sintaxe

if condicao 
  faca_algo
else
  faca_outra_coisa
end

Estrutura condicional com operadores relacionais

valor = 20
if valor > 50
  puts "Eu sou maior que 50"
else
  puts "Eu sou menor que 50"
end

Estrutura condicional com operadores relacionais && lĂłgicos

valor = 65
if valor >= 50 && valor <= 100
  puts "Estou entre 50 e 100"
end

Estrutura 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"
end

Apenas nil e false sã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
end

Operador 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"
end

Exemplo 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"
end

SaĂ­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"
end

SaĂ­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"
end

SaĂ­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"
end

SaĂ­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"
end

SaĂ­da (Output):

Eu nĂŁo tenho nada

[Ruby] Laços de Repetição (Loops)

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á encerrada

SaĂ­da (Output)

5
4
3
2
1

Entrada (Input)

valor = 5
while valor > 0
  puts valor
  valor = valor - 0
end

SaĂ­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}"
end

Until 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
end

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
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
end

SaĂ­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
end

SaĂ­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}"
end

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: Range For Entrada (Input):

range = 0..7
for meu_valor in range
  puts "Meu valor Ă© #{meu_valor}"
end

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: For Range Entrada (Input):

for meu_valor in 0..7
  puts "Meu valor Ă© #{meu_valor}"
end

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: For para Arrays Entrada (Input):

lista = [0,1,2,3,4,5,6,7]
for meu_valor in lista
  puts "Meu valor Ă© #{meu_valor}"
end

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 Entrada (Input):

lista = [0,1,2,3,4,5,6,7]
lista.each do |meu_valor|
  puts "O valor Ă© #{meu_valor}"
end

Em 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"
end

SaĂ­da (Output):

Meu nome Ă© Isaac e tenho 21 anos

đź’Ž [Ruby] Paradigma funcional

đź’Ž [Ruby] OOP

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:

Classes e Objetos - Poo

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:

.RB

class NomeDaClasse
end

Sintaxe para objeto:

.RB

obj NomeDaClasse.new

Instanciando uma classe pelo objeto:

.RB

class MinhaClasse
end

objeto = MinhaClasse.new

p objeto.object_id

irb

irb
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

.RB

=> "isaac"
=> 180
=> "outro_nome"
=> 200
=> "isaac"
=> "isaac"
=> "isaac"
=> 180
=> 180
=> "ISAAC"
=> "isaac"
=> "ISAAC"
=> "ISAAC"
=> "ISAAC"

[Ruby] Métodos

def meu_metodo
  puts "meu_metodo foi executado"
end
def meu_metodo(parametro1, parametro2)
  puts "meu_metodo foi executado com #{parametro1} e #{parametro2}"
end

a 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
end

Exemplo 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) # valor1

SaĂ­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

[Ruby] Atribuição condicional de variável

variavel = nil
variavel = "Algum valor" if variavel.nil?
variavel = nil
variavel = "Algum valor" unless variavel
variavel ||= "Valor"

Exemplo:

variavel = 10
variavel ||= 20
variavel
variavel = nil
variavel
variavel ||= 20
variavel
nova_variavel ||= 100
nova_variavel

Exercí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

[Ruby] Métodos e atributos para as instâncias de um objeto

Foi feita uma classe chamada NomeDaClasse, porém essa está em branco (BLANK).

Sintaxe de uma classe em Ruby:

class NomeDaClasse
end

Vamos 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 chamado NomeDaClasse.

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
end

O 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} o Olá # 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.nome

Quando 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.

.RB

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.nome

No 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.

.RB

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.nome

[Ruby] Getters e Setters

Para 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.

.RB

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.nome

Se 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.

.RB

class Pessoa
  def initialize(nome)
    @nome = nome
  end
end

pessoa = Pessoa.new("isaac")
p pessoa

.RB

#<Pessoa:0x000000000304c2e0 @nome="isaac">

Analisando o código com o método p, esse método retorna a inspeção do método pessoa, ou seja, daria o mesmo resultado se fizessemos da seguinte forma:

.RB

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?

.RB

class Pessoa
    def initialize(nome)
      @nome = nome
    end
end

pessoa = Pessoa.new("isaac")
pessoa2 = Pessoa.new("matheus")

p pessoa, pessoa2

.RB

#<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:

.RB

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_ola

.RB

Olá, isaac
Olá, matheus

E se eu colocar um novo nome:

.RB

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_ola

Dessa forma, podemos trocar os valores de objetos no Ruby.

.RB

Olá, isaac
Olá, Foo

Podemos também fazer o mesmo com uma linha só utilizando getters e setters:

.RB

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_ola

.RB

Olá, isaac
Olá, Foo

Podemos fazer o Poo Ruby também com o irb:

irb

irb
class MinhaClasse
  def initialize(nome)
    @nome = nome
  end
end

objeto = MinhaClasse.new("isaac")

.RB

:initialize
=> #<MinhaClasse:0x000000000351e020 @nome="isaac">

Podemos pegar a variável de instância pelo irb, da seguinte forma:

.RB

objeto.instance_variable_get(:@nome)

.RB

=> "isaac" 

[Ruby] Importando outros arquivos

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.

.RB

# arquivo: classes/pessoa.rb
class Pessoa
  def initialize(nome)
    @nome = nome
  end
end

.RB

# arquivo: classes/carro.rb
class Carro
  def initialize(modelo,dono)
    @modelo = modelo
    @dono = dono
  end
end

.RB

# 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.

RubyGems

gem install awesome_print

Depois que instalamos essa biblioteca, também devemos importá-la no arquivo utilizando o require.

.RB

# 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 importada

[Ruby] Herança

O conceito de herança é quando uma classe precisa herdar as funcionalidades de outra classe.

Herança (Poo Ruby)

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.

Exemplo de Herança (Poo Ruby)

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.

Herança com Object (Poo Ruby)

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:

.RB

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
end

Podemos também fazer o mesmo em arquivos separados e importando a classe Sensor para 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 o super).

.RB

super # executa o método sobrescrito da super classe

Herança é para reuso de funcionalidades.

Exemplo em somente um arquivo com todas as classes:

.RB

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_metricas

.RB

Sensor instalado
Sensor iniciado
Métricas de temperatura coletadas
Métricas analisadas e coletadas
Métricas analisadas e coletadas novamente

[Ruby] Métodos e atributos de classe

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.

.RB

Pessoa.gerar

Os 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.

.RB

class Pessoa
  def self.gerar
    puts "Estou gerando uma nova pessoa partir do método de classe"
  end
end

Com 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.

.RB

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
end

Quando definimos @@ estamos definindo variáveis (atributos) de classe e os métodos definidos com self conseguem 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.

.RB

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 

[Ruby] Visibilidade dos métodos

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.

.RB

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

O método m1 imprime: Método 1, m2 e m3. 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:

.RB

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
end

Tudo abaixo da palavra private fica privado, portanto o m2 e o m3 estĂŁo privados.

Os métodos privados podem também serem chamados por uma subclasse.

.RB

class MinhaSubClasse < MinhaClasse
  def m4
    puts "Método m4 - subclass"
    m3
  end
end

Existem 3 tipos de acessibilidade de métodos no Ruby:

  • public (padrĂŁo) podem ser acessados por qualquer mĂ©todo em qualquer objeto.
  • private sĂł 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.
  • protected podem 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!

.RB

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.m3

.RB

Método 1
Método 2
Método 3

.RB

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.m3

.RB

c:/Users/ipinheiro/Desktop/MinhaClasse.rb:23:in `': private method `m1' called for 
# (NoMethodError)

.RB

Como privatizar um método específico: m1 será 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.m3

Todavia, na saída do código, o m1 será o primeiro a ser executado, gerando a finalização dele por ser privado.

.RB

c:/Users/ipinheiro/Desktop/MinhaClasse.rb:23:in `': private method `m1' called for 
# (NoMethodError)

.RB

A diferença entre o private e o protected, o protected não funciona inline com o método e, além disso, o protected serve para poder chamar outros métodos dentro de outros objetos, diferente do private que é 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.m5

.RB

c:/Users/ipinheiro/Desktop/MinhaClasse.rb:38:in `': protected method `m5' called for 
# (NoMethodError)
Método 3 privado
Método 4
Método 5

irb

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

.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 # 250

.RB

class 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
  
end

Plus: Taxa na transferĂŞncia

Estrutura de arquivos

├── classes
|   ├── conta_com_taxa.rb
|   └── conta_bancaria.rb
└── principal.rb

.RB

# conta_com_taxa.rb

class ContaComTaxa < ContaBancaria
   def transferir(outra_conta, valor)
     if saldo >= valor
       debitar(2)
       super
     end
   end
end

.RB

# 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 # 250

🛤️ RoR - RubyOnRails

O 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 rails

O comando abaixo mostra as seguintes opções que temos para criar um projeto RubyOnRails:

rails new -h

Logo, podemos criar o nosso primeiro projeto utilizando o Rails:

rails new meu_projeto

ApĂł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 s

O 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 postgresql

Caso 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.

[RoR] Criando um CRUD com scaffold

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:string

O 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:rollback

Comando para deletar o scaffold: O comando abaixo deleta tudo relacionado ao scaffold criado.

rails d scaffold Product

Criando 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:create

Portanto, 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.

[RoR] Criando um CRUD sem scaffold

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:text

Dessa 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:migrate

Dessa 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
end

O comando null: false significa que o dado não será aceito ser ele conter o valor null (nulo).

Comando para acessar o console do Rails:

rails console

Vamos 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.

E agora, vamos aprender a criar as nossas rotas para um projeto RoR:

.RB

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"
end

Dessa 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.

[RoR] Construindo um blog

Para mais detalhes de como inserir o bootstrap numa aplicação RoR: https://gorails.com/forum/install-bootstrap-with-webpack-with-rails-6-beta

[RoR] Deploying: Rails + PostgreSQL

Para saber mais acesse: https://docs.docker.com/samples/rails/

đź§Ş [Ruby] DDD, BDD e TDD

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.

About

đź’Ž It's a repository of Ruby programming language and his content.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages