Skip to content

Latest commit

 

History

History
262 lines (220 loc) · 10.1 KB

File metadata and controls

262 lines (220 loc) · 10.1 KB

activerecord-spanner-adapter for Rails tutorial

This example shows how to use activerecord-spanner-adapter for Cloud Spanner as a backend database for Rails's tutorials.

Create a Spanner instance

This step will create a Cloud Spanner instance. Cloud Spanner is a billable component of the Google Cloud. For information on the cost of using Cloud Spanner, see Pricing.

Note: If you want to try the tutorial without Cloud Spanner cost, you can use the emulator. Read the doc for more details.

  1. Set the project environment variable:
    export PROJECT_ID=[your-cloud-project-id]
  2. Set the default project:
    gcloud config set project $PROJECT_ID
  3. If you haven't enabled the Cloud Spanner service, enable it:
    gcloud services enable spanner.googleapis.com
  4. Create an instance. This tutorial will use a one-node instance in regional-us-central1. You can choose a region close to you:
    gcloud spanner instances create test-instance --config=regional-us-central1 \
      --description="Rails Demo Instance" --nodes=1
  5. Verify the instance has been created:
    gcloud spanner instances list
    You should see output like the following:
    NAME           DISPLAY_NAME         CONFIG                NODE_COUNT  STATE
    test-instance  Rails Demo Instance  regional-us-central1  1           READY
    
  6. Set the default instance:
    gcloud config set spanner/instance test-instance

Read the Cloud Spanner setup guide for more details.

Create a Rails project

If you don't have Ruby and Rails installed, please follow the steps in the following links to install them:

If you are not familiar with Active Record, you can read more about it on Ruby on Rails Guides

  1. Verify the Ruby and Rails versions:

    ruby --version
    rails --version

    The versions should be Ruby 2.6 or higher and Rails 6.0 or higher.

  2. Create a new Rails project:

    rails new blog
  3. The blog directory will have a number of generated files and folders that make up the structure of a Rails application. You can list them:

    cd blog
    ls -l
  4. Starting up the web server and make sure the sample application works:

    bin/rails server

    After the server starts, open your browser and navigate to http://localhost:3000. You should see the default Rails page with the sentence: Yay! You're on Rails!

Create a service account

  1. Create a service account:
    gcloud iam service-accounts create activerecord-spanner
  2. Grant an IAM role to access Cloud Spanner:
    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
    --member="serviceAccount:activerecord-spanner@${PROJECT_ID}.iam.gserviceaccount.com" \
    --role="roles/spanner.databaseAdmin"
    Here the role roles/spanner.databaseAdmin is granted to the service account. If you want to restrict the permissions further, you can choose to create a custom role with proper permissions.
  3. Create a key file and download it:
    gcloud iam service-accounts keys create activerecord-spanner-key.json \
    --iam-account=activerecord-spanner@${PROJECT_ID}.iam.gserviceaccount.com
    This tutorial uses the key file to access Cloud Spanner. If you are using services such as Compute Engine, Cloud Run, or Cloud Functions, you can associate the service account to the instance and avoid using the key file.
  4. From the previous step, a key file should be created and downloaded. You can run the following command to view its content:
    cat activerecord-spanner-key.json

Use Cloud Spanner adapter in Gemfile

  1. Edit the Gemfile file of the blog app and add the activerecord-spanner-adapter gem:

    gem 'activerecord-spanner-adapter'
  2. Install gems:

    bundle install

Update database.yml to use Cloud Spanner.

After the Cloud Spanner instance is running, you'll need a few variables:

  • Cloud project id
  • Cloud Spanner instance id, such as test-instance
  • Database name, such as blog_dev
  • Credential: Credential key file path or export GOOGLE_CLOUD_KEYFILEenvironment variable.

Edit the file config/database.yml and make the section DATABASES into the following:

default: &default
  adapter: "spanner"
  pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 10 } %>
  project: [PROJECT_ID]
  instance: test-instance
  credentials: activerecord-spanner-key.json

development:
  <<: *default
  database: blog_dev

test:
  <<: *default
  database: blog_test

production:
  <<: *default
  database: blog

