Como usar o Cloud Datastore com Ruby

Nesta página do tutorial do Bookshelf, você aprende como os dados permanentes do app de amostra são armazenados no Cloud Datastore. No código da amostra, são fornecidos exemplos de como criar, ler, atualizar e excluir (CRUD, na sigla em inglês) dados armazenados no Cloud Datastore.

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 instalar dependências e definir configurações

  1. Acesse o diretório getting-started-ruby/2-cloud-datastore e digite o seguinte comando:

    bundle install
    
  2. Copie o arquivo database.example.yml.

    cp config/database.example.yml config/database.yml
    
  3. Para que o aplicativo use o Cloud Datastore, edite o arquivo config/database.yml. Substitua [YOUR_PROJECT_ID] pelo código do projeto.

    Por exemplo, suponha que o código do projeto seja my-project. As seções development e production do arquivo database.yml teriam a seguinte aparência:

    development:
      dataset_id: my-project
    
    production:
      dataset_id: my-project
    

O Cloud Datastore é um serviço totalmente gerenciado iniciado automaticamente e conectado ao seu aplicativo do App Engine. Ele não requer nenhuma outra configuração.

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, navegue nas páginas da Web do aplicativo para 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 aplicativo

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

Processo de implantação e estrutura do app Bookshelf

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

Esta seção analisa o código de amostra e explica como ele funciona.

Interagir com o Cloud Datastore

O aplicativo de amostra Bookshelf usa o RubyGem google-cloud, que é uma biblioteca de cliente para acessar os serviços do Google Cloud Platform (GCP).

Para interagir com o Cloud Datastore, o aplicativo configura um objeto Dataset com base no ID do projeto que você inseriu no arquivo config/database.yml.

As seções a seguir explicam como o aplicativo usa o Dataset para consultar listas de livros no Cloud Datastore.

require "google/cloud/datastore"

class Book

  attr_accessor :id, :title, :author, :published_on, :description

  # Return a Google::Cloud::Datastore::Dataset for the configured dataset.
  # The dataset is used to create, read, update, and delete entity objects.
  def self.dataset
    @dataset ||= Google::Cloud::Datastore.new(
      project_id: Rails.application.config.
                        database_configuration[Rails.env]["dataset_id"]
    )
  end

Listar livros

Ao visitar a página inicial do aplicativo, você é direcionado para a ação index da classe BooksController. Isso é configurado em config/routes.rb.

Rails.application.routes.draw do

  # Route root of application to BooksController#index action
  root "books#index"

  # Restful routes for BooksController
  resources :books

end

A ação BookController#index recupera uma lista de livros do Cloud Datastore. O método Book.query retorna uma matriz de objetos Book e um cursor de consulta que pode ser usado para recuperar entidades adicionais. Leia mais sobre cursores de consulta.

class BooksController < ApplicationController

  PER_PAGE = 10

  def index
    @books, @cursor = Book.query limit: PER_PAGE, cursor: params[:cursor]
  end

O método Book.query consulta o Cloud Datastore em busca das entidades do tipo Book e as retorna como instâncias da classe Book:

# Query Book entities from Cloud Datastore.
#
# returns an array of Book query results and a cursor
# that can be used to query for additional results.
def self.query options = {}
  query = Google::Cloud::Datastore::Query.new
  query.kind "Book"
  query.limit options[:limit]   if options[:limit]
  query.cursor options[:cursor] if options[:cursor]

  results = dataset.run query
  books   = results.map {|entity| Book.from_entity entity }

  if options[:limit] && results.size == options[:limit]
    next_cursor = results.cursor
  end

  return books, next_cursor
end

O método Book.query cria um objeto Google::Cloud::Datastore::Query e o configura para solicitar entidades do tipo Book com um limite de resultados retornados. Se houver um cursor de consulta, a solicitação retornará resultados que se iniciam nele.

Depois que Book.query recupera uma lista de livros, o código do Ruby incorporado em books/index.html.erb gera a lista.

<% @books.each do |book| %>
  <div class="media book">
    <%= link_to book_path(book) do %>
      <div class="media-body">
        <h4><%= book.title %></h4>
        <p><%= book.author %></p>
      </div>
    <% end %>
  </div>
<% end %>

<% if @cursor %>
  <nav>
    <ul class="pager">
      <li><%= link_to "More", books_path(cursor: @cursor) %></li>
    </ul>
  </nav>
<% end %>

Para consultar e recuperar results do Cloud Datastore, Book.query chama Dataset#run, que executa a consulta e retorna um conjunto de objetos Entity.

Os objetos Entity retornados do Cloud Datastore são representados neste formato:

