Como usar o Cloud Storage com Ruby

Nesta parte do tutorial do Bookshelf, veja como o aplicativo de amostra armazena imagens no Cloud Storage.

Esta página faz parte de um tutorial com várias páginas. Para começar do início e ver as instruções de configuração, consulte Aplicativo Bookshelf em Ruby.

Como criar um intervalo do Cloud Storage

O Cloud Storage permite armazenar e exibir dados binários. Chamamos de intervalo um contêiner de alto nível para objetos binários.

Veja nas instruções a seguir como criar um intervalo do Cloud Storage. Intervalos são os contêineres básicos que armazenam dados no Cloud Storage.

  1. Em uma janela de terminal, digite o seguinte comando:

    gsutil mb gs://[YOUR-BUCKET-NAME]

    [YOUR-BUCKET-NAME] representa o nome do intervalo do Cloud Storage.

  2. Para visualizar imagens que foram carregadas no aplicativo Bookshelf, defina a lista de controle de acesso (ACL, na sigla em inglês) padrão do intervalo como public-read.

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

Como instalar dependências

Acesse o diretório getting-started-ruby/3-cloud-storage e insira o seguinte comando:

bundle install

Como definir as configurações

  1. Copie o arquivo de exemplo settings:

    cp config/settings.example.yml config/settings.yml
    
  2. Abra settings.yml para edição. Substitua os marcadores pelo seu projeto e pelos nomes do intervalo do Cloud Storage.

    Por exemplo, suponha que o nome do projeto seja my-project e o nome do intervalo seja my-bucket. Então, a seção default do seu arquivo settings.yml ficaria assim:

    default: &default
      project_id: my-project
      gcs_bucket: my-bucket
    
  3. Copie o arquivo de exemplo database:

    cp config/database.example.yml config/database.yml
    
  4. Configure o aplicativo de amostra para usar o mesmo banco de dados que você configurou durante a parte Como usar dados estruturados deste tutorial:

    Cloud SQL

    • Edite o arquivo database.yml. Remova os comentários das linhas da parte do Cloud SQL no arquivo.

       mysql_settings: &mysql_settings
         adapter: mysql2
         encoding: utf8
         pool: 5
         timeout: 5000
         username: [MYSQL_USER]
         password: [MYSQL_PASS]
         database: [MYSQL_DATABASE]
         socket: /cloudsql/[YOUR_INSTANCE_CONNECTION_NAME]
      
      • Substitua [MYSQL_USER] e [MYSQL_PASS] pelo nome de usuário e pela senha da instância do Cloud SQL criados anteriormente.

      • Substitua [MYSQL_DATABASE] pelo nome do banco de dados criado anteriormente.

      • Substitua [YOUR_INSTANCE_CONNECTION_NAME] pelo Instance Connection Name da instância do Cloud SQL.

    • Execute as migrações.

      bundle exec rake db:migrate
      

    PostgreSQL

    • Edite o arquivo database.yml. Remova os comentários das linhas da parte do PostgreSQL no arquivo. Substitua os marcadores your-postgresql-* pelos valores do banco de dados e da instância do PostgreSQL. Por exemplo, suponha que seu endereço IPv4 seja 173.194.230.44, seu nome de usuário seja postgres, sua senha seja pword123 e o nome do seu banco de dados seja bookshelf. Então, a parte do PostgreSQL do seu arquivo database.yml seria assim:

      # PostgreSQL Sample Database Configuration
      # ----------------------------------------
        adapter: postgresql
        encoding: unicode
        pool: 5
        username: postgres
        password: pword123
        host: 173.194.230.44
        database: bookshelf
      
    • Crie as tabelas e o banco de dados necessários.

      bundle exec rake db:create
      bundle exec rake db:migrate
      

    Cloud Datastore

    • Edite o arquivo database.yml. Remova os comentários da linha na parte do Cloud Datastore no arquivo. Substitua your-project-id pelo código do projeto do Google Cloud Platform. Por exemplo, se o código do projeto for my-project, a parte do Cloud Datastore do arquivo database.yml será assim:

      # Google Cloud Datastore Sample Database Configuration
      # ----------------------------------------------------
      dataset_id: my-project
      
    • Execute uma tarefa "rake" para copiar os arquivos do projeto de amostra para o Cloud Datastore.

      bundle exec rake backend:datastore
      

Como executar o app na máquina local

  1. Inicie um servidor da Web local.

    bundle exec rails server
    
  2. No navegador da Web, digite este endereço:

    http://localhost:3000

Agora, é possível procurar as páginas da Web do app e adicionar, editar e excluir livros.

Para sair do servidor da Web local, pressione Control+C.

Como implantar o app no ambiente flexível do App Engine

  1. Compile os recursos do JavaScript para produção.

    RAILS_ENV=production bundle exec rake assets:precompile
    
  2. Implante o app de amostra.

    gcloud app deploy
    
  3. No navegador da Web, digite o endereço a seguir.

    https://[YOUR_PROJECT_ID].appspot.com
    

