<repo_name>eluminatis/roteiros<file_sep>/ruby on rails/rails.md
# Rails

## Convenções

É um framework web que permite um desenvolvimento agil porém ele tem uma forma bem rigida de programar onde o dev precisa seguir suas convenções para extrair o maximo rendimento, ele usa massivamente geradores para tudo que vc precisar e as principais convenções são:

- views que atendem um metodo de um controller devem ficar no caminho

``` bash
app/views/nome_do_controller/nome_do_metodo_do_controller.html.erb
```

- variaveis de instancia - *@var* - criadas no metodo do controller estarão automaticamente disponiveis para serem usadas na views
- metodos ruby escritos no helper application estarão disponiveis em todo o sistema e metodos escritos nos helpers com nome de recurso estarão disponíveis no controler, models e views do recurso especifico
- nos métodos a ultima linha sempre é retornada como se fosse precedida implicitamente por um return, se precisar usar o return no meio de um metodo ele tambem está disponivel

### criar projeto

Para criar um novo projeto em rails existem as seguintes opções:

```bash
rails new app_name # novo projeto com configs default
rails new app_name --database=mysql # pré definindo o db
rails new app_name -api # nova api
rails new app_name -m https://raw.github.com/RailsApps/rails-composer/master/composer.rb # novo projeto com rails composer, uma espécie de wizard que te ajuda a deixar tudo configurado
```

Loga após cria faça ...

``` bash
cd nome_projeto         #entra na pasta
bundle install          #instala as dependencias
```

No arquivo config/database.yml vc deve colocar as configurações de acesso ao seu bd e rodar

``` bash
rails db:create         #cria o banco de dados
```

## Generator

### Scaffold

``` bash
rails generate scaffold User name:string description:text age:integer cpf:integer:uniq username:string{30}:uniq social_class:references birthday:datetime active:boolean
```

Esse comando irá criar model(User), migration(users), tabela no banco(users), fixture, helper, controller, views, assets (js, sass) e tests para todo o CRUD de users e ainda adicionará a rota recurso no começo de seu arquivo de rotas. De acordo com os campos passados sua tabela no banco será criada com as seguintes colunas:

- name (varchar 255)
- description (text)
- age (int)
- cpf (int, unique)
- username (varchar 30)
- social_class_id (integer, not null, que vai guardar o id da relação com social_classes)
- birthday (datetime)
- active (boolean)

#### Outros tipos que podem ser usados no scaffold

- integer
- primary_key
- decimal
- float
- boolean
- binary
- string
- text
- date
- time
- datetime
- timestamp

Caso precise alterar colunas no recurso criado gere um migração com a seguinte estrutura no comando generate.
por exemplo, se voce quiser adicionar a coluna nome a tabela pessoas, e nome é do tipo string, seria assim:

```bash

rails g migration add_nome_to_pessoas nome:string

#o generate migration funciona da seguinte forma: verbo(add/remove/change),nome da coluna, to/from, nome da tabela no plural e depois um espaço e o nome da coluna:tipo da coluna.
```

Caso precise remover um recurso adicionado com scaffold faça

```bash
rails destroy scaffold ModelName
```

## Rotas

O arquivo de rotas fica em *config/routes.rb*, ele aceita os seguintes tipos de rotas

``` ruby
get 'welcome/hello' # verbo 'controller/metodo'
root 'posts#index' # rota default do projeto
resources :posts # rota recurso (laravel like)
```

## Validações

no rails as validações ficam no model, um exemplo de como tornar o campo 'title' obrigatorio é adicionar no model do recurso o seguinte:

``` ruby
validates_presence_of :title #title agora é required nesse recurso
validates_uniqueness_of :titulo # o title deve ser unico na tabela
validates_presence_of :nome, message: 'não pode ser deixado em branco'
validates :email, presence: {message: 'não pode ser deixado em branco'}, length: {minimum: 10, message: 'deve ter pelo menos 10 caracteres'}, uniqueness: {message: 'deve ser único'} # varias validações para um campo
validates_length_of :telefone, maximum: 11, message: 'deve ter até 11 caracteres'
validates_length_of :endereco, in: 10..100, message: 'deve ter entre 10 e 100 caracteres'
validates_numericality_of :idade, message: 'deve ser um número'

validates_length_of :cpf, :is => 11, :allow_blank => true # o numero deve ter exatamente 11 digitos mas é permitido valor em branco
```

Com as validações criadas no model fica disponivel para você o metodo valid? que retorna um boolean informando se o objeto passa em todas as validações ou não

``` ruby
post.valid? # true/false de acordo com o resultado nos testes de validações do model
```

## Seeders

Seeders servem para popular seu banco de dados a fim de ter dados para fazer suas funcionalidades sem precisar inseri-los na mão toda vez que instala uma nova instancia do app, eles ficam em *db/seeds.rb* e usam a seguinte sintaxe:

``` ruby
movies = Movie.create([{ name: 'Star Wars' }, { name: 'Lord of the Rings' }])

Character.create(name: 'Luke', movie: movies.first)

Product.create(name: 'Apple', price: 1)
Product.create(name: 'Orange', price: 1)
Product.create(name: 'Pineapple', price: 2.4)
Product.create(name: 'Marble cake', price: 3)
```

Se a sua intenção for apenas popular o banco com dados fakers para simular o funcionamento do app vc pode fazer algo assim:

``` ruby
# criando 50 posts no banco (aprender gem faker)
50.times do |i|
    Post.create(title: "Titulo de um post #{i}", body: "Corpo de um post #{i}")
end
```

Após configurá-los com seus dados vc pode rodá-los com o comando

``` bash
rails db:seed #popula o banco
```

## Dicas

Você pode ativar um console interativo com seu projeto carregado digitando

``` bash
rails console
```

para resetar um banco de dados *nunca faça isso em produção*

``` bash
rails db:drop db:create db:migrate #joga o bd fora, cria um novo e cria as tabelas
rails db:seed #popula o banco
```

Você pode visualizar no navegador todas as rotas da aplicação em

``` bash
localhost:3000/rails/info/routes
```

## Simbolos

``` ruby
:exemplo
```

À princípio o conceito de Símbolos pode parecer estranho e
confuso pois trata-se de algo específico de Ruby que você não vai
encontrar na maioria das outras linguagens.

Símbolos são textos iniciados com o sinal de dois pontos “:” - Eles estão presentes por todo o framework Rails (como nos exemplos
de relacionamento entre models que fizemos acima em que usamos
os símbolos :eventos e :categoria)

Pense em símbolos como “String levinhas”: Como tudo na linguagem
Ruby é um objeto, todas as vezes que você cria um string um novo
objeto é instanciado na memória. Os símbolos representam nomes
mas não são tão pesadas como strings.
<file_sep>/javascript/redux_for_react.md
# Configuração e uso do redux no react

instale redux e react-redux no projeto

```bash
yarn add redux react-redux
```

vamos usar para esse exemplo uma lista de cursos

## crie o store/index.js

```javascript
import { createStore } from "redux";

const INITIAL_STATE = {
  data: ["React Native", "ReactJS", "NodeJS"]
};

function courses(state = INITIAL_STATE, action) {
  switch (action.type) {
    case "ADD_COURSE":
      return { ...state, data: [...state.data, action.payload] };
    default:
      return state;
  }
}

const store = createStore(courses);

export default store;
```

imagine o `courses` como uma função que recebe um objeto com o attr `action` que tem um attr `type:string` e com base nesse type vc vai executar uma ação, essa ação sempre deve receber o state anterior e devolve-lo com as alterações desejadas, seja inclusive, update ou exclusão de algum item especifico do state, dentro desse action vc pode colocar um attr contendo o conteudo necessário para essa alteração, normalmente se usa o attr com nome de `payload` para se manter um padrão.

## crie seu App.js

```javascript
import React from "react";
import { Provider } from "react-redux";

import store from "./store";

import CourseList from "./components/CourseList";

function App() {
  return (
    <Provider store={store}>
      <CourseList />
    </Provider>
  );
}

export default App;
```

o Provider vai receber o store e garantir que todos os filhos dele tenham acesso a esse store, por isso é importante que ele fique no topo da arvore de componentes da aplicação

## criando a lista de cursos

```javascript
import React, { useState } from "react";
import { useSelector, useDispatch } from "react-redux";

// actions sempre retornam um objeto com o type usado para identificar a ação no reducer e os dados necessários para realizar a ação
function addCourseAction(title) {
  return { type: "ADD_COURSE", payload: title };
}

export default function CourseList() {
  const [input, setInput] = useState("");
  const courses = useSelector(state => state.data);
  const dispatch = useDispatch();

  function addCourse() {
    dispatch(addCourseAction(input));
    setInput("");
  }

  return (
    <>
      <ul>
        {courses.map(course => (
          <li key={course}>{course}</li>
        ))}
      </ul>
      <input
        type="text"
        value={input}
        onChange={e => setInput(e.target.value)}
      />
      <button type="button" onClick={addCourse}>
        Adicionar curso
      </button>
    </>
  );
}
```

os dois hooks principais para se usar o redux são `useSelector` e `useDispatch`

#### useSelector

recebe uma função que recebe o state inteiro da aplicação e devolve o que vc precisa para esse componente

#### useDispatch

Devolve uma função que recebe um objeto `{ type: "nome da ação", payload: dados necessários para essa ação }`, normalmente esse objeto é montado por uma action, no nosso exemplo a action é `addCourseAction` mas basicamente esssa action faz alguma coisa e devolve um objeto que carrega o nome da ação e os dados necessários para executa-la.

concluimos que para adicionar ou remover algo do redux precisamos criar o reducer que recebe o state inteiro da aplicação e action e de acordo com o type da action manipula esse state e devolve ele com o novo valor, cria-se uma action para montar o objeto com o type e dados e passa esse objeto para o nosso reducer por meio do useDispatch e quando é preciso ler algo desse reducer usa-se o useSelector.

repo desse exemplo https://github.com/PetersonJFP/react-hooks-redux-example
<file_sep>/django/django-admin.md
# Django admin

no seu urls.py vc pode reescrever as 3 principais variáveis de nome do django-admin

```python
admin.site.site_header = 'My project'                    # default: "Django Administration"
admin.site.index_title = 'Features area'                 # default: "Site administration"
admin.site.site_title = 'HTML title from adminsitration' # default: "Django site admin"
```

Alterando o padrão de campos ManyToMany no admin do django para ficar igual ao de permissões.

```python
#em admin.py da sua app
class EmployeeAdmin(admin.ModelAdmin):
   filter_horizontal = ('field',)
```

Nas listagens que o django-admin cria, ainda é possível definir um, ou vários filtros a serem usados na listagem. Esse recurso permite a visualização apenas do que interessa na listagem ou um subconjunto de dados mais relevante.

```python
#em admin.py da sua app
class MyModelAdmin(admin.ModelAdmin):
   list_filter = ['field_01', 'field_02']
```

Definindo um campo como apenas leitura

