Anotações do curso gratuito: https://onebitcode.com/course/ruby-puro/
Todos os exercícios desse curso estão no repositório
Roda várias linguagens https://repl.it/languages/ruby
Instalação do Ruby:
- Rbenv
- Rvm
- Asdf
- Codeanywhere: ruby online
Colocando irb e enter, ele executa códigos ruby direto, sem necessidade de criar um arquivo para teste.
- Integer: conjunto de números positivos, negativos e 0
- Float: são números decimais, números que contêm ponto flutuante
- Boolean: possui apenas dois estados, sendo eles true que é uma instância da classe TrueClass e false que é uma instância da classe FalseClass.
- String: conjunto de letras, símbolos ou números.
- Array: permite armazenar uma lista ordenada de dados em um único objeto.
No ruby não é preciso definir o tipo de dado antes de atribuir um valor à uma variável. O tipo é dinâmico, ou seja, ele é definido de acordo com o dado atribuído. Não existem "tipos primitivos" em Ruby; todos os tipos são classes:
- Object é a classe mãe de todas as outras classes em Ruby
- Numeric é uma classe abstrata que representa números
- Integer é uma classe que representa números inteiros
- Fixnum representa números inteiros de precisão fixa
- Bignum representa números inteiros de precisão infinita, dependente apenas da memória disponível
- Float é uma classe que representa números de ponto flutuante (números reais)
- String uma cadeia de caracteres. Pode ser delimitado por apóstrofes (') ou aspas ("). Tudo o que há entre apóstrofes é interpretado literalmente, entre aspas o programador deve se utilizar de símbolos para representar caracteres específicos, como em C. Exemplos: 'azul', "a\nb\nc"
- Symbol é semelhante a uma string, mas dois símbolos iguais possuem o mesmo endereço de memória, sendo assim é ótimo para se utilizar como índice numa Hash. Porém, devido à sua natureza, o coletor de lixo do Ruby não os elimina. É definido com um sinal de dois pontos (:), por exemplo, :nome
- Array são arrays dinâmicos, que podem ser usados para representar matrizes e vetores. É delimitado por colchetes ([]) e cada valor é separado por vírgula. Exemplo: [4, 'azul', :termometro]
- Hash representa um vetor associativo, e, assim como as Arrays, é dinâmica. É delimitada por chaves ({}), e o índice precede o valor com um sinal '=>'. Exemplo: {:controller => 'user', :action => 'index'}. Qualquer objeto pode ser um índice, mas os mais usados são as Strings e os Symbols
- Regexp representa expressões regulares, delimitadas por //. Funciona de forma semelhante a Perl. Exemplo: /a|ae/
Um objeto em Ruby é declarado com uma atribuição comum:
class Carro
@@marcas = [ "Ford", "GM", "Fiat", "VW" ]
end
- Uma variável local é declarada normalmente.
- Uma variável de instância é declarada com um "@" no nome.
- Uma variável de classe é declarada com "@@".
- Uma variável global é declarada com "$".
- Variáveis que iniciam com uma letra maiúscula são consideradas constantes.
class A
@@contexto = "classe"
def initialize
@contexto = "instância"
end
def contexto
@contexto
end
def A.contexto
@@contexto
end
end
a = A.new
a.contexto # >> "instância"
A.contexto # >> "classe"
Para resolver operações matemáticas no ruby contamos com a seguinte lista de operadores aritméticos:
- + (Adição)
- – (Subtração)
- * (Multiplicação)
- / (Divisão)
- % (Módulo)
- ** (Expoente)
Essas duas operações manipulam dados, com a diferença que a entrada ocorre quando o programa lê dados que podem ter sido recebidos de um teclado, de um arquivo, ou então de outro programa e a saída é um dado produzido pelo programa que pode ser exibido em uma tela, enviado para um arquivo ou então para outro programa.
gets é um método que recebe como entrada um dado inserido pelo teclado. Como ele captura qualquer coisa precisamos do .chomp para que quando o enter for pressionado ele não crie uma quebra de linha.
.to_i transforma a string em número inteiro
Tipo de estrutura de controle que executa um trecho de código dependendo do resultado de uma condição. Instruções Condicionais If, Else, Elsif, Unless e Case:
- If: Expressão que verifica se uma condição é verdadeira(true), e a partir deste resultado determina se as instruções dentro de seu corpo serão ou não executadas.
- Else: Informa o que fazer quando a verificação de uma condição if for falsa.
- Elsif: Utilizado quando há a necessidade de verificar mais de uma condição em um if.
- Unless: Enquanto o if é executado quando sua condição é verdadeira, o unless ocorre de forma contrária. É executado apenas quando a condição é falsa.
- Case: Instrução muito parecida com o if. Ele se enquadra muito bem a situações com diversas condições.
Tipo de estrutura de controle que gerencia quantas vezes um trecho de código será executado. Instruções de iteração For, While, Times, Do/While:
- For: Usado para percorrer uma coleção de elementos.
- While: Instrução que repete um bloco de código enquanto sua condição é verdadeira.
- Times: Executa uma repetição por um especificado número de vezes.
- Do/While: Na verdade, no Ruby utilizamos uma estrutura de repetição chamada loop que faz o mesmo que o do/while em outras linguagens de programação. Ele cria um laço de repetição que só é parado quando uma instrução break for verdadeira.
O que são Collections? Na programação, collection representa um conjunto de dados semelhantes em uma única unidade.
Array: existem várias maneiras de manipular arrays. Abaixo encontram-se algumas muito úteis para todo programador.
- Criando um array vazio:
estados = []
Collections podem ter zero ou mais elementos.
estados.push('Espírito Santo')
O push sempre irá adicionar itens de forma sequencial.
- Também é possível inserir vários elementos de uma só vez.
estados.push('Minas Gerais', 'Rio de Janeiro', 'São Paulo')
- Veja o array estados com a instrução
puts estados
- Para manter nossa coleção organizada em ordem alfabética ao inserir os itens ‘Acre’ e ‘Amapá’, devemos especificar que eles ocuparão as primeiras posições do array. Para isso contamos com o insert.
estados.insert(0, 'Acre', 'Amapá')
Primeiro é passado o valor do índice onde a instrução será aplicada acompanhado por um ou mais itens a serem adicionados.
O item de um array pode ser acessado pelo valor de seu index.
- Recupere o segundo elemento do array estados
estados[1]
Saiba que o primeiro elemento não inicia no índice 1, mas sim no 0.
- Você também pode acessar índices através de intervalos
estados[2..5]
Retorna os itens dos índices 2, 3, 4 e 5
- Utilizando números negativos conseguimos recuperar elementos a partir do ultimo item do array, de forma regressiva. O número -1 representa o ultimo elemento. Adquira o penúltimo elemento de estados
estados[-2]
- Também funciona com intervalos
estados[-3..-1]
- Uma forma muito intuitiva e natural de recuperar o primeiro item é usar first
estados.first
- Seguindo a mesma ideia, use last para o último
estados.last
- Para saber a quantidade de itens em um Array você pode utilizar qualquer uma destas duas instruções
estados.count
estados.length
- Descubra se o array está vazio
estados.empty?
O resultado será verdadeiro ou falso
- Verifique se um item específico está presente
estados.include?('São Paulo')
Igual ao empty, também resulta um valor verdadeiro ou falso
- Remova um item através de seu índice
estados.delete_at(2)
- Exclua o ultimo item do array estados
estados.pop
- Para excluir o primeiro item faça
estados.shift
Hash: a seguir veja exemplos importantíssimos sobre manipulação de Hashes
- Crie um hash vazio
capitais = Hash.new
- Um Hash também pode ser iniciado com vários pares de chave-valor
capitais = { acre: 'Rio Branco', sao_paulo: 'São Paulo'}
- A chave de um Hash pode ser qualquer tipo de dado
hash = {1 => 'Chave do tipo inteiro', true => 'Chave do tipo booleano', [1,2,3] => 'Chave do tipo array'}
- Adicione um novo item ao hash estados
capitais[:minas_gerais] = "Belo Horizonte"
- Acesse a capital que acabamos de inserir utilizando sua chave
capitais[:minas_gerais]
De forma sucinta, a chave é o index de nossos itens
- Para retornar todas as chaves de um hash
capitais.keys
- Agora, todos os valores de um hash
capitais.values
- Remova um elemento chave-valor
capitais.delete(:acre)
- Descubra o tamanho do hash
capitais.size
- Verifique se o Hash está vazio
capitais.empty?
Percorre uma coleção de forma parecida ao for, porém, não sobrescrevendo o valor de variáveis fora da estrutura de repetição.
Em um array:
names = ['Joãozinho', 'Manoel', 'Juca']
name = 'Leonardo Scorza'
names.each do |name|
puts name
end
puts name
Ao executar o programa perceba que não foi alterado o valor da variável name, definida antes da estrutura de repetição.
Em um hash:
aulas = {'Aula 1 ' => 'liberada', 'Aula 2 ' => 'liberada', 'Aula 3 ' => 'liberada', 'Aula 4 ' => 'liberada', 'Aula 5 ' => 'em breve'}
aulas.each do |key, value|
puts "#{key} #{value}"
end
Em cada vez que a estrutura percorre o hash, o elemento atual é representado por key e value.
Cria um array baseando-se em valores de outro array existente.
array = [1, 2, 3, 4]
# \n é uma quebra de linha
puts "\n Executando .map multiplicando cada item por 2"
# .map não altera o conteúdo do array original
new_array = array.map do |a|
a * 2
end
puts "\n Array Original"
puts " #{array}"
puts "\n Novo Array"
puts " #{new_array}"
puts "\n Executando .map! multiplicando cada item por 2"
# .map! força que o conteúdo do array original seja alterado
array.map! do |a|
a * 2
end
puts "\n Array Original"
puts " #{array}"
puts ''
Podemos forçar que o array original seja alterado utilizando map!
Realiza uma seleção de elementos presentes em uma collection através de uma condição pré definida. Traz como resultado somente os valores que passam nesta condição.
Em um array:
array = [1, 2, 3, 4, 5, 6]
selection = array.select do |a|
a >= 4
end
puts selection
A condição para que um item do array seja selecionado é que seu valor seja maior ou igual a 4.
Em um hash:
hash = {0 => 'zero', 1 => 'um', 2 => 'dois', 3 => 'tres'}
puts 'Selecionando keys com valor maior que 0'
selection_key = hash.select do |key, value|
key > 0
end
puts selection_key
Veja que dentro de um Hash podemos fazer uma seleção por chave ou valor.
Alguns links importantes:
- https://ruby-doc.org/core-2.6/Enumerable.html
- https://ruby-doc.org/core-2.6/Enumerable.html#method-i-sort_by
- http://www.rubyinside.com/how-to/ruby-sort-hash
Forma de organizar funções específicas de um programa. Caso necessário permite a reutilização de código.
Como criar?
- Para definir um método utiliza-se a palavra reservada def seguida pelo nome do método. Depois é escrito um conjunto de expressões, e por fim, a palavra end determina o término do método.
- Para executar um método basta apenas escrever o seu nome.
Parâmetros: Um método pode depender de um ou mais parâmetros para realizar determinada tarefa. Definindo um valor padrão ao parâmetro, ele torna-se opcional.
Retorno: O retorno de um método ruby é sempre o resultado de sua última instrução.
Pacote que oferece funcionalidades a fim de resolver uma necessidade específica de um programa Ruby. Pense como o conceito de biblioteca em outras linguagens de programação.
Como instalar uma gem:
gem install [gem_name]
Novas Funcionalidades: No começo do arquivo, o require ‘gem_name’ carrega os arquivos da gem. Isso possibilita a declaração de códigos com funcionalidades da biblioteca.
Desinstalar uma gem:
gem uninstall [gem_name]
Informação: Liste todas as gems instaladas na máquina rodando
gem list
Bundler: Para ter controle sobre as dependências de um projeto contamos com uma ferramenta que procura e instala gems chamada Bundler.
gem install bundler
Salve a lista de gems do projeto em um arquivo chamado Gemfile
source 'https://rubygems.org'
gem 'os'
Na primeira linha é definido onde o bundle deve procurar pelas gems. Depois é listado as dependências do projeto. Instale estas gems com o comando:
bundle install
POO (Programação Orientada a Objetos) é um Paradigma de programação criado para lidar com softwares grandes e complexos.
Sua estrutura é definida por 04 pilares: Abstração, Encapsulamento, Herança e Poliformismo.
Abstração: Ação de abstrair uma entidade do mundo real e transformá-la em uma classe.
Encapsulamento: Ato de dividir um programa em diversas partes tornando-o flexível, fácil de modificar e incluir novas funcionalidades.
Herança: Habilidade de criar uma Classe com características de outra existente. A herança prove o reuso e reaproveitamento de código.
Poliformismo: Capacidade de utilizar um método de diferentes formas para diferentes Objetos.
Objeto
Objeto é toda coisa material que pode ser percebida pelos sentidos, como por exemplo um carro, livro, cachorro, caneta, avião e etc. Na programação um objeto é a representação de um objeto do mundo real. Todos estes objetos apresentam duas característica em comum: informações e comportamentos.
Ex: Cachorro
Informações = attributes
- Raça: Pastor Alemão
- Peso: 35 Quilos
- Idade: 3 Anos
Comportamento = methods
- Late
- Come
- Corre
Classe
Tendo como exemplo o objeto carro, pense em uma classe como a planta deste carro. Com ela é possível construir vários carros. Uma classe é como a planta de um objeto.
Classes no Ruby: definida pela palavra class seguida de seu Nome, e finalizada pela palavra end. O nome de uma classe deve sempre começar com letra maiúscula. Para nomes compostos utilize o padrão CamelCase.
class Computer
def turn_on
puts 'turn on the computer'
end
def shutdown
puts 'shutdown the computer'
end
end
Para herdar características de outra classe, adicione na frente do nome de uma classe filha o símbolo de menor e depois o nome da classe pai.
class ClasseFilha < ClassePai
end
Poder chamar o mesmo método com o mesmo nome e ter comportamentos diferentes.
Se usar a palavra reservada super ela chama o método pai mesmo que você coloque outra instrução dentro do método.
É possível importar arquivos que eu mesma escrevi e não só gems.
Assim vai especificar o arquivo que será procurado require './nomedoarquivo.rb'
Se só existe um arquivo com aquele nome, é possível chamar assim: require_relative 'animal'
Se o aquivo animal estivesse dentro de uma pasta example, ficaria assim: require_relative 'example/animal'
Se o arquivo já faz um require, não precisa fazer de novo no mesmo arquivo.
Variável Local: É declarada com a primeira letra de seu nome sendo uma letra minúscula ou sublinhado. Pode ser acessada apenas onde foi criada. Por exemplo, se você definir uma variável local dentro de de uma classe ela estará disponível apenas dentro desta classe, se a definiu dentro de um método conseguirá acessá-la apenas dentro deste método e assim por diante.
Variável Global: Declarada com o prefixo $. Pode ser acessada em qualquer lugar do programa. Seu uso é FORTEMENTE DESENCORAJADO pois além de ser visível em qualquer lugar do código, também pode ser alterada em inúmeros locais ocasionando dificuldades no rastreamento de bugs.
Variável de Classe: É declarada com o prefixo @@. Pode ser acessada em qualquer lugar da classe onde foi declarada e seu valor é compartilhado entre todas as instâncias de sua classe.
Variável de Instância: Seu nome começa com o símbolo @. Semelhante a variável de classe, tendo como única diferença o valor que não é compartilhado entre todas as instâncias de sua classe.
Também conhecidos como variáveis de instância, em Ruby são sempre privados e começam com @. Não há como alterá-los de fora da classe; apenas os métodos de um objeto podem alterar os seus atributos (encapsulamento!).
O ruby disponibiliza um método chamado attr_accessor que cria os métodos var e var= para todos atributos declarados.
class Dog
attr_accessor :name, :age
end
dog = Dog.new
dog.name = 'Marlon'
puts dog.name
dog.age = '1 ano'
puts dog.age
Podemos fazer com que algum código seja executado na criação de um objeto. Para isso, todo objeto pode ter um método especial, chamado de initialize:
class Pessoa
def initialize
puts "Criando nova Pessoa"
end
end
Pessoa.new
# => "Criando nova Pessoa"
Os initializers são métodos privados (não podem ser chamados de fora da classe) e podem receber parâmetros.
class Pessoa
def initialize(nome)
@nome = nome
end
end
joao = Pessoa.new("João")
Métodos acessores e modificadores são muito comuns e dão a ideia de propriedades.
O número de parâmetros utilizados no método initialize é opcional.
Um bloco pode ser entendido como uma função anônima = função sem nome. Definido entre do..end ou colchetes e pode receber parâmetros para sua execução.
5.times { puts "Exec the block" }
sum = 0
numbers = [5, 10, 5]
numbers.each {|number| sum += number }
puts sum
foo = {2 => 3, 4 => 5}
foo.each do |key, value|
puts "key = #{key}"
puts "value = #{value}"
puts "key * value = #{key * value}"
puts '---'
end
def foo
# Call the block
yield
yield
end
foo { puts "Exec the block"}
Quando você adiciona o yield ele automaticamente já sabe que deve chamar um bloco que foi declarado como parâmetro.
O ruby oferece um método chamado block_given? para verificar se o bloco foi passado como argumento
def foo
if block_given?
# Call the block
yield
else
puts "Sem parâmetro do tipo bloco"
end
end
foo
foo { puts "Com parâmetro do tipo bloco"}
A saída do programa será:
Sem parâmetro do tipo bloco
Com parâmetro do tipo bloco
Outra forma de receber blocos como parâmetro é utilizar o símbolo &. Para executar um bloco recebido desta forma é necessário apenas utilizar o nome do bloco acompanhado pelo método call. Outra dica importante é sempre deixar o &nome_do_bloco como último parâmetro a ser recebido pelo método.
def foo(name, &block)
@name = name
block.call
end
foo('Leonardo') { puts "Hellow #{@name}" }
def foo(numbers, &block)
if block_given?
numbers.each do |key, value|
block.call(key, value)
end
end
end
numbers = { 2 => 2, 3 => 3, 4 => 4 }
foo(numbers) do |key, value|
puts "#{key} * #{value} = #{key * value}"
puts "#{key} + #{value} = #{key + value}"
puts "---"
end
São similares aos blocks, mas podem ser salvas em variáveis para serem reutilizadas. É uma versão especial de um bloco. Ela pode ser guardada em uma variável para ser chamada futuramente com o método call.
first_lambda = lambda { puts "my first lambda"}
first_lambda.call
também funciona com o -> no lugar da palavra lambda
first_lambda = -> { puts "my first lambda"}
first_lambda.call
também pode ter vários parâmetros para a execução
first_lambda = -> (names){ names.each { |name |puts name} }
names = ["joão", "maria", "pedro"]
first_lambda.call(names)
lambdas que ocupam várias linhas, não declare a lambda de forma abreviada e utilize o do..end
my_lambda = lambda do |numbers|
index = 0
puts 'Número atual + Próximo número'
numbers.each do |number|
return if numbers[index] == numbers.last
puts "(#{numbers[index]}) + (#{numbers[index + 1]})"
puts numbers[index] + numbers[index + 1]
index += 1
end
end
numbers = [1, 2, 3, 4]
my_lambda.call(numbers)
você pode passar mais de uma lambda como argumentos de um método.
def foo(first_lambda, second_lambda)
first_lambda.call
second_lambda.call
end
first_lambda = lambda { puts "my first lambda"}
second_lambda = lambda { puts "my second lambda"}
foo(first_lambda, second_lambda)
Possuem duas funções:
- namespace: serve como container para agrupar objetos relacionados (classes, constantes, métodos ou outros modules)
- mixins: serve para incluir funcionalidades extras nas classes.
Namespace:
module ReverseWorld
def self.puts text
print text.reverse.to_s
end
end
ReverseWorld::puts 'O resultado é'
puts 'O resultado é'
Mixins:
module ImpressaoDecorada
def imprimir text
decoracao = '#' * 100
puts decoracao
puts text
puts decoracao
end
end
module Pernas
include ImpressaoDecorada
def chute_frontal
imprimir 'Chute Frontal'
end
def chute_lateral
imprimir 'Chute Lateral'
end
end
module Bracos
include ImpressaoDecorada
def jab_de_direita
imprimir 'Jab de direita'
end
def jab_de_esquerda
imprimir 'Jab de esquerda'
end
def gancho
imprimir 'Gancho'
end
end
class LutadorX
include Pernas
include Bracos
end
class LutadorY
include Pernas
end
lutadorx = LutadorX.new
lutadorx.chute_frontal
lutadorx.jab_de_direita
lutadory = LutadorY.new
lutadory.chute_lateral
Um pedaço de código que pode ser executado e passado como parâmetro para outros métodos.
hello_proc = Proc.new do
puts "Hello World"
end
hello_proc.call
podemos ainda usar "proc" ao invés de "proc.new"
hello_proc = proc do
puts "Hello World"
end
hello_proc.call
hello_lambda = lambda {}
hello_proc = proc {}
hello_proc.class #=> Proc
hello_lambda.class #=> Proc
hello_proc = proc do |msg|
puts msg
end
hello_proc.call
A saída é uma linha vazia, pois o parâmetro “msg” não foi passado. Assim, podemos ver que procs automaticamente atribuem “nil” para variáves cujo valor não tenha sido definido.
hello_lambda = lambda do |msg|
puts msg
end
hello_lambda.call
Aqui ele lançará uma exceção “ArgumentError: wrong number of arguments (0 for 1)”! Ou seja, os argumentos são necessários para a execução de um lambda. No entanto, podemos contornar esse problema utilizando valores default para o lambda.
hello_lambda = lambda do |msg = nil|
puts msg
end
hello_lambda.call
Outra grande diferença está em como o “return” é tratado. O “return” em um lambda retorna o fluxo de execução para o método onde o lambda foi chamado.
hello_lambda = lambda do |msg|
return msg
end
def run_hello_block(block)
puts "Preparando para executar lambda..."
puts "Lambda em execução: #{block.call("Hello World")}"
return "Lambda executado com sucesso!"
end
puts run_hello_block(hello_lambda)
Tudo funciona como esperado e todas as mensagens são exibidas. No entanto, o mesmo pedaço de código, agora utilizando proc, tem um resultado bem diferente:
hello_proc = proc do |msg|
return msg
end
def run_hello_block(block)
puts "Preparando para executar proc..."
puts "Proc em execução: #{block.call("Hello World")}"
return "Proc executado com sucesso!"
end
puts run_hello_block(hello_proc)
Ao tentar executar este código veremos uma exceção “LocalJumpError: unexpected return”. Esta exceção é lançada quando tentamos executar um return dentro de um argumento, exceto quando o argumento é um lambda.
Uma maneira de resolver o problema seria definir o proc dentro do método, assim ele não seria mais um parâmetro e poderia retornar algo:
def run_hello_block
hello_proc = proc do |msg|
return msg
end
puts "Preparando para executar proc..."
puts "Proc em execução: #{hello_proc.call("Hello World")}"
return "Proc executado com sucesso!"
end
puts run_hello_block
Referência: https://brizeno.wordpress.com/2013/10/30/conceitos-na-pratica-ruby-procs/
Abreviatura de Regular Expressions (Expressões Regulares), regex é uma sequência de caracteres especiais que nos ajudam a identificar (e selecionar) padrões de caracteres em strings.
3 maneiras de criar um regex
- utilizando o formato /.../ sendo a mais comum
/expressao/
- através do formato %r{...}
%r{expressao}
- utilizando um construtor através do Regex.new('...')
Regex.new('expressao')
Casamento de padrões: é um ato que verifica a presença de padrões em uma cadeia de caracteres. Pode ser realizado através do operador =~ ou do método match.
- O operador =~ retorna o offset, ou seja, a distância entre o começo da string até o local onde ocorre o casamento de padrão especificado na expressão.
- A mesma comparação pode ser realizada iniciando pela string.
- Quando não ocorre o casamento de padrão, o resultado é nulo.
- Retorna um objeto do tipo MatchData, contendo todos os resultados do casamento de padrão.
- Em um objeto do tipo MatchData você pode, por exemplo, acessar o que vem antes do casamento através do método pre_match
- Ou acessar o que vem depois do casamento com post_match
Os símbolos (, ), [, ], {, }, ., ?, +, *, são metacharacters. Eles possuem um significado quando utilizados em expressões regulares. Caso o padrão que você procura seja um metacharacter, utilize o símbolo de escape \ para realizar a busca.
Character Classes: É uma lista que informa quais caracteres devem aparecer em um ponto do casamento.
- Uma character class é delimitada por colchetes [, ]
- Você pode especificar um range com o símbolo –
- O range pode ser utilizado para letras
- Existem alguns metacharacters que se comportam como character classes, exemplo, o metacharacter \d verifica o padrão [0-9].
Repetition: É possível definir a repetição de um mesmo padrão, evitando escrever a mesma coisa diversas vezes.
- Ao em vez de digitar \d\d\d você pode escrever \d{3}
- A vírgula em {3, } informa que a repetição pode ocorrer 3 ou mais vezes
É um método nativo para funções matemáticas.
- Raiz quadrada de 64:
Math.sqrt(64)
- Logaritmo de 10000 na base 10:
Math.log10(10000)
- Logaritmo de 16 na base 2:
Math.log2(16)
- Calculando o cosseno para o ângulo de 30º
- Primeiro transforme o ângulo em um valor radiano:
radian = 30 * (Math::PI / 180)
- Depois utilize o método cos:
Math.cos(radian)
- Primeiro transforme o ângulo em um valor radiano:
- Para consultar o valor da constante E execute:
Math::E
- Consulte o valor da constante PI com a instrução:
Math::PI
O Ruby conta com uma classe chamada Time para representar datas e horas.
- Para imprimir o horário atual execute:
time = Time.now
puts time
- Para o ano, year:
puts time.year
- Para o mês:
puts time.month
- Para o dia:
puts time.day
- O método strftime permite a formatação de uma data em uma forma específica. Essa formatação é feita por diretivas que começam com o símbolo de %.
time.strftime('%d/%m/%y')
Significado das diretivas:
- %d -> Dia do mês
- %m -> Mês do ano
- %y -> Ano
- Verificando se o dia da semana é sábado:
puts time.saturday?
- Você também pode comparar duas datas.
- Crie um novo objeto com o horário atual:
time2 = Time.now
- Ao comparar as datas de forma completa o resultado será false:
time == time2 # => false
- Comparando o ano das duas datas, o resultado será true:
time.year == time2.year # => true
- Crie um novo objeto com o horário atual:
Ele é utilizado para interceptar chamadas a métodos que não existem. Quando um método que não existe é chamado, o método method_missing faz uma interceptação.
No ruby, self é uma variável especial que aponta para o objeto atual. A variável self não precisa ser declarada. Ela é disponível em qualquer lugar, mas não esqueça que seu valor é referente ao objeto que pertence. Variáveis self em objetos diferentes possuem valores diferentes. Com o self é possível criar métodos de classe, que não precisam de uma instância para serem chamados. Você também pode utilizá-lo para se referir a atributos do objeto atual.
Por padrão, todos os métodos definidos são públicos. Isso significa que eles podem ser acessados por qualquer um.
Mas além dos métodos públicos, existem outros dois tipos de métodos chamados private e protected.
Private: Método interno de uma classe. Apenas os métodos públicos dessa classe ou de classes descendentes podem chamá-lo. O self é o único receptor de um método private
Protected: A diferença entre ele e o private, é que o método protected pode ter como receptor qualquer instância de sua classe.
Através de poucas instruções, é possível ler o conteúdo, ou então, escrever algumas informações dentro de um arquivo externo. Isso é feito por meio de uma classe chamada File, a qual conta com diversas opções para manipulação de arquivos.
Leitura de arquivo: método open da classe File para acessar o arquivo list.txt. Depois o método each para percorrer e exibir o conteúdo do arquivo.
Escrita de arquivo: Para adicionar conteúdo sem sobrescrever o que já existe , foi necessário passar o argumento ‘a’. Este argumento significa append, ou seja, acrescentar conteúdo. Perceba que o método puts e print tem o mesmo significado do que em outros exemplos deste curso. Os dois inserem valores ao arquivo, com a diferença de que apenas o puts insere uma nova linha após a string.
Caso queira saber o tamanho do arquivo: O método size retorna o tamanho do arquivo em bytes.
File.open('shopping-list.txt').size
Para substituir o conteúdo desse arquivo utilize o argumento ‘w’ no lugar do 'a', de write.
Para isso o ruby conta com uma biblioteca chamada Net::HTTP que é capaz de realizar chamadas web.
require 'net/http'
example = Net::HTTP.get('example.com', '/index.html')
File.open('example.html', 'w') do |line|
line.puts(example)
end
O que aconteceu?
- No início, é preciso adicionar a biblioteca Net::HTTP
- Depois é feito uma requisição HTTP do tipo GET para o domínio example.com, com o caminho /index.html.
- É a mesma coisa que entrar no browser e procurar pelo endereço http://example.com/index.html
- Você salvou a resposta dentro de uma variável para depois escrevê-la dentro de um arquivo.
- Quando você utilizou File.open para um arquivo inexistente, o ruby detectou isso e criou o arquivo antes de escrever as informações nele.
Para fazer as próximas requisições você utilizará o site https://reqres.in Ele está preparado para receber e responder suas requisições, o que facilitará os testes de requisições https.
require 'net/http'
https = Net::HTTP.new('reqres.in', 443)
# para fazer chamadas https
https.use_ssl = true
response = https.get("/api/users")
# status code
puts response.code
# status message
puts response.message
# body (json)
puts response.body
O que aconteceu?
- Você construiu um objeto Net::HTTP iniciando com os valores de domínio e porta
- Você informou que é uma requisição que utiliza o certificado ssl com o método
use_ssl = true
- Fez um GET para o caminho api/users
- Por fim exibiu o código da resposta, o status e o corpo da resposta
require 'net/http'
req = Net::HTTP::Post.new("/api/users")
# para fazer chamadas https
req.set_form_data({ name:'Mario', job:'Encanador' })
response = Net::HTTP.start('reqres.in', use_ssl: true) do |http|
http.request(req)
end
puts response.code
puts response.body
O que aconteceu?
- Você inicializou um objeto
Net::HTTP::Post.new()
passando como argumento o caminho da url - Depois informou quais são os parâmetros a serem enviados com o método
set_form_data
- Por fim utilizou o método start para criar uma conexão com o servidor e dentro de um bloco fez a requisição POST
O Web Scraping existe para evitar essas tarefas manuais, ou então, trabalhosas. Uma técnica que automatiza o processo de extração de dados de uma página web.
Uma das bibliotecas mais utilizadas no mundo ruby para fazer isso é a nokogiri
require 'nokogiri'
require 'net/http'
https = Net::HTTP.new('onebitcode.com', 443)
# para fazer chamadas https
https.use_ssl = true
response = https.get("/")
doc = Nokogiri::HTML(response.body)
h1 = doc.at('h1')
puts h1.content
O que aconteceu?
- No começo nenhuma novidade. Você realizou uma requisição para o site do onebitcode
- Depois utilizou Nokogiri::HTML para parsear o documento HTML
- Por fim, você fez uso do método at para buscar a tag h1 e imprimir o seu conteúdo.
O último post do onebitcode encontra-se dentro das tags <h3><a href=’/ultimo-post’>Título Ultimo Post</a></h3>. Para buscar este post faça:
last_post = doc.at('h3 a')
puts last_post.content
puts last_post['href']
Você também pode procurar por todos os posts que estão na página inicial do onebitcode com o método search
doc.search('h3 a').each do |a|
puts a.content
puts a['href']
puts ''
end