One place for hosting & domains

      Aplicativo

      Como empacotar e publicar um aplicativo Snap no Ubuntu 18.04


      O autor selecionou a Electronic Frontier Foundation para receber uma doação como parte do programa Write for DOnations.

      Introdução

      Um dos maiores desafios no desenvolvimento de aplicativos é o passo final da distribuição do produto acabado para seus usuários ou clientes. Muitas metodologias existentes para implantação de aplicativos não são fáceis de usar e carecem de segurança, ou não fornecem métodos para atualizar automaticamente um aplicativo assim que estiver instalado.

      O Snap é um formato moderno de empacotamento de aplicativos, com recursos de área restrita e segurança eficazes, incluindo o isolamento do sistema de arquivos, atualizações automáticas e o gerenciamento de dependências integrado. Os aplicativos do Snap, conhecidos como Snaps, podem ser baixados e instalados usando um programa de linha de comando, de maneira semelhante às ferramentas apt ou yum. O Ubuntu vem com Snap pré-instalado, o que significa que há uma amplo público-alvo para os aplicativos Snap.

      Neste tutorial, você criará um aplicativo Snap e irá publicá-lo na Snap Store.

      Pré-requisitos

      Para completar este tutorial, você precisará de:

      • Um servidor Ubuntu 18.04 configurado de acordo com o tutorial de Configuração inicial de servidor com o Ubuntu 18.04, incluindo um usuário sudo não raiz.

      • Um aplicativo que você queira empacotar e lançar como um Snap. Esse pode ser um aplicativo complexo que você criou, um projeto de código aberto comum, ou um simples programa “Hello, world!” (“Olá, mundo!”) . Caso ainda não tenha um aplicativo, o Passo 1 deste tutorial irá abranger como criar um programa Hello World em Go.

      • Uma conta no Snapcraft Developer Snapcraft [Painel de desenvolvimento do Snapcraft].

      Assim que tiver tudo pronto, faça login no seu servidor como usuário não raiz para começar.

      Passo 1 — Preparando seu aplicativo para o empacotamento

      Primeiro, você irá preparar seu aplicativo para o empacotamento como um aplicativo Snap, assegurando que tudo o que é necessário esteja armazenado em um único diretório.

      Comece criando um diretório para seu Snap, acessando-o:

      • mkdir ~/your-snap
      • cd ~/your-snap

      Em seguida, caso já tenha um aplicativo, coloque uma cópia completa do código fonte do seu aplicativo no diretório que acabou de criar. O processo aqui será significativamente diferente, dependendo do aplicativo exato que estiver empacotando. No entanto, caso o código fonte estiver armazenado em um repositório do Git, você pode usar o comando git init para criar um repositório no diretório e puxar todo o código relevante.

      Caso ainda não tenha um aplicativo que deseja empacotar, você pode, em vez disso, criar um programa “Hello World” para usar. Caso queira mais contexto sobre como escrever esse programa com o Go, confira o tutorial Como escrever seu primeiro programa em Go.

      Você pode fazer isso, primeiramente criando um arquivo Go, abrindo-o com o seu editor de texto preferido:

      Depois, adicione o código a seguir ao arquivo:

      helloworld.go

      package main
      import "fmt"
      func main() {
        fmt.Println("Hello, world!")
      }
      

      Então, salve e saia do arquivo.

      Caso não tenha o Go instalado, instale-o usando o seguinte comando:

      • sudo apt install golang-go

      Assim que o Go estiver instalado, execute seu novo programa para verificar se ele está funcionando:

      Você verá o seguinte resultado:

      Output

      Hello, world!

      Você preparou seu aplicativo para empacotar como um Snap. Em seguida, você instalará o software necessário para iniciar o processo de empacotamento.

      Passo 2 — Instalando o Snapcraft

      Neste passo, você irá baixar e instalar o Snapcraft, que é o nome da ferramenta oficial de empacotamento do aplicativo Snap. O Snapcraft está disponível na Snap Store, que, por padrão, vem integrada ao Ubuntu. Isso significa que você pode instalar o Snapcraft a partir da linha de comando, usando o comando snap.

      O comando snap é equivalente ao comando apt, mas você pode usá-lo para instalar softwares da Snap Store, em vez de pacotes dos repositórios da Apt.

      Para instalar o Snapcraft, execute o seguinte comando:

      • sudo snap install snapcraft --classic

      Use o argumento de comando --classic para que o Snapcraft faça a instalação sem os recursos rigorosos de área restrita que os Snaps normalmente usam. O Snapcraft exige esse argumento, já que precisa de acesso mais privilegiado ao seu sistema para empacotar de maneira confiável os aplicativos.

      Assim que instalar o Snapcraft, verá o seguinte:

      Output

      snapcraft 3.9.8 from Canonical✓ installed

      Por fim, você pode verificar novamente a instalação do Snapcraft, executando:

      Isso exibirá algo similar a:

      Output

      snapcraft, version 3.9.8

      Agora que você instalou o Snapcraft, pode começar a definir a configuração e os metadados para o seu aplicativo Snap.

      Neste passo, você começará a definir a configuração, a estrutura e os metadados para seu aplicativo Snap.

      Comece certificando-se de que ainda está trabalhando no diretório do seu aplicativo Snap:

      Em seguida, crie e edite o arquivo snapcraft.yaml, usando seu editor de texto preferido:

      Você usará o arquivo snapcraft.yaml para armazenar toda a configuração do seu aplicativo Snap, incluindo o nome, descrição e versão, além de configurações relacionadas ao gerenciamento de dependências e ao uso de área restrita.

      Comece definindo o nome, resumo, descrição e número de versão do seu aplicativo:

      snapcraft.yaml

      name: your-snap
      summary: A summary of your application in 78 characters or less.
      description: |
        A detailed description of your application.
        The description can have multiple lines.
      version: '1.0'
      

      O nome do seu Snap precisa ser único caso deseje publicá-lo na Snap Store — procure outros aplicativos com o mesmo nome para garantir que ele já não esteja sendo usado.

      Em seguida, defina o(s) comando(s) que deseja associar ao seu aplicativo. Isso permitirá que seu Snap seja usado diretamente a partir da linha de comando do Bash, como um comando normal.

      Adicione o seguinte ao seu arquivo snapcraft.yaml:

      snapcraft.yaml

      . . .
      apps:
        your-snap-command:
          command: your-snap
      

      your-snap-command é o nome do comando que deseja definir. Por exemplo, pode ser que queira usar o comando helloworld para executar seu programa Hello World.

      Você usará o command: your-snap para dizer ao Snapcraft o que fazer quando o comando do aplicativo for executado. No caso do programa Hello World, você usaria o valor helloworld para fazer referência ao arquivo helloworld.go, o que permitirá que o Snapcraft execute seu programa com sucesso.

      Isso resulta na seguinte configuração de exemplo:

      snapcraft.yaml

      apps:
        helloworld:
          command: helloworld
      

      Caso o nome do comando corresponda exatamente ao nome do Snap, você será capaz de executá-lo diretamente da linha de comando. Caso o comando não corresponda ao nome do Snap, o comando será prefixado automaticamente com o nome do Snap. Por exemplo, helloworld.command1.

      Por fim, você pode definir as partes que compõem seu aplicativo Snap. Os aplicativos Snap consistem em várias partes, as quais são todos os componentes que compõem seu aplicativo. Em muitos casos, há apenas uma parte, que é o aplicativo propriamente dito.

      Cada parte tem um plug-in associado. Por exemplo, para os componentes do seu aplicativo escritos em Ruby, o plug-in ruby é usado e, para os componentes escritos em Go, o plug-in go é usado.

      Use o comando list-plugins do Snapcraft para identificar o(s) plug-in(s) correto(s) para seu aplicativo:

      Isso irá gerar uma lista parecida com a seguinte:

      Output

      ant catkin-tools conda dump gradle make nil python rust autotools cmake crystal go kbuild maven nodejs qmake scons catkin colcon dotnet godeps kernel meson plainbox-provider ruby waf

      Os plug-ins mais comuns são os para linguagens de programação comuns, como Go, Rust, Ruby, ou Python.

      Assim que tiver identificado os plug-ins corretos para o seu aplicativo, você pode começar a adicionar a configuração das parts (partes) ao seu arquivo snapcraft.yaml:

      snapcraft.yaml

      . . .
      parts:
        your-snap:
          plugin: plugin-name
          source: .
      

      Utilize o parâmetro de configuração source para especificar o caminho relativo para o código fonte para o seu aplicativo. Normalmente, esse será o mesmo diretório do arquivo snapcraft.yaml em si. Assim, o valor source é um único ponto (.).

      Nota: caso o componente de seu aplicativo tenha quaisquer dependências que sejam necessárias para que o compile ou execute, você pode especificá-las usando os atributos build-packages e stage-packages. Os nomes de dependências especificados serão, então, obtidos automaticamente com o gerenciador de pacotes padrão para seu sistema.

      Por exemplo:

      snapcraft.yaml

      parts:
        your-snap:
        plugin: plugin-name
        source: .
        build-packages:
        - gcc
        - make
        stage-packages:
        - libcurl4
      

      Alguns plug-ins do Snapcraft têm suas próprias opções específicas que podem ser necessárias para seu aplicativo. Assim, vale a pena rever as páginas relevantes do manual do seu plug-in:

      • snapcraft help plugin-name

      No caso dos aplicativos Go, você também especificaria o caminho go-importpath. Para a configuração Hello World, isso resulta na seguinte configuração de exemplo:

      snapcraft.yaml

      parts:
        helloworld:
          plugin: go
          source: .
          go-importpath: helloworld
      

      Deixe seu arquivo snapcraft.yaml aberto para adicionar mais configurações no próximo passo.

      Você definiu a configuração base para seu aplicativo Snap. Em seguida, você irá configurar os aspectos de segurança e de área restrita do seu aplicativo.

      Passo 4 — Protegendo seu aplicativo Snap

      Os aplicativos Snap foram criados para executarem em um ambiente de área restrita, de modo que, neste passo, você irá configurar a área restrita para o seu Snap. Primeiro, precisará habilitar a área restrita para o seu aplicativo, conhecida dentro do Snapcraft como confinement (confinamento).

      Adicione o seguinte ao seu arquivo snapcraft.yaml:

      snapcraft.yaml

      . . .
      confinement: strict
      

      Isso habilitará a área restrita para o seu aplicativo, impedindo-o de acessar a internet, outros Snaps em execução, ou o sistema do host propriamente dito. No entanto, na maioria dos casos, os aplicativos precisam ser capazes de se comunicar fora da área restrita, como quando precisam acessar a internet ou ler/gravar no sistema de arquivos.

      Essas permissões, conhecidas dentro do Snapcraft como interfaces, podem ser concedidas ao seu aplicativo Snap usando os Plugs. Usando o Plugs, você pode ter o controle fino sobre a área restrita do seu aplicativo, para lhe dar o acesso que precisa e nada mais (princípio do menor privilégio).

      As interfaces exatas que são necessárias variam, dependendo do seu aplicativo. Algumas das interfaces mais comuns são:

      • audio-playback – permite saída de som/reprodução de sons.
      • audio-record – permite a entrada/gravação de áudio.
      • camera – permite o acesso a webcams conectadas.
      • home – permite o acesso a arquivos não ocultos dentro do seu diretório home.
      • network – permite o acesso à rede/internet.
      • network-bind – permite a vinculação às portas para operar como um serviço de rede.
      • system-files – permite o acesso ao sistema de arquivos completo da máquina de hospedagem.

      A lista completa de interfaces disponíveis pode ser encontrada dentro da documentação do Snapcraft, em Interfaces compatíveis.

      Assim que tiver identificado todas as interfaces necessárias para o seu aplicativo, você pode começar a atribuí-las aos plugs dentro do seu arquivo snapcraft.yaml.

      A configuração do exemplo a seguir permitirá que o aplicativo acesse a rede e a área inicial de usuários:

      snapcraft.yaml

      . . .
      plugs:
        your-snap-home:
          interface: home
        your-snap-network:
          interface: network
      

      Salve e saia do seu arquivo.

      O nome do Plug deve ser um nome descritivo para ajudar os usuários a identificar o propósito do Plug.

      Você habilitou a área restrita para o seu Snap e configurou alguns Plugs para conceder acesso limitado aos recursos do sistema. Em seguida, terminará a compilação do seu app Snap.

      Passo 5 — Compilando e testando seu aplicativo Snap

      Agora que você escreveu toda a configuração necessária para o seu Snap, prossiga com a compilação e teste do pacote Snap localmente.

      Caso esteja acompanhando este tutorial com a utilização de um programa Hello World como seu aplicativo, seu arquivo completo snapcraft.yaml será agora semelhante ao seguinte:

      snapcraft.yaml

      name: helloworld
      summary: A simple Hello World program.
      description: |
        A simple Hello World program written in Go.
        Packaged as a Snap application using Snapcraft.
      version: '1.0'
      confinement: strict
      
      apps:
        helloworld:
          command: helloworld
      
      parts:
        helloworld:
          plugin: go
          source: .
          go-importpath: helloworld
      
      plugs:
        helloworld-home:
          interface: home
        helloworld-network:
          interface: network
      

      Para compilar seu aplicativo Snap, execute o comando snapcraft dentro do diretório para seu Snap:

      Então, o Snapcraft irá iniciar automaticamente uma máquina virtual (VM) e começará a compilar seu Snap. Assim que terminar, o Snapcraft fechará e você verá algo semelhante ao seguinte:

      Output

      Snapped your-snap_1.0_amd64.snap

      Agora, você pode instalar o seu Snap localmente para verificar se ele está funcionando:

      • sudo snap install your-snap.snap --dangerous

      O argumento de comando --dangerous é necessário, já que você está instalando um Snap local que não foi assinado.

      Output

      your-snap 1.0 installed

      Assim que o processo de instalação estiver completo, execute seu Snap usando seu comando associado. Por exemplo:

      No caso do programa exemplo Hello World, o resultado seguinte seria:

      Output

      Hello, world!

      Você também pode visualizar a política de área restrita para seu Snap para se certificar de que as permissões atribuídas foram devidamente concedidas:

      • snap connections your-snap

      Isso irá gerar uma lista de Plugs e interfaces, parecida com a seguinte:

      Output

      snap connections your-snap Interface Plug Slot Notes home your-snap:your-snap-home :home - network your-snap:your-snap-network :network -

      Neste passo, você construiu seu Snap e o instalou localmente para testar se ele está funcionando. Em seguida, irá publicar seu Snap na Snap Store.

      Passo 6 — Publicando seu Snap

      Agora que você compilou e testou seu aplicativo Snap, é hora de lançá-lo na Snap Store.

      Comece fazendo login na sua conta de desenvolvedor do Snap, usando o aplicativo de linha de comando Snapcraft:

      Siga os prompts e digite seu endereço de e-mail e senha.

      Em seguida, você precisa registrar o nome do aplicativo na Snap Store:

      • snapcraft register your-snap

      Assim que tiver registrado o nome do Snap, poderá enviar o pacote do Snap compilado para a loja:

      • snapcraft push your-snap.snap

      Você verá um resultado similar ao seguinte:

      Output

      Preparing to push 'your-snap_1.0_amd64.snap'. Install the review-tools from the Snap Store for enhanced checks before uploading this snap. Pushing 'your-snap_1.0_amd64.snap' [===================================================================================================] 100% Processing...| Ready to release! Revision 1 of 'your-snap' created.

      Cada vez que você manda para a loja do Snap, o número de revisão é incrementado, começando em um. Isso é útil para ajudar a identificar as diferentes compilações do seu Snap.

      Por fim, você pode lançar seu Snap para o público:

      • snapcraft release your-snap revision-number channel

      Caso essa seja a primeira vez que você envia algo para a Snap Store, o número da revisão será 1. Você também pode escolher entre lançar nos canais stable, candidate, beta e edge, caso tenha várias versões do seu aplicativo em diferentes fases de desenvolvimento.

      Por exemplo, o comando a seguir lançará a revisão 1 do Snap Hello World no canal stable:

      • snapcraft release helloworld 1 stable

      Você verá um resultado similar ao seguinte:

      Output

      Track Arch Channel Version Revision latest amd64 stable 1.0 1 candidate ^ ^ beta ^ ^ edge ^ ^ The 'stable' channel is now open.

      Agora, você pode procurar pelo seu aplicativo na Snap Store e instalá-lo em qualquer um dos seus dispositivos.

      Loja do Snapcraft com o app Hello World exibido nos resultados de busca

      Neste passo final, você enviou seu pacote compilado do Snap para a Snap Store e o lançou para o público.

      Conclusão

      Neste artigo, você configurou e compilou um aplicativo Snap e, depois, lançou-o para o público através da Snap Store. Agora, possui o conhecimento básico necessário para manter o seu aplicativo e compilar novos.

      Caso queira explorar os Snaps ainda mais, confira a Snap Store completa. Você também pode querer rever a referência YAML do Snapcraft para entender mais sobre ela e identificar atributos adicionais para sua configuração do Snap.

      Por fim, caso queira investigar ainda mais o desenvolvimento do Snap, pode ser que goste de ler sobre a implementação de Snap Hooks, que permitem que os Snaps reajam dinamicamente às alterações do sistema, como as atualizações ou ajustes de política de segurança.



      Source link

      Como adicionar o Sidekiq e o Redis a um aplicativo Ruby on Rails


      Introdução

      Ao desenvolver um aplicativo Ruby on Rails, você pode se deparar com tarefas de aplicativos que devem ser executadas de maneira assíncrona. O processamento de dados, envio de e-mails em lote, ou a interação com APIs externas são todos exemplos de trabalho que podem ser feitos de maneira assíncrona com o background jobs. O uso de jobs em segundo plano pode melhorar o desempenho de seu aplicativo, descarregando tarefas potencialmente demoradas em uma fila de processamento em segundo plano, liberando o ciclo de solicitação/resposta original.

      O Sidekiq é uma das frameworks mais amplamente utilizadas em jobs de segundo plano que você pode implementar em um aplicativo Rails. Ele é apoiado pelo Redis, um armazenamento de valores-chave dentro da memória conhecido pela sua flexibilidade e desempenho. O Sidekiq utiliza o Redis como um armazenamento de gerenciamento de tarefas para processar milhares de tarefas por segundo.

      Neste tutorial, você adicionará o Redis e o Sidekiq a um aplicativo existente do Rails. Você criará um conjunto de classes e métodos de trabalho do Sidekiq para lidar com:

      • Um upload em lote de informações de tubarões ameaçados de extinção para o banco de dados do aplicativo de um arquivo CSV no repositório de projeto.
      • A remoção desses dados.

      Quando terminar, terá um aplicativo de demonstração que utilizará trabalhadores e trabalhos para processar tarefas de maneira assíncrona. Esta será uma boa base para que você adicione trabalhadores e trabalhos ao seu próprio aplicativo, usando este tutorial como um ponto de partida.

      Pré-requisitos

      Para seguir este tutorial, você vai precisar do seguinte:

      Passo 1 — Clonando o projeto e instalando dependências

      Nosso primeiro passo será clonar o repositório de rails-bootstrap da conta do GitHub da Comunidade da DigitalOcean. Esse repositório inclui o código da configuração descrita em Como adicionar o Bootstrap em um aplicativo Ruby on Rails, que explica como adicionar o Bootstrap a um projeto Rails 5 existente.

      Clone o repositório em um diretório chamado rails-sidekiq:

      • git clone https://github.com/do-community/rails-bootstrap.git rails-sidekiq

      Navegue até o diretório rails-sidekiq:

      Para trabalhar com o código, primeiro será necessário instalar as dependências do projeto, que estão listadas em seu Gemfile. Você também precisará adicionar o sidekiq gem ao projeto para trabalhar com o Sidekiq e o Redis.

      Abra o Gemfile do projeto para editá-lo usando o nano ou seu editor favorito:

      Adicione a gem em qualquer lugar das dependências principais do projeto (acima das dependências de desenvolvimento):

      ~/rails-sidekiq/Gemfile

      . . .
      # Reduces boot times through caching; required in config/boot.rb
      gem 'bootsnap', '>= 1.1.0', require: false
      gem 'sidekiq', '~>6.0.0'
      
      group :development, :test do
      . . .
      

      Salve e feche o arquivo quando terminar de adicionar o gem.

      Use o seguinte comando para instalar os gems:

      Você verá na saída que o redis gem também está instalado como um requisito para o sidekiq.

      Em seguida, você instalará suas dependências do Yarn. Como esse projeto Rails 5 foi modificado para atender ativos com o webpack, as dependências de JavaScript dele são gerenciadas agora pelo Yarn. Isso significa que é necessário instalar e verificar as dependências listadas no arquivo do projeto package.json.

      Execute o yarn install para instalar essas dependências:

      Em seguida, execute seu banco de dados de migrações:

      Assim que suas migrações terminarem, teste o aplicativo para garantir que ele esteja funcionando como esperado. Caso esteja trabalhando localmente, inicie seu servidor no contexto do seu pacote local com o seguinte comando:

      Caso esteja trabalhando em um servidor de desenvolvimento, inicie o aplicativo com:

      • bundle exec rails s --binding=your_server_ip

      Navegue até o localhost:3000 ou http://your_server_ip:3000. Você verá a seguinte página inicial:

      Página inicial do aplicativo

      Para criar um novo tubarão, clique no botão Get Shark Info, que levará você até a rota sharks/index:

      Rota do Índice de Tubarões

      Para verificar se o aplicativo está funcionando, podemos adicionar algumas informações de demonstração a ele. Clique em New Shark. Será solicitado que coloque um nome de usuário (sammy) e senha (shark), graças às configurações de autenticação do projeto.

      Na página New Shark, digite “Great White” no campo Name e “Scary” no campo Facts.

      Criar Tubarão

      Clique no botão Create Shark para criar o tubarão. Assim que ver que seu tubarão foi criado, encerre o servidor com CTRL+C.

      Você instalou as dependências necessárias para seu projeto e testou sua funcionalidade. Em seguida, você pode fazer algumas alterações no aplicativo Rails para trabalhar com seus recursos de tubarões ameaçados de extinção.

      Passo 2 — Gerando um controlador para recursos de tubarões ameaçados de extinção

      Para trabalhar com nossos recursos de tubarões ameaçados de extinção, adicionaremos um novo modelo ao aplicativo e um controlador que controlará como as informações sobre tubarões ameaçados de extinção serão apresentadas aos usuários. Nosso objetivo final é tornar possível que os usuários enviem um lote grande de informações sobre tubarões ameaçados de extinção sem bloquear a funcionalidade geral do nosso aplicativo e excluírem essas informações quando não precisarem mais delas.

      Primeiro, vamos criar um modelo Endangered para nossos tubarões ameaçados de extinção. Vamos incluir um campo string em nossa tabela de banco de dados para o nome do tubarão e outro campo string para as categorias da União Internacional para a Conservação da Natureza (IUCN), que determina o grau em que cada tubarão está em risco.

      Por fim, nossa estrutura de modelo corresponderá às colunas do arquivo CSV que usaremos para criar nosso upload do lote. Este arquivo está localizado no diretório db e você pode verificar seu conteúdo com o seguinte comando:

      O arquivo contém uma lista de 73 tubarões ameaçados de extinção e seus status de IUCN – vu para vulneráveis, en para ameaçados de extinção e cr para criticamente ameaçados de extinção.

      Nosso modelo Endangered se correlacionará com esses dados, permitindo-nos criar novas instâncias de Endangered a partir deste arquivo CSV. Crie o modelo com o seguinte comando:

      • rails generate model Endangered name:string iucn:string

      Em seguida, gere um controlador Endangered com uma ação index:

      • rails generate controller endangered index

      Isso nos dará um ponto de partida para desenvolver a funcionalidade do nosso aplicativo, embora também seja necessário adicionar métodos personalizados ao arquivo do controlador que o Rails gerou para nós.

      Abra aquele arquivo agora:

      • nano app/controllers/endangered_controller.rb

      O Rails nos forneceu um rascunho que podemos começar a preencher.

      Primeiro, vamos precisar determinar quais rotas precisamos trabalhar com nossos dados. Graças ao comando generate controller, temos um método index para começar. Isso se correlacionará a uma visualização do index, onde apresentaremos usuários com a opção de fazer o upload de tubarões ameaçados de extinção.

      No entanto, também queremos lidar com casos onde os usuários podem já ter feito upload dos tubarões; eles não precisarão de uma opção de upload neste caso. De algum modo precisaremos avaliar quantas instâncias da classe Endangered já existem, uma vez que mais de uma indica que o upload do lote já ocorreu.

      Vamos começar criando um método private set_endangered que capturará cada instância de nossa classe Endangered a partir do banco de dados. Adicione o código a seguir ao arquivo:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all
          end
      
      end
      

      Note que o filtro before_action garantirá que o valor @endangered seja definido apenas para as rotas index e data, que serão as rotas onde lidaremos com os dados dos tubarões ameaçados de extinção.

      Em seguida, adicione o seguinte código ao método index para determinar a rota correta para usuários visitando esta parte do aplicativo:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      . . .
      

      Caso não exista nenhuma instância de nossa classe Endangered, redirecionaremos os usuários para a rota data, onde podem visualizar informações sobre os tubarões que eles criaram. Caso contrário, eles visualizarão o index.

      Em seguida, abaixo do método index, adicione um método data, que se correlacionará a uma visualização do método data:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data
        end
      . . .
      

      Em seguida, adicionaremos um método para lidar com o upload de dados propriamente dito. Vamos chamar este método de upload e chamaremos uma classe trabalhadora e um método Sidekiq para realizar o upload de dados do arquivo CSV. Criaremos a definição para essa classe trabalhadora, AddEndangeredWorker, no próximo passo.

      Por enquanto, adicione o seguinte código ao arquivo para fazer o trabalhador do Sidekiq realizar o upload:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def data
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      . . .
      

      Ao chamar o método perform_async da classe AddEndangeredWorker usando o arquivo CSV como um argumento, este código garante que os dados do tubarão e o trabalho de upload sejam passados para o Redis. Os trabalhadores do Sidekiq que vamos configurar monitoram a fila de trabalho e reagirão quando novos trabalhos surgirem.

      Após chamar o perform_async, nosso método de upload redireciona para o caminho data, onde os usuários poderão ver os tubarões carregados.

      Em seguida, adicionaremos um método destroy para destruir os dados. Adicione o seguinte código abaixo do método do upload:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      . . .
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      . . .
      

      Da mesma forma que nosso método de upload, nosso método destroy inclui uma chamada do perform_async de uma classe RemoveEndangeredWorker — o outro trabalhador Sidekiq que vamos criar. Após chamar este método, ele redireciona os usuários para o caminho do aplicativo raiz.

      O arquivo final se parecerá com este:

      ~/rails-sidekiq/app/controllers/endangered_controller.rb

      class EndangeredController < ApplicationController
        before_action :set_endangered, only: [:index, :data]
      
        def index          
          if @endangered.length > 0
            redirect_to endangered_data_path
          else
            render 'index'
          end
        end
      
        def data
        end
      
        def upload
          csv_file = File.join Rails.root, 'db', 'sharks.csv'   
          AddEndangeredWorker.perform_async(csv_file)
          redirect_to endangered_data_path, notice: 'Endangered sharks have been uploaded!'
        end
      
        def destroy
          RemoveEndangeredWorker.perform_async
          redirect_to root_path
        end
      
        private
      
          def set_endangered
            @endangered = Endangered.all
          end
      
      end
      

      Salve e feche o arquivo quando você terminar a edição.

      Como passo final na consolidação das rotas do nosso aplicativo, vamos modificar o código em config/routes.rb, o arquivo onde ficam nossas declarações de rota.

      Abra aquele arquivo agora:

      O arquivo se parece com esse:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      Vamos precisar atualizar o arquivo para incluir as rotas que definimos em nosso controlador: data, upload e destroy. Nossa rota de data corresponderá a uma solicitação GET para recuperar os dados do tubarão, enquanto nossas rotas de upload e destroy mapearão as solicitações POST, que farão o upload e a destruição desses dados.

      Adicione o código a seguir ao arquivo para definir essas rotas:

      ~/rails-sidekiq/config/routes.rb

      Rails.application.routes.draw do
        get 'endangered/index'
        get 'endangered/data', to: 'endangered#data'
        post 'endangered/upload', to: 'endangered#upload'
        post 'endangered/destroy', to: 'endangered#destroy'
        get 'home/index'
        resources :sharks do
                resources :posts
        end
        root 'home#index'
        # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
      end
      

      Salve e feche o arquivo quando você terminar a edição.

      Com seu modelo e controlador Endangered em funcionamento, continue para definir suas classes de trabalhadores do Sidekiq.

      Passo 3 — Definindo os trabalhadores do Sidekiq

      Chamamos os métodos do perform_async nos trabalhadores do Sidekiq em nosso controlador, mas ainda precisamos criar os trabalhadores em si.

      Primeiro, crie um diretório workers para os trabalhadores:

      Abra um arquivo para o trabalhador AddEndangeredWorker:

      • nano app/workers/add_endangered_worker.rb

      Neste arquivo, adicionaremos códigos que nos permitirá trabalhar com os dados em nosso arquivo CSV. Primeiro, adicione códigos ao arquivo que criarão a classe, inclua a biblioteca Ruby CSV e certifique-se de que essa classe funcione como um trabalhador Sidekiq:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      Também incluiremos a opção retry: false para garantir que o Sidekiq não tente fazer o upload novamente em caso de falha.

      Em seguida, adicione o código para a função perform:

      ~/rails-sidekiq/app/workers/add_endangered_worker.rb

      class AddEndangeredWorker
        require 'csv'
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform(csv_file)
          CSV.foreach(csv_file, headers: true) do |shark|
          Endangered.create(name: shark[0], iucn: shark[1])
        end
       end
      
      end
      

      O método perform recebe argumentos do método perform_async definido no controlador, por este motivo, é importante que os valores do argumento estejam alinhados. Aqui, passamos a csv_file, a variável que definimos no controlador, e usamos o método foreach da biblioteca CSV para ler os valores no arquivo. Definir headers: true para este loop garante que a primeira linha do arquivo seja tratada como uma linha de cabeçalhos.

      Então, o bloco lê os valores do arquivo nas colunas que definimos para nosso modelo Endangered: name e iucn. Executar este loop criará instâncias Endangered para cada uma das entradas em nosso arquivo CSV.

      Assim que terminar a edição, salve e feche o arquivo.

      Em seguida, criaremos um trabalhador para lidar com a exclusão desses dados. Abra um arquivo para a classe RemoveEndangeredWorker:

      • nano app/workers/remove_endangered_worker.rb

      Adicione o código a seguir para definir a classe, e para garantir que ela utilize a biblioteca e as funções CSV como um trabalhador Sidekiq:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
      end
      

      Em seguida, adicione um método perform para lidar com a destruição dos dados dos tubarões ameaçados de extinção:

      ~/rails-sidekiq/app/workers/remove_endangered_worker.rb

      class RemoveEndangeredWorker
        include Sidekiq::Worker
        sidekiq_options retry: false
      
        def perform
          Endangered.destroy_all
        end
      
      end
      

      O método perform chama a função destroy_all na classe Endangered, que removerá todas as instâncias da classe a partir do banco de dados.

      Salve e feche o arquivo quando você terminar a edição.

      Com seus trabalhadores em funcionamento, continue para a criação de um layout para suas visualizações de endangered e a criação de modelos para a visualização de seus index e data, de modo que os usuários possam fazer upload e visualizar tubarões ameaçados de extinção.

      Passo 4 — Adicionando layouts e modelos de visualização

      Para que os usuários aproveitem suas informações de tubarões ameaçados de extinção, precisaremos abordar duas coisas: o layout para as visualizações definidas em nosso controlador endangered e os modelos de visualização para as visualizações de index e de data.

      Atualmente, nosso aplicativo utiliza um layout em todo o aplicativo, localizado em app/views/layouts/application.html.erb, uma navegação parcial e um layout para visualizações de sharks. O layout do aplicativo verifica se há um bloco de conteúdo que nos permita carregar diferentes layouts com base em qual parte do aplicativo nosso usuário se encontra: para a home index, os usuários verão um layout, e para quaisquer visualizações relacionadas a tubarões individuais, eles verão outro layout.

      Podemos reaproveitar o layout sharks para nossas visualizações endangered, uma vez que este formato também funcionará para a apresentação de dados de tubarões em massa.

      Copie o arquivo de layout de sharks para criar um layout de endangered:

      • cp app/views/layouts/sharks.html.erb app/views/layouts/endangered.html.erb

      Em seguida, vamos trabalhar na criação dos modelos de visualização para nossas visualizações de index e de data.

      Abra o modelo index primeiro:

      • nano app/views/endangered/index.html.erb

      Exclua o código boilerplate e adicione o código a seguir, o qual dará informações gerais aos usuários sobre as categorias ameaçados de extinção e os apresentará com a opção de fazer o upload das informações sobre eles:

      ~/rails-sidekiq/app/views/endangered/index.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <br>
      
        <%= form_tag endangered_upload_path do %>
        <%= submit_tag "Import Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      Uma form_tag torna o upload de dados possível, apontando uma ação posterior para a endangered_upload_path — a rota que definimos para nossos uploads. Um botão de enviar, criado com o submit_tag, solicita que os usuários façam o "Import Endangered Sharks​".

      Além deste código, incluímos algumas informações gerais sobre os códigos ICUN, de modo que os usuários possam interpretar os dados que eles verão.

      Salve e feche o arquivo quando você terminar a edição.

      Em seguida, abra um arquivo para a visualização de data:

      • nano app/views/endangered/data.html.erb

      Adicione o código a seguir, que adicionará uma tabela com os dados de tubarões ameaçados de extinção:

      ~/rails-sidekiq/app/views/endangered/data.html.erb

      <p id="notice"><%= notice %></p>
      
      <h1>Endangered Sharks</h1>
      
      <p>International Union for Conservation of Nature (ICUN) statuses: <b>vu:</b> Vulnerable, <b>en:</b> Endangered, <b>cr:</b> Critically Endangered </p>
      
      <div class="table-responsive">
      <table class="table table-striped table-dark">
        <thead>
          <tr>
            <th>Name</th>
            <th>IUCN Status</th>
            <th colspan="3"></th>
          </tr>
        </thead>
      
        <tbody>
          <% @endangered.each do |shark| %>
            <tr>
              <td><%= shark.name %></td>
              <td><%= shark.iucn %></td>
            </tr>
          <% end %>
        </tbody>
      </table>
      </div>
      
      <br>
      
        <%= form_tag endangered_destroy_path do %>
        <%= submit_tag "Delete Endangered Sharks" %>
        <% end %>
      
        <br>
      
      <%= link_to 'New Shark', new_shark_path, :class => "btn btn-primary btn-sm" %> <%= link_to 'Home', home_index_path, :class => "btn btn-primary btn-sm" %>
      

      Esse código inclui os códigos de status da ICUN novamente e uma tabela de Inicialização para os dados produzidos. Ao fazer loop através de nossa variável @endangered, produziremos o nome e o status de ICUN de cada tubarão para a tabela.

      Abaixo da tabela, temos outro conjunto de form_tags e de submit_tags que foram enviados para o caminho destroy, oferecendo aos usuários a opção "Delete Endangered Sharks".

      Salve e feche o arquivo quando você terminar a edição.

      A última modificação que vamos fazer às visualizações será feita na visualização de index associada ao nosso controlador home. Você deve se lembrar de que essa visualização está definida como a raiz do aplicativo em config/routes.rb.

      Abra este arquivo para edição:

      • nano app/views/home/index.html.erb

      Encontre a coluna na linha que afirma que Sharks are ancient​​​:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . .
              <div class="col-lg-6">
                  <h3>Sharks are ancient</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago.
                  </p>
              </div>
          </div>
      </div>
      

      Adicione o código a seguir ao arquivo:

      ~/rails-sidekiq/app/views/home/index.html.erb

      . . .
              <div class="col-lg-6">
                  <h3>Sharks are ancient and SOME are in danger</h3>
                  <p>There is evidence to suggest that sharks lived up to 400 million years ago. Without our help, some could disappear soon.</p>
                  <p><%= button_to 'Which Sharks Are in Danger?', endangered_index_path, :method => :get,  :class => "btn btn-primary btn-sm"%>
                  </p>
              </div>
          </div>
      </div>
      

      Incluímos uma chamada de ação para os usuários aprenderem mais sobre os tubarões ameaçados de extinção, primeiramente compartilhando uma mensagem importante e, em seguida, adicionando um auxiliar button_to que envia uma solicitação GET para nossa rota de endangered index, dando acesso a essa parte do aplicativo. A partir daí, eles poderão fazer o upload e visualizar informações sobre tubarões ameaçados de extinção.

      Salve e feche o arquivo quando você terminar a edição.

      Com seu código funcionando, você está pronto para inicializar o aplicativo e fazer o upload de alguns tubarões!

      Passo 5 — Inicializando o Sidekiq e testando o aplicativo

      Antes de inicializar o aplicativo, precisaremos executar as migrações em nosso banco de dados e iniciar o Sidekiq para habilitar nossos trabalhadores. O Redis já deve estar em execução no servidor, mas podemos verificar isso para termos certeza. Com tudo isso funcionando, estaremos prontos para testar o aplicativo.

      Primeiro, verifique se o Redis está funcionando:

      Deverá ver um resultado como o seguinte:

      Output

      ● redis-server.service - Advanced key-value store Loaded: loaded (/lib/systemd/system/redis-server.service; enabled; vendor preset: enabled) Active: active (running) since Tue 2019-11-12 20:37:13 UTC; 1 weeks 0 days ago

      Em seguida, execute seu banco de dados de migrações:

      Agora, você pode iniciar o Sidekiq no contexto do seu pacote atual do projeto, usando o comando bundle exec sidekiq​​​:

      Você verá um resultado como este, indicando que o Sidekiq está pronto para processar trabalhos:

      Output

      m, `$b .ss, $$: .,d$ `$$P,d$P' .,md$P"' ,$$$$$b/md$$$P^' .d$$$$$$/$$$P' $$^' `"/$$$' ____ _ _ _ _ $: ,$$: / ___|(_) __| | ___| | _(_) __ _ `b :$$ ___ | |/ _` |/ _ |/ / |/ _` | $$: ___) | | (_| | __/ <| | (_| | $$ |____/|_|__,_|___|_|__|__, | .d$$ |_| 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Running in ruby 2.5.1p57 (2018-03-29 revision 63029) [x86_64-linux] 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: See LICENSE and the LGPL-3.0 for licensing details. 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Upgrade to Sidekiq Pro for more features and support: http://sidekiq.org 2019-11-19T21:43:00.540Z pid=17621 tid=gpiqiesdl INFO: Booting Sidekiq 6.0.3 with redis options {:id=>"Sidekiq-server-PID-17621", :url=>nil} 2019-11-19T21:43:00.543Z pid=17621 tid=gpiqiesdl INFO: Starting processing, hit Ctrl-C to stop

      Abra uma segunda janela de terminal, navegue para o diretório rails-sidekiq e inicialize seu servidor do aplicativo.

      Caso esteja executando o aplicativo localmente, use o seguinte comando:

      Caso esteja trabalhando com um servidor de desenvolvimento, execute o seguinte:

      • bundle exec rails s --binding=your_server_ip

      Navegue para o localhost:3000 ou http://your_server_ip:3000 no navegador. Você verá a seguinte página inicial:

      Página inicial do App Sidekiq

      Clique no botão Which Sharks Are in Danger? [Quais tubarões estão em perigo?] . Como não fez upload de nenhum tubarão ameaçado de extinção, isso levará você até a visualização de endangered index:

      Exibição do índice Endangered [Em perigo]

      Clique em Import Endangered Sharks para importar os tubarões. Você verá uma mensagem de status informando que os tubarões foram importados:

      Iniciar importação

      Você verá também o início da importação. Atualize sua página para ver a tabela inteira:

      Atualizar tabela

      Graças ao Sidekiq, o upload de nosso lote grande de tubarões em perigo foi bem-sucedido, sem bloquear o navegador ou interferir com outras funcionalidades do aplicativo.

      Clique no botão Home, no final da página, para voltar à página principal do aplicativo:

      Página inicial do App Sidekiq

      A partir daqui, clique em Which Sharks Are in Danger? novamente. Isso levará você diretamente para a visualização de data, uma vez que você já fez o upload dos tubarões.

      Para testar a funcionalidade de exclusão, clique no botão Delete Endangered Sharks​​​ abaixo da tabela. Você deve ser redirecionado para a página inicial do aplicativo novamente. Clicando em Which Sharks Are in Danger? uma última vez levará você de volta para a visualização do index, onde terá a opção de fazer o upload dos tubarões novamente:

      Exibição do índice Endangered [Em perigo]

      Seu aplicativo agora está funcionando com os trabalhadores Sidekiq, que estão prontos para processar trabalhos e garantir que os usuários tenham uma boa experiência ao trabalhar com seu aplicativo.

      Conclusão

      Agora, você tem um aplicativo Rails em funcionamento com o Sidekiq habilitado, o que permitirá que você descarregue operações dispendiosas em uma fila de trabalho gerenciada pelo Sidekiq e apoiada pelo Redis. Isso permitirá que você melhore a velocidade e a funcionalidade do seu site à medida que desenvolve.

      Caso queira aprender mais sobre o Sidekiq, os docs são um bom lugar para começar.

      Para aprender mais sobre o Redis, confira nossa biblioteca dos recursos do Redis. Você também pode aprender mais sobre a execução de um cluster gerenciado do Redis na DigitalOcean, conferindo a documentação do produto.



      Source link

      Como desenvolver um aplicativo de citações inspiradoras utilizando o AdonisJs e o MySQL


      O autor selecionou a Tech Education Fund para receber uma doação como parte do programa Write for DOnations.

      Introdução

      O AdonisJs é um framework Web Node.js, escrito em JavaScript simples, que é executado em todos os grandes sistemas operacionais. Ele utiliza o padrão de design popular MVC (Modelo – Visão – Controle) e oferece um ecossistema estável para a escrita de aplicativos Web do servidor. O framework possui autenticação contínua, SQL ORM (mapeamento objeto-relacional), migrations e a propagação de banco de dados. O AdonisJs tem uma arquitetura semelhante ao framework PHP de aplicativo Web, o Laravel, incluindo a mesma estrutura de pasta e vários conceitos de configuração compartilhados.

      Por padrão, o AdonisJs utiliza o mecanismo de modelo Edge, projetado para um uso intuitivo. Assim como o Laravel, o AdonisJs vem com um ORM chamado Lucid que funciona como uma interface para a comunicação entre os modelos de um aplicativo e o banco de dados. Com o AdonisJs, os desenvolvedores podem desenvolver um aplicativo de pilha completa, onde o servidor de back-end será o responsável pela aplicação da lógica de negócios, roteamento e renderização de todas as páginas do aplicativo. Também é possível criar um serviço Web API para retornar as respostas JSON de um controlador; esses serviços Web podem ser consumidos usando os frameworks de front-end, como o Vue.js, o React e o Angular.

      Neste tutorial, você desenvolverá um aplicativo com o AdonisJs usando sua CLI. Você criará rotas, controladores, modelos e visualizações dentro do seu aplicativo e executará as validações de formulário. O exemplo neste tutorial será um aplicativo de citações inspiradoras, no qual um usuário pode se inscrever e fazer o login para criar uma citação inspiradora. Este aplicativo de demonstração dará a você a oportunidade de realizar as operações CRUD (Criar, Ler, Atualizar e Excluir).

      Pré-requisitos

      Antes de iniciar este guia, você precisará do seguinte:

      Nota: este tutorial utiliza uma máquina macOS para desenvolvimento. Caso esteja usando outro sistema operacional, talvez seja necessário, nos primeiros passos, usar os comandos sudo para o npm.

      Passo 1 — Instalando o Adonis CLI

      Nesta seção, você instalará o Adonis CLI e todos os seus pacotes necessários em sua máquina local. O CLI permitirá que você faça a exibição de scaffold em um novo projeto do AdonisJs, bem como criar e gerar um boilerplate para controladores, middlewares e modelos em seu aplicativo. Você também criará seu banco de dados para o projeto.

      Execute o seguinte comando para instalar o AdonisJs CLI em sua máquina, de maneira global, via npm:

      Assim que o processo de instalação terminar, digite o seguinte comando no terminal para confirmar a instalação do AdonisJs e visualizar a versão atual:

      Você verá o resultado mostrando a versão atual do AdonisJs:

      Output

      4.1.0

      Com a instalação do AdonisJs CLI bem-sucedida, você tem acesso e pode usar o comando adonis para criar novas instalações de um projeto AdonisJs, gerenciar seu projeto e gerar arquivos relevantes, como os controladores, modelos, etc.

      Agora, você pode prosseguir para criar um novo projeto do AdonisJs usando o comando adonis como mostrado aqui:

      • adonis new adonis-quotes-app

      O comando anterior criará um aplicativo chamado adonis-quotes-app em um novo diretório com o mesmo nome em seu diretório local com a estrutura relevante do AdonisJs MVC.

      Vá para a pasta do novo aplicativo:

      Então, inicie seu aplicativo executando:

      Isso inicializará o servidor de desenvolvimento na porta padrão 3333, como especificado no arquivo root .env para seu aplicativo. Vá para http://localhost:3333 para visualizar a página de boas-vindas do AdonisJs.

      Página de boas-vindas do AdonisJs

      Agora, você completará a configuração do seu banco de dados. Aqui, você instalará o driver do mysql para se conectar ao seu servidor MySQL através do seu aplicativo Node.js via npm. Para começar, volte para seu terminal onde o aplicativo está funcionando, pare o processo com CTRL + C e execute o seguinte comando:

      Agora que você instalou o driver do MySQL Node.js com êxito para este aplicativo, será necessário criar o banco de dados do aplicativo e configurar a conexão apropriada para ele.

      A versão mais recente do MySQL que você instalou através do tutorial de pré-requisitos utiliza um plug-in de autenticação padrão chamado caching_sha2_password. Ele ainda não é compatível com drivers do Node.js para o MySQL. Para evitar qualquer problema de conexão de banco de dados do seu aplicativo, será necessário criar um novo usuário do MySQL e usar o plug-in de autenticação atualmente suportado, o —mysql_native_password.

      Para começar, acesse o cliente do MySQL usando a conta root:

      Será solicitado que você digite sua senha de conta root, definida durante a instalação do MySQL.

      Em seguida, crie o usuário e a senha usando o plug-in do mysql_native_password:

      • CREATE USER 'sammy'@'localhost' IDENTIFIED WITH mysql_native_password BY 'password';

      Você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.02 sec)

      Em seguida, crie um banco de dados para o aplicativo com:

      Você verá o seguinte resultado:

      Output

      Query OK, 1 row affected (0.03 sec)

      Você criou o banco de dados para este aplicativo com sucesso.

      Agora, habilite o acesso ao banco de dados criado para o novo usuário do MySQL. Execute o seguinte comando para conceder todos os privilégios ao usuário no banco de dados:

      • GRANT ALL PRIVILEGES ON adonis.* TO 'sammy'@'localhost';

      Recarregue as tabelas de concessão, executando o seguinte comando para aplicar as alterações que acabou de fazer:

      Você verá o seguinte resultado:

      Output

      Query OK, 0 rows affected (0.00 sec)

      Saia do cliente do MySQL com:

      Você instalou o AdonisJs CLI com sucesso, criou um novo projeto do AdonisJs e instalou o mysql via npm. Você também criou o banco de dados para este aplicativo e configurou um usuário do MySQL com os privilégios apropriados a ele. Esta é a configuração básica do seu aplicativo e, na seção seguinte, você começará a criar as visualizações necessárias para seu aplicativo.

      Passo 2 — Usando o mecanismo de modelagem Edge

      O AdonisJs vem com seu próprio mecanismo de modelo chamado Edge. Ele permite que você crie um modelo HTML reutilizável e habilita a introdução da lógica de front-end em seu aplicativo com o mínimo de código. O Edge fornece aos desenvolvedores de JavaScript as ferramentas ao desenvolver um aplicativo para compilar um layout baseado em componentes, escrever condicionais, usar iterações e criar camadas de visualização para reter a lógica. Todos os arquivos do modelo terminam com a extensão .edge, e são armazenados no diretório resources/views.

      A seguir, são exibidas as visualizações que seu aplicativo precisará para funcionar corretamente:

      • Master Layout: com o Edge, é possível criar uma página que terá CSS, arquivos comuns do JavaScript, jQuery e as partes comuns da interface do usuário que serão as mesmas ao longo do aplicativo — por exemplo, a barra de navegação, logotipo, cabeçalho, etc. Uma vez que tiver estabelecido a página de Layout Mestre, outras visualizações (páginas) em seu aplicativo a herdarão.
      • Index view: essa página utilizará o layout mestre para herdar arquivos comuns e também renderizará o conteúdo para a página inicial do aplicativo.
      • Login page: essa página também usará o layout mestre e renderizará o formulário com os campos de entrada para o nome de usuário e a senha para os usuários fazerem o login.
      • Register page: aqui, os usuários verão um formulário para registrar e ter seus detalhes permanentes no banco de dados.
      • Create quote page: os usuários utilizarão essa página para criar uma citação inspiradora.
      • Edit quote page: os usuários usarão esta página para editar uma citação.
      • View quote page: os usuários utilizarão está página para visualizar uma citação em particular.

      Para começar, use o comando adonis para criar a página de layout mestre executando o seguinte comando:

      • adonis make:view layouts/master

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create resources/views/layouts/master.edge

      Esse comando criará automaticamente um arquivo master.edge em sua pasta resources/views/layouts. Abra o novo arquivo:

      • nano resources/views/layouts/master.edge

      Adicione o seguinte código nele:

      /resources/views/layouts/master.edge

      <!DOCTYPE html>
      <html lang="en">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <meta http-equiv="X-UA-Compatible" content="ie=edge">
          <title>adonis-quotes-app</title>
          {{ style('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css') }}
          {{ style('style') }}
          {{ script('https://code.jquery.com/jquery-3.3.1.slim.min.js') }}
      </head>
      <body>
          <div class="container-fliud">
              @include('navbar')
              @!section('content')
          </div>
          {{ script('https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js') }}
      
      </body>
      </html>
      

      Neste arquivo, inclua os arquivos CDN para o Bootstrap CSS, o Bootstrap JavaScript e o jQuery. Adicione um nome de arquivo CSS global de nome style.css e dentro do div, inclua um arquivo partial chamado navbar. Para reutilizar os fragmentos do código HTML necessários em várias páginas em seu aplicativo, como nav ou footer, incorpore as parciais. Esses são arquivos menores que contêm o código repetido, tornando mais rápida a atualização do código desses elementos em um único local, em vez de toda instância que ele ocorre. O navbar contém marcações para botões de Login e de Register, um logotipo e um link de página inicial.

      Com isso funcionando, todas as páginas seguintes que serão criadas para este aplicativo podem estender o layout mestre e ter a navbar renderizada sem a necessidade de escrever o conteúdo novamente. Você criará este arquivo navbar mais tarde no tutorial.

      Por fim, defina uma tag de seção @! section() para incluir o conteúdo de outras páginas e tê-las renderizadas pelo layout mestre. Para que isso funcione como esperado, todas as novas páginas que estendem o layout mestre também devem definir uma tag de seção com o mesmo nome (ou seja, @section('content')​​​).

      Salve e saia do arquivo assim que terminar de editá-lo.

      Em seguida, você usará o comando adonis para criar a barra de navegação:

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/navbar.edge

      Abra o arquivo recém-criado:

      • nano resources/views/navbar.edge

      Então, adicione o seguinte código a ele:

      /resources/views/navbar.edge

      <nav class="navbar navbar-expand-lg navbar-dark text-white">
          <a class="navbar-brand" >LOGO</a>
          <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
          </button>
      
          <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                  <li class="nav-item active ">
                      <a class="btn text-white" href="https://www.digitalocean.com/">Home</a>
                  </li>
              </ul>
          </div>
          <div class="navbar-right" id="navbarNav">
              @loggedIn
                  <ul class="navbar-nav">
                          <li>
                              <div class="text-right">
                                   <a href="{{route('create.quote')}}" class="btn btn-outline-primary">Create Quote</a>
                              </div>
                          </li>
      
                      <li class="nav-item dropdown">
                          <a class="nav-link dropdown-toggle" href="https://www.digitalocean.com/#" id="navbarDropdownMenuLink" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
                             {{ auth.user.username}}
                          </a>
                          <div class="dropdown-menu" aria-labelledby="navbarDropdownMenuLink">
                              <form method="POST" action="{{route('logout')}}">
                                  {{ csrfField() }}
                                    <button  type="submit" class="dropdown-item" href="">logout</button>
                              </form>
                          </div>
                      </li>
                  </ul>
              @else
                  <ul class="navbar-nav">
                      <li class="nav-item active pr-2">
                          <a href="{{route('login.create')}}" class="btn btn-outline-danger">
                            login
                          </a>
                      </li>
                      <li class="nav-item active pr-2">
                          <a href="{{route('register.create')}}" class="btn btn-outline-primary">
                              Register
                          </a>
                      </li>
                  </ul>
              @endloggedIn
          </div>
      </nav>
      

      Além de definir os links para a página inicial e um botão para registrar e fazer login, adicione uma tag @loggedIn. Com isso funcionando, é possível escrever uma instrução condicional em torno do usuário autenticado e exibir o conteúdo adequado, sempre que necessário. Para um usuário autenticado, o aplicativo exibirá seu nome de usuário e um botão para criar uma nova citação. Caso um usuário não esteja logado, seu aplicativo exibirá um botão para fazer login ou registrar-se. Essa página será incluída como uma parcial em cada página, como estava antes no layout mestre para este aplicativo.

      Salve e saia do arquivo.

      Agora, você criará a página de índice que será usada para a página inicial do aplicativo. Ele renderizará e exibirá a lista de todas citações inspiradoras que os usuários escrevem:

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create resources/views/index.edge

      O arquivo criado aqui estará localizado em resources/views/index.edge. Abra o arquivo:

      • nano resources/views/index.edge

      Então, adicione as linhas a seguir:

      /resources/views/index.edge

      @layout('layouts/master')
      @section('content')
      
      <div class="container">
          <div class="text-center">
              @if(flashMessage('successmessage'))
                  <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
              @endif
          </div>
          <div class="row">
              @each(quote in quotes)
                  <div class="col-md-4 mb-4 quote-wrapper">
                      <a href="https://www.digitalocean.com/view-quote/{{quote.id}}" class="w-100">
                          <div class="card shadow-lg bg-dark text-white">
                              <div class="card-body">
                                  <blockquote class="blockquote mb-0">
                                      <p>{{quote.body}}</p>
                                      <footer class="blockquote-footer">
                                          <cite title="Source Title"> {{quote.username}}</cite>
                                      </footer>
                                  </blockquote>
                                  @if(auth.user.id == quote.user_id)
                                    <div>
                                      <a  href="http://www.digitalocean.com/edit-quote/{{quote.id}}" class="btn btn-primary">edit</a>
                                      <a href="http://www.digitalocean.com/delete-quote/{{quote.id}}" class="btn btn-danger">delete</a>
                                    </div>
                                  @endif
                              </div>
                          </div>
                      </a>
                  </div>
              @else
               <div class="col-md-12 empty-quote text-center">
                      <p>No inspirational quote has been created</p>
               </div>
              @endeach
          </div>
      </div>
      @endsection
      

      Aqui, indique que essa visualização utilizará o layout master, estendendo-a. Esta página pode ter acesso a todas as bibliotecas, folhas de estilos e a navbar incluída no layout master. Em seguida, itere sobre uma matriz de quotes utilizando a tag integrada @each. A matriz de quotes será enviada para essa visualização a partir do QuoteController, que você criará mais tarde neste tutorial. Caso não haja aspas, uma mensagem adequada será exibida.

      Salve e saia deste arquivo.

      Agora, para criar a página de login, execute o seguinte comando a partir do terminal:

      • adonis make:view auth/login

      Você verá um resultado semelhante a:

      Output

      ✔ create resources/views/auth/login.edge

      Isso criará automaticamente uma pasta auth dentro de resources/views e também criará um arquivo login.edge dentro dela. Abra o arquivo login.edge:

      • nano resources/views/auth/login.edge

      Adicione o conteúdo a seguir:

      /resources/views/auth/login.edge

      @layout('layouts/master')
      @section('content')
        <div class="container">
          <div class="row">
            <div class="col-md-4 shadow bg-white mt-5 rounded offset-md-4">
              <form method="POST" action="{{route('login.store')}}">
                {{ csrfField() }}
                  <div>
                    @if(flashMessage('successmessage'))
                      <span class="alert alert-success p-1">{{ flashMessage('successmessage') }}</span>
                    @endif
                  </div>
                  <div class="form-group">
                    <label for="email">Email address</label>
                    <input type="email" class="form-control" id="email" name="email" value="{{old('email','')}}"  placeholder="Enter email">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                  </div>
                  <div class="form-group">
                    <label for="pasword">Password</label>
                    <input type="password" class="form-control" id="password" name="password" value="{{old('password','')}}" placeholder="Password">
                    {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                  </div>
      
                  <div class="text-center">
                    <button type="submit" class="btn btn-primary">Submit</button>
                  </div>
              </form>
            </div>
          </div>
        </div>
      @endsection
      

      Esse arquivo possui um formulário que contém elementos de entrada que você utilizará para coletar o nome de usuário e a senha de um usuário registrado, antes de serem autenticados e começarem a criar citações com sucesso. Outro elemento importante para notar nesta página é o {{ csrfField() }}. É uma variável global que o AdonisJs utilizará para passar o token de acesso CSRF quando enviarem um pedido POST, PUT e DELETE de seu aplicativo.

      Isso foi colocado em funcionamento para proteger seu aplicativo de ataques de Falsificação de Solicitação Entre Sites (CSRF). Ele funciona criando um segredo de CSRF único para cada usuário que visita seu site e assim que eles enviarem um pedido HTTP a partir do front-end, um token correspondente é gerado para este segredo e transmitido com o pedido. Isso permitirá que o middleware, criado para essa solicitação dentro do AdonisJs, verifique se o segredo do token e do CSRF é válido e pertence ao usuário atualmente autenticado.

      Salve e saia do arquivo assim que terminar.

      Em seguida, você criará a página de registro com este comando:

      • adonis make:view auth/register

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/auth/register.edge

      Localize e abra o arquivo recém-criado em resources/views/auth/register.edge:

      • nano resources/views/auth/register.edge

      Adicione as linhas a seguir:

      resources/views/auth/register.edge

      @layout('layouts/master')
      @section('content')
        <div class="container ">
          <div class="row">
              <div class="col-md-4  bg-white p-3 mt-5 shadow no-border rounded offset-md-4">
                <form method="POST" action="{{route('register.store')}}">
                  {{ csrfField() }}
                    <div class="form-group">
                      <label for="name">Fullname</label>
                      <input type="text" class="form-control" id="name" name="name"  value="{{old('name','')}}" placeholder="Enter Fullname">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('name'), hasErrorFor('name')) }}
                    </div>
                    <div class="form-group">
                      <label for="email">Email address</label>
                      <input type="email" class="form-control" id="email"  name="email" value="{{old('email','')}}" placeholder="Enter email">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('email'), hasErrorFor('email')) }}
                    </div>
                    <div class="form-group">
                      <label for="pasword">Password</label>
                      <input type="password" class="form-control" id="password" name="password" placeholder="Password">
                      {{ elIf('<span class=text-danger>$self</span>', getErrorFor('password'), hasErrorFor('password')) }}
                    </div>
                    <div class="text-center">
                        <button type="submit" class="btn btn-primary">Submit</button>
                    </div>
                </form>
              </div>
          </div>
        </div>
      @endsection
      

      De maneira similar a que você tem na página de login, este arquivo contém um formulário HTML com campos de entrada para coletar o name, email e o password de um usuário durante o processo de registro. O {{ csrfField() }} também está incluído, uma vez que ele é necessário para cada pedido de postagem em um aplicativo do AdonisJs.

      Salve e saia do arquivo.

      Agora, gere um novo arquivo para criar uma citação inspiradora, executando o seguinte comando a partir do terminal:

      • adonis make:view quotes/create-quote

      Você verá um resultado como:

      Output

      ✔ create resources/views/quotes/create-quote.edge

      Abra o resources/views/quotes/create-quote.edge:

      • nano resources/views/quotes/create-quote.edge

      E adicione o conteúdo a seguir a ele:

      /resources/views/quotes/create-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-3"></div>
              <div class="col-md-6 shadow bg-white mt-5 rounded p-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                      <br>
      
                  <div class="clear-fix"></div>
                      <form method="POST" action="{{route('store.quote')}}">
                          {{ csrfField() }}
                          <div class="form-group">
                              <label for="quote">Create Quote</label>
                              <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="Write an inspirational quote"></textarea>
                          </div>
      
                          <div class="text-center">
                              <button type="submit" class="btn btn-primary">Submit</button>
                          </div>
                      </form>
                  </div>
              </div>
              <div class="col-md-3"></div>
          </div>
      </div>
      @endsection
      

      Essa página estende o layout mestre e contém um formulário HTML com um elemento de área de texto. Este elemento permite que um usuário digite um texto em várias linhas antes de ser postado e tratado pela rota apropriada.

      Salve e saia do arquivo assim que terminar.

      Em seguida, crie uma página para edição de uma citação em particular. Execute o comando a seguir a partir do terminal:

      • adonis make:view quotes/edit-quote

      Você verá o seguinte resultado:

      Output

      ✔ create resources/views/quotes/edit-quote.edge

      Abra o arquivo com:

      • nano resources/views/quotes/edit-quote.edge

      Adicione o conteúdo a seguir ao resources/views/quotes/edit-quote:

      /resources/views/quotes/edit-quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 shadow bg-white rounded p-3 offset-md-3">
                  <div class="float-right">
                      <a href="https://www.digitalocean.com/" class="btn btn-outline-dark ">back</a>
                  </div>
                  <br>
      
                  <div class="clear-fix"></div>
                  <form method="POST" action="/update-quote/{{quote.id}}">
                      {{ csrfField() }}
                      <div class="form-group">
                          <label for="pasword">Edit Quote</label>
                          <textarea type="text" rows="5"  name='body' id="body" class="form-control" id="quote" placeholder="write the inspirational quote">{{quote.body}}</textarea>
                      </div>
                      <div class="text-center">
                          <button type="submit" class="btn btn-primary">Update</button>
                      </div>
      
                  </form>
              </div>
          </div>
      </div>
      @endsection
      

      Essa página possui conteúdo semelhante ao do arquivo create-quote.edge—a diferença é que ela contém os detalhes de uma citação em particular que precisa ser editada, o <form method="POST" action="/update-quote/{{quote.id}}">.

      Salve e saia do arquivo.

      Por fim, gere uma página para visualizar uma única citação inspiradora:

      • adonis make:view quotes/quote

      Você verá um resultado parecido com este:

      Output

      ✔ create resources/views/quotes/quote.edge

      Abra o arquivo com:

      • nano resources/views/quotes/quote.edge

      Adicione as linhas a seguir:

      /resources/views/quotes/quote.edge

      @layout('layouts/master')
      @section('content')
      <div class="container">
          <div class="row">
              <div class="col-md-6 offset-md-3">
                  <div class="card shadow-lg bg-dark text-white">
                      <div class="card-body">
                          <div class="float-right">
                              <a href="https://www.digitalocean.com/" class="btn btn-outline-primary ">back</a>
                          </div>
                              <br>
                          <div class="clear-fix"></div>
                          <blockquote class="blockquote mb-0">
                              <p>{{quote.body}}</p>
                              <footer class="blockquote-footer">
                                  <cite title="Source Title">{{quote.username}}</cite>
                              </footer>
                          </blockquote>
                      </div>
                  </div>
              </div>
          </div>
      </div>
      @endsection
      

      Essa página renderiza os detalhes de uma citação em particular, que inclui o corpo da citação, quote.body e o autor que a criou, quote.username.

      Quando terminar o arquivo, salve e saia.

      Você criou todas as páginas necessárias para o seu aplicativo, utilizando o mecanismo de modelagem Edge. Em seguida, você configurará e criará uma conexão para o banco de dados do seu aplicativo.

      Passo 3 — Criando um esquema de banco de dados

      Se oferecer o seu aplicativo agora, ele emitirá um erro, pois você ainda deve conectar o aplicativo a um banco de dados. Nesta seção, você configurará uma conexão com o banco de dados e, depois, usará o comando adonis para gerar um arquivo de migração que será usado para criar as tabelas para ele.

      O AdonisJs vem com um ORM chamado Lucid ORM, que fornece a implantação de registro ativo para trabalhar com o seu banco de dados. Ele elimina o incômodo de escrever consultas SQL que recuperam os dados do banco de dados em tempo real. Isso é especialmente útil ao trabalhar em um aplicativo complexo que exige muitas consultas. Como exemplo, é possível recuperar todas as citações do seu aplicativo escrevendo isso:

      const quotes = await Quote.all()
      

      Para prosseguir com a configuração apropriada para o banco de dados do seu aplicativo, certifique-se de que você ainda esteja dentro do diretório raiz do seu aplicativo e crie um arquivo .env:

      Abra o arquivo recém-criado e adicione o seguinte conteúdo:

      .env

      HOST=127.0.0.1
      PORT=3333
      NODE_ENV=development
      APP_URL=http://${HOST}:${PORT}
      CACHE_VIEWS=false
      APP_KEY=bTVOEgUvmTCfkvgrK8gEBC3Qxt1xSYr0
      DB_CONNECTION=mysql
      DB_HOST=127.0.0.1
      DB_PORT=3306
      DB_USER=sammy
      DB_PASSWORD=password
      DB_DATABASE=adonis
      SESSION_DRIVER=cookie
      HASH_DRIVER=bcrypt
      

      Por padrão, a conexão de banco de dados para um aplicativo AdonisJs é a SQLite, que você atualizará para o MySQL aqui. Você também especificará o PORT para o aplicativo, o ambiente do aplicativo e as credenciais de seu banco de dados. Certifique-se de substituir o espaço reservado para o DB_USER, DB_PASSWORD e DB_DATABASE pelas suas credenciais.

      Em seguida, você criará o modelo e um arquivo de migração para o Quote usando o Adonis CLI. Para fazer isso, execute o seguinte comando:

      • adonis make:model Quote --migration

      Você verá um resultado parecido com o seguinte:

      Output

      ✔ create app/Models/Quote.js ✔ create database/migrations/1568209992854_quote_schema.js

      Esse comando criará um modelo para o Quote na pasta app/Models e um arquivo de esquema na pasta database/migrations. O arquivo de esquema recém-criado será prefixado com o carimbo de data/hora atual. Abra o arquivo de esquema com:

      • nano database/migrations/1568209992854_quote_schema.js

      Atualize seu conteúdo com o seguinte código:

      database/migrations/…quote_schema.js

      'use strict'
      /** @type {import('@adonisjs/lucid/src/Schema')} */
      const Schema = use('Schema')
      class QuoteSchema extends Schema {
        up () {
          this.create('quotes', (table) => {
            table.increments()
            table.integer('user_id').notNullable()
            table.string('username', 80).notNullable()
            table.string('body').notNullable()
            table.timestamps()
          })
        }
        down () {
          this.drop('quotes')
        }
      }
      module.exports = QuoteSchema
      

      Um arquivo de esquema no AdonisJs exige dois métodos diferentes, que são:

      • up: usado para criar uma nova tabela ou alterar uma tabela existente.
      • down: usado para reverter as alterações feitas no método up.

      Além dos campos timestamps() e increments(), atualize o conteúdo do arquivo de esquema com os atributos de campo user_id, username e o body de uma citação que será criada. O user_id e username fazem referência aos detalhes do usuário que criam uma citação em particular. Isso define uma relação de um para vários, e significa que um usuário pode ter um número infinito de citações, ao mesmo tempo que uma única citação pode pertencer a somente um usuário.

      Salve e saia do arquivo.

      O AdonisJs vem instalado com um modelo de User e seu arquivo de migração por padrão, que exige apenas uma pequena modificação para estabelecer a relação entre o modelo de User e o Quote.

      Abra o modelo de User no app/Models/User.js:

      Adicione este método imediatamente após o método tokens():

      app/Models/User.js

      ...
      class User extends Model {
        ...
        tokens () {
          return this.hasMany('App/Models/Token')
        }
      
        quote () {
          return this.hasMany('App/Models/Quote')
        }
      }
      
      module.exports = User
      

      Isso estabelecerá um relacionamento de um para vários com a tabela Quote utilizando o user_id como a chave estrangeira.

      Salve e saia do arquivo.

      Para terminar essa seção, utilize o comando a seguir para executar as migrações, que executará o método up() de todos os arquivos de migração:

      Você verá um resultado similar ao seguinte:

      Output

      migrate: 1503248427885_user.js migrate: 1503248427886_token.js migrate: 1568209992854_quote_schema.js Database migrated successfully in 3.42 s

      Você configurou e protegeu uma conexão com seu banco de dados. Você também criou um modelo de Quote e seu arquivo de esquema correspondente e criou um relacionamento de one to many entre o User e o Quote. Em seguida, você gerará rotas e criará controladores para lidar com as solicitações HTTP e a lógica de negócios para criar, editar e excluir uma citação inspiradora.

      Passo 4 — Criando controladores e configurando rotas

      Nesta seção, você começará a criar controladores para lidar com toda a lógica para o aplicativo e, depois, anexará esses controladores a uma rota específica para que ele seja acessado pelos usuários através de uma URL.

      Para começar, utilize o Adonis CLI para criar um novo controlador de solicitação HTTP para lidar com todos os processos de autenticação para seu aplicativo, executando o seguinte comando:

      • adonis make:controller Auth --type http

      Este comando criará um arquivo AuthController.js e o salvará dentro da pasta app/Controllers/Http. Use o sinalizador --type para indicar que quer que este controlador seja um controlador HTTP.

      Você verá um resultado similar ao seguinte:

      Output

      ✔ create app/Controllers/Http/AuthController.js

      Em seguida, abra o arquivo controlador recém-criado:

      • nano app/Controllers/Http/AuthController.js

      Atualize-o com o seguinte conteúdo:

      app/Controllers/Http/AuthController.js

      'use strict'
      const User = use('App/Models/User')
      class AuthController {
      
          loginView({ view }) {
              return view.render('auth.login')
          }
          registrationView({ view }) {
              return view.render('auth.register')
          }
      
          async postLogin({ request, auth, response}) {
              await auth.attempt(request.input('email'), request.input('password'))
              return response.route('index')
          }
      
          async postRegister({ request, session, response }) {
              const user = await User.create({
                  username: request.input('name'),
                  email: request.input('email'),
                  password: request.input('password')
              })
              session.flash({ successmessage: 'User have been created successfully'})
              return response.route('login.create');
          }
      
          async logout ({ auth, response }) {
              await auth.logout()
              return response.route("https://www.digitalocean.com/")
          }
      }
      module.exports = AuthController
      

      Neste arquivo, importe o modelo User e, depois, crie dois métodos chamados loginView() e registerView() para renderizar as páginas de login e de registro, respectivamente. Por fim, crie os seguintes métodos assíncronos:

      • postLogin(): este método obterá o valor do email e password postados com a ajuda do método request integrado no AdonisJs e validará esse usuário com os detalhes no banco de dados. Caso tal usuário exista no banco de dados e tenha digitado as credenciais corretas, ele será redirecionado para a homepage e autenticado antes de criar uma nova citação. Caso contrário, será exibida uma mensagem indicando as credenciais erradas.
      • postRegister(): receberá o valor do nome do username, email e password para um usuário criar uma conta para ele no banco de dados. Uma mensagem indicando que esse usuário foi criado com sucesso será enviada para a sessão e o usuário será redirecionado para a página de login para ser autenticado e começar a criar uma citação.
      • logout(): este método lidará com a funcionalidade de logout e redirecionará o usuário para a página inicial.

      Salve e saia do arquivo.

      Agora que configurou o controlador para registrar e autenticar usuários, prossiga criando um controlador de pedido HTTP para gerenciar todas as operações a respeito das citações.

      De volta ao terminal, execute o comando a seguir para criar o QuoteController:

      • adonis make:controller Quote --type http --resource

      O uso do sinalizador --resource criará um controlador com métodos de recursos pré-definidos para fazer as operações CRUD (criação, consulta, atualização e destruição de dados).

      Você verá:

      Output

      ✔ create app/Controllers/Http/QuoteController.js

      Localize este arquivo dentro de app/Controllers/Http/QuoteController.js:

      • nano app/Controllers/Http/QuoteController.js

      Atualize-o com o seguinte conteúdo:

      app/Controllers/Http/QuoteController.js

      'use strict'
      const Quote = use('App/Models/Quote')
      
      class QuoteController {
      
        async index ({ view }) {
          const quote = await Quote.all()
          return view.render('index', {
            quotes: quote.toJSON()
          })
        }
      
        async create ({ view }) {
          return view.render('quotes.create-quote')
        }
      
        async store ({ request,auth,session, response }) {
          const quote = await Quote.create({
            user_id: auth.user.id,
            username: auth.user.username,
            body: request.input('body')
          })
          session.flash({ 'successmessage': 'Quote has been created'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async show ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.view-quote', {
            quote: quote.toJSON()
          })
        }
      
        async edit ({ params, view }) {
          const quote = await Quote.find(params.id)
          return view.render('quotes.edit-quote', {
            quote: quote.toJSON()
          })
        }
      
        async update ({ params, request, response, session }) {
          const quote = await Quote.find(params.id)
          quote.body = request.input('body')
          await quote.save()
          session.flash({'successmessage': 'Quote has been updated'})
          return response.redirect("https://www.digitalocean.com/")
        }
      
        async destroy ({ params, response, session }) {
          const quote = await Quote.find(params.id)
          await quote.delete()
          session.flash({'successmessage': 'Quote has been deleted'})
          return response.redirect("https://www.digitalocean.com/")
        }
      }
      module.exports = QuoteController
      

      Neste controlador, você importou o modelo Quote e atualizou os métodos a seguir, criados automaticamente usando o AdonisJs CLI:

      • index(): busca todas as citações do banco de dados e as renderiza na página inicial do aplicativo.
      • create(): renderiza uma página para a criação de citações.
      • store(): persiste uma citação recém-criada no banco de dados e retorna uma resposta adequada.
      • show(): obtém a id de uma citação em particular, recupera-a do banco de dados e a renderiza na página de edição de citação.
      • edit(): obtém os detalhes de uma citação em particular do banco de dados e a renderiza para a edição.
      • update(): processa qualquer atualização para uma citação e redireciona o usuário para a página inicial.
      • destroy(): exclui uma citação em particular e remove-a por completo do banco de dados.

      Salve e saia do arquivo.

      Após criar todos os controladores necessários para este aplicativo, é possível configurar as rotas para que os usuários possam interagir com seu aplicativo com facilidade. Para começar, vá para o arquivo start/routes.js

      Substitua seu conteúdo com o seguinte:

      start/routes.js

      'use strict'
      const Route = use('Route')
      
      Route.get("https://www.digitalocean.com/",'QuoteController.index').as('index')
      Route.get('/register','AuthController.registrationView').as('register.create')
      Route.post('/register-store','AuthController.postRegister').as('register.store').validator('Register')
      Route.get('/login','AuthController.loginView').as('login.create')
      Route.post('/login-store','AuthController.postLogin').as('login.store')
      Route.get('/view-quote/:id','QuoteController.show').as('view.quote')
      
      Route.group(() => {
          Route.get('/create-quote','QuoteController.create').as('create.quote')
          Route.post('/store-quote','QuoteController.store').as('store.quote')
          Route.get('/edit-quote/:id','QuoteController.edit').as('edit.quote')
          Route.post('/update-quote/:id','QuoteController.update').as('update.quote')
          Route.get('/delete-quote/:id','QuoteController.destroy').as('delete.quote')
          Route.post('/logout','AuthController.logout').as('logout')
      }).middleware(['auth'])
      

      Aqui, você define o caminho para cada rota em seu aplicativo, especifica os verbos HTTP para cada ação e associa a rota a um método em particular em cada controlador. Você também nomeia cada uma destas rotas, já que elas foram referenciadas dentro dos controladores e das visualizações.

      Para garantir que apenas os usuários autenticados possam acessar todas as rotas das citações, atribui-se um middleware de grupo nomeado para ela. Por fim, você anexa um método validador para a rota register.store para validar as entradas do usuário.

      Salve e saia do arquivo.

      Você criou seus controladores e configurou as rotas para seu aplicativo. Em seguida, você criará o método validador definido neste passo.

      Passo 5 — Validando a entrada do usuário

      O AdonisJs não possui validadores integrados por padrão. Como resultado, você instalará e registrará o validador para seu aplicativo manualmente.

      Execute o comando a seguir para instalá-lo:

      Abra o arquivo a seguir para registrar o provedor validador:

      Então, registre o provedor validador adicionando ele à lista de provedores como mostrado a seguir:

      start/app.js

      ...
      const providers = [
         ...
         '@adonisjs/cors/providers/CorsProvider',
         '@adonisjs/shield/providers/ShieldProvider',
         '@adonisjs/session/providers/SessionProvider',
         '@adonisjs/auth/providers/AuthProvider',
         '@adonisjs/validator/providers/ValidatorProvider'
      ]
      

      Agora que você instalou e registrou o provedor validador dentro do seu aplicativo, crie um validador personalizado para validar as entradas do usuário durante o registro com o seguinte comando:

      • adonis make:validator Register

      Isso criará um arquivo de Register.js no diretório App/validators. Abra o arquivo com:

      • nano app/Validators/Register.js

      Adicione o código a seguir ao arquivo:

      app/Validators/Register.js

      'use strict'
      class Register {
        get rules () {
          return {
            name:'required',
            email:'required|email|unique:users',
            password:'required|min:8'
          }
        }
      
        get messages(){
          return{
            'name.required':'Full name is required',
            'email.required':'email is required',
            'email.unique':'email already exists',
            'password.required':'password is required',
            'password.min':'password should be at least 8 characters'
          }
        }
      }
      module.exports = Register
      

      Defina as regras para campos específicos em seu aplicativo. Caso as validações falhem em algum momento, o validador definirá automaticamente o erro como uma mensagem de erro e o usuário será redirecionado para o formulário.

      Salve e saia do arquivo assim que terminar de editar.

      Por fim, adicione estilos para o seu aplicativo. Abra o seguinte arquivo:

      Substitua o conteúdo dele com o seguinte:

      /public/style.css

      @import url('https://fonts.googleapis.com/css?family=Montserrat:300');
      
      html, body {
        height: 100%;
        width: 100%;
      }
      
      body {
        font-family: 'Montserrat', sans-serif;
        font-weight: 300;
        background-image: url("/splash.png");
        background-color: #220052;
      }
      
      * {
        margin: 0;
        padding: 0;
      }
      
      a {
        color: inherit;
        text-decoration: underline;
      }
      
      p {
        margin: 0.83rem 0;
      }
      
      .quote-wrapper {
        margin-top: 20px;
      }
      
      .quote-wrapper a {
        text-decoration: none;
      }
      
      .quote-wrapper a:hover {
        color: #ffffff;
      }
      
      .empty-quote {
        color: #ffffff;
      }
      
      form {
        padding: 20px;
      }
      

      Neste arquivo, você atualiza o estilo CSS do seu aplicativo no arquivo style.css.

      Você instalou e registrou um provedor validador com o propósito de verificar a entrada de usuários durante o processo de registro. Você também atualizou o conteúdo da sua folha de estilos para adicionar mais estilos ao aplicativo. No passo final, você testará seu aplicativo.

      Passo 6 — Exibindo o aplicativo

      Neste passo, você exibirá seu aplicativo e criará um usuário e senha para testar a autenticação. Você também adicionará uma citação para seu aplicativo e visualizará isso na página inicial.

      Para testar seu aplicativo, inicie o servidor de desenvolvimento com o comando a seguir a partir do diretório raiz do seu aplicativo:

      Isso inicializará o aplicativo na porta definida dentro do arquivo raiz .env, que é a 3333. Vá para http://localhost:3333 em seu navegador.

      Página inicial do aplicativo de citações

      A página inicial está vazia no momento, já que você não criou nenhuma citação. Clique no botão Register.

      Página de registro

      Digite seus detalhes e clique no botão Submit para completar o processo de registro. Você será redirecionado para a página de login. Digite seu endereço de e-mail e senha para a autenticação.

      Página de login

      Assim que estiver autenticado, clique no botão Create Quote.

      Página de criar citação

      Digite uma citação e vá para a página View all para ver sua citação.

      Página de visualização de todas citações

      Você testou seu aplicativo criando e autenticando um usuário e, em seguida, escreveu uma citação.

      Conclusão

      Neste tutorial você criou um aplicativo Web com o AdonisJs. Você configurou o aplicativo utilizando o AdonisJs CLI e usou o CLI para a criação de outros arquivos relevantes, como controladores, modelos e visualizações.

      Você pode desenvolver aplicativos Web com este framework independente do tamanho e complexidade deles. Fique à vontade para baixar o código-fonte para este projeto aqui no GitHub. Para explorar recursos adicionais, visite a documentação oficial.

      Caso queira explorar alguns de nossos outros tutoriais de framework do JavaScrip,confira o seguinte:



      Source link