```python
#em admin.py da sua app
class MyModelAdmin(admin.ModelAdmin):
   readonly_fields = (''field’,)
```

Personalizando as colunas que aparecem na listagem do django-admin ('index do model')

```python
#em admin.py da sua app
class MyModelAdmin(admin.ModelAdmin):
   list_display = ('nome', 'email')
```

Configure _search_fields_ para habilitar uma caixa de busca na página de listagem do admin. Este deve ser configurado com uma lista de nomes de campos que serão afetados pela busca, sempre que alguém submeter um texto por esta caixa de texto.

```python
#em admin.py da sua app
class MyModelAdmin(admin.ModelAdmin):
   search_fields = ('nome', 'email')
```

Você pode também executar uma pesquisa relacionada a ForeignKey com a lookup API “siga” a notação:

```python
#em admin.py da sua app
class MyModelAdmin(admin.ModelAdmin):
   search_fields = ['foreign_key__related_fieldname']
```
<file_sep>/composer.md
# Trabalhando com composer

## Criando um Pacote

Inicialmente você precisa de uma conta no Packagist e o composer instalado na sua máquina.

Feito isso rode o comando:

```bash
composer init
```

Siga as instruções na tela descritas abaixo

### Passo 1 - Package name

Ele deve respeitar o nome de usuário do GitHub/repositório do GitHub

```bash
eluminatis/meu_projeto
```

### Passo 2 - Descrição

Essa descrição ficará disponível no site do Packagist

### Passo 3 - Autor

O autor deve seguir exatamente a máscara abaixo:

```bash
<NAME> <<EMAIL>>
```

### Passo 4 - Estabilidade

Aqui eu coloquei `dev`. Necessário checar a documentação para mais detalhes

### Passo 5 - Tipo de pacote

Escolher um dos disponíveis que o Composer sugere. Os nomes são autoexplicativos

### Passo 6 - Licença (Obrigatório para subir pro Packagist)

