Sintaxe OOP para JavaScript em 5 minutos

Criar uma classe

class Funcionario {

}

Adicionar um construtor

class Funcionario {
    constructor () {
    }
}

Criar propriedades

class Funcionario {
    constructor (nome, salario) {
        this._nome = nome;
        this._salario = salario;
        this._bonificacao = 1.05;
    }
}

Criar método

class Funcionario {
    constructor (nome, salario) {
        this._nome = nome;
        this._salario = salario;
        this._bonificacao = 1.05;
    }
    calculaSalarioFinal () {
        return this._salario * this._bonificacao;
    }
}

Propriedades estáticas

class Funcionario {
    static contador = 0;

    constructor (nome, salario) {
        this._nome = nome;
        this._salario = salario;
        this._bonificacao = 1.05;

        Funcionario.contador += 1;
    }
    calculaSalarioFinal () {
        return this._salario * this._bonificacao;
    }
}

Getters e setters

class Funcionario {
    static contador = 0;

    constructor (nome, salario) {
        this._nome = nome;
        this._salario = salario;
        this._bonificacao = 1.05;

        Funcionario.contador += 1;
    }
    calculaSalarioFinal () {
        return this._salario * this._bonificacao;
    }
    get nome () {
        return this._nome;
    }
    set nome (novoNome) {
        this._nome = novoNome;
    }
}

Herança

class Gerente extends Funcionario {
    constructor (nome, salario) {
        super(nome, salario);
        this._bonificacao = 1.07;
    }
}
class Diretor extends Funcionario {
    constructor (nome, salario) {
        super(nome, salario);
        this._bonificacao = 1.09;
    }
}

Sobrescrever um método

class Diretor extends Funcionario {
    constructor (nome, salario) {
        super(nome, salario);
        this._bonificacao = 1.09;
    }
    calculaSalarioFinal (adicional=0) {
        return super.calculaSalarioFinal() + adicional;
    }
}

Simular um classe abstrata

class MinhaClasse {
    constructor () {
        if (this.constructor === MinhaClasse) {
            throw new Error('"MinhaClasse" é abstrata');
        }
    }
}

Simular um método abstrato

class MinhaClasse {
    constructor () {
        if (this.constructor === MinhaClasse) {
            throw new Error('"MinhaClasse" é abstrata');
        }
    }
    meuMetodo () {
        throw new Error('Método não implementado');
    }
}

Referências

  • https://cursos.alura.com.br/course/javascript-polimorfismo
  • https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes

Alterar URL de uploads no WordPress

Em algumas ocasiões pode ser necessário que a URL dos arquivos de uploads seja modificada para apontar para outro endereço diferente do padrão. Isso pode ser feito usando a opção upload_url_path.

Para alterar o caminho http://example.com/wp-content/uploads e deixar como http://static.example.com/wp-content/uploads, a opção upload_url_path deve ser definida como abaixo.

update_option(
    'upload_url_path',
    'http://static.example.com/wp-content/uploads'
);

Referência

  • https://developer.wordpress.org/reference/functions/wp_upload_dir/

Manipulando arquivos com NodeJS

Estes exemplos foram feitos a partir dos exercícios disponíveis no nodeschool, pelo workshopper learnyounode.

Lendo um arquivo de forma síncrona

A ideia aqui era fazer um programa em node que pudesse contar o número de linhas em um arquivo cujo caminho foi fornecido via parâmetro.

// countLines.js
var fs = require('fs');
var filename = process.argv[2]; // parametro
var buffer = fs.readFileSync(filename);
var str = buffer.toString();
console.log(str.split('\n').length - 1);

Lendo arquivo de forma assíncrona

// countLinesAsync.js
var fs = require('fs');
var filename = process.argv[2];
fs.readFile(filename, function(err, data) {
    var str = data.toString();
    console.log(str.split('\n').length - 1);
});

Listando arquivos de um diretório

O programinha abaixo funciona mais ou menos como o comando ls do linux. O primeiro parâmetro é o diretório que se quer listar arquivos e o segundo parâmetro é a extensão dos arquivos que serão listados.

// ls.js
var fs = require('js');
var path = require('path');
var dirPath = process.argv[2];
var ext = '.' + process.argv[3];

fs.readdir(dirPath, function (err, list) {
    if (err) {
        return;
    }
    var files = list.filter(function(f) {
        return path.extname(f) === ext;
    });
    console.log(files.join('\n'));
});

Referências

  • http://nodeschool.io/#workshopper-list
  • https://github.com/rvagg/learnyounode

Hello World com NodeJS

NodeJS é uma plataforma para programação de Javascript no lado do servidor. Foi construído sobre o interpretador Javascript que é usado no Chrome, o V8.

Instalando no Archlinux

sudo pacman -S nodejs

Depois de instalado é possível acessar um shell interativo através do comando node.

Um ‘Hello World

# hello-world.js
console.log('HELLO WORLD');

Para executar o arquivo acima, basta digitar no console:

$ node hello-world.js 
HELLO WORLD

