---
# System prepended metadata

title: Mini Curso

---

# Mini Curso Ruby & Ruby on Rails

## Guia de Ruby

Este guia fornece uma visão geral dos conceitos fundamentais de Ruby, incluindo lógica booleana, tipos de dados, manipulação de strings, estruturas de controle, funções, variáveis, estruturas de dados, tratamento de erros e exceções, e uma introdução à orientação a objetos.

### Índice

1. [Lógica Booleana](#lógica-booleana)
2. [Variáveis e Tipos de Dados Primitivos](#variáveis-e-tipos-de-dados-primitivos)
3. [Strings e Manipulação de Texto](#strings-e-manipulação-de-texto)
4. [Conversão entre Tipos de Dados](#conversão-entre-tipos-de-dados)
5. [Operadores](#operadores)
6. [Estruturas de Controle](#estruturas-de-controle)
7. [Funções](#funções)
8. [Escopo de Variáveis](#escopo-de-variáveis)
9. [Estruturas de Dados Básicas](#estruturas-de-dados-básicas)
10. [Tratamento de Erros e Exceções](#tratamento-de-erros-e-exceções)
11. [Orientação a Objetos](#orientação-a-objetos)

### Lógica Booleana

Em Ruby, a lógica booleana é usada para realizar operações que retornam `true` ou `false`.

```ruby
# Exemplos de lógica booleana
verdadeiro = true
falso = false

puts verdadeiro && falso  # AND lógico, retorna false
puts verdadeiro || falso  # OR lógico, retorna true
puts !verdadeiro         # NOT lógico, retorna false
```

### Variáveis e Tipos de Dados Primitivos

Ruby é uma linguagem dinamicamente tipada, o que significa que você não precisa declarar o tipo de uma variável ao criá-la.

```ruby
# Inteiros
inteiro = 10

# Ponto flutuante
ponto_flutuante = 10.5

# Booleanos
booleano = true

# Strings
texto = "Olá, mundo!"

# Símbolos (um tipo especial de string imutável)
simbolo = :meu_simbolo
```

### Strings e Manipulação de Texto

Ruby fornece uma ampla gama de métodos para manipulação de strings.

```ruby
texto = "Ruby é incrível!"

puts texto.upcase   # Converte para maiúsculas
puts texto.downcase # Converte para minúsculas
puts texto.reverse  # Inverte a string
puts texto.length   # Retorna o comprimento da string
```

### Conversão entre Tipos de Dados

Você pode converter entre diferentes tipos de dados em Ruby.

```ruby
numero = "10".to_i    # Converte string para inteiro
texto = 10.to_s       # Converte inteiro para string
ponto_flutuante = "10.5".to_f  # Converte string para ponto flutuante
```

### Operadores

#### Aritméticos

```ruby
# Adição
puts 1 + 1  # Resultado: 2

# Subtração
puts 2 - 1  # Resultado: 1

# Multiplicação
puts 2 * 3  # Resultado: 6

# Divisão
puts 6 / 2  # Resultado: 3

# Módulo (resto da divisão)
puts 5 % 2  # Resultado: 1

# Exponenciação
puts 2 ** 3 # Resultado: 8
```

#### Relacionais

```ruby
puts 1 == 1  # Igualdade, resultado: true
puts 1 != 2  # Desigualdade, resultado: true
puts 2 > 1   # Maior que, resultado: true
puts 1 < 2   # Menor que, resultado: true
puts 2 >= 2  # Maior ou igual a, resultado: true
puts 1 <= 2  # Menor ou igual a, resultado: true
```

#### Lógicos

```ruby
puts true && false  # AND lógico, resultado: false
puts true || false  # OR lógico, resultado: true
puts !true          # NOT lógico, resultado: false
```

#### Bit a bit

```ruby
puts 3 & 1  # AND bit a bit, resultado: 1
puts 3 | 1  # OR bit a bit, resultado: 3
puts 3 ^ 1  # XOR bit a bit, resultado: 2
puts ~3     # NOT bit a bit, resultado: -4 (complemento de dois)
puts 3 << 1 # Deslocamento para a esquerda, resultado: 6
puts 3 >> 1 # Deslocamento para a direita, resultado: 1
```

### Estruturas de Controle

#### Loops

```ruby
# Loop for
for i in 0..5
  puts i
end

# Loop while
contador = 0
while contador < 5 do
  puts contador
  contador += 1
end

# Loop do-while
begin
  puts contador
  contador -= 1
end while contador > 0

# Loop each
(0..5).each do |i|
  puts i
end

# Loop map
resultados = [1, 2, 3].map do |numero|
  numero * 2
end
puts resultados  # [2, 4, 6]
```

#### Condições

```ruby
numero = 10

if numero > 5
  puts "Número é maior que 5"
elsif numero == 5
  puts "Número é igual a 5"
else
  puts "Número é menor que 5"
end

# Operador ternário
resultado = numero > 5 ? "Maior que 5" : "Menor ou igual a 5"
puts resultado
```

### Funções

```ruby
def saudacao(nome)
  return "Olá, #{nome}!"
end

puts saudacao("Mundo")  # "Olá, Mundo!"
```

### Escopo de Variáveis

```ruby
# Variável local
variavel_local = "Eu sou local"

# Variável de instância
@variavel_instancia = "Eu sou uma variável de instância"

# Variável de classe
@@variavel_classe = "Eu sou uma variável de classe"

# Variável global
$variavel_global = "Eu sou global"
```

### Estruturas de Dados Básicas

#### Arrays/Listas

```ruby
lista = [

1, 2, 3, 4, 5]

puts lista[0]  # Acesso ao elemento
lista.push(6)  # Adiciona ao final
lista.pop      # Remove do final
lista.shift    # Remove do início
lista.unshift(0)  # Adiciona ao início
```

#### Dicionários/Hashes

```ruby
dicionario = { "chave1" => "valor1", "chave2" => "valor2" }

puts dicionario["chave1"]  # Acesso ao valor
dicionario["chave3"] = "valor3"  # Adiciona novo par chave-valor
dicionario.delete("chave2")  # Remove par chave-valor
```

### Tratamento de Erros e Exceções

```ruby
begin
  # Código que pode causar uma exceção
  resultado = 10 / 0
rescue ZeroDivisionError => e
  puts "Erro: #{e.message}"
ensure
  puts "Este código sempre será executado"
end
```

### Orientação a Objetos

```ruby
class Pessoa
  attr_accessor :nome

  def initialize(nome)
    @nome = nome
  end

  def falar
    puts "Olá, meu nome é #{@nome}"
  end
end

pessoa = Pessoa.new("João")
pessoa.falar  # "Olá, meu nome é João"
```

---

## Lista de Conteúdos e Matérias a Estudar

- **Paradigma de Linguagem de Programação**: Estude sobre programação imperativa, declarativa, funcional, e orientada a objetos.
- **Arquitetura de Computadores**: Entenda como a memória RAM, CPU, HD/SSD funcionam, além de conceitos como Threads, Processos, MultiCore, e MultiThreads.
- **io bound e cpu bound**: Aprenda a diferença entre operações limitadas pela CPU e operações limitadas pela entrada/saída.
- **JIT vs Compilador**: Estude sobre Just-In-Time Compilation e como ele se compara à compilação tradicional.
- **Diferença de Sintaxe**: Compare a sintaxe e características de Java, Ruby, Python, e C.
- **Networking (Redes)**: Aprofunde-se em conceitos de redes de computadores.
- **HTTP vs HTTPS**: Entenda o protocolo HTTP e a importância da camada de segurança em HTTPS.
- **Como funciona o protocolo HTTP**: Estude o funcionamento detalhado do protocolo HTTP.
- **Status Code HTTP**: Conheça os diferentes status codes HTTP e seus significados.
- **Tudo é Binário**: Aprenda como a informação é representada e transmitida em forma binária.
- **GitFlow**: Estude essa metodologia de trabalho com Git.
- **Git e GitHub**: Aprenda a usar essas ferramentas essenciais para controle de versão e colaboração em projetos de software.
- **Programação Assíncrona e Funcional**: Explore esses paradigmas de programação.
- **Inteligência Artificial Generativa**: Introduza-se aos conceitos de IA generativa.
- **SCRUM e seus Eventos**: Aprenda sobre essa metodologia ágil e seus eventos.
- **SSO (Single Sign-On)**: Entenda como funciona a integração de SSO.
- **LDAP (Lightweight Directory Access Protocol)**: Estude esse protocolo para acesso a serviços de diretório.
- **POC (Proof of Concept)**: Aprenda o que é uma POC e como ela é utilizada para validar ideias.
- **RFC (Request for Comments)**: Entenda o que é um RFC e como ele é usado para documentar especificações e políticas.

Para um guia mais detalhado e específico, você pode consultar o [Backend Developer Roadmap](https://roadmap.sh/backend).


# Requisitos para codificar o Ruby

### Título: Geração e Envio de Relatório Meteorológico

### História do Usuário
Como um usuário interessado em condições climáticas,  
Eu quero inserir o nome de uma cidade e receber um relatório meteorológico dos últimos 8 dias,  
Para que eu possa analisar as tendências climáticas e planejar minhas atividades de acordo.

### Critérios de Aceitação
1. **Entrada do Usuário**: 
   - O sistema deve solicitar ao usuário para inserir o nome de uma cidade.
   - A entrada do usuário deve ser capturada e utilizada para buscar os dados meteorológicos.

2. **Busca de Dados Meteorológicos**: 
   - O sistema deve utilizar a API do OpenWeather para buscar os dados meteorológicos dos últimos 8 dias para a cidade inserida.
   - A chave de API para acessar o OpenWeather deve ser armazenada de forma segura e acessada via variáveis de ambiente.

3. **Geração de Relatório CSV**: 
   - O sistema deve gerar um arquivo CSV contendo a data, temperatura (em Celsius) e descrição do clima para cada um dos 8 dias.
   - O arquivo CSV deve ser nomeado com base no nome da cidade e armazenado no diretório atual.

4. **Envio de E-mail Fake**: 
   - Após a geração do relatório CSV, o sistema deve enviar um e-mail fake para o usuário, informando que o relatório foi gerado com sucesso.
   - O e-mail deve ser visualizável localmente para fins de teste e desenvolvimento, utilizando a gem Letter Opener.

5. **Feedback ao Usuário**: 
   - O sistema deve informar ao usuário no terminal quando todas as operações estiverem concluídas.
   - Deve ser fornecido ao usuário o caminho para o arquivo CSV gerado e instruções para visualizar o e-mail fake.

6. **Tratamento de Erros**: 
   - O sistema deve lidar graciosamente com possíveis erros, como cidade não encontrada ou problemas na API, informando ao usuário sobre o problema e sugerindo ações corretivas.

### Notas Técnicas
- Utilizar a gem HTTParty para fazer requisições à API do OpenWeather.
- Utilizar a gem Dotenv para gerenciar variáveis de ambiente.
- Utilizar a gem Letter Opener para simular o envio de e-mails em ambiente de desenvolvimento.
- O código deve seguir as convenções e boas práticas de programação em Ruby.

### Tarefas
- [ ] Configurar o ambiente e instalar as gems necessárias.
- [ ] Implementar a classe para buscar dados meteorológicos.
- [ ] Implementar a classe para gerar o arquivo CSV.
- [ ] Implementar a classe para enviar o e-mail fake.
- [ ] Implementar a lógica principal para coordenar as operações.
- [ ] Testar o script para garantir que tudo está funcionando como esperado.
- [ ] Documentar o uso do script e as instruções para o usuário.

### Testes de Aceitação
- Dado que o usuário fornece um nome de cidade válido, quando o script é executado, então um arquivo CSV é gerado e um e-mail fake é enviado com sucesso.
- Dado que o usuário fornece um nome de cidade inválido, quando o script é executado, então uma mensagem de erro é exibida e nenhuma operação adicional é realizada.
- Dado que ocorre um problema na API do OpenWeather, quando o script é executado, então uma mensagem de erro é exibida e nenhuma operação adicional é realizada.


## Execução da Tarefa

Primeiramente, você precisará configurar o ambiente e instalar as gems necessárias. Certifique-se de ter o Ruby e o Bundler instalados em seu sistema.

### Configuração do Ambiente
1. Crie um novo diretório para o seu projeto e navegue até ele no terminal.
2. Crie um arquivo `Gemfile` e adicione as seguintes linhas:
   ```ruby
   source 'https://rubygems.org'
   gem 'httparty'
   gem 'letter_opener', group: :development
   gem 'dotenv'
   ```
3. Execute `bundle install` para instalar as gems.

### Criação do Script Ruby
Agora, você criará o script Ruby com métodos separados, seguindo as boas práticas e o clean code.

4. Crie um arquivo chamado `.env` e adicione sua chave de API do OpenWeather:
   ```
   OPENWEATHER_API_KEY=ef75f6c2b8e5de3e2d49bfe21f3146a2
   ```

5. Crie um arquivo chamado `weather_script.rb` e adicione o seguinte código:

```ruby
require 'httparty'
require 'csv'
require 'dotenv/load'
require 'letter_opener'

class WeatherFetcher
  include HTTParty
  base_uri 'https://api.openweathermap.org/data/2.5'

  def initialize(city)
    @city = city
    @api_key = ENV['OPENWEATHER_API_KEY']
  end

  def fetch_weather
    self.class.get("/forecast/daily?q=#{@city}&cnt=8&appid=#{@api_key}&units=metric")
  end
end

class CSVGenerator
  def self.generate(data, city)
    CSV.open("#{city}_weather.csv", "w") do |csv|
      csv << ["Date", "Temperature (C)", "Weather Description"]
      data.each do |day|
        csv << [day['dt'], day['temp']['day'], day['weather'][0]['description']]
      end
    end
  end
end

class EmailSender
  def self.send_email(city)
    LetterOpener.configure do |config|
      config.location = File.expand_path("../tmp/letter_opener", __FILE__)
    end

    mail = Mail.new do
      from    'weather@example.com'
      to      'user@example.com'
      subject 'Weather Report'
      body    "The weather report for #{city} for the last 8 days has been generated. Please check the CSV file."
    end

    mail.delivery_method :letter_opener
    mail.deliver!
  end
end

puts "Enter the city:"
city = gets.chomp
weather_fetcher = WeatherFetcher.new(city)
response = weather_fetcher.fetch_weather

if response.success?
  weather_data = response.parsed_response['list']
  CSVGenerator.generate(weather_data, city)
  EmailSender.send_email(city)
  puts "Weather report generated and email sent. Check your tmp/letter_opener directory for the email."
else
  puts "Failed to fetch weather data. Please try again."
end
```

### Passo a Passo do Código
1. **Configuração e Requisitos**: Importe as gems necessárias e configure o ambiente.
2. **Classe WeatherFetcher**: Responsável por buscar os dados meteorológicos da API do OpenWeather.
3. **Classe CSVGenerator**: Gera um arquivo CSV com os dados meteorológicos.
4. **Classe EmailSender**: Envia um e-mail falso com a gem Letter Opener informando que o relatório foi gerado.
5. **Execução do Script**: Pede ao usuário para inserir o nome da cidade, busca os dados meteorológicos, gera o CSV e envia o e-mail.

### Execução do Script
1. Salve o script como `weather_script.rb`.
2. Execute o script com `ruby weather_script.rb`.
3. Insira o nome da cidade quando solicitado.
4. Verifique o diretório `tmp/letter_opener` para visualizar o e-mail falso enviado.
5. Abra o arquivo CSV gerado para visualizar o relatório meteorológico.


## Desafio: Aprimoramento do Script de Previsão do Tempo

### Contexto
Após completar o mini curso e aprender sobre a manipulação de APIs, manipulação de arquivos CSV, e envio de e-mails em Ruby, você está agora pronto para enfrentar um desafio que irá consolidar seu aprendizado e aprimorar suas habilidades de programação.

### User Story
Como usuário final do script de previsão do tempo,
Eu quero que o script seja capaz de buscar informações adicionais da API OpenWeather,
E quero que essas novas informações sejam incluídas no arquivo CSV gerado,
Com os cabeçalhos traduzidos para português,
Para que eu possa ter um relatório mais completo e fácil de entender.

### Critérios de Aceitação
1. **Busca de Informações Adicionais**: O script deve ser capaz de buscar pelo menos duas informações adicionais da API OpenWeather. Essas informações podem ser, por exemplo, a velocidade do vento e a pressão atmosférica.

2. **Atualização do CSV**: O script deve adicionar essas novas informações ao arquivo CSV existente. Se o arquivo CSV ainda não existir, o script deve criá-lo.

3. **Tradução dos Cabeçalhos**: Os cabeçalhos do arquivo CSV devem estar em português. Por exemplo:
   - "Data" em vez de "Date"
   - "Temperatura Máxima" em vez de "Max Temperature"
   - "Velocidade do Vento" para a nova informação de velocidade do vento
   - "Pressão Atmosférica" para a nova informação de pressão atmosférica

4. **Manutenção da Qualidade do Código**: O código deve seguir as boas práticas de programação em Ruby, estar bem organizado e ser fácil de entender.

5. **Documentação**: Adicione comentários ao código explicando as partes mais complexas do script e como as novas funcionalidades foram implementadas.

### Recursos e Dicas
- Consulte a documentação da API OpenWeather para descobrir como buscar as informações adicionais.
- Lembre-se de manter suas chaves API seguras e use a gem `dotenv` para gerenciar suas variáveis de ambiente.
- Certifique-se de testar seu código em diferentes cenários para garantir que ele está funcionando corretamente.

### Entrega
Uma vez que você tenha completado o desafio, compartilhe seu código com um mentor ou colega para revisão. Discuta sobre as escolhas que você fez e receba feedback para continuar melhorando suas habilidades de programação.

Boa sorte!



#  Ruby on Rails

## Básico sobre Rails

Ruby on Rails, frequentemente chamado apenas de Rails, é um framework de desenvolvimento web escrito na linguagem de programação Ruby. Ele foi criado por David Heinemeier Hansson e é mantido pelo Rails Core Team. O Rails é conhecido por sua simplicidade e produtividade, seguindo o paradigma de convenção sobre configuração (CoC) e o princípio DRY (Don't Repeat Yourself).

### Características Principais

- **MVC (Model-View-Controller)**: Rails segue o padrão arquitetural MVC, que ajuda a organizar o código de aplicação em três componentes principais, facilitando a manutenção e escalabilidade.

- **Convenção sobre Configuração (CoC)**: Rails assume convenções inteligentes para configuração, minimizando a quantidade de código necessário para criar uma aplicação.

- **DRY (Don't Repeat Yourself)**: Rails encoraja a reutilização de código, ajudando a reduzir a duplicidade e facilitando a manutenção.

- **Gems e Bundler**: Rails utiliza um sistema de pacotes chamado RubyGems, e o Bundler para gerenciar essas dependências.

- **Migrações de Banco de Dados**: Rails fornece uma forma de alterar o esquema do banco de dados de forma versionada e reversível através de migrações.

- **Testes**: Rails vem com uma estrutura embutida para testes unitários, testes de integração e testes de funcionalidades.

- **Desenvolvimento Rápido**: Com a geração de código e uma vasta gama de gems disponíveis, Rails permite um desenvolvimento rápido e eficiente.

- **Convenções de Roteamento**: Rails facilita a criação de URLs amigáveis e RESTful.

- **Segurança**: Rails inclui várias características para ajudar a proteger aplicações contra ataques comuns, como SQL Injection, Cross-Site Scripting, e Cross-Site Request Forgery.

### Componentes do Rails

- **Active Record**: ORM (Object-Relational Mapping) para interação com o banco de dados.
- **Action View**: Sistema para manipulação de templates e views.
- **Action Controller**: Controla o fluxo entre o modelo e a view.
- **Action Mailer**: Envia e recebe e-mails.
- **Active Job**: Gerencia filas de tarefas em background.
- **Action Cable**: Permite funcionalidades de WebSockets para aplicações em tempo real.
- **Rails Router**: Define rotas e distribui requisições para os controladores apropriados.
- **Active Storage**: Facilita o upload e anexação de arquivos.

### Como Começar

1. **Instalação**: Instale o Ruby, o RubyGems e o Rails em seu sistema.
2. **Criar uma Nova Aplicação**: Use o comando `rails new nome_da_aplicacao` para criar uma nova aplicação Rails.
3. **Desenvolvimento**: Utilize a estrutura MVC para desenvolver sua aplicação.
4. **Migrações**: Use migrações para criar e modificar tabelas no banco de dados.
5. **Rotas**: Defina rotas em `config/routes.rb`.
6. **Views e Controllers**: Crie views e controllers para manipular a lógica da aplicação e apresentar dados ao usuário.
7. **Modelos**: Use modelos para interagir com o banco de dados.
8. **Testes**: Escreva testes para garantir que sua aplicação está funcionando corretamente.
9. **Deploy**: Faça o deploy da sua aplicação em um servidor ou plataforma de hospedagem.

Ruby on Rails é uma escolha popular para desenvolvimento web devido à sua simplicidade, eficiência e comunidade ativa. Ele continua a ser uma ferramenta valiosa para desenvolvedores que querem criar aplicações web robustas e escaláveis.


## Fluxo Básico de uma Aplicação Rails

O fluxo básico de uma aplicação Rails envolve várias camadas, desde a requisição feita pelo cliente até a resposta enviada de volta. Aqui está um exemplo simplificado e uma explicação de cada etapa:


1. **Cliente**: O usuário interage com a aplicação através de um navegador web ou cliente API, enviando uma requisição HTTP.

2. **Web Server (Puma)**: O servidor web recebe a requisição e a passa para a aplicação Rails. Puma é um dos servidores web populares usados com Rails.

3. **Rota**: O sistema de rotas do Rails (`config/routes.rb`) determina qual controlador e ação (método) devem ser invocados com base na URL e no método HTTP da requisição.

4. **Controller**: O controlador é uma classe Ruby que herda de `ApplicationController`. Ele é responsável por processar a requisição, interagir com o modelo se necessário, e determinar qual resposta deve ser enviada de volta.

5. **Model**: O modelo interage com o banco de dados para buscar, salvar ou manipular dados. Ele é uma representação dos dados da aplicação e contém lógica relacionada a esses dados.

6. **Controller (Novamente)**: Após interagir com o modelo, o controlador recebe os dados necessários e decide qual resposta enviar de volta. Ele também escolhe qual view deve ser renderizada, se aplicável.

7. **HTML, JSON (View)**: A view é responsável por gerar a resposta final que será enviada ao cliente. Pode ser um arquivo HTML, JSON, XML, etc. O Rails suporta vários formatos de resposta.

8. **Cliente**: O cliente recebe a resposta e a apresenta ao usuário. Se for uma página web, o navegador renderiza o HTML. Se for uma API, o cliente processa os dados recebidos.


![Fluxo Rails](https://miro.medium.com/v2/resize:fit:1400/format:webp/1*KK61kGXrkaFBDfY7uWukyQ.png)

## Exemplo de Código

Vamos considerar um exemplo simples de uma aplicação Rails que gerencia livros. Aqui está como cada parte do fluxo seria implementada:

### 1. Cliente

O usuário acessa a aplicação em seu navegador ou através de um cliente API.

### 2. Web Server (Puma)

O `Gemfile` inclui a gem Puma, e o servidor é iniciado automaticamente quando você executa a aplicação Rails.

### 3. Rota (`config/routes.rb`)

```ruby
Rails.application.routes.draw do
  resources :books
end
```

### 4. Controller (`app/controllers/books_controller.rb`)

```ruby
class BooksController < ApplicationController
  def index
    @books = Book.all
  end
end
```

### 5. Model (`app/models/book.rb`)

```ruby
class Book < ApplicationRecord
  # Lógica relacionada ao modelo, como validações, pode ser colocada aqui
end
```

### 6. Controller (Novamente)

O controlador já preparou os dados para a view.

### 7. View (`app/views/books/index.html.erb`)

```html
<h1>Lista de Livros</h1>
<ul>
  <% @books.each do |book| %>
    <li><%= book.title %></li>
  <% end %>
</ul>
```

### 8. Cliente

O navegador do usuário renderiza a página HTML com a lista de livros.

Este é um exemplo muito básico, mas cobre o fluxo geral de uma requisição em uma aplicação Rails.



## Tarefa

# User Story: API de Previsão do Tempo com Armazenamento de Dados

## Contexto

Desenvolveremos uma API que permitirá aos usuários interagir com dados de previsão do tempo. Os usuários poderão enviar o nome de uma cidade, receber previsões do tempo para os próximos 8 dias via OpenWeather, e armazenar essas previsões em um banco de dados. Além disso, os usuários poderão buscar previsões anteriores, fornecendo o ID da cidade cadastrada.

## História do Usuário

Como usuário da API de Previsão do Tempo,
Eu quero poder enviar o nome de uma cidade e receber previsões do tempo para os próximos 8 dias,
E quero poder armazenar essas previsões em um banco de dados,
E também quero poder buscar previsões anteriores usando o ID da cidade,
Para que eu possa ter acesso rápido e fácil às informações meteorológicas quando precisar.

## Critérios de Aceitação

1. **Envio do Nome da Cidade**: O usuário deve ser capaz de enviar o nome de uma cidade para a API e receber as previsões do tempo para os próximos 8 dias.

2. **Integração com OpenWeather**: A API deve integrar-se com a API OpenWeather para buscar as previsões do tempo.

3. **Armazenamento de Dados**: As previsões do tempo recebidas devem ser armazenadas em um banco de dados. Deve haver duas tabelas: uma para as cidades e outra para as previsões do tempo, onde cada previsão está associada a uma cidade.

4. **Busca de Previsões Anteriores**: O usuário deve ser capaz de buscar previsões anteriores fornecendo o ID da cidade. A API deve retornar as previsões do tempo armazenadas para essa cidade.

5. **Cadastro de Cidades**: O usuário deve ser capaz de cadastrar uma nova cidade no banco de dados.

6. **Associação com o Tempo**: Cada cidade cadastrada deve estar associada às suas respectivas previsões do tempo.

7. **Documentação da API**: A API deve ter uma documentação clara, explicando como realizar cada uma das operações disponíveis.

8. **Validação e Tratamento de Erros**: A API deve validar as entradas do usuário e fornecer mensagens de erro úteis em caso de dados inválidos ou problemas na busca das previsões.

## Recursos e Dicas

- Utilize frameworks como Rails ou Sinatra para criar a API em Ruby.
- Utilize uma biblioteca como ActiveRecord para interagir com o banco de dados.
- Certifique-se de seguir as boas práticas de desenvolvimento de API, incluindo a utilização de status HTTP adequados nas respostas.

## Entrega
A API deve ser entregue com todas as funcionalidades implementadas e testadas. Inclua instruções claras sobre como configurar e executar a aplicação, bem como exemplos de como interagir com a API.

Boa sorte na implementação da sua API de Previsão do Tempo!

# Guia Passo a Passo para Criar a API de Previsão do Tempo com Rails no Replit

## 1. Configuração Inicial no Replit

1.1. Crie uma nova aplicação Rails no Replit e escolha PostgreSQL como banco de dados.

1.2. No arquivo `Gemfile`, adicione as gems necessárias:

```ruby
gem 'httparty'
gem 'rspec-rails', '~> 5.0', '>= 5.0.1'
```

1.3. Execute `bundle install` para instalar as dependências.

## 2. Configuração do Banco de Dados

2.1. No arquivo `config/database.yml`, configure o banco de dados PostgreSQL:

```yaml
default: &default
  adapter: postgresql
  encoding: unicode
  pool: 5
  username: <%= ENV['REPLIT_DB_USERNAME'] %>
  password: <%= ENV['REPLIT_DB_PASSWORD'] %>
  host: <%= ENV['REPLIT_DB_HOST'] %>
  port: <%= ENV['REPLIT_DB_PORT'] %>

development:
  <<: *default
  database: weather_api_development

test:
  <<: *default
  database: weather_api_test

production:
  <<: *default
  database: weather_api_production
```

2.2. Execute `rails db:create` para criar o banco de dados.

## 3. Criação dos Modelos e Migrações

```sh
rails generate model City name:string
rails generate model Forecast city:references date:date temperature:float condition:string
rails db:migrate
```

## 4. Configuração dos Modelos

```ruby
# app/models/city.rb
class City < ApplicationRecord
  has_many :forecasts
end

# app/models/forecast.rb
class Forecast < ApplicationRecord
  belongs_to :city
end
```

## 5. Criação da Lib para Integração com OpenWeather

5.1. Crie um diretório `lib` na raiz do projeto.

5.2. Dentro do diretório `lib`, crie um arquivo chamado `open_weather.rb`.

5.3. No arquivo `open_weather.rb`, adicione o seguinte código:

```ruby
require 'httparty'

module OpenWeather
  BASE_URL = "https://api.openweathermap.org/data/2.5/forecast/daily"

  def self.fetch_forecast(city_name)
    response = HTTParty.get("#{BASE_URL}?q=#{city_name}&cnt=8&appid=#{ENV['OPEN_WEATHER_API_KEY']}")
    response.parsed_response['list'].map do |day|
      {
        date: Time.at(day['dt']).to_date,
        temperature: day['temp']['day'],
        condition: day['weather'].first['description']
      }
    end
  end
end
```

5.4. Adicione sua chave da API OpenWeather ao arquivo `.env`:

```
OPEN_WEATHER_API_KEY=your_api_key_here
```

5.5. No arquivo `config/application.rb`, adicione a seguinte linha para carregar os arquivos da pasta `lib`:

```ruby
config.autoload_paths << Rails.root.join('lib')
```

## 6. Implementação dos Controllers

```sh
rails generate controller Cities
rails generate controller Forecasts
```

Após gerar os controllers com os comandos `rails generate controller Cities` e `rails generate controller Forecasts`, você pode implementá-los para lidar com as ações específicas relacionadas às cidades e previsões do tempo. Aqui está um guia passo a passo sobre como você pode fazer isso:

### 1. Controller de Cidades (CitiesController)

No arquivo `app/controllers/cities_controller.rb`, você pode adicionar métodos para lidar com as diferentes ações relacionadas às cidades. Aqui está um exemplo de como você pode implementar este controller:

```ruby
class CitiesController < ApplicationController
  before_action :set_city, only: [:show, :update, :destroy]

  # GET /cities
  def index
    @cities = City.all
    render json: @cities
  end

  # GET /cities/1
  def show
    render json: @city
  end

  # POST /cities
  def create
    @city = City.new(city_params)
    if @city.save
      render json: @city, status: :created, location: @city
    else
      render json: @city.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /cities/1
  def update
    if @city.update(city_params)
      render json: @city
    else
      render json: @city.errors, status: :unprocessable_entity
    end
  end

  # DELETE /cities/1
  def destroy
    @city.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_city
      @city = City.find(params[:id])
    end

    # Only allow a list of trusted parameters through.
    def city_params
      params.require(:city).permit(:name)
    end
end
```

### 2. Controller de Previsões do Tempo (ForecastsController)

No arquivo `app/controllers/forecasts_controller.rb`, você pode adicionar métodos para lidar com as diferentes ações relacionadas às previsões do tempo. Aqui está um exemplo de como você pode implementar este controller:

```ruby
class ForecastsController < ApplicationController
  before_action :set_city, only: [:index, :previous]

  # GET /forecasts?city_name=São Paulo
  def index
    forecasts = OpenWeather.fetch_forecast(params[:city_name])
    render json: forecasts
  end

  # GET /forecasts/previous?city_id=1
  def previous
    forecasts = @city.forecasts
    render json: forecasts
  end

  private
    def set_city
      @city = City.find(params[:city_id])
    end
end
```


Com esses controllers e rotas configurados, você deve ser capaz de interagir com a sua API de previsão do tempo, realizando operações CRUD em cidades e buscando previsões do tempo.

6.1. Implemente os controllers conforme especificado anteriormente.

## 7. Configuração das Rotas

7.1. Configure as rotas conforme especificado anteriormente.


No arquivo `config/routes.rb`, você precisa configurar as rotas para os controllers que você acabou de criar. Aqui está um exemplo de como você pode fazer isso:

```ruby
Rails.application.routes.draw do
  resources :cities, only: [:index, :show, :create, :update, :destroy]
  get 'forecasts', to: 'forecasts#index'
  get 'forecasts/previous', to: 'forecasts#previous'
end
```

## 8. Testes com RSpec

8.1. Execute `rails generate rspec:install` para configurar o RSpec.

8.2. Crie seus testes em `spec/controllers` e `spec/models`.

8.3. Execute `rspec` para rodar os testes.

Testes automatizados são essenciais em qualquer aplicação para assegurar que tudo está funcionando como esperado e para prevenir que futuras alterações no código quebrem funcionalidades existentes. O RSpec é uma ferramenta popular para escrever testes em aplicações Ruby e Rails, oferecendo uma sintaxe clara e a capacidade de escrever testes para modelos, controladores, rotas, e mais.

### Por que usar Testes Automatizados?

1. **Garantia de Qualidade**: Testes automatizados ajudam a garantir que o código está funcionando corretamente e que novas alterações não introduzam bugs.

2. **Desenvolvimento Mais Rápido**: Com uma suíte de testes confiável, os desenvolvedores podem fazer alterações no código com mais confiança, sabendo que os testes irão capturar qualquer regressão.

3. **Documentação**: Testes também servem como uma forma de documentação do código, mostrando como as diferentes partes da aplicação são supostas a funcionar.

4. **Refatoração**: Testes facilitam a refatoração do código, permitindo que os desenvolvedores melhorem a estrutura do código sem mudar seu comportamento.

### Exemplo de Testes com RSpec

Vamos criar alguns testes básicos para os modelos e controladores da nossa aplicação de previsão do tempo.

#### 1. Testes para o Modelo City

Crie um arquivo `spec/models/city_spec.rb`:

```ruby
require 'rails_helper'

RSpec.describe City, type: :model do
  it "is valid with a valid name" do
    city = City.new(name: "São Paulo")
    expect(city).to be_valid
  end

  it "is invalid without a name" do
    city = City.new(name: nil)
    expect(city).not_to be_valid
  end
end
```

#### 2. Testes para o Controlador CitiesController

Crie um arquivo `spec/controllers/cities_controller_spec.rb`:

```ruby
require 'rails_helper'

RSpec.describe CitiesController, type: :controller do
  describe "GET #index" do
    it "returns a success response" do
      City.create!(name: "São Paulo")
      get :index
      expect(response).to be_successful
    end
  end

  describe "GET #show" do
    it "returns a success response" do
      city = City.create!(name: "São Paulo")
      get :show, params: { id: city.to_param }
      expect(response).to be_successful
    end
  end
end
```

### Como Funciona o Fluxo de Testes com RSpec

1. **Preparação**: O RSpec carrega o ambiente de teste e prepara a base de dados.

2. **Execução**: Os testes são executados. Cada teste é isolado, significando que a execução de um teste não afeta os outros.

3. **Asserções**: Dentro de cada teste, asserções (expectativas) são feitas para verificar se o código está se comportando como esperado.

4. **Limpeza**: Após cada teste, o estado é limpo para evitar interferências entre testes.

5. **Relatório**: Ao final da execução, um relatório é gerado, mostrando quais testes passaram e quais falharam.

* https://github.com/simplecov-ruby/simplecov
* https://github.com/DatabaseCleaner/database_cleaner
* https://rspec.info/
* https://www.betterspecs.org/

## 9. Execução e Teste da API

9.1. Inicie o servidor Rails com `rails server`.

9.2. Use ferramentas como Postman ou cURL para testar os endpoints da sua API.

Aqui estão exemplos de comandos `curl` que você pode usar para interagir com os endpoints da sua API de previsão do tempo, assumindo que você já implementou os controllers e configurou as rotas conforme as instruções anteriores.

#### 1. Cadastrar uma Cidade

Para cadastrar uma nova cidade no banco de dados:

```sh
curl -X POST http://localhost:3000/cities -d "city[name]=São Paulo"
```

#### 2. Buscar Previsões do Tempo

Para buscar previsões do tempo para uma cidade específica:

```sh
curl http://localhost:3000/forecasts?city_name=São Paulo
```

### 3. Buscar Previsões Anteriores

Para buscar previsões anteriores armazenadas no banco de dados para uma cidade específica:

```sh
curl http://localhost:3000/forecasts/previous?city_id=1
```

(Substitua `1` pelo ID da cidade desejada.)

#### 4. Atualizar uma Cidade

Para atualizar o nome de uma cidade no banco de dados:

```sh
curl -X PUT http://localhost:3000/cities/1 -d "city[name]=Novo Nome"
```

(Substitua `1` pelo ID da cidade e `Novo Nome` pelo novo nome da cidade.)

#### 5. Deletar uma Cidade

Para deletar uma cidade do banco de dados:

```sh
curl -X DELETE http://localhost:3000/cities/1
```

(Substitua `1` pelo ID da cidade.)

#### Notas Importantes:

- Certifique-se de que o servidor Rails está rodando e acessível na porta especificada (por padrão, `3000`).
- Os exemplos acima assumem que você configurou as rotas e controllers para aceitar essas requisições.
- Você pode precisar ajustar os URLs e parâmetros de acordo com a implementação específica da sua API.
- Para enviar dados JSON em vez de dados de formulário, você pode usar a opção `-H "Content-Type: application/json"` e incluir o payload JSON com a opção `-d '{"key":"value"}'`.
- Se a sua API requer autenticação, você precisará incluir as informações necessárias nas suas requisições `curl`, seja via cabeçalhos HTTP, parâmetros de consulta ou cookies.

## 10. Documentação

10.1. Documente sua API, explicando como realizar cada operação, quais parâmetros são necessários, e o que cada endpoint retorna.

[README.MD exemplo](https://gist.github.com/lohhans/f8da0b147550df3f96914d3797e9fb89)



---

Com esses passos, você terá uma API de previsão do tempo funcional e testada, pronta para ser utilizada e expandida conforme necessário.


## DESAFIO

Agora você precisa experimentar a ferramenta, adicione novas funcionalidades.


# Siga a skill.dev

Há muito conteúdo na 

![skilldev](https://hackmd.io/_uploads/HyiVFhGfp.jpg)

[Link youtube.com/@skilldevs](https://www.youtube.com/@skilldevs)