Para escolher um tipo de licença existe um site interessante [aqui](http://choosealicense.com/)

O Composer tem as strings válidas para cada tipo de licença, que devem seguir o padrão abaixo

- Apache-2.0
- BSD-2-Clause
- BSD-3-Clause
- BSD-4-Clause
- GPL-2.0-only / GPL-2.0-or-later
- GPL-3.0-only / GPL-3.0-or-later
- LGPL-2.1-only / LGPL-2.1-or-later
- LGPL-3.0-only / LGPL-3.0-or-later
- MIT

Mais detalhes na [documentacao do composer](https://getcomposer.org/doc/04-schema.md#license)

Depois o composer perguntará sobre dependências do seu projeto. Você pode definí-las aqui se necessário.

A saída deve ser algo assim:

```json
{
    "name": "eluminatis/meu_projeto",
    "description": "Projeto de teste do Composer",
    "type": "library",
    "license": "GPL-3.0-or-later",
    "authors": [
        {
            "name": "<NAME>",
            "email": "<EMAIL>"
        }
    ],
    "minimum-stability": "dev",
    "require": {}
}
```

## Preparando os diretórios para o seu pacote

Uma boa prática é incluir os fontes em `src`, por convenção da comunidade.

## Namespaces

Para que seu pacote seja alocado corretamente, você precisa dizer onde "mora" seu namespace. Baseando no namespace escolhido, adicione a diretiva abaixo em seu `composer.json`

```json
"autoload": {
    "psr-4" : {
        "Eluminatis\\MeuOutroNamespace\\" : "src"
    }
}
```

## Publicando no Packagist

Vá na área "Submit" e aponte para o link do seu repositório no GibHub

Ele fará checagens de sintaxe no seu arquivo `composer.json` e corrija os erros que porventura apareçam

## Autoload no Laravel / Gerando pacotes para Laravel

O Laravel permite que você carregue Service Providers automaticamente se você adicionar a diretiva no `composer.json`

Adicione seu pacote seguindo esse padrão:

```json
"extra": {
    "laravel": {
        "providers": [
            "Eluminatis\\MeuOutroNamespace\\EluminatisServiceProvider"
        ]
    }
}
```

Tudo pronto, teste com:

```bash
composer require eluminatis/meu_projeto dev-master
```

## TODO

Escrever sobre SemVer e tags/releases no github<file_sep>/laravel/email_laravel.md
# Email com laravel

#### FROM

Se todos os emails enviados pelo seu app forem ter o mesmo endereço de remetente, você não precisar ficar definindo isso a cada envio, basta criar e configurar as seguintes variaveis em seu .env

	MAIL_FROM_ADDRESS=<EMAIL>
	MAIL_FROM_NAME=SeuNome
	
caso cada email possa ter um remetente diferente configure diretamente no `->from()` do metodo `build()`

```php
public function build()
{
    return $this->from('<EMAIL>')
        ->view('emails.orders.shipped');
}
```

### Mailables

Cada tipo de email disparado por seu app é representado por uma classe mailable, você deve gerar asssim:
	
	php artisan make:mail SeuMailable
	
Toda a configuração é feita no build. Dentro deste método, você pode chamar vários métodos, como from, subject, view, e attach para configurar apresentação e entrega do e-mail.

```php
public function build()
{
    return $this->from('<EMAIL>')
        ->subject('Seu assunto')
        ->view('emails.seuTemplate')
        ->attach('caminho para o anexo se necessário');
}

```

Ao anexar arquivos a uma mensagem, você também pode especificar o nome de exibição e / ou o tipo MIME, passando um segundo argumento (do tipo `array`) para o método `attach()`:

```php
public function build()
{
    return $this->from('<EMAIL>')
        ->subject('Seu assunto')
        ->view('emails.seuTemplate')
        ->attach('/path/to/file', [
                    'as' => 'name.pdf',
                    'mime' => 'application/pdf',
        ]);
        
        //também existe o ->text('texto desagatemelizado') para textos planos
}

```

## Passando variaveis para a classe Mailable

Você deve definir variáveis públicas na classe mailable e passar variáveis pelo construtor para ela e automaticamente ela estará disponível dentro de sua view
 
```php
<?php

namespace App\Mail;

use App\Order;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;

class OrderShipped extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * a variavel que recebe um array de variveis que vc queira passar
     */
    public $data;

    /**
     * o construtor recebe a variavel e a joga dentra da var publica
     * e agora vc pode usa-la dentro da view
     */
    public function __construct($data)
    {
        $this->data = $data;
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('emails.template');
    }
}
```

Depois de os dados serem passados pelo construtor e definidos como propriedade publica, você poderá acessá-los de dentro da view

```php    
<div>
    <p>Preço: {{ $data['var1'] }}</p>
</div>
```

## Inserindo imagens no corpo do email

o laravel disponibiliza a variavel `$message` nos mailables com alguns métodos que facilitam seu trabalho. Um deles é o método de inserir imagens no corpo do email. Na view, coloque a imagem da seguinte forma:

```php
<body>
    Aqui temos um exemplo de inserção de imagem no corpo
    
    <img src="{{ $message->embed(asset('images/email_rodape.png')) }}">
</body>
```

## Enviando emails

No seu controller registre o uso da fachade `Illuminate\Support\Facades\Mail` e o seu mailable `App\Mail\SeuMailable`. Feito isso é só chamar o método`Mail::to('destinatario')->send(New SeuMailable($vars))`

O `to()` aceita um endereço de email, uma instância do usuário ou uma coleção de usuários. Se você passar um objeto ou uma coleção de objetos, o programa de email usará automaticamente as propriedades email e name ao configurar os destinatários de e-mail.

```php
<?php

namespace App\Http\Controllers;

use App\Http\Controllers\Controller;
use App\Mail\SeuMailable; //importando seu mailable
use Illuminate\Support\Facades\Mail; //importando facade de emails

class OrderController extends Controller
{
    /**
     * Envia um email qualquer a um tolo qualquer
     */
    public function enviaEmail(){
        $data['var1'] = 'bla bla bla';
        $data['var2'] = 'ble ble ble';
        
        Mail::to('<EMAIL>')->send(new SeuMailable($data));
        
        ou
        
        Mail::to('<EMAIL>')
            ->cc($moreUsers)
            ->bcc($evenMoreUsers)
            ->send(new SeuMailable($data));
        
    }
}
```

## Visualizando mailables no navegador

Para fins de desenvolvimento você pode visualizar seus mailables no navegador simplesmente retornando-o na rota de testes:

```php
Route::get('/mailable_teste', function () {
    $data['var1'] = 'bla bla bla';
    $data['var2'] = 'ble ble ble';

    return new App\Mail\SeuMailable($data);
});
```
<file_sep>/laravel/roteiro_laravel.md
# Roteiro Laravel

### Configurações Iniciais

**Criando um projeto:**

Vá com o terminal ate a pasta htdocs

    cd /opt/lampp/htdocs

Digite o comando:

    composer create-project --prefer-dist laravel/laravel nome_projeto

Feito isso, o composer vai baixar o laravel, criar a pasta `nome_projeto` e instalá-lo dentro dele

Você deve dar permissao de escrita para a pasta `storage` que é onde o fw guarda os logs e arquivos. 

Se for trabalhar com uploads crie uma pasta `uploads` dentro de `public`

Verifique qual é o usuário que seu webserver utiliza. No Ubuntu, o usuário do apache é o `www-data`

    # Muda o grupo da pasta para o do apache
    sudo chown -R seu_usuario:www-data public/uploads
    sudo chown -R seu_usuario:www-data storage

    # Aplica as permissões corretas
    sudo chmod -R 774 storage
    sudo chmod -R 774 public/uploads

No netbeans, crie um novo projeto com codigo fonte existente e aponte para a pasta do seu projeto

Crie o banco para seu projeto com a seguinte collation: 

`utf8mb4_unicode_ci` padrão do laravel

Abra o projeto na pasta raiz e abra o arquivo `.env`. Caso não exista, renomeie o `.env.example` para `.env` e insira os seguintes dados:

    APP_URL = url base de seu projeto
    APP_NAME = nome do seu projeto

Inserir também dados de acesso ao database

Altere o timezone default para o BR em: 
    
    config/app.php 
    
    'timezone' => 'America/Sao_Paulo',

### Ajustes finos

Em:

    app/Providers/AppServiceProvider.php@boot

addicionar no método:

    Schema::defaultStringLength(191)

No `namespace`:

    use Illuminate\Support\Facades\Schema; 

Isso evita conflitos de tamanho de string no Banco de Dados MySQL e MariaDB

### Configurando tradução / linguagem / locale

    cd resources/lang/

Clone um projeto de traduçao open do git

    git clone https://github.com/enniosousa/laravel-5.5-pt-BR-localization.git ./pt-br

Para que a tradução entre no seu controle de versão principal faça:
    
    # Remove o repositório do vendor anterior
    rm -r pt-br/.git/


Agora só configurar no `config/app.php`

    'locale' => 'pt-br',

### Adicionando barra de debbug ao projeto (app_debug === true)

    composer require barryvdh/laravel-debugbar

### Inserindo Helper próprio

coloque seu helper dentro da pasta App/MyHelper.php

add ao composer

```javascript
"autoload": {
    "classmap": [
        "database/seeds",
        "database/factories"
    ],
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/MyHelper.php" //Seu arquivo aqui
    ]
},
```

### Removendo arquivos desnecessários ao controle de versão

Adicione ao .gitignore da pasta raiz as seguintes linhas

```bash
/nbproject //se estiver usando netbeans
/storage/*
```

### Convenções de nomenclatura

Quando você vai criar um `model`, coloque o nome no singular com a primeira letra maiúscula. Ele irá alterar essa string para gerar `controler` e `migration` compatíveis com a nomenclatura padrão

Links de ações colocados em botos nas tabelas de crud devem seguir a seguinte formação

    tabela/{{id_item}}/editar

## Banco de dados

### Criando os dados da aplicação (Migrations)

Nesse ponto você precisa já ter definido todas as tabelas e relações requeridas para sua aplicação. De preferência utilizar algum gerador de MER (Modelo Entidade Relacionamento)

Para cada tabela  necessária a seu app, digite no terminal já dentro da pasta de seu app 

    php artisan make:model –all Models\\NOME
    
onde `NOME` é o nome no singular e com a primeira letra maiuscula de sua classe.

Feito isso, o `artisan` ira criar a `model`, o `controller` e a `migration`, tudo com as convenções de nomenclatura do fw e nas suas respectivas pastas e também registrar os autoloads necessarios.

Abra a migration criada e preencha as colunas necessárias à sua tabela

Rode `php artisan migrate` que serão criadas todas as tabelas das quais você criou as `migrations`

**Estudar melhor os conceitos de migrations**

**Vale lembrar**

Não mexer no `id`.
Por padrão o laravel salva o horario de criação e uúltima edição de cada tupla do banco, 
se quiser manter esse comportamento não delete `timestamps` da migration e caso não precise
retire o `timestamps` e adiciona na model a variavel protected $timestamps = false;

### Principais tipos de dados para colunas na migration:

```php
$table->string('name', 100); // VARCHAR 2° param tamanho opcional
$table->text('description'); // TEXT
$table->longText('description'); // LONGTEXT
$table->integer('votes'); // INT
$table->tinyInteger('votes'); // TINYINT
$table->bigInteger('votes'); // BIGINT
$table->float('amount', 8, 2) // FLOAT 8,2
$table->dateTime('created_at'); // DATETIME
```

**Principais modificadores de colunas:**

```php
$table->integer('votes')->charset('utf8'); // charset da coluna
$table->integer('votes')->collation('utf8_unicode_ci'); //collation da coluna
$table->integer('votes')->comment('my comment'); // comentário da coluna
$table->integer('votes')->nullable(); // aceitar null
$table->string('email')->unique(); //não aceita dois registros com o mesmo valor nessa coluna
```

### Add chave estrangeira

```php
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
```

a tabela `user` já deve estar criada e a coluna que a referencia também, após isso você pode criar a relação.

adicionar `->ondelete(‘cascade’)` à `fk` para que se um pai for deletado, deletar tambem os filhos, não deixando assim registros orfãos no sistema.

Tabelas pivo devem ser feitas com as models na ordem alfabética `model1_model2`

Caso tenha feito um `php artisan make:model` com nome errado, delete os arquivos e após isso rode um 

    composer dump-autoload

## Integrando o adminLTE

Após ter feito todos os passos anteriores vamos integrar o `adminLTE` ao laravel. Instalar o pacote com o `composer`

    composer require jeroennoten/laravel-adminlte

Adicione o serviço a `config/app.php`

    JeroenNoten\LaravelAdminLte\ServiceProvider::class

Publique os assets públicos

    php artisan vendor:publish --provider="JeroenNoten\LaravelAdminLte\ServiceProvider" --tag=assets

Crie a integração

    php artisan make:adminlte

Publique o arquivo de configurações

    php artisan vendor:publish --provider="JeroenNoten\LaravelAdminLte\ServiceProvider" --tag=config

Rode as migrations para criar as tabelas necessárias ao sistema de autenticação

    php artisan migrate

As configurações de menus e defaults você faz em `config/adminlte`.

Pronto, já está integrado e com sistema de autenticação funcionando. Veja a documentação no repositório

https://github.com/jeroennoten/Laravel-AdminLTE

## Mensagens flash:

São mensagens que ficam na sessão apenas pela próxima requisição, ideal para mensagens de aviso/sucesso ao usuario.

Crie a view `messages/msgs.blade.php` com o seguinte conteudo:

```html
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
            <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
@if(Session::has('flash_msg'))
    <div class="alert alert-primary text-center">
        <p class="text-bold">{{Session::get('flash_msg')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_primary'))
    <div class="alert alert-primary text-center">
        <p class="text-bold">{{Session::get('flash_msg_primary')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_success'))
    <div class="alert alert-success text-center">
        <p class="text-bold">{{Session::get('flash_msg_success')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_info'))
    <div class="alert alert-info text-center">
        <p class="text-bold">{{Session::get('flash_msg_info')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_warning'))
    <div class="alert alert-warning text-center">
        <p class="text-bold">{{Session::get('flash_msg_warning')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_danger'))
    <div class="alert alert-danger text-center">
        <p class="text-bold">{{Session::get('flash_msg_danger')}}</p>
    </div>
@endif
@if(Session::has('flash_msg_alert'))
    <script>
        alert('{{Session::get("flash_msg_alert")}}');
    </script>
@endif
```

**Criada a view e usada como include nos forms e telas que vc precisa exibir a mensagem basta defini-la antes do redirect com:**

```php
\Session::flash('flash_msg', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_primary', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_success', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_info', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_warning', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_danger', 'Ação realizada com sucesso.');
\Session::flash('flash_msg_alert', 'Ação realizada com sucesso.');
```

**Laravel BD Transaction**

No laravel você pode colocar uma sequencia de transações com o banco dentro de uma especie de `try/catch` onde se todas tiverem sucesso serão todas gravadas e se acontecer algum erro no meio do caminho todas as transações do bloco serão desfeitas.

**Exemplo de uso:**

```php
use DB;
DB::beginTransaction();                 //abre o bloco de transaction
    $insercao_1 = create(‘ble ble’);    //transação 1
    $insercao_2 = create(‘bla bla’);    //transação 2
if($insercao_1 && $insercao_2){         //verifica se tudo correu bem
    DB::commit();                       //salva tudo no banco
}else{
    DB::rollback();                     //caso deu algum erro da rollback em todas as transações feitas dentro do bloco
}
```

## Eloquent

Quando você cria um model através do `artisan` ele já vem associado à tabela criada pelo seu migration e vários metodos usaveis do ORM eloquent.

Para exemplificar usaremos um registro `user` com:

- name
- telefone
- status

Seguindo as convenções de nomenclatura do laravel o model sera User e a tabela users.

Entre os principais métodos estão:

**Criando um usuario:**

```php
$user = new User();
$user->name = ‘Peter’;
$user->telefone = ‘992192851’;
$user->status =1;
$user->save();
$id = $user->id;                //voce pode recuperar o id imediatamente após salvar o objeto no banco se precisar
```

**Resgatando um registro:**

```php
$user = User::find($id);                    //retorna o registro em forma de objeto se existir ou null
$user = User::findOrFail($id)               // retorna o registro em forma de objeto ou da erro se ele não existir
$users = User::find([1, 2, 3]);             // retorna um array de objetos (Collection) usuários dos ids passados
$users = User::all();                       // retorna um array de objetos com todos os registros do banco
$users = User::where(‘name’, ‘Peterson’)    // retorna um array de objetos 
            ->orderBy(‘name’, ‘desc’)       // onde name = peterson order by 
            ->take(10)                      // name desc limit 0,10
            ->get();
$user = User::where(‘status’, 1)->first();  //retorna o primeiro status 1 da tabela ou null
$user = User::where(‘status’, ‘>’, 0)->firstOrFail(); //retorna o primeiro status maior que zero da tabela ou um erro
$usersActives = User::where(‘status’, 1)->count();  //int com o número de status =1 da tabela
```

**Alterando um registro**

```php
$user = User::find($id);
$user->name = ‘<NAME>’;
$user->save();
```

**Apagando o registro `id=1` do banco**

```php
$user = User::find(1);
$user->delete();
```

ou

```php
User::destroy(1);
User::destroy([1,2,3]); //vc pode deletar vários se precisar
```

**Sobre SoftDeletes**

`SoftDelete` é um conceito muito interessante que você tem que estudar para implementar no projeto. Trata-se de uma lixeira para onde vão os registros e excluidos e que podem ser listados, recuperados ou excluídos definitivamente depois.

## Fluxo de programação

Diferente de outros frameworks, o laravel não define rotas automaticamente para cada controller. 

Se a rota não existir vai dar erro, logo você precisar registrar todas as rotas de seu app.

Principais tipos de rotas:

```php
# Chamando uma view
Route::get('/', function () {
    return view('welcome');
});

# Chamando view passando variaveis a ela
Route::get('/', function () {
    $dados = array(
      'titulo' => 'Peterson'
    );
    return view('welcome', $dados);
});

# Chamando um metodo de um controller
Route::get('/home', 'HomeController@index');
```

## Acrescentando helpers personalizados

Há duas maneiras de adicionar seus próprios helpers a aplicação,

A primeira é jogar suas functions helpers no arquivo: 

`vendor\laravel\framework\src\Illuminate\Foundation\helpers.php`

A segunda é criando dentro de `app/helpers/seu_helper.php`, adiciona-lo ao `composer.json` e dar um `composer dump` no terminal

Exemplo de como add ao `composer.json`:

```json
    "psr-4": {
        "App\\": "app/"
    },
    "files": [
        "app/Helpers/MyHelper.php"
    ]
```

## Logs

```php

use Illuminate\Support\Facades\Log; //registre o uso do log no seu controller

# use um dos niveis de log definidos na rfc5424 e registre sua mensagem, 
# os logs ficam em storage/logs
    Log::emergency($message);
    Log::alert($message);
    Log::critical($message);
    Log::error($message);
    Log::warning($message);
    Log::notice($message);
    Log::info($message);
    Log::debug($message);
```

## Requisições

- todo o formulario deve conter a linha `{{ csrf_field() }}`
- a rota que recebe o formulario deve especificar se é uma requisição POST ou GET ou qualquer outra personalizada
- no controller a requisição vem na forma de um objeto `$request` do laravel e para receber os dados você usa assim:

```php
nome = $request->nome #sendo nome = name do input que você tá recebendo
```

- no formulario de edição você deve especificar o `id` do item editado na url para o routes saber que se trata de uma variavel e passar para o controller ex.:

```php

<form method="post" action="{{ url('noticia/'.$news->id.'/editar') }}">

Route::post('/noticia/{news}/editar', 'newsController@edit');

public function update(Request $request, News $news)
{

    $news->title = $request->title;
    $news->text = $request->text;
    $news->save();

    return redirect(route('listar_noticias'));
}
```

No formulario de edição os `values` dos inputs devem ser preenchidos assim value="{{ $news->title }}"

## Validando requisições

a forma mais simples de fazer isso é validando no controllers antes de salvar os dados vindos da request. 

Exemplo:

```php
$request->validate([
    'title' => 'required|unique:posts|max:255',
    'text' => 'required|min:6',
]);
```

dentro do array validate você passa como primeiro parametro o name do campo que esta chegando pela request e no segundo parametro as regras de validação.

Se passar na validação, o método vai prosseguir normalmente, se não passar irá retornar para o form onde você deve colocar o seguinte metodo antes da abertura do form para exibir os erros:

```php
@if ($errors->any())
    <div class="alert alert-danger">
        <ul>
            @foreach ($errors->all() as $error)
                <li>{{ $error }}</li>
            @endforeach
        </ul>
    </div>
@endif
```

## Principais regras de validação

Regra | Efeito
--- | ---
accepted  | somente checkbox marcado
alpha  | somente caracteres alphabetics
alpha_num  | somente alfanumericos
confirmed | deve bater com outro campo de nome igual mais sufixo _confirmation ex.: pass = pass_confirmation
e-mail  | deve ser um e-mail valido
image  | deve ser uma imagem jpeg, png, bmp, gif ou svg
integer  | deve ser um inteiro
max:999  | numero maximo de caracteres
min:9 | numero minimo de caracteres
nullable | pode ser nulo input type text
numeric | somente numeros
required | obrigatorio
string | somente texto
unique:tabela | deve ser unico na tabela com a coluna do mesmo name

## Traduzindo nomes de campos nas mensagens de erro

Vá ate o final do arquivo `resources/lang/pt-BR/validation.php` e edite o seguinte array:

```php
'attributes' => [
    'name_do_input'    => 'Nome conforme você quer que apareça na mensagem',
    'name_do_input'    => 'Nome conforme você quer que apareça na mensagem',
],
```

## Sistema de autenticação nativo

Se você for inserir um usuário por outro método, você deve passar a senha dele pela funcao `bcrypt(‘123’)` para que depois o metodo autenticador reconheça essa senha

## Sistema de niveis de acesso nativo

Existem dois métodos de se fazer isso:

1) As regras (Gates) que servem para visualização de itens ou acesso a area restritas daquele nivel entre outras coisa

2) As politicas onde você define regras para cada model especifico.