Replace [PROJECT_ID] with the project id you are currently using.

Create database

You now can run the following command to create the database:

./bin/rails db:create

You should see output like the following: Created database 'blog_dev'

Generate a Model and apply the migration

  1. Use the model generato to define a model:
    ./bin/rails generate model Article title:string body:text
  2. Apply the migration:
    ./bin/rails db:migrate
    The command takes a while to complete. When it's done, you will have an output like the following:
    $ ./bin/rails db:migrate
    == 20210803025742 CreateArticles: migrating ===================================
    -- create_table(:articles)
      -> 23.5728s
    == 20210803025742 CreateArticles: migrated (23.5729s) =========================
    

Use the CLI to interact with the database

  1. Run the following command to start irb:
    bin/rails console
  2. At the prompt, initialize a new Article object:
    article = Article.new(title: "Hello Rails", body: "I am on Rails!")
  3. Run the following command to save the object to the database:
    article.save
  4. Review the object and you can see the field id, created_at, and updated_at have been set:
    article
    Sample output:
    => #<Article id: 4170057092403543076, title: "Hello Rails", body: "I am on Rails!", created_at: "2021-08-03 03:06:26.096275000 +0000", updated_at: "2021-08-03 03:06:26.096275000 +0000">
    
  5. You can find Article.find(id) or Article.all to fetch data from the database. For example:
    irb(main):007:0> Article.find(4170057092403543076)
    Article Load (49.2ms)  SELECT `articles`.* FROM `articles` WHERE `articles`.`id` = @p1 LIMIT @p2
    => #<Article id: 4170057092403543076, title: "Hello Rails", body: "I am on Rails!", created_at: "2021-08-03 03:06:26.096275000 +0000", updated_at: "2021-08-03 03:06:26.096275000 +0000">
    
    irb(main):008:0> Article.all
    Article Load (73.9ms)  SELECT `articles`.* FROM `articles` /* loading for inspect */ LIMIT @p1
    => #<ActiveRecord::Relation [#<Article id: 4170057092403543076, title: "Hello Rails", body: "I am on Rails!", created_at: "2021-08-03 03:06:26.096275000 +0000", updated_at: "2021-08-03 03:06:26.096275000 +0000">]>

Update the app to show a list of records

  1. Use the controller generator to create a controller:
    bin/rails generate controller Articles index
  2. Open the file app/controllers/articles_controller.rb, and change the index action to fetch all articles from the database:
    class ArticlesController < ApplicationController
      def index
        @articles = Article.all
      end
    end
  3. Open app/views/articles/index.html.erb, and update the file as the following:
    <h1>Articles</h1>
    <ul>
      <% @articles.each do |article| %>
        <li>
          <%= article.title %>
        </li>
      <% end %>
    </ul>
  4. Run your server again
    ./bin/rails s
  5. In your browser, navigate to the URL http://localhost:3000/articles/index. And you will see the Hello Rails record you entered previously.
  6. [Optional] you can follow the rest of the steps in the Getting Started with Rails guide.

Clean up

To avoid incurring charges to your Google Cloud account for the resources used in this tutorial, you can delete the resources you created. You can either delete the entire project or delete individual resources.

Deleting a project has the following effects:

  • Everything in the project is deleted. If you used an existing project for this tutorial, when you delete it, you also delete any other work you've done in the project.
  • Custom project IDs are lost. When you created this project, you might have created a custom project ID that you want to use in the future. To preserve the URLs that use the project ID, delete selected resources inside the project instead of deleting the whole project.

If you plan to explore multiple tutorials, reusing projects can help you to avoid exceeding project quota limits.

Delete the project

The easiest way to eliminate billing is to delete the project you created for the tutorial.

  1. In the Cloud Console, go to the Manage resources page.
  2. In the project list, select the project that you want to delete and then click Delete.
  3. In the dialog, type the project ID and then click Shut down to delete the project.

Delete the resources

If you don't want to delete the project, you can delete the provisioned resources:

gcloud iam service-accounts delete \
activerecord-spanner@${PROJECT_ID}.iam.gserviceaccount.com

gcloud spanner instances delete test-instance