Atualize o app e implante a versão atualizada com o mesmo comando usado para implantá-lo pela primeira vez. A implantação cria uma nova versão do app e a define como padrão. As versões mais antigas são mantidas, bem como as instâncias de VM associadas. Lembre-se de que essas versões do aplicativo e instâncias de VM são recursos passíveis de cobrança.

Reduza os custos excluindo as versões não padrão do app.

Para excluir uma versão do app:

  1. No Console do GCP, acesse a página "Versões do App Engine".

    Acessar a página Versões

  2. Clique na caixa de seleção ao lado da versão do aplicativo não padrão que você quer excluir.
  3. Clique no botão Excluir na parte superior da página para excluir a versão do aplicativo.

Para informações detalhadas sobre a remoção de recursos faturáveis, consulte a seção Como fazer a limpeza na etapa final deste tutorial.

Estrutura do app

O diagrama a seguir mostra os componentes do aplicativo e como eles se relacionam.

Exemplo de estrutura de dados binários

O aplicativo utiliza {storage_name_short}} para armazenar dados binários (imagens, nesse caso), mas continua usando um banco de dados estruturado para as informações do livro (Cloud Datastore, Cloud SQL ou PostgreSQL).

Noções básicas sobre o código

Esta seção analisa o código do aplicativo e explica como ele funciona.

Processar uploads de usuários

Para que os usuários possam fazer upload de imagens, o formulário de adição/edição foi modificado para permitir uploads de arquivos. Agora o formulário tem várias partes.

<%= form_for @book, :html => { :multipart => true } do |f| %>

Além disso, o formulário tem um campo novo para a imagem de capa de um livro.

<div class="form-group">
  <%= f.label :cover_image %>
  <%= f.file_field :cover_image %>
</div>

Conectar-se ao Cloud Storage

O aplicativo Bookshelf usa a gem google-cloud-storage para acessar os serviços do Google Cloud Platform (GCP). Ele cria uma conexão com o Cloud Storage por meio das credenciais locais que você adquiriu para sua estação de trabalho ou pelas credenciais ambientais durante a execução nas VMs do GCP.

O método de classe storage_bucket da classe Book retorna uma referência ao intervalo de armazenamento especificado pelas configurações no arquivo settings.yml. Esse intervalo é usado para armazenar imagens de capa.

require "google/cloud/storage"

class Book < ActiveRecord::Base

  def self.storage_bucket
    @storage_bucket ||= begin
      config = Rails.application.config.x.settings
      storage = Google::Cloud::Storage.new project_id: config["project_id"],
                                           credentials: config["keyfile"]
      storage.bucket config["gcs_bucket"]
    end
  end

Fazer upload para o Cloud Storage

A classe Book tem um método upload_image que é chamado sempre que um livro é criado. Em upload_image, com a chamada de image.save, um novo arquivo disponível para leitura pública é criado no intervalo do Google Cloud Storage usando o conteúdo de cover_image. Depois que a imagem é salva, o image_url do livro é atualizado para o URL público da imagem salva.

after_create :upload_image, if: :cover_image

def upload_image
  file = Book.storage_bucket.create_file \
    cover_image.tempfile,
    "cover_images/#{id}/#{cover_image.original_filename}",
    content_type: cover_image.content_type,
    acl: "public"

  update_columns image_url: file.public_url
end

Exibir imagens do Cloud Storage

Vale a pena fazer isso direto do Cloud Storage porque as solicitações aproveitam a infraestrutura de exibição global do Google e o aplicativo não precisa responder a solicitações de imagens, liberando ciclos de CPU para outras solicitações.

Para que uma imagem de capa fique visível no aplicativo, atualize a visualização do livro e do índice.

<div class="media">
  <div class="media-left">
    <img src="<%= @book.image_url %>">
  </div>
  <div class="media-body">
    <h4><%= @book.title %> | &nbsp; <small><%= @book.published_on %></small></h4>
    <h5>By <%= @book.author || "unknown" %></h5>
    <p><%= @book.description %></p>
  </div>
</div>

Excluir imagens

Quando você exclui um livro, a classe de modelo de livro verifica se ele tem uma imagem de capa salva no intervalo do Cloud Storage. Se houver uma imagem de capa, ela será excluída.

before_destroy :delete_image, if: :image_url

def delete_image
  image_uri = URI.parse image_url

  if image_uri.host == "#{Book.storage_bucket.name}.storage.googleapis.com"
    # Remove leading forward slash from image path
    # The result will be the image key, eg. "cover_images/:id/:filename"
    image_path = image_uri.path.sub("/", "")

    file = Book.storage_bucket.file image_path
    file.delete
  end
end

Atualizar imagens

Ao atualizar um livro, é possível trocar a imagem de capa. Se já houver uma imagem de capa, ela será excluída. A nova imagem será salva no intervalo do Google Cloud Storage.

before_update :update_image, if: :cover_image

def update_image
  delete_image if image_url?
  upload_image
end
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…