```php
Gate::define('habilidade_requerida', function ($user, $post) {
    return 'uma logica que retorne true ou false para a permissao';
});
```

Nesse exemplo estou validando um `post` passado como parametro. O `user` **não** precisa ser passado pois o Gate já pega o objeto user logado.

No controller verifique assim:

```php
if (Gate::denies('habilidade_requerida', $post)) {
    // se entrou aqui é porque o usuario não pode executar essa ação então mande um erro.
}
```

Não esqueça de dar um `use Gate` no controller.

## Upload de arquivos

Existem varias formas mas a que eu achei mais facil é a seguinte:

- dentro da pasta `public`, crie uma pasta `images` e ponha a `sua_imagem.jpeg` lá
- dentro de sua pasta public crie uma pasta uploads e de permissões para ela
- no arquivo config/filesystem.php configura o root do disco local na linha 48 para public_path()
- no formulario não esquece o enctype e o input tipe file
- no controler você recebe conforme o exemplo abaixo onde usei o nome image para o input

```php
if ($request->hasFile('image') && $request->file('image')->isValid()) {
     $nome_da_imagem_salva = $request->image->store('uploads');
}
```

Na view para exibir a imagem você usa o source assim:

    {{ asset($nome_da_imagem_salva) }}

Na hora de excluir a imagem do banco, exclua o arquivo da seguinte forma:

```php
if (!empty($post->image) && file_exists(public_path($post->image))) {
    unlink(public_path($post->image));
}
```

## Front-end

Atalhos úteis do Blade Template:

```php
{{ url(‘/seu link’) }} = url base
{{ asset('css/app.css') }} = url base da pasta public
{{ config('app.name', 'Laravel') }} = pega o nome da aplicação do .env ou coloca o segundo parametro se a opção não estiver definida
{{ Auth::user()->name }} = exibir dados do usuario logado
{{ route('name_da_rota') }} = você pode definir um ->name(‘nome’) para suas rotas e chamar os links delas no front dessa forma simplificada 
{{ csrf_field() }} = campo de segurança obrigatorio em todos os formularios do app
```

### Exibir itens somente para quem esta logado

@guest
    ‘convidado’
@else
    ‘usuario logado’
@endguest = if que faz ações diferentes se o usuario for ou não convidado

@auth
    ‘logado’
@else
    ‘nao logado’
@endauth = if que faz ações diferentes se o usuario estiver ou não logado

## Exibir itens somente para quem tem permissao de ver aquele item

```php
@can(‘nivel de acesso exigido’, alguma variavel que você precise passar para verificação)
    ‘pode visualizar pois tem o nivel necessario de acesso’
@else 
    ‘opcional para aparecer caso o conteudo tenha sido bloqueado por falta de acesso’
@endcan

value="{{ old('email') }}" = preenche o campo com o valor submisso anteriormente caso de algum erro

```

## Usando layouts do blade

Você cria um layout mestre com cabeçalho e rodapé no meio dele você utiliza a tag `@yield('content')` por exemplo.

Quando você for colocar algo dentro daquele espaço você faz assim:

```php
# Exemplo de um arquivo que extende um layout master

# Vai buscar a view dentro de /resources/views/layouts e extende a view 'app.blade.php'
@extends('layouts.app')
@section('content')
// Seu HTML vai aqui
@endsection
```

você estendeu o layout padrao e definiu aquele bloco de codigo `//Seu HTML vai aqui`  como aquela section dele

## Projeto no mundo real

- crie um novo site no painel da hostinger
- acesse ele por ssh e com o composer crie uma nova aplicação laravel
- crie outra pasta na raiz chamada repo.git pára abrigar seu repositorio
- dentro dessa pasta crie um repositório git do tipo **bare** com: `git init –-bare`
- puxe o projeto da pasta da aplicação para esta do repo
- crie o hook post receive
- puxe a aplicaçao para sua maquina local via git clone
- configure o git remoto para o repo.git do servidor
- as vezes vem com permissoes eradas, puxe a pasta para a pasta home, rode `sudo chown -R seu_user:seu_user`
- jogue ela devolta para o htdocs
- codifique mt e a cada commit você da um push para o repositorio remoto que você configurou
- quando você cria algo no artisan em localhost, ao subir deve executar um composer dump-autoload para as novas classes serem reconhecidas
<file_sep>/adicionar_repositorio_remoto.md
# Adicionar repositorio remoto no git 

## Adicionando o host abra o arquivo /etc/host

    sudo nano /etc/hosts
    adicione o ip do servidor junto com o nome que vc quiser dar a conexão
    172.16.17.32   exemplo_homologa
  
## Adicionando o ssh Editar o arquivo (se não existir crie)

    sudo nano ~/.ssh/config
  
### adicione aqui o host que vc criou com user e port

    Host exemplo_homologa
      User meu_user
      Port 1234
      
### adicione sua chave ssh ao servidor p não precisar mais digitar senha

    ssh-copy-id usuário@host
    
## Adicionando ao git Agora que vc add o host e os dados de ssh vc pode adicionar o remote ao git

    git remote add homologa exemplo_homologa:repo.git
 
Pronto, agora vc ja pode dar push para homologa que o git so vai pedir a senha de ssh
<file_sep>/django/models.md
## Campos disponiveis para models no django

```python
from django.db import models

#tupla de tuplas que serão usadas como opções de um select
BEBIDAS = (('cafe',u'Café expresso'), ('mate',u'Chá mate'), ('chocolate',u'Chocolate quente'))

# perceba que campos de textos não obrigatórios devem ser 'blank=True' pq o valor minimo que o
# django trabalho para um campo texto é um texto em branco, o 'null=True' deve ser usado em todos
# os outros tipos de campo não obrigatorios exceto em campos texto que deve obrigatoriamente ser
# blank

class Pessoa(Models.model):
    # campo de texto com max 191 caracteres, pode ser um teto em branco e unique com mensagens de erro personalizadas para cada tipo de validação que pode dar errada
    name = models.CharField(
        'Nome',
        max_length=191,
        blank=True,
        unique=True,
        error_messages={
            'unique': _("A user with that username already exists."),
            'null': _('Não pode ser nulo!')
        },
    )

    # campo inteiro, se n for passado assume o valor padrao de 0
    bank_balance = models.IntegerField('Saldo na conta', default=0)

    # campo inteiro que não aceita numeros negativos
    qt_friends = models.PositiveIntegerField('Quantidade de amigos', default=0)

    # decimal de 8 casas sendo 2 apos a virgula ('ideal para valores monetarios')
    value_in_the_pocket = models.DecimalField('Valor no bolso', max_digits=8, decimal_places=2)

    # campo date
    birth_date = models.DateField('Data de nascimento')

    # campo datetime
    first_kiss = DateTimeField('Data e hora do primeiro beijo')

    # campo time
    when_wake_up = TimeField('Horário em que acorda')

    # campo texto com validação 'é um slug'
    slug = models.slugField('Slug', help_text='Texto de ajuda do campo. Usado em formulário gerados pelo Django. Útil para exibir exemplo de preenchimento')

    # campo texto longo permite texto em branco
    description = models.TextField('Descrição', blank=True)

    # fk apontando para um objeto cpf com relação 1 x 1 e clausula de ser deletado em cascata
    credit_card = models.OneToOneField(CreditCard, on_delete=models.CASCADE)

    # fk para varios objetos Livro com tabela pivot
    livros = models.ManyToManyField(Livro)

    # campo texto que é apresentado como um select apresentando as opções definidas na constante que é passada como parametro
    favorite_drink = models.CharField('Bebida Favorita', max_length=16, choices=BEBIDAS)

    # campo texto com validação para email not null
    email = EmailField('Email', null=False)

    # campo texto com validação para url
    site = URLField('Endereço na web')

    # campo texto apresentado como um input file que armazenara o caminho no banco e o arquivo no sistema de arquivos
    curriculum = FileField('Currículo em PDF')

    # campo texto apresentado como um input file que armazenara o caminho no banco e o arquivo no sistema de arquivos, com validação para o arquivo ser tipo imagem
    photo = ImageField('Foto do perfil')

    #######################################################################################################
    # O Django trata uploads salvando o arquivo no sistema de arquivos e o caminho do arquivo no banco de #
    # dados, para isso vc deve setar em seu settings do projeto a pasta onde ele salvara os arquivos      #
    # Colocar no settings:  MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')                                #
    #######################################################################################################

    # campo file que armazenara o arquivo em uploads/files/
    curriculum = models.FileField('Currículo em PDF', upload_to='files', null=True, blank=True)
    # campo file com validação para imagens que armazenara o arquivo em uploads/files/images/
    photo = models.ImageField('Foto do perfil', upload_to='images', null=True, blank=True)
    # auto_now_add=True significa que sera preenchido com o datetima atual quando o objeto for criado
    created_at = models.DateTimeField('Criado em', auto_now_add=True)
    # auto_now=True significa que sera preenchido com o datetima atual sempre que o objeto for salvo
    updated_at = models.DateTimeField('Atualizado em', auto_now=True)

    # A 'class Meta' serve para definir metadados da classe
    class Meta:
        # como a classe sera ordenada na exibição em lista
        ordering = ('name', 'birth_date', 'qt_friends')

        # label do model
        verbose_name = 'Serumaninho'

        # label do model no plural
        verbose_name_plural = 'Pessoinhas'

        # Estabelece o campo DateTime a ser usado como critério para o método de consulta latest.
        get_latest_by = self.first_kiss

        # Define que este é um modelo abstrato (abstract model), que não será persistido em uma tabela mas será usado para definir um esquema reutilizável por herança.
        abstract = False

        # Define o nome da tabela que corresponde ao modelo. Quando esta opção não é usada o nome da tabela é aplicao_modelo (ex.: catalogo_livro é o modelo Livro da aplicação catalogo.
        db_table = 'nem rela aqui, so com banco legado'
```
<file_sep>/git_workflow.md
# Workflow básico de desenvolvimento