{
  key: {
    dataset_id: "your-project-id",
    kind: "Book",
    id: "5726256557457408"
  },
  properties: {
    title: "A Tale of Two Cities",
    author: "Charles Dickens"
  }
}

A classe "Book" inclui métodos para tradução entre objetos Entity e Book. Por exemplo, Book.from_entity seleciona um objeto Entity e retorna uma instância de Book.

def self.from_entity entity
  book = Book.new
  book.id = entity.key.id
  entity.properties.to_hash.each do |name, value|
    book.send "#{name}=", value if book.respond_to? "#{name}="
  end
  book
end

Exibir detalhes do livro

Quando você clica em um livro individual na página da Web, a ação BookController#show chama Book.find para recuperá-lo do Cloud Datastore.

def show
  @book = Book.find params[:id]
end

O método Book.find recupera o livro do Cloud Datastore por meio da chave id de número inteiro gerada automaticamente.

# Lookup Book by ID.  Returns Book or nil.
def self.find id
  query    = Google::Cloud::Datastore::Key.new "Book", id.to_i
  entities = dataset.lookup query

  from_entity entities.first if entities.any?
end

Depois que Book.find recupera os livros, o código do Ruby incorporado em books/show.html.erb gera a lista.

<div class="media">
  <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>

Criar livros

Ao clicar em Add book na página da Web, a ação BooksController#new cria um novo Book. O código do Ruby incorporado em new.html.erb aponta para _form.html.erb, que exibe o formulário para inclusão de um novo livro.

<%= form_for @book do |f| %>
  <div class="form-group">
    <%= f.label :title %>
    <%= f.text_field :title %>
  </div>
  <div class="form-group">
    <%= f.label :author %>
    <%= f.text_field :author %>
  </div>
  <div class="form-group">
    <%= f.label :published_on, "Date Published" %>
    <%= f.date_field :published_on %>
  </div>
  <div class="form-group">
    <%= f.label :description %>
    <%= f.text_area :description %>
  </div>
  <button class="btn btn-success" type="submit">Save</button>
<% end %>

Quando você envia o formulário, a ação BooksController#create salva o livro no Cloud Datastore. Se o novo livro for salvo com êxito, a página dele será exibida. Caso contrário, o formulário será exibido novamente com mensagens de erro. O método book_params usa parâmetros fortes para especificar quais campos do formulário são permitidos. Neste caso, somente title, author, published_on e description do livro são permitidos:

def create
  @book = Book.new book_params

  if @book.save
    flash[:success] = "Added Book"
    redirect_to book_path(@book)
  else
    render :new
  end
end

private

def book_params
  params.require(:book).permit(:title, :author, :published_on, :description)
end

O campo title é necessário para que um livro seja considerado válido. Somente livros válidos são salvos no Cloud Datastore.

# Add Active Model validation support to Book class.
include ActiveModel::Validations

validates :title, presence: true

O método Book.create chama Book.save, que traduz o objeto Book para um objeto Entity. Em seguida, ele usa o dataset do Datastore para salvar o livro no Cloud Datastore.

# Save the book to Datastore.
# @return true if valid and saved successfully, otherwise false.
def save
  if valid?
    entity = to_entity
    Book.dataset.save entity
    self.id = entity.key.id
    true
  else
    false
  end
end

Editar livros

Ao clicar em Edit book na página da Web, a ação BooksController#update recupera o livro do Cloud Datastore. O código do Ruby incorporado em edit.html.erb aponta para _form.html.erb, que exibe o formulário para editar o livro.

def update
  @book = Book.find params[:id]

  if @book.update book_params
    flash[:success] = "Updated Book"
    redirect_to book_path(@book)
  else
    render :edit
  end
end

A ação BooksController#update chama o método update da instância de Book.

# Set attribute values from provided Hash and save to Datastore.
def update attributes
  attributes.each do |name, value|
    send "#{name}=", value if respond_to? "#{name}="
  end
  save
end

Se os detalhes do livro forem atualizados com êxito, o usuário será direcionado para a página do livro. Caso contrário, o formulário será exibido novamente com mensagens de erro.

Excluir livros

Ao clicar em Delete Book na página da Web, a ação BooksController#destroy exclui o livro do Cloud Datastore e exibe a lista dos restantes.

def destroy
  @book = Book.find params[:id]
  @book.destroy
  redirect_to books_path
end

A ação BooksController#destroy chama o método destroy da instância de Book.

def destroy
  Book.dataset.delete Google::Cloud::Datastore::Key.new "Book", id
end
Esta página foi útil? Conte sua opinião sobre:

Enviar comentários sobre…