-
-
Save reginadiana/a454ef891b19d00d519995646e2f34f9 to your computer and use it in GitHub Desktop.
string.bytesize # retorna o número de bits
Ao declarar uma variável com a primeira letra maiúscula, ela torna-se uma constante. Por convenção, uma constante deve estar inteira maiuscula e uma classe deve estar em CamelCase.
Podemos usar o splat operator para obter o restante de uma lista:
lista = ['pizza', 'alface', 'refrigerante']
alimentos, outros_alimentos = lista
alimentos # pizza
outros_alimentos # ['alface', 'refrigerante']
Declarando array de strings:
array = %w{a b c d} # ['a', 'b', 'c', 'd']
Para fazer operações com arrays, temos
a + b # soma o conteúdo de a com b
a | b # soma o conteúdo de a com b, eliminando elementos duplicados
a & b # soma o conteúdo de a com b, deixando apenas os elementos duplicados
Temos também metodos de objetos que podemos acessar:
lista.reverse # retorna a lista contendo os elementos em ordem invertida
lista.join('e') # retorna uma string com cada elemento separado pelo 'e'
lista.compact # retorna a lista sem nil, se houver
lista.sort # retorna a lista de forma ordenada e vale para strings
lista.uniq # retorna a lista sem elementos duplicados
lista.flatten # retorna uma unica lista com todos os elementos, mesmo que tenhamos uma lista dentro de outra lista
lista.pop # retorna o ultimo elemento
lista.shift # retorna o primeiro elemento
📝 Podemos usar bang (!) para persistir a mudança dos metodos acima ou disparar uma exceção caso eles falharem. Exemplo ao buscar um post inesistente:
Post.find_by_title # retorna nil
Post.find_by_title # retorna ActiveError::RecordNotFound
📝 Metodos com # indicam que são usados para instancias e :: para metodos de classe
Pra quem conhece python, podemos fazer uma associação com dicionários. Podemos criar hashs de 3 formas:
frequency = { "hello" => 1, "world" => 2, 1 => 10 }
frequency = { :hello => 1, :world => 2 } # usando símbolos como chaves
frequency = { hello: 1, world: 2 }
Podemos acessar alguns métodos como:
frequency.keys # ["hello", "world"]
frequency.values # [1, 2]
frenquency.has_key?("hello") # true
frequency.has_value?(3) # false
Acessando hashs
hash['key']
Agora, vamos supor que estamos recolhendo dados de uma API e nem sempre os dados estão presentes. Para não ficar toda hora checando se um dado é nil, podemos usar o que o Rails chama de Menção Honrosa, assim nosso código fica mais limpo. Exemplos:
user = user_data.fetch('age', 'not found')
user.born # retorna 'not found'
Outro problema também, é que o Ruby não acusa o nil como uma falha, mas a presença dele pode acarretar em um erro em um passo seguinte do código, ficando dificil de detectar aonde exatamente está o bug. Portanto, podemos usar o #fatch sem fallback, disparando uma exceção KeyError quando a chave não existir:
user_data.fetch('address') # KeyError: key not found: "address"
📝 Garbage Collector é um mecanismo usado pelo interpretador Ruby para detectar os recursos que estamos usando ou não a fim de liberar espaço de memória quando necessário.
"palavra".respond_to? :upcase # retorna true, pois a string é upcase
Símbolos devem ser usados quando estamos descrevendo o tipo do dado Strings devem ser usadas quando a chave é um valor
Convertendo strings em simbolos e vice-versa:
"string".to_sym # retorna :string
:simbolo.to_s # retorna 'simbolo'
'a'..'e' # Letras entre 'a' e 'e'
'a'...'e' # Letras entre 'a' e 'd', o 'e' fica de fora
valid_years.include? 1998 # retorna true pois 1998 está dentro de valid_years
📝 Todo bloco de código ruby retorna alguma coisa 📝 É sempre bom fazer trechos curtos de código
&& Se a expressão da esquerda for falsa, a expressão da direita não vai ser avaliada Se a expressão da esquerda for verdadeira, a expressão da diretira será avaliada Exemplo:
mkdir pasta && cd pasta # Cria pasta e entra nela
Se existisse, tomariamos um erro pois a pasta já foi criada.
O resultado de "mkdir pasta" é verdadeiro se a pasta for criada e falso se ela já existir
|| Se a expressão da esquerda for falsa, a expressão da direita vai ser avaliada Se a expressão da esquerda for verdadeira, a expressão da diretira não será avaliada Exemplo:
mkdir pasta || cd pasta # Somente cria a pasta
Se a pasta já existir, tomariamos um erro disendo que a pasta já existe mas entrariamos nela mesmo assim.
Devido a confusão na hora de interpretar e ler essas lógicas, é uma boa prática usar as operações que envolvam && e || em parenteses.
Se um valor é verdadeiro, o if é executado, se falso, não. No ruby, apenas false e nil são falsos, todos os outros tipos são verdadeiros, mesmo que sejam "0" ou "" (string vazia).
O bloco associado a ele é executado se a expressão retornar false. É recomendado usar quando o if estiver sozinho. Se for usar else, use logo o if..else.
Eles enxutanm a lógica if..else mas devem ser usados em pequenas linhas de código para não prejudicar a legibilidade.
condição ? o que fazer se for verdade : o que fazer se for falso
Em algumas linguagens como C e JavaScript, quando uma condição é verdadeira, todos os cases abaixo são executados. Por esse motivo, usamos break no final de cada um. O ruby não posui esse comportamento
É usado em blocos para executar algo enquanto uma condição estiver satisfeita.
Exemplo: lista.lenght > 0
# algo será executado enquanto a lista for maior que zero
É usado para executar uma condição até que a condição for satisfeita.
Exemplo: lista.empty?
# algo será executado até que a lista esteja vazia.
Assim como no python, também conseguimos usar o for..in em ruby.
Exemplo com hash:
frequencies = {'hello' => 10, 'world' => 20}
for key, value in frequencies
puts "A frequência da palavra '#{key}' é #{value}"
end
Podemos usar maps, each, etc tanto em uma unica linha como usando do..end. Sobre esse uso, a comunidade adotou:
Para blocos curtos, de apenas uma linha, adota-se as chaves; Para blocos longos, de duas ou mais linhas, adota-se o do ... end
Outra sacada dos loops é essa:
a = {:a => 1, :b => 2, :c => 3}
a.each do |_, value| # '_' substitui o que seria 'key'
puts value
end
Para acessar os valores do hash precisamos de dois parametros dentro de 'do', mas como não vamos usar as keys, não precisamos declarar uma variável que nao vamos usar. Ao inves disso, podemos usar o _ no lugar dela
break para um loop next devido alguma condição, passa para a próxima interação. Exemplo:
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.each do |number|
next if number.odd?
puts number
end # 2; 4; 6; 8; 10
É possível omitir os parênteses de funções que levam parametros:
def print_text text, more_text
puts text + more_text
end
Usar return quando precisamos retornar algo que não esteja referenciado como ultimo retorno do bloco.
Usando o alias, não precisamos chamar a função exatamente com o nome dela. Pode ser util na legibilidade de código. Exemplo:
def factorial(n)
return 1 if n == 1
n * factorial(n-1)
end
alias fac factorial
fac(5) # 120
Podemos criar métodos que aceitam um número variado de argumen-tos. Conseguimos isso através do uso do operador splat:
def sum(*values)
puts values.inspect
values.reduce { |sum, value| sum + value }
end
sum(1) # [1]; 1
sum(1, 1) # [1,1]; 2
sum(1, 2, 3, 4, 10) # [1, 2, 3, 4, 10]; 20
É possível destacar alguns parâmetros caso isso seja interessante:
def sum(first, *values)
A variável RAILS_ENV é usada para armazenar o ambiente de desenvolvimento e conseguimos rodar comandos em ambientes especificos. Exemplo: RAILS_ENV=production rake db:create
Migrations registram as modificações que o banco vai sofrendo ao longo do tempo. O metodo up é usado quando o banco evolui a sua versão e down quando regride.
- Use apenas dependencias necessárias.
- Exceto os testes de integração, os testes podem e devem ser isolados. Para fazer isso, não carregue/escreva muitas linhas de código nos controllers.
- Evite depender do Rails para rodar os seus testes. Fazemos isso ao carregar o arquivo spec_helper.rb. Caso precise, prefira criar um arquivo que irá chamar somente as dependencias que voce precisa.
- Acredito que a regra geal é pare de usar coisas que voce não precisa.
def identify_class(obj)
className = obj.class.to_s # Pega o nome da classe do objeto e converte em string
classResult = {
'Hacker' => "It's a Hacker!",
'Submission' => "It's a Submission!",
'TestCase' => "It's a TestCase!",
'Contest' => "It's a Contest!"
}
puts classResult[className] || "It's an unknown model" # Consegue devolver o conteúdo quando a chave existe, se não mostra um valor diferente, que seria o caso do else ou default
end
Vai criar um arquivo temporário com nome unico. É necessário tomar cuidado para que esses arquivos não se acumulem, gerando acumo no arquivos no filesystem. Para usar esse recurso não é necessário nenhuma gem, pois é nativo do ruby.
Se não for provido o parametro content type o active storage não vai poder determinar o tipo do arquivo automaticamente, então ele irá atribuir o valor application/octer-stream
O active cria tabelas em sua migration:
-
Armazena informações do arquivo.
-
Armazena informações sobre o model que armazenará esse arquivo (que fará o attach). Ex: Tabela de usuários, onde cada um terá um avatar.
O arquivo storage.yml é usado para informar ao active onde ele vai armazenar os arquivos.
Podemos usar o método purge
para deletar o attach. Ex:
@bucket.file.find(params[:id]).purge
Também temos o método purge_later
para excluir arquivos grandes.
Serviços de armazenamento de imagem: AWS S3, Google Cloud Storage, Microsoft Azure Storage.
Podemos usar a gem Image Magic para redimensionar as imagens.
config.active_storage.service
determinal qual serviço vamos utilizar e este precisa estar definido em storage.yml
Mirror service serve para realizar cópidas entre serviços.
É um servidor object storage 100% compátivel com o protocolo S3 da AWS.
Precisamos configurar o nosso storage para fazer um upload para algum serviço de cloud. É necessário mudar as configurações de CORS na AWS para permitir o upload feito pelo nosso dominio.
Serve para fazermos upload dos arquivos de forma assincrona.
Na view, use:
<%= form_tag(children_path, :method =>:get) do %>
<%= text_field_tag 'search', nil, placeholder: 'Enter search term ...' %>
<%= submit_tag 'Search' %>
<% end %>
Vamos usar o metodo get para capturar os dados preenchidos no campo após submeter os dados clicando no botão 'Search'. Os dados serão enviados para a rota children_path. Exemplo: http://localhost:3000/children?search=lu&commit=Search
Veja que search é a chave e 'lu' foi o conteúdo submetido.
No controller, use:
def index
return result_search unless params[:search] == ''
@children = Child.all
end
def result_search
@children = Child.search(params[:search])
end
Basicamente, estamos dizendo que a menos que a pesquisa seja nula, vamos mostrar o resultado dela. Se nada for preenchido no campo, todos os dados serão mostrados.
No model, trataremos a regra de negocio, que no caso, seria a pesquisa de fato:
Aqui existem duas opções:
Usando metodo de classe:
# Criando um método de classe
def self.search(query)
where("name like ?", "%#{query}%")
end
Usando scope, podemos encadear pesquisas futuramente:
# Usando scope
scope :search, ->(query) { where("name like ?", "%#{query}%") }
Basicamente, estamos dizendo: onde o nome for algo como o conteúdo da query ... retorne os dados
Temos um model chamado Child que tem possui como parametros o nome e sexo, mas queremos adicionar alguns campos referentes ao seu endereço. Para isso, ao invés de simplesmente adcionar outros campos vamos associar com outra tabela chamada Address, que receberá como parametro os itens street e zip.
Vamos começar pelo terminal criando esse novo model:
rails g model Address street zip child:references
Estamos pedindo que o Rails gere o model Adress com os parametros street e zip como strings e associando ao model Child. No seu model, teremos:
class Address < ApplicationRecord
belongs_to :child
end
Aqui, estamos dizendo: Address belongs to Child (Endereço pertence ao Filho). Já o model de Child, teremos:
class Child < ApplicationRecord
has_one :address
# Vai aceitar os atributos de address
accepts_nested_attributes_for :address
end
Estamos dizendo que Child has one Address (Filho tem um endereço) e que aceita os atributos do model Adress.
No controller de Child, além de permitir os parametros name e sex, teremos também os atributos para o endereço:
# Only allow a list of trusted parameters through.
def child_params
params.require(:child).permit(:name, :sex, :address_attributes => [:street, :zip])
end
Ao criar um novo Child, temos:
def new
@child = Child.new
@child.build_address
end