## Divisão de Branches

**Branches ativos**
- `master` -> Código estável e testado, publicado tanto em homologação quanto em produção
- `homologacao` -> Código que foi testado na máquina de desenvolvimento e está sendo testado no servidor de testes
- `peterson` -> Branch _*work in progress*_ do trabalho do Peterson
- `girol`- > Branch _*work in progress*_ do trabalho do Girol

As divisões de trabalho serão feitas nos cards.

**Branches tópicos (temporários)**

Branches que serão usados para resolver um problema pontual. Na maioria dos casos será para resolução de *bugs* :bug: .

### Passo a passo para resolução de problemas com branches tópicos:

1. Abrir uma _issue_
    
    Exemplo: Sistema não redireciona para painel após login.

2. Criar um `branch` com o nome da issue + seu número. Exemplo:

```bash
# Supondo que a issue tenha o número 42
git checkout -b issue_42
```

3. Commitar mudanças
4. Incluir no seu commit a mensagem: `Fix #42` (número da issue que foi aberta)
5. Dar merge em todos os branches ativos para integrar a resolução do bug em todos os cenários

## Integrando funcionalidades

As funcionalidades só podem ser integradas através de _*Pull Requests*_.

_*Pull Requests*_. são como um documento ativo que registra integrações de código no sistema _estável_.

Passo a Passo:

1. Depois de testado em ambiente de desenvolvimento, abrir um `pull request` no GitHub
2. Verificar quais _issues_ esse `pull request` resolve e marcar na caixa de comentários
3. Verificar conflitos e integrar as mudanças
4. Sincronizar seu clone na máquina de desenvolvimento
5. Dar merge no branch `homologacao`
6. Publicar em `homologação` e enviar para o cliente testar
<file_sep>/django/objetosDoBanco.md
Como trabalhar com objetos vindos do banco de dados em django

```python
#criando um objetona memoria
q = Question(question_text="What's new?", pub_date=timezone.now())
# salvando no banco
>>> q.save()
# agora ele ja tem um ID.
>>> q.id
1
# acessando os valores de seus campos
>>> q.question_text
"What's new?"
>>> q.pub_date
datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>)
# Mudando o valor de um campo e depois salvando-o
>>> q.question_text = "What's up?"
>>> q.save()
# objects.all() retorna todos os objetos do banco daquele model
>>> qs = Question.objects.all()
# contando os objetos
>>> qs.count()
# retorna todos os objetos do banco daquele model em ordem pelo campo passado
>>> qs = Question.objects.order_by('headline')
# retorna todos os objetos do banco daquele model em ordem descendente pelo campo passado
>>> qs = Question.objects.order_by('headline').desc()
# retorna todos os objetos do banco daquele model em ordem ascendente pelo campo passado
>>> qs = Question.objects.order_by('headline').asc()
# pegando por chave primaria ('id')
>>> q = Question.objects.get(pk=1)

###############################################################################
#                                  Lookups                                    #
###############################################################################
# são sufixos que começam com __ e que representam filtros para serem usados  #
# na query                                                                    #
###############################################################################

# pegando por id passando um array, retorna um queryset
>>> q = Question.objects.filter(id__in=[1, 3, 4])
# filtrando por campos
>>> q = Question.objects.filter(question_text="What's up?")
# filtrando por campos mas ignorando caixa alta/caixa baixa
>>> q = Question.objects.get(name__iexact="what's up?")
# filtrando por campos que contem aquele conteudo
>>> q = Question.objects.get(name__contains='up')
# filtrando por campos que contem aquele conteudo mas ignorando caixa alta/caixa baixa
>>> q = Question.objects.get(name__icontains='uP')
# inicia com
>>> q = Question.objects.filter(question_text__startswith='What')
# inicia com, mas ignorando caixa alta/caixa baixa
>>> q = Question.objects.filter(question_text__istartswith='What')
# termina com
>>> q = Question.objects.filter(question_text__endswith='up')
# termina com, mas ignorando caixa alta/caixa baixa
>>> q = Question.objects.filter(question_text__iendswith='UP')
# datetime pertence ao ano de 2018
>>> q = Question.objects.get(pub_date__year=2018)
# datetime tem mes de 12
>>> q = Question.objects.get(pub_date__month=12)
# datetime tem dia de 21
>>> q = Question.objects.get(pub_date__day=21)
# datetime tem dia da semana como segunda-feira
# ('1 == domingo' '2 == segunda' ... '7 == sabado')
>>> q = Question.objects.get(pub_date__week_day=2)
# datetime tem data == Null
>>> q = Question.objects.get(pub_date__isnull=True)
# datetime tem data != Null
>>> q = Question.objects.get(pub_date__isnull=False)
# datetime com ano maior ou igual a 2015
>>> q = Question.objects.get(pub_date__year__gte=2015)
# exclui pub com data maior a hoje ('__gt == grand than')
>>> q = Question.objects.exclude(pub_date__gt=datetime.date.today())
# filtra os com data menor a hoje ('__lt == less than')
>>> q = Question.objects.filter(pub_date__lt=datetime.date.today())
# exclui pub com data maior ou igual a hoje ('__gte == grand than equal')
>>> q = Question.objects.exclude(pub_date__gte=datetime.date.today())
# filtra os com data menor ou igual a hoje ('__lte == less than equal')
>>> q = Question.objects.filter(pub_date__lte=datetime.date.today())
# pega as questions filtrando por um name no Blog que é um attr relacionado ('fk')
# basta usar o nome do model relacionado todo em caixa baixa
>>> q = Question.objects.filter(blog__name='Beatles Blog')
# Este exemplo retorna todos os objetos Blog``os quais tem pelo menos uma ``Entry a qual o headline contém 'Lennon':
>>> b = Blog.objects.filter(entry__headline__contains='Lennon')

# LIMIT
# pega 5 objetos ('indices negativos não sao suportados')
>>> q = Question.objects.all()[:5]
# pega do 5° ao 10° objeto ('indices negativos não sao suportados')
>>> q = Question.objects.all()[5:10]
# pega do 5° ao 10° objeto ('indices negativos não sao suportados')
>>> q = Question.objects.all()[5:10]
# range de datas ('BETWEEN')
import datetime
start_date = datetime.date(2005, 1, 1)
end_date = datetime.date(2005, 3, 31)
>>> q = Question.objects.filter(pub_date__range=(start_date, end_date))

```
<file_sep>/laravel/cidades_e_estados_laravel/README.md
# Cidades e estados para projetos laravel

adicione todos os arquivos do repositorio cada um em sua pasta e roda

	composer dump-autoload
	
	php artisan migrate:fresh --seed
	
pronto, vc já tem uma base de dados com todos os estados brasileiros e suas cidades

## Instruções de uso

#### create do model que terá no endereço fk's para estado e cidade

Para ter todos os estados em ordem alfabética disponíveis para seleção no formulário, no metodo create passe pasa a view a seguinte variavel

```php
$states = \App\Models\State::orderBy('name')->get();
```
	
no seu **routes/web** registre a seguinte rota publica auxiliar

```php
Route::get('api/cidades_por_estado/{estado}', 'StateController@cities_by_state');
```
	
No **StateController** registre o metodo que retornará as cidades do estado atual do select

```php
/**
* Busca no banco por todas as cidades do estado passado e as retorna
* 
* @return JSON
*/
public function cities_by_state($id_estado) {
$state = \App\Models\State::find($id_estado);
$cities = $state->cities;
return $cities;
}
```
	
na **view** adicione os seguintes campos

```html
<!-- estado -->
<div class="form-group">
    <label class="control-label" for="estado">Estado</label>
    <select id="estado" name="state_id" class="form-control">
	<option value="">Escolha um estado</option>
	@foreach($states as $state)
		<option value="{{ $state->id }}">{{ $state->name }}</option>
	@endforeach
    </select>
</div>

<!-- cidade -->
<div class="form-group">
    <label class="control-label" for="cidade">Cidade</label>
    <select id="cidade" name="city_id" class="form-control" disabled>
	<option value="">Escolha um estado</option>
    </select>
</div>
```
        
e o seguine javascript

```javascript
@section('js')
<script>
    function atualizar_cidades(assincrono = true){
        var estado = $('#estado').val();
        var page = "{{ url('api/cidades_por_estado') }}/" + estado;
        $.ajax({
            type: 'GET',
            dataType: 'html',
            url: page,
            async: assincrono,
            beforeSend: function () {
                $("#cidade").prop('disabled', true);
            },
            success: function (msg) {
            var cidades = JSON.parse(msg);
            var options = '';
            for (var i = 0; i < cidades.length; i++) {
                var obj = cidades[i];
                options += '<option value="' + obj.id + '">' + obj.name + '</option>';
            }
            $("#cidade").empty();
            $("#cidade").append(options);
            $("#cidade").prop('disabled', false);
            }
        });
    }
    $(document).ready(function () {

        $('#estado').val('{{ $user->state_id }}');      //seleciona o estado do $user
        atualizar_cidades(false);                       //atualiza cidades de acordo com o estado 
        $('#cidade').val('{{ $user->city_id }}');       //seleciona a cidade do $user
        
        @if (old('city_id') !== NULL)
            $('#estado').val({{ old('state_id') }});    // se existir um old('cidade') faz o 
            atualizar_cidades(false);                   // mesmo processo acima dando 
            $('#cidade').val({{ old('city_id') }});     // prioridade ao old()
        @endif

        $('#estado').change(function () {
            atualizar_cidades();                        // atualiza as cidades a cada alteração no estado
        });
    });
</script>
@endsection
```
<file_sep>/laravel/tdd.md
# TDD com Laravel e PHPUnit