Algo mais elaborado que isso poderia ser uma mensagem vinda por parâmetro, quando o comando é invocado.

# hello-world-2.js
console.log(process.argv[2]);

A execução do arquivo ficaria da seguinte forma:

$ node hello-world-2.js 'Hello World'
Hello World

Referências

  • http://nodeschool.io/
  • https://github.com/rvagg/learnyounode

Ambiente de desenvolvimento Django

O Django é um framework de desenvolvimento Web escrito em Python. Toda vez que começo um novo projeto em Django, eu sigo quase sempre as mesmas etapas. Algumas etapas são auxiliadas por outros programinhas bem bacanas que são o pip, o virtualenv e o virtualenvwrapper.

O pip é um gerenciador e instalador de pacotes Python.  Uso o pip para baixar as dependências dos meus projetos. Eu costumo guardar os nomes das dependência em um arquivo de texto, na raiz do projeto, para aqueles que forem instalar o projeto saberem o que devem instalar com o pip.

O virtualenv é uma ferramenta que permite isolar um ambiente Python. Para cada projeto, eu crio um ambiente Python e uso o pip para instalar as dependências do meu projeto nesse ambiente isolado.

O virtualenvwrapper é um facilitador de uso do virtualenv. Ele já define o lugar onde serão criados os ambientes isolados e provê alguns atalhos para ativar, desativar e apagar esses ambientes.

Instalação das ferramentas

Mostro a seguir como eu instalo o pip, virtualenv e virtualenvwrapper em minha estação de desenvolvimento.

Instalando do pip

Eu costumo instalar o pip através do gerenciador de pacotes do sistema operacional. Eu uso o Archlinux, então instalo da seguinte forma:

$ sudo pacman -S python-pip

Se a versão do pip que foi instalada é muito antiga, você pode usar o próprio pip para atualiza-la.

$ sudo pip install pip --upgrade

Instalando o virtualenv

No mesmo estilo acima, eu uso o gerenciador de pacotes do sistema operacional para instalar o virtualenv. Como eu uso o Archlinux, instalo da seguinte forma:

$ sudo pacman -S python-virtualenv

Dependendo do seu sistema operacional, alguns pacotes podem estar mais velhos do o que o desejado. Caso você desconfie disso, você pode instalar o virtualenv através do pip.

$ sudo pip install virtualenv

Instalando o virtualenvwrapper

Da mesma forma que os pacotes acima, eu uso o gerenciador de pacotes do Archlinux para instalar o virtualenvwrapper.

$ sudo pacman -S python-virtualenvwrapper

Só que esse pacote precisa de um passo a mais, que é para carregá-lo automaticamente quando você faz login em um terminal. Para isso tente:

$ echo 'source /usr/bin/virtualenvwrapper.sh' >> ~/.bashrc

Criação de um projeto com um novo ambiente python

Meu ponto de partida agora é a pasta ~/devel, onde eu guardo todos os meus projetos.

Criando o virtualenv

Eu acho importante ser explícito em relação a versão de Python que vou usar. O Archlinux tem o python na versão 3 por padrão. No caso abaixo, quero criar um ambiente isolado com python 2.

$  mkvirtualenv meu_novo_projeto -p /usr/bin/python2

Instalando o Django

Depois que você ativa o virtualenv, seu shell ganha o prefixo com o nome do projeto que você deu, no caso ‘meu_novo_projeto’. Tendo isso, vamos instalar o Django.

(meu_novo_projeto)$ pip install django

Tá demorando né? Sim, o pip é um bocado demorado pra baixar as coisas. Como lição de casa, procure no Google por PIP_DOWNLOAD_CACHE.

Começando o projeto com o Django

Legal, temos o Django instalado no nosso ambiente, agora vamos começar nosso projeto, com o mesmo nome do ambiente que criamos, só pra sermos organizados.

(meu_novo_projeto)$ django-admin startproject meu_novo_projeto

Vamos iniciar o Django pra saber se tudo deu certo.

(meu_novo_projeto)$ cd meu_novo_projeto
(meu_novo_projeto)$ ./manage.py syncdb --noinput
(meu_novo_projeot)$ ./manage.py runserver

Agora veja em seu navegador no endereço http://localhost:8000. Se estiver vendo a telinha inicial do Django, tudo deu certo.

Referências

  • https://docs.djangoproject.com/en/1.6/
  • https://pip.pypa.io/en/latest/installing.html#using-package-managers
  • http://virtualenvwrapper.readthedocs.org/en/latest/

Nginx e php5-fpm

Eu precisava rodar no meu servidor uma aplicação PHP, sem que isso despendesse muito esforço e tempo em configurações complicadas, mas que ao mesmo tempo fosse flexível o suficiente para compartilhar o webserver com outras aplicações que rodam em Python.

A solução foi usar o php-fpm, que para minha alegria está no repositório do Ubuntu 12.10. A ideia é instalar o pacote php5-fpm e configurar a diretiva fastcgi_pass no Nginx. Eu fiz o seguinte para começar com uma configuração básica:

