LoginSignup
8
9

More than 5 years have passed since last update.

Google Cloud DataStoreをHeroku上のRailsアプリから使う

Last updated at Posted at 2017-01-10

なぜやるか

GCPは無料枠が大きく、小規模のサービスであればDataStoreは無料枠で使い続けられると思います。( http://my-android-server.appspot.com/ は、実際に無料枠で収まっています。)

Google App Engineも小規模であれば無料で使い続けられますが、利用できる言語に制限があります。

Rubyをやりたくなったので、Herokuへの移行を検討していますが、DataStoreはそのまま使い続けたかったので、DataStoreを外部から利用する方法を試しました。

GCP上でサービスアカウントを作成

https://console.cloud.google.com/iam-admin/serviceaccounts/project?project=my-android-server
my-android-serverの部分は、プロジェクトに合わせて変える。

image

「サービスアカウントを作成」をクリック

image

「サービスアカウント名」を適当に入力、
「役割」にて必要な権限(今回であれば「編集者」と「データストアオーナー」)を選択し、
「新しい秘密鍵の提供」にチェックを入れ、「作成」をクリックします。

※「データストアオーナー」だけだと、権限のエラーが出ました。。。けど、今「編集者」を外しても動作する。謎。

JSONファイルがダウンロードされるので、Railsアプリケーションの任意の場所に保管します。
今回は、直下にcertディレクトリを作成し、そこに配置しました。
(ファイル名はmy-android-server-000000000000.jsonとして進めます。)

Herokuで使うための準備

用意したcertディレクトリをGitにコミットしたくなかったので、Herokuの環境変数として登録することにしました。

heroku config:add GCP_KEY="$(cat cert/my-android-server-000000000000.json)"

これで、jsonの内容を環境変数から取得できるようになります。

Railsアプリケーションの実装

https://developers.google.com/api-client-library/ruby/auth/service-accounts
https://cloud.google.com/datastore/reference/rest/v1beta3/projects/lookup
を参考に実装していきます。

とりあえず、controllerにべた書きしました。(ホントはlibディレクトリの中とかで抽象化したほうが良いのかな?)

require 'googleauth'
require 'google/apis/datastore_v1'

class WelcomeController < ApplicationController
  # https://github.com/google/google-api-ruby-client/blob/master/generated/google/apis/datastore_v1/classes.rb
  ServiceAccountCredentials  = Google::Auth::ServiceAccountCredentials
  Datastore  = Google::Apis::DatastoreV1
  RunQueryRequest = Google::Apis::DatastoreV1::RunQueryRequest
  GqlQuery = Google::Apis::DatastoreV1::GqlQuery
  GqlQueryParameter = Google::Apis::DatastoreV1::GqlQueryParameter
  Value = Google::Apis::DatastoreV1::Value

  def index
    datastore = Google::Apis::DatastoreV1::DatastoreService.new

    dummyFile = DummyFile.new(ENV['GCP_KEY']) if ENV['GCP_KEY'].present?
    datastore.authorization = ServiceAccountCredentials.make_creds(
        json_key_io: dummyFile || File.open('cert/my-android-server-000000000000.json'),
        scope: [
          Datastore::AUTH_CLOUD_PLATFORM,
          Datastore::AUTH_DATASTORE
        ]
    )

    query = GqlQuery.new(
        query_string: 'SELECT * FROM GcmModel LIMIT @limit',
        named_bindings: {
          limit: GqlQueryParameter.new(value: Value.new(integer_value: '5'))
        }
    )
    request = RunQueryRequest.new(gql_query: query)
    result = datastore.run_project_query('my-android-server', request)
    render json: result.batch.entity_results[0].entity.as_json
  end

  class DummyFile
    attr_accessor :read
    def initialize(read)
       @read = read
    end
  end
end

my-android-serverというプロジェクトの、GcmModelを5件取得して、1件目をjson形式で返しています。

DummyFileあたりが上手く実装できなくて、GCP_KEYが存在する場合はそこから情報を読み取り、それ以外(ローカル)ではファイルから読み取るようにしています。
内部的にreadを実行していたので、readというプロパティを持たせることで回避しました。

結果

下記のようなjsonを取得できます。

{
  "properties": {
    "registrationId": {
      "string_value": "XXXX"
    },
    "registDate": {
      "timestamp_value": "2012-10-08T21:59:59.661960Z"
    }
  },
  "key": {
    "partition_id": {
      "project_id": "my-android-server"
    },
    "path": [
      {
        "kind": "GcmModel",
        "id": "111111"
      }
    ]
  }
}

GcmModelとしては、registrationIdregistDateがあります。
XXX_valueというのがあるのが、ちょっと面倒ですね。

8
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9