Tutorial baseado na série de artigos de <NAME>. Link [aqui](https://medium.com/@jsdecena/simple-tdd-in-laravel-with-11-steps-c475f8b1b214). (Em inglês)

Foi utilizado também [este link](https://www.devmedia.com.br/test-driven-development-tdd-simples-e-pratico/18533) do DevMedia. (Em português)

## Preparando a suíte de testes do Laravel

No diretório raiz do projeto, atualize o arquivo `phpunit.xml` com:

```xml
<env name="DB_CONNECTION" value="sqlite"/>
<env name="DB_DATABASE" value=":memory:"/>
<env name="API_DEBUG" value="false"/>
<ini name="memory_limit" value="512M" />
```

Ficará algo parecido com isso:

```xml
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
         backupStaticAttributes="false"
         bootstrap="vendor/autoload.php"
         colors="true"
         convertErrorsToExceptions="true"
         convertNoticesToExceptions="true"
         convertWarningsToExceptions="true"
         processIsolation="false"
         stopOnFailure="false">
    <testsuites>
        <testsuite name="Feature">
            <directory suffix="Test.php">./tests/Feature</directory>
        </testsuite>

        <testsuite name="Unit">
            <directory suffix="Test.php">./tests/Unit</directory>
        </testsuite>
    </testsuites>
    <filter>
        <whitelist processUncoveredFilesFromWhitelist="true">
            <directory suffix=".php">./app</directory>
        </whitelist>
    </filter>
    <php>
        <env name="APP_ENV" value="testing"/>
        <env name="CACHE_DRIVER" value="array"/>
        <env name="SESSION_DRIVER" value="array"/>
        <env name="QUEUE_DRIVER" value="sync"/>
        <env name="DB_CONNECTION" value="sqlite"/>
        <env name="DB_DATABASE" value=":memory:"/>
        <env name="API_DEBUG" value="false"/>
        <env name="MAIL_DRIVER" value="log"/>
        <ini name="memory_limit" value="512M" />
    </php>
</phpunit>
```

Usando o banco de dados como `:memory` acelera os testes, bem como `sqlite`. Futuramente, com os testes ficando mais complexos, deve-se ajustar o `memory_limit` para um valor maior.

O Debugging também é desabilitado para mostrar apenas os resultados dos testes.

### Sanity Checks

Caso você utilize o servidor de desenvolvimento incluído com o Laravel, você não terá tantos problemas com isso. Caso contrário, é necessário que você limpe os caches de `views`, `rotas` e demais recursos que o Laravel cacheia. Utilize os comandos:

```bash
artisan cache:clear
artisan view:clear
artisan route:clear
artisan clear-compiled
artisan config:clear
```

Uma boa ideia é encapsular esses comandos em um único comando do Artisan

## Tipos de testes

### Testes Unitários (Unit Testing)

Servem para testar suas classes: Models, Repositórios, Funções, etc.

### Testes de Funcionalidade (Feature Testing)

Servem para testar se seu código, por exemplo, acessa os controllers e verica (asserts) se as ações tomadas são as esperadas, ou até mesmo erros. Por exemplo, acessando uma página que precisa de autenticação, se um erro gera uma _Flash Message_ na sessão ou até mesmo se um redirecionamento ocorre de forma correta.


## Ciclo do TDD

Red, Green, Refactor. Ou seja:

- Escrevemos um Teste que inicialmente não passa (Red)
- Adicionamos uma nova funcionalidade do sistema
- Fazemos o Teste passar (Green)
- Refatoramos o código da nova funcionalidade (Refactoring)
- Escrevemos o próximo Teste


    Novo Teste -> Teste Falhando -> Nova Funcionalidade -> Teste Passando -> Refatoração (Retorna)

## Sanity Checks

Perdi muito tempo tentando debugar testes por assumir que a suíte de testes fará algumas coisas por mim. Abaixo algumas dicas:

- Ao gerar um recurso com uma factory utilizando `make()`, lembre-se de ter todos os atributos que precisa na definição da factory. Normalmente assumimos os campos com valores `default` no banco quando vamos gerar seeders, mas no teste isso não acontece.

- Ao testar o envio de uma request de qualquer tipo que não `GET`, certifique-se de ter todos os atributos que precisa na request. O phpunit por padrão não exporta os erros, mostrando apenas um internal error com status 500. Às vezes é possível debugar pelo log, mas às vezes ele não loga, como por exemplo, um atributo required que não foi enviado, vai gerar um `return back()` jogando você de volta para `localhost`.

### Exemplos de TDD com Laravel

## TODO
<file_sep>/README.md
# Roteiros
Uma coletânea de roteiros e anotações sobre as ferramentas e linguagens de programação
<file_sep>/ambiente_local_apache_dns.md
# Preparando ambiente local de desenvolvimento com Apache

Este roteiro visa auxliar a configuração de um dns local em sua máquina para trabalhar com urls completas

Crie suas pastas de projeto na seguinte estrutura:

    /caminho/para/pasta/projetos/site1/www

`site1` é onde estará armazenado um projeto. `www` será a pasta visível para o apache.

## Editando arquivo de hosts

Supondo que o seu projeto será hospedado no domínio site1.com.br

Edite o arquivo `/etc/hosts` e adicione a entrada:

    127.0.0.1   site1.com.br

## Configurando o virtualhost no apache

Vá até:

    /etc/apache2/sites-available

[ Descrever aqui o processo de deploy de um site ]

### Dnsmasq<file_sep>/laravel/basic_api_authentication.md
# Autenticação basica para rotas de API no laravel

No arquivo de rotas proteja a rota desejada com o middleware auth.basic

```php
Route::resource('vehicles', 'VehicleController')->middleware('auth.basic')
```

Para ter acesso a essa rota vc deve mandar um header na requisição chamado Authorization e seu conteudo devera ser a string 'Basic' + espaço + um base64 do '<EMAIL>:userPassword' do usuario

### Exemplo:

Dado um usuario com email `<EMAIL>` e senha `<PASSWORD>`

- concatenamos `email` + `:` + `senha` resultando na string `<EMAIL>:<PASSWORD>`

- convertemos essa string para base64 resultando em `YWRtaW5AYWRtaW4uY29tOnBhc3N3b3Jk`

e Enviamos o seguinte header na request protegida por autenticação

```
Authorization  :  Basic YWRtaW5AYWRtaW4uY29tOnBhc3N3b3Jk
```
<file_sep>/laravel/cidades_e_estados_laravel/app/Http/Controllers/CityController.php
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Models\City;

class CityController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return City::all();
    }
}
<file_sep>/laravel/queue.md
# Laravel Queues

Nesse tutorial usaremos apenas o modo database

## Conceito

- Criamos as tabelas que abrigarão as filas
- Criamos varias filas de acordo com nossa necessidade para classificar os tipos de jobs que vamos enfileirar
- Criamos os jobs que receberão nossas variaveis pelo construct e jogarão em atributos protected para poder usar no processamento
- Uma vez criado um job e preparado para receber as variaveis pelo construtor e passar para seus proprios atributos 'protected', criamos nossa logica de processamento dentro do metodo handle() usando os atributos protected criados no construtor para popular as variaveis da logica
- Nos controllers instanciamos o job passando o que precisamos de variaveis para seu construtor ('as variaveis devem ser passadas no método dispatch para cair no construtor do job') e damos um dispatch para mandar o job pra fila
- Instanciamos um laravel-worker que vai tomar conta dessa fila e processar cada job que cair nela, apagando os concluidos e mandando para a tabela failed_jobs aqueles que não puderam ser feitos por algum motivo

## Instruções

### Criamos as tabelas que abrigarão as filas

Primeiramente você deve gerar a tabela e rodar a migration para que os jobs possam ser enfileirados nessa tabela e os falhados enfileirados na tabela failedjobs para tratamento posterior

```php
php artisan queue:table
php artisan queue:failed-table

php artisan migrate
```

### Criamos varias filas de acordo com nossa necessidade para classificar os tipos de jobs que vamos enfileirar

arquivo config/queue.php

```php
//fila default
'database' => [             //nome da conexão
    'driver' => 'database', //driver
    'table' => 'jobs',      //tabela ('mantenha o padrao jobs')
    'queue' => 'default',   //nome da fila
    'retry_after' => 90,    //tempo para tentar refazer um job falhado
],
//nossa fila personalizada emails
    'database' => [         //nome da conexão
    'driver' => 'database', //driver
    'table' => 'jobs',      //tabela ('mantenha o padrao jobs')
    'queue' => 'emails',    //nome da fila
    'retry_after' => 90,    //tempo para tentar refazer um job falhado
],
```

### Criamos os jobs que receberão nossas variaveis pelo construct e jogarão em atributos protected para poder usar no processamento

#### para esse exemplo vamos fazer uma fila de emails que recebe duas variaveis: o remetente e o laravel_mailable ja instanciado e preenchido

- Crie a fila

```php
php artisan make:job EmailQueue
```

- A classe job ficará +- assim

```php
<?php

namespace App\Jobs;

use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Mail;// <<< use no Mail
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;

class EmailQueue implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    //attrs que recebem os dados que vem pelo construct
    protected $destinatario;
    protected $mailable;

    /**
     * Create a new job instance.
     *
     * @return void
     */
    public function __construct($destinatario, $mailable)
    {
        //passando vars recebidas no construct para attrs do job
        $this->destinatario = $destinatario;
        $this->mailable = $mailable;
    }

    /**
     * Execute the job.
     *
     * @return void
     */
    public function handle()
    {
        //aqui fica a logica do job
        Mail::to($this->destinatario)->send($this->mailable);
    }
}

```

## No controller instanciamos o job e damos um dispatch para mandar ele pra fila

### Instanciamos o job passando o que precisamos de variaveis para seu metodo dispatch() que jogara as vars passadas no construct do job

```php
$data['token'] = '123'; //dados para criar o mailable
$mailable = new App\Mail\EmailConfirmation($data); //criando mailable
$destinatario = '<EMAIL>'; //destinatario do mailable
App\Jobs\EmailQueue::dispatch($destinatario, $mailable);
                ->delay(now()->addSeconds(30)) //add um delay para execução apos cair na fila
                ->onQueue('emails') //escolhe a fila p colocar o job, se nenhuma for escolhida caira na fila default
```

## Instanciamos um laravel-worker para tomar conta da fila

### O worker processa cada job que cair na fila, apagando os concluidos e mandando para a tabela failed_jobs aqueles que não puderam ser feitos por algum motivo

```php
php artisan queue:work
```
<file_sep>/bs_configurar_accordion.md
Como configurar corretamente o accordion bootstrap para se montar dinamicamente com os videos do bd

	- o id do panel-group que envolve tudo deve ser o mesmo do data-parent dos button do panel-title
	- o id do panel-collapse deve ser colocado em href e aria-controls do button do panel-title
	- o id do panel-heading deve ser colocado em aria-labelledby no panel-collapse
<file_sep>/django/otimizacoes.md
# Otimização de consultas django