fabio:~$ sudo apt-get install php5-fpm
fabio:~$ sudo mkdir /var/www/teste.montefuscolo.com.br
fabio:~$ echo "<?php echo 'oi mundo';" | \
         sudo tee  /var/www/teste.montefuscolo.com.br/index.php
fabio:~$ sudo tee /etc/nginx/sites-enabled/teste.montefuscolo.com.br << EOF
server {
    server_name teste.montefuscolo.com.br;
    root /var/www/teste.montefuscolo.com.br/;

    location / {
        index.php index.html index.htm;
    }

    location ~ \.php$ {
        include fastcgi_params;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
    }
}
EOF
fabio:~$ sudo service nginx restart

Pode ser que ao invés de um arquivo sock, o php5-fpm esta rodando em uma porta TCP, pois depende de como ele vem pré-configurado. Neste caso a configuração da diretiva fastcgi_pass pode ser um pouco diferente, como a seguinte:

fastcgi_pass 127.0.0.1:9000;

Para descobrir isso você pode consultar o arquivo de configuração do php-fpm em /etc/php5/fpm/pool.d/www.conf, procurando pela linha que começa com listen.

fabio:~$ grep ^listen /etc/php5/fpm/pool.d/www.conf
listen = /var/run/php5-fpm.sock

Depois desses passos consegui uma página imprimindo ‘oi mundo’ em http://teste.montefuscolo.com.br/.

Referências

O ‘git revert’

Eu precisava fazer com que minha cópia local do git ficasse com o conteúdo igual estava há uns 4 commits atrás. Esses 4 commits no meio do caminho já estavam no servidor remoto, então não posso simplesmente jogá-los fora. Então tive de aprender o comando ‘git revert‘.

O ‘git revert‘ cria um ou mais commits com as alterações que desfazem o conteúdo dos commits indesejados. Abaixo escrevi sequências de códigos que ilustram o uso ‘git revert‘.

Desfazendo 1 commit

Quero desfazer o commit 23a10ce que cria o arquivo de nome “CCC”.

[email protected]:git-revert(master)$ git log --pretty=oneline
9d1d944c5f153c4dafb80a8a19009527e6fe9f1a commit 5 - arquivo FFF
66622af8cbf38cf3749145bb37929367dadb8a84 commit 4 - arquivo EEE
35a4e32012dec7931d5f4b32f1121dbcd9318e52 commit 3 - arquivo DDD
23a10ce4592080ac32b1f1e1a779f295ac26a720 commit 2 - arquivo CCC
5d2c7d5b39892afba41ee8537c9384a77ed1e15e commit 1 - arquivo BBB
21d969d160108eb2acecfc9ea5ede8590fba5494 commit 0 - arquivo AAA

[email protected]:git-revert(master)$ ls
AAA BBB CCC DDD EEE FFF

[email protected]:git-revert(master)$ git revert --no-edit 23a10ce
[master cd4fa8a] Revert "commit 2 - arquivo CCC"
1 file changed, 1 deletion(-)
delete mode 100644 CCC

[email protected]:git-revert(master)$ ls
AAA BBB DDD EEE FFF

Desfazendo um conjunto de commits

Quero desfazer desde agora (HEAD) até o commit 23a10ce. Vão sobrar em meu diretório os arquivos AAA e BBB.

[email protected]:git-revert(master)$ git log --pretty=oneline
9d1d944c5f153c4dafb80a8a19009527e6fe9f1a commit 5 - arquivo FFF
66622af8cbf38cf3749145bb37929367dadb8a84 commit 4 - arquivo EEE
35a4e32012dec7931d5f4b32f1121dbcd9318e52 commit 3 - arquivo DDD
23a10ce4592080ac32b1f1e1a779f295ac26a720 commit 2 - arquivo CCC
5d2c7d5b39892afba41ee8537c9384a77ed1e15e commit 1 - arquivo BBB
21d969d160108eb2acecfc9ea5ede8590fba5494 commit 0 - arquivo AAA

[email protected]:git-revert(master)$ ls
AAA BBB CCC DDD EEE FFF
[email protected]:git-revert(master)$ git revert --no-edit 23a10ce^..HEAD
[master aafe3b1] Revert "commit 5 - arquivo FFF"
1 file changed, 1 deletion(-)
delete mode 100644 FFF
[master 55a9493] Revert "commit 4 - arquivo EEE"
1 file changed, 1 deletion(-)
delete mode 100644 EEE
[master ff45a7a] Revert "commit 3 - arquivo DDD"
1 file changed, 1 deletion(-)
delete mode 100644 DDD
[master a2c4050] Revert "commit 2 - arquivo CCC"
1 file changed, 1 deletion(-)
delete mode 100644 CCC

[email protected]:git-revert(master)$ ls
AAA BBB

O ‘git revert’ não volta na história nem reposiciona ponteiros, como faz o ‘git reset’. Ao invés disso, o ‘git revert‘ desfaz alterações que estão no histórico de commits. As alterações feitas pelo ‘git revert‘ podem ser vistas através do log.

Referências

  • https://www.kernel.org/pub/software/scm/git/docs/git-revert.html