RubyのGoogle API ClientでGoogle Driveを扱う - Spreadsheetの操作あり

# 以下で対応されたようです

![image](https://qiita-image-store.s3.amazonaws.com/0/30079/04723ebb-e5ec-d194-3f13-e15d220f2ee1.png)



# このドキュメント何？

[google_drive](https://github.com/gimite/google-drive-ruby)と、[google-api-client](https://github.com/google/google-api-ruby-client)を同時に使おうと思ったら、google_driveがgoogle-api-clientのバージョン0.8を使っており、最新の0.9が使えなかったので、Google Driveを扱うのに、google-api-clientで全部やるかと決意した人のためのドキュメント。

コードはpryで実行したので、一部結果を載せています。
serviceは```Google::Apis::DriveV3::DriveService.new```のことです。

# バージョン

* google-api-client: 0.9.6

# 導入編

* [Ruby Quickstart](https://developers.google.com/apps-script/guides/rest/quickstart/ruby#prerequisites)を見る
* [APIs Explorer](https://developers.google.com/apis-explorer/#p/)で全部のGoogle APIの仕様がみれる。ここで、[Drive API](https://developers.google.com/apis-explorer/#p/drive/v3/)を眺めて何ができるか確認する。別途[Drive REST API](https://developers.google.com/drive/v3/web/about-sdk?hl=ja)ドキュメントもある
* google-api-clientのgemの[Reference](https://developers.google.com/api-client-library/ruby/apis/)を見る。[ここ](http://www.rubydoc.info/github/google/google-api-ruby-client)にもAPIドキュメントがる。[DriveService](http://www.rubydoc.info/github/google/google-api-ruby-client/Google/Apis/DriveV3/DriveService)を見ると各Drive APIに対応したrubyのメソッドの呼び出し形式がわかる
* [Supported MIME Types](https://developers.google.com/drive/v3/web/mime-types?hl=ja)を見ると、フォルダを作成するときのMEME Typeや、tsvをspreadsheetに変換するときのMIME Typeがわかる

# Drive API呼び出し

## tsvファイルをSpreadsheet形式でアップロードする

* [ここ](https://developers.google.com/drive/v3/web/manage-uploads#importing_to_google_docs_types_wzxhzdk8wzxhzdk9)を参考にして実装する

```
file_metadata = {
  name: 'test',
  mime_type: 'application/vnd.google-apps.spreadsheet',
}
service.create_file(file_metadata, upload_source: 'data.tsv')
=> #<Google::Apis::DriveV3::File:0x007ffb66894e50
 @id="1zhbfOjzwSs5d4k0vTMYjJenB20JvkHjIkJgrsB6_y3U",
 @kind="drive#file",
 @mime_type="application/vnd.google-apps.spreadsheet",
 @name="test">
```

ばっちりできました。mime_typeをつけないと普通のtsvとしてアップロードされます。csvでアップロードしたいときも同じような感じでいけます。
![image](https://qiita-image-store.s3.amazonaws.com/0/30079/ee602e1f-cb8f-3a00-c3fc-d786fc25309b.png)

## フォルダを作成する

```
file_metadata = {
  name: 'test-folder',
  mime_type: 'application/vnd.google-apps.folder',
}
service.create_file(file_metadata, fields: 'id')
=> #<Google::Apis::DriveV3::File:0x007ffb6316a6f0 @id="0Byz3oGJQilf-a3hGbWVXV2ZSbXc">
```

## Spreadsheetを特定のフォルダ以下にアップロードする

さっき作ったフォルダに入れてみます。

```
file_metadata = {
  name: 'test',
  mime_type: 'application/vnd.google-apps.spreadsheet',
  parents: ['0Byz3oGJQilf-a3hGbWVXV2ZSbXc']
}
service.create_file(file_metadata, upload_source: 'data.tsv')
=> #<Google::Apis::DriveV3::File:0x007ffb62f13050
 @id="10Wvb1xVGNsdB5ZQIGSDqzDCFToJxH4vh4CMEB2J34jc",
 @kind="drive#file",
 @mime_type="application/vnd.google-apps.spreadsheet",
 @name="test">
```

## 特定のフォルダにある既存のSpreadsheetを特定のフォルダ以下に移動する
before-folder/test　から after-folder/test にファイルを移動させます。

```
file_id = '1zhbfOjzwSs5d4k0vTMYjJenB20JvkHjIkJgrsB6_y3U'  # before-folder/test
after_folder_id = '0Byz3oGJQilf-aHBGUk9sMTN4N0U'
file = service.get_file(file_id, fields: 'parents')
previous_parents = file.parents.join(',')
file = service.update_file(file_id,
                           add_parents: after_folder_id,
                           remove_parents: previous_parents,
                           fields: 'id, parents')
=> #<Google::Apis::DriveV3::File:0x007ffb62b92278
 @id="1zhbfOjzwSs5d4k0vTMYjJenB20JvkHjIkJgrsB6_y3U",
 @parents=["0Byz3oGJQilf-aHBGUk9sMTN4N0U"]>
```

## 特定のフォルダ以下にあるファイルをリストアップする

ページング無し

```
response = service.list_files(q: "'0Byz3oGJQilf-aHBGUk9sMTN4N0U' in parents",
                              spaces: 'drive',
                              fields:'nextPageToken, files(id, name)')
for file in response.files
  puts "Found file: #{file.name} #{file.id}"
end
```

ページングあり

```
page_token = nil
begin
  response = service.list_files(q: "'0Byz3oGJQilf-aHBGUk9sMTN4N0U' in parents",
                                spaces: 'drive',
                                fields:'nextPageToken, files(id, name)',
                                page_token: page_token)
  for file in response.files
    # Process change
    puts "Found file: #{file.name} #{file.id}"
  end
  page_token = response.next_page_token
end while !page_token.nil?
```

なお、qのクエリ方法については[Search for Files](https://developers.google.com/drive/v3/web/search-parameters#fields)にあります。

## Spreadsheetを削除する

削除されたファイルはゴミ箱にいかずに削除されます。
フォルダを指定した場合は、フォルダ以下のファイルがすべて消去されます。

```
service.delete_file('1zhbfOjzwSs5d4k0vTMYjJenB20JvkHjIkJgrsB6_y3U')
```

## Spreadsheetをコピーする

from_idがコピー元のID. parentsには、所属させたいフォルダを指定します。

```
file_metadata = {
  name: name,
  parents: [to_folder_id],
}
service.copy_file(from_id, file_metadata, {})
```

## スプレッドシートの内容を読み取る

ここまでで、Drive APIを通して、Spreadsheetをアップロードできましたので、その中身の操作をしたいと思います。
ここで、問題があるのですが、Spreadsheetの中身はDrive APIを通しては操作できません。操作するには、[Sheet API](https://developers.google.com/google-apps/spreadsheets/)を通して行うか、[Apps Script](https://developers.google.com/apps-script/)を実行することによって行います。
google_driveのgemはSheet APIを通してSpreadsheetを操作していますが、表現力がやや限られている事もあり、より良い感じで操作したければ、Apps Scriptを使う必要があります。

Apps ScriptをRubyから呼び出す基本的な方法は、[ここ](https://developers.google.com/apps-script/guides/rest/quickstart/ruby#step_1_turn_on_the_api_name)を参照するといと思います。さらに[qiitaの別の投稿](http://qiita.com/wapa5pow/items/c2aef3e83a496bd95410)でApps Scriptを使ったSpreadsheetの逆引き操作方法も載せています。

# よくあるエラー

スクリプト実行後に以下のようなエラーが出ることがあります。

```
Unauthorized (Google::Apis::AuthorizationError)
```

そのようなときは、SCOPEが足りていない時があるので、直接Google Apps Scriptをみて、ファイル -> プロジェクトのプロパティ -> スコープを見てください。

![image](https://qiita-image-store.s3.amazonaws.com/0/30079/307bd6a4-b4bb-9982-a61b-2df9dccb9293.png)

rubyのスクリプトで実際に上記のSCOPEを含めているか確認してください。

# あとがき
ここまでやってきて、Apps Scriptを使う流れは、JavaScriptを書く必要があり、rubyで完結できないので、google_driveをgoogle-api-clientの0.9対応するのもひとつの手だなとは思いました。
google_dirveで対応できないものは適宜、Apps Scriptでやれば、Rubyでほぼかけるので便利そうではあります。