```python
# para pré carregar os objetos relacionados ('one_to_one') de um objeto 'pai' use a seguinte sintaxe

    pessoa = Pessoa.objects.select_related('cpf').get(id=1)

# e ja teremos o objeto cpf que carrega a fk daquela pessoa acessivel em pessoa.cpf

# para relação one_to_many utilize

    pessoa = Pessoa.objects.prefetch_related('carros').get(id=1)

# e ja teremos todos os carros da pessoa acessivel no iteravel pessoa.carros

```
<file_sep>/django/django.md
# Instalação basica de um projeto em python/django

Para esse exemplo vamos usar _wttd_ como nome do diretorio de trabalho e _eventex_ como nome do projeto

_Para facilitar sua vida crie o seguinte alias em seu bashrc ou zshrc_

    alias manage='python $VIRTUAL_ENV/../manage.py'

## Criando o projeto

crie a pasta do projeto e entre nela

    mkdir wttd
    cd wttd

crie o venv

    # Como boa prática, utilizar o nome venv ou .venv
    python -m venv .venv

ative o `venv`

    source .wttd/bin/activate

instale o django

    pip install django

inicialize o projeto

    django-admin startproject eventex .

entre no projeto e crie a app núcleo do projeto

    cd eventex
    manage startapp core

no arquivo _wttd/eventex/settings.py_ adicione a lista INSTALLED_APPS o app que vc acabou de criar para o projeto reconhecê-lo

    'eventex.core',

no arquivo _eventex/urls.py_ importe as views do core e adicione a rota que sera atendida por seu metodo **home**

```python
    import eventex.core.views
    ...
    path('', eventex.core.views.home),
```

no arquivo _eventex/core/views.py_ adicione o método que atenderá essa rota

```python
    def home(request):
        return render(request, 'index.html')
```

perceba que o metodo home chama o arquivo index.html que é um template, crie uma pasta _templates/_ dentro de _core/_ e coloque seu _index.html_ la

ainda na pasta _core/_ crie a pasta _static/_ e coloque todos os arquivos estaticos dos quais seu template depende dentro dela

nas chamadas para arquivos estaticos substitua o caminha relativo pela função static do python

```python
    para fins de exemplo substitua todas as strings do tipo
    "img/favicon.ico"
    por
    {% static 'img/favicon.ico' %}
```

## separando configurações por instância e servindo arquivos estáticos de forma mais perfomática

em _wttd/_ instale as dependencias

```python
    pip install python-decouple     # desacopla as vars do settings para um .env
    pip install dj-database-url     # ajuda a criar url de database a partir do .env
    pip install dj-static           # serve os arquivos estaticos sem precisar passar pelo processamento
    pip install pillow              # lib para/se trabalhar com upload e validação de imagens
```

configurar o arquivo settings.py e o arquivo .env

#### arquivo _eventex/settings.py_

faça as substituições:

```python
    import os
    from decouple import config
    from dj_database_url import parse as dburl

    ALLOWED_HOSTS = ['*']

    SECRET_KEY = config('SECRET_KEY')

    DEBUG = config('DEBUG', default=False, cast=bool)

    default_dburl = 'sqlite:///' + os.path.join(BASE_DIR, 'db.sqlite3')
    DATABASES = {
    'default': config('DATABASE_URL', default=default_dburl, cast=dburl),
    }

    LANGUAGE_CODE = 'pt-br'

    TIME_ZONE = 'America/Sao_Paulo'

    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') # pasta que receberá os estáticos do projeto
    MEDIA_ROOT = os.path.join(BASE_DIR, 'uploads')      # pasta que receberá os uploads do projeto
```

#### arquivo _wttd/.env_

crie o arquivo .env na pasta raiz do projeto e adicione:

    SECRET_KEY=#coloque_aqui_sua_secret_key (sem espaços nem aspas)
    DEBUG=True

#### arquivo _eventex/wsgi.py_

importe o Cling e envolva o get_wsgi_application() com ele

```python
    from dj_static import Cling
    ...
    application = Cling(get_wsgi_application())
```

#### exportando as dependencias do projeto

    pip freeze > requirements.txt

## Preparando o projeto para o Heroku

no _wttd/requirements.txt_ adicione as seguintes dependencias

    gunicorn==19.8.1
    psycopg2==2.7.4

#### em _wttd/_ crie o arquivo Procfile com o seguinte conteudo

    web: gunicorn eventex.wsgi --log-file -

## Inicializando o repositório git

em _wttd/_

    git init

ainda em _wttd/_ crie o arquivo .gitignore e adicione o seguinte conteudo

    .env            //seu .env local
    .vscode         //arquivos de sua ide
    .wttd           //seu venv
    *.sqlite3       //bd de dev
    *.pyc           //arquivos compilados
    __pycache__     //cache de arquivos compilados do python

add o .gitignore a seu projeto, faça commit e em seguida adicione todo o resto

## criando uma app no heroku e colocando seu projeto no ar

    heroku apps:create eventex-petersonpassos
    heroku config:set SECRET_KEY='sua_key_entre_aspas_simples'
    heroku config:set DEBUG=False
    git push heroku master --force

## começando a trabalhar com banco de dados e o admin do django

roda as migrations

    manage migrate

crie o super usuário

    manage createsuperuser

pronto, já pode acessar o admin do django em http://127.0.0.1:8000/admin/
<file_sep>/laravel/comandos_artisan.md
### criar projeto

composer create-project laravel/laravel laravel-api

### listar rotas

php artisan route:list

### criar controller

php artisan make:controller \<ResourceName-Plural>Controller

### criar model

php artisan make:model \<ResourceName-Singular>

### criar migration

php artisan make:migration create\_\<ResourceName-Plural-minusculo>\_table --create=\<ResourceName-Plural-minusculo>

### terminal do projeto

php artisan tinker
<file_sep>/laravel/faker_laravel.md
# Faker laravel

Faker oferece um meio prático de criar dados falsos para pupular seus bancos de dados para teste, em qualquer lugar do laravel você pode gerar uma instancia em pt-BR da biblioteca faker fazendo:

```php

$faker = Faker\Factory::create('pt_BR');

```

Isso inclui o Laravel `tinker`. Caso precise testar, basta chamar o comando acima no shell do tinker.

Uma vez gerada vc pode chamar os atributos dela mesmo dentro de um loop que sempre vai sair diferente.

## Principais tipos de dados

### Dados especificos para brasileiros
	
```php
// Generates a random region name
$faker->region; // 'Nordeste'

// Generates a random region abbreviation
$faker->regionAbbr; // 'NE'

$faker->areaCode;  // 21
$faker->cellphone; // 9432-5656
$faker->landline;  // 2654-3445
$faker->phone;     // random landline, 8-digit or 9-digit cellphone number

// Using the phone functions with a false argument returns unformatted numbers
$faker->cellphone(false); // 74336667

// cellphone() has a special second argument to add the 9th digit. Ignored if generated a Radio number
$faker->cellphone(true, true); // 98983-3945 or 7343-1290

// Using the "Number" suffix adds area code to the phone
$faker->cellphoneNumber;       // (11) 98309-2935
$faker->landlineNumber(false); // 3522835934
$faker->phoneNumber;           // formatted, random landline or cellphone (obeying the 9th digit rule)
$faker->phoneNumberCleared;    // not formatted, random landline or cellphone (obeying the 9th digit rule)

// The name generator may include double first or double last names, plus title and suffix
$faker->name; // 'Sr. <NAME>'

// Valid document generators have a boolean argument to remove formatting
$faker->cpf;        // '145.343.345-76'
$faker->cpf(false); // '45623467866'
$faker->rg;         // '84.405.736-3'
$faker->rg(false);  // '844057363'

// Generates a Brazilian formatted and valid CNPJ
$faker->cnpj;        // '23.663.478/0001-24'
$faker->cnpj(false); // '23663478000124'
```	

### Textos
	
```php
	$faker->text;
	// Dolores sit sint laboriosam dolorem culpa et autem. Beatae nam sunt fugit
	// et sit et mollitia sed.
	// Fuga deserunt tempora facere magni omnis. Omnis quia temporibus laudantium
	// sit minima sint.
	
	$faker->word                                             // 'aut'
	$faker->words($nb = 3, $asText = false)                  // array('porro', 'sed', 'magni')
	$faker->sentence($nbWords = 6, $variableNbWords = true)  // 'Sit vitae voluptas sint non voluptates.'
	$faker->sentences($nb = 3, $asText = false)              // array('Optio quos qui illo error.', 'Laborum vero a officia id corporis.', 'Saepe provident esse hic eligendi.')
	$faker->paragraph($nbSentences = 3, $variableNbSentences = true) // 'Ut ab voluptas sed a nam. Sint autem inventore aut officia aut aut blanditiis. Ducimus eos odit amet et est ut eum.'
	$faker->paragraphs($nb = 3, $asText = false)             // array('Quidem ut sunt et quidem est accusamus aut. Fuga est placeat rerum ut. Enim ex eveniet facere sunt.', 'Aut nam et eum architecto fugit repellendus illo. Qui ex esse veritatis.', 'Possimus omnis aut incidunt sunt. Asperiores incidunt iure sequi cum culpa rem. Rerum exercitationem est rem.')
	$faker->text($maxNbChars = 200)
	// 'Fuga totam reiciendis qui architecto fugiat nemo. Consequatur recusandae qui cupiditate eos quod.'
	
```

### Empresas

```php
	$faker->catchPhrase             // 'Monitored regional contingency'
	$faker->bs                      // 'e-enable robust architectures'
	$faker->company                 // 'Bogan-Treutel'
	$faker->companySuffix           // 'and Sons'
	$faker->jobTitle                // 'Cashier'
```

### Pessoas

```php
	$faker->title($gender = null|'male'|'female')     // 'Ms.'
	$faker->titleMale                                 // 'Mr.'
	$faker->titleFemale                               // 'Ms.'
	$faker->suffix                                    // 'Jr.'
	$faker->name($gender = null|'male'|'female')      // 'Dr. <NAME>'
	$faker->firstName($gender = null|'male'|'female') // 'Maynard'
	$faker->firstNameMale                             // 'Maynard'
	$faker->firstNameFemale                           // 'Rachel'
	$faker->lastName                                  // 'Zulauf'
```
	
### Endereços

```php
	$faker->cityPrefix                          // 'Lake'
	$faker->secondaryAddress                    // 'Suite 961'
	$faker->state                               // 'NewMexico'
	$faker->stateAbbr                           // 'OH'
	$faker->citySuffix                          // 'borough'
	$faker->streetSuffix                        // 'Keys'
	$faker->buildingNumber                      // '484'
	$faker->city                                // 'West Judge'
	$faker->streetName                          // 'Keegan Trail'
	$faker->streetAddress                       // '439 Karley Loaf Suite 897'
	$faker->postcode                            // '17916'
	$faker->address                             // '8888 Cummings Vista Apt. 101, Susanbury, NY 95473'
	$faker->country                             // 'Falkland Islands (Malvinas)'
	$faker->latitude($min = -90, $max = 90)     // 77.147489
	$faker->longitude($min = -180, $max = 180)  // 86.211205
```

### Datas

```php
	$faker->unixTime($max = 'now')                // 58781813
	$faker->dateTime($max = 'now', $timezone = null) // DateTime('2008-04-25 08:37:17', 'UTC')
	$faker->dateTimeAD($max = 'now', $timezone = null) // DateTime('1800-04-29 20:38:49', 'Europe/Paris')
	$faker->iso8601($max = 'now')                 // '1978-12-09T10:10:29+0000'
	$faker->date($format = 'Y-m-d', $max = 'now') // '1979-06-09'
	$faker->time($format = 'H:i:s', $max = 'now') // '20:49:42'
	$faker->dateTimeBetween($startDate = '-30 years', $endDate = 'now', $timezone = null) // DateTime('2003-03-15 02:00:49', 'Africa/Lagos')
	$faker->dateTimeInInterval($startDate = '-30 years', $interval = '+ 5 days', $timezone = null) // DateTime('2003-03-15 02:00:49', 'Antartica/Vostok')
	$faker->dateTimeThisCentury($max = 'now', $timezone = null)     // DateTime('1915-05-30 19:28:21', 'UTC')
	$faker->dateTimeThisDecade($max = 'now', $timezone = null)      // DateTime('2007-05-29 22:30:48', 'Europe/Paris')
	$faker->dateTimeThisYear($max = 'now', $timezone = null)        // DateTime('2011-02-27 20:52:14', 'Africa/Lagos')
	$faker->dateTimeThisMonth($max = 'now', $timezone = null)       // DateTime('2011-10-23 13:46:23', 'Antarctica/Vostok')
	$faker->amPm($max = 'now')                    // 'pm'
	$faker->dayOfMonth($max = 'now')              // '04'
	$faker->dayOfWeek($max = 'now')               // 'Friday'
	$faker->month($max = 'now')                   // '06'
	$faker->monthName($max = 'now')               // 'January'
	$faker->year($max = 'now')                    // '1993'
	$faker->century                               // 'VI'
	$faker->timezone                              // 'Europe/Paris'
```

### Internet

```php
	$faker->email                   // '<EMAIL>'
	$faker->safeEmail               // '<EMAIL>'
	$faker->freeEmail               // '<EMAIL>'
	$faker->companyEmail            // '<EMAIL>'
	$faker->freeEmailDomain         // 'yahoo.com'
	$faker->safeEmailDomain         // 'example.org'
	$faker->userName                // 'wade55'
	$faker->password                // '<PASSWORD>['
	$faker->domainName              // 'wolffdeckow.net'
	$faker->domainWord              // 'feeney'
	$faker->tld                     // 'biz'
	$faker->url                     // 'http://www.skilesdonnelly.biz/aut-accusantium-ut-architecto-sit-et.html'
	$faker->slug                    // 'aut-repellat-commodi-vel-itaque-nihil-id-saepe-nostrum'
	$faker->ipv4                    // '192.168.127.12'
	$faker->localIpv4               // '10.242.58.8'
	$faker->ipv6                    // 'fc00:db20:35b:7399::5'
	$faker->macAddress              // '43:85:B7:08:10:CA'
```

### Cartão de credito

```php
	$faker->creditCardType          // 'MasterCard'
	$faker->creditCardNumber        // '4485480221084675'
	$faker->creditCardExpirationDate // 04/13
	$faker->creditCardExpirationDateString // '04/13'
	$faker->creditCardDetails       // array('MasterCard', '4485480221084675', '<NAME>', '04/13')
```

### Cores

```php
	$faker->hexcolor               // '#fa3cc2'
	$faker->rgbcolor               // '0,255,122'
	$faker->rgbColorAsArray        // array(0,255,122)
	$faker->rgbCssColor            // 'rgb(0,255,122)'
	$faker->safeColorName          // 'fuchsia'
	$faker->colorName              // 'Gainsbor'
```

### Arquivos

```php
	$faker->fileExtension          // 'avi'
	$faker->mimeType               // 'video/x-msvideo'
	// Copy a random file from the source to the target directory and returns the fullpath or filename
	$faker->file($sourceDir = '/tmp', $targetDir = '/tmp') // '/path/to/targetDir/13b73edae8443990be1aa8f1a483bc27.jpg'
	$faker->file($sourceDir, $targetDir, false) // '13b73edae8443990be1aa8f1a483bc27.jpg'
```

### Imagens

```php
	// Image generation provided by LoremPixel (http://lorempixel.com/)
	$faker->imageUrl($width = 640, $height = 480) // 'http://lorempixel.com/640/480/'
	$faker->imageUrl($width, $height, 'cats')     // 'http://lorempixel.com/800/600/cats/'
	$faker->imageUrl($width, $height, 'cats', true, 'Faker') // 'http://lorempixel.com/800/400/cats/Faker'
	$faker->imageUrl($width, $height, 'cats', true, 'Faker', true) // 'http://lorempixel.com/grey/800/400/cats/Faker/' Monochrome image
	$faker->image($dir = '/tmp', $width = 640, $height = 480) // '/tmp/13b73edae8443990be1aa8f1a483bc27.jpg'
	$faker->image($dir, $width, $height, 'cats')  // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat!
	$faker->image($dir, $width, $height, 'cats', false) // '13b73edae8443990be1aa8f1a483bc27.jpg' it's a filename without path
	$faker->image($dir, $width, $height, 'cats', true, false) // it's a no randomize images (default: `true`)
	$faker->image($dir, $width, $height, 'cats', true, true, 'Faker') // 'tmp/13b73edae8443990be1aa8f1a483bc27.jpg' it's a cat with 'Faker' text. Default, `null`.
```

### Html

```php
	//Generate HTML document which is no more than 2 levels deep, and no more than 3 elements wide at any level.
	$faker->randomHtml(2,3)   
	
	
	<html><head><title>Aut illo dolorem et accusantium eum.</title></head><body><form action="example.com" method="POST"><label for="username">sequi</label><input type="text" id="username"><label for="password">et</label><input type="password" id="password"></form><b>Id aut saepe non mollitia voluptas voluptas.</b><table><thead><tr><tr>Non consequatur.</tr><tr>Incidunt est.</tr><tr>Aut voluptatem.</tr><tr>Officia voluptas rerum quo.</tr><tr>Asperiores similique.</tr></tr></thead><tbody><tr><td>Sapiente dolorum dolorem sint laboriosam commodi qui.</td><td>Commodi nihil nesciunt eveniet quo repudiandae.</td><td>Voluptates explicabo numquam distinctio necessitatibus repellat.</td><td>Provident ut doloremque nam eum modi aspernatur.</td><td>Iusto inventore.</td></tr><tr><td>Animi nihil ratione id mollitia libero ipsa quia tempore.</td><td>Velit est officia et aut tenetur dolorem sed mollitia expedita.</td><td>Modi modi repudiandae pariatur voluptas rerum ea incidunt non molestiae eligendi eos deleniti.</td><td>Exercitationem voluptatibus dolor est iste quod molestiae.</td><td>Quia reiciendis.</td></tr><tr><td>Inventore impedit exercitationem voluptatibus rerum cupiditate.</td><td>Qui.</td><td>Aliquam.</td><td>Autem nihil aut et.</td><td>Dolor ut quia error.</td></tr><tr><td>Enim facilis iusto earum et minus rerum assumenda quis quia.</td><td>Reprehenderit ut sapiente occaecati voluptatum dolor voluptatem vitae qui velit.</td><td>Quod fugiat non.</td><td>Sunt nobis totam mollitia sed nesciunt est deleniti cumque.</td><td>Repudiandae quo.</td></tr><tr><td>Modi dicta libero quisquam doloremque qui autem.</td><td>Voluptatem aliquid saepe laudantium facere eos sunt dolor.</td><td>Est eos quis laboriosam officia expedita repellendus quia natus.</td><td>Et neque delectus quod fugit enim repudiandae qui.</td><td>Fugit soluta sit facilis facere repellat culpa magni voluptatem maiores tempora.</td></tr><tr><td>Enim dolores doloremque.</td><td>Assumenda voluptatem eum perferendis exercitationem.</td><td>Quasi in fugit deserunt ea perferendis sunt nemo consequatur dolorum soluta.</td><td>Maxime repellat qui numquam voluptatem est modi.</td><td>Alias rerum rerum hic hic eveniet.</td></tr><tr><td>Tempore voluptatem.</td><td>Eaque.</td><td>Et sit quas fugit iusto.</td><td>Nemo nihil rerum dignissimos et esse.</td><td>Repudiandae ipsum numquam.</td></tr><tr><td>Nemo sunt quia.</td><td>Sint tempore est neque ducimus harum sed.</td><td>Dicta placeat atque libero nihil.</td><td>Et qui aperiam temporibus facilis eum.</td><td>Ut dolores qui enim et maiores nesciunt.</td></tr><tr><td>Dolorum totam sint debitis saepe laborum.</td><td>Quidem corrupti ea.</td><td>Cum voluptas quod.</td><td>Possimus consequatur quasi dolorem ut et.</td><td>Et velit non hic labore repudiandae quis.</td></tr></tbody></table></body></html>
```
<file_sep>/django/tests.md
classe exemplo de teste

```python
from django.test import TestCase

# Create your tests here.


class HomeTest(TestCase):
    # o metódo setUp roda automaticamente antes de cada teste e colocar as
    # vars que vc vai precisar dentro de self é a forma de vc torna-la global na classe
    def setUp(self):
        # o client é uma ferramenta do django capaz de fazer requests no projeto para fins de teste
        self.response = self.client.get('/')

    def test_get(self):
        """GET / must return code 200""" # docstring serve para descrever o teste
        self.assertEqual(200, self.response.status_code) # é igual?

    def test_template(self):
        """Must use subscription_form.html"""
        self.assertTemplateUsed(
            self.response, 'subscription_form.html') # é esse template usado?

    def test_html(self):
        """Html must contain tags"""
        self.assertContains(self.response, '<form')
        self.assertContains(self.response, '<input', 6) # contem isso no html? esse numerop de vezes?
        self.assertContains(self.response, 'type="text"', 3)
        self.assertContains(self.response, 'type="email"')
        self.assertContains(self.response, 'type="submit"')

    def test_csrf_token(self):
        """Html must contain csrf token"""
        self.assertContains(self.response, 'csrfmiddlewaretoken')
```
<file_sep>/django/setup.md
# Setup inicial do ambiente de trabalho

Você precisará das seguintes ferramentas:

- python virtualenv
- python pip

Dependendo da versão do Python que irá utilizar, o nome do pacote em sua distribuiçao muda também.

No Ubuntu Linux, instale utilizando o `apt`

```shell
apt install python-virtualenv python-pip
```

Caso esteja utilizando o Python3, instale da seguinte forma:

```shell
apt install python3-virtualenv python3-pip
```
