Rubyの標準ライブラリ net/http を使って kintone の REST API を叩いてみる

このところ学習用にkintoneのREST API を色々と叩いているのですが、そういえば大好きなRubyからだってHTTPリクエスト投げれればできそうじゃんね。と思ったんでやってみました。

色々試しながら上手くいったものから、都度追加していくよ。

# レコード

## レコードの取得（GET）
https://developer.cybozu.io/hc/ja/articles/202331474

```get_record.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/record.json"
uri = URI.parse(url)
api_token = ENV['SELECT_TOKEN']
req = Net::HTTP::Get.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'application/json'
req.body = JSON.generate({"app" => "100", "id" => "1"})

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

```get_records.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/records.json"
uri = URI.parse(url)
api_token = ENV['SELECT_TOKEN']
req = Net::HTTP::Get.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'application/json'
fields = ["\$id", "商品名", "金額"]
query = %q(金額 >= "50000")
req.body = JSON.generate({"app" => "100", "fields" => fields, "query" => query, "totalCount" => true})
```

## レコードの一括取得
https://developer.cybozu.io/hc/ja/articles/360029152012

### カーソルの作成

```get_records_cursor.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/records/cursor.json"
uri = URI.parse(url)
api_token = ENV['SELECT_TOKEN']
req = Net::HTTP::Post.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'application/json'
fields = ["\$id", "商品名", "金額"]
query = %q(金額 >= "50000")
req.body = JSON.generate({"app" => "100", "fields" => fields, "query" => query, "totalCount" => true, "size" => "500"})
cursor = ""
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
    cursor = JSON.parse(res.body)["id"]
    pp cursor
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

### カーソル範囲のレコード取得

```get_records_cursor.rb
req = Net::HTTP::Get.new(uri.path)
req['X-Cybozu-API-Token'] = api_token
req['Content-Type'] = 'application/json'
req.body = JSON.generate({"id" => cursor})
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

## レコードの削除

### レコードの一括削除

https://developer.cybozu.io/hc/ja/articles/201941794

ids に レコードIDの配列を渡します。

```delete_records.rb
req_delete = Net::HTTP::Delete.new(uri.path)
req_delete['X-Cybozu-API-Token'] = api_token
req_delete['Content-Type'] = 'application/json'
req_delete.body = JSON.generate(
  {"app" => app_id,
   "ids" => ary_ids}
)
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req_delete)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

## ファイルアップロード
https://developer.cybozu.io/hc/ja/articles/201941824

kintoneの領域にファイルをアップロードします。

### ファイルアップロード

```file.rb
begin
  upload_file = File.open '1.txt', "r"
  data = [["file", upload_file, {"filename" => "1.txt", "content_type" => "text/plain"}]]
  url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/file.json"
  uri = URI.parse(url)
  api_token = ENV['SELECT_TOKEN']
  req = Net::HTTP::Post.new(uri.path)
  req['X-Cybozu-API-Token'] = api_token
  req['Content-Type'] = 'multipart/form-data'
  req.set_form(data, "multipart/form-data")
  pp req  
  Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
    res = http.request(req)
    res.each_header do |name, val|
      puts "name=#{name}, val=#{val}"
    end
    case res.code.to_i
    when 200
      pp JSON.parse(res.body)
    else
      pp %Q(#{res.code} #{res.message})
      pp JSON.parse(res.body)
    end
  }
rescue => exception
  pp exception
  upload_file.close
end
```

### アップロードしたファイルとレコードの関連付け
https://developer.cybozu.io/hc/ja/articles/201941784

アップロードしたファイルの filekey と kintoneレコードを紐付けします。
[レコードの更新API](https://developer.cybozu.io/hc/ja/articles/201941784)を利用します。

```file_upload.rb
begin
  url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/record.json"
  uri = URI.parse(url)
  api_token = ENV['UPDATE_TOKEN']
  req = Net::HTTP::Put.new(uri.path)
  req['X-Cybozu-API-Token'] = api_token
  req['Content-Type'] = 'application/json'

  req.body = JSON.generate({
      "app" => "100",
      "id" => "1",
      "record" => {"file" => {"value" => [{"fileKey"=>"590279cd-6657-419f-8fac-d760a4a6caaa"}]}}
    })
    Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
    res = http.request(req)
    res.each_header do |name, val|
      puts "name=#{name}, val=#{val}"
    end
    case res.code.to_i
    when 200
      pp JSON.parse(res.body)
    else
      pp %Q(#{res.code} #{res.message})
      pp JSON.parse(res.body)
    end
  }
rescue => exception
  pp exception
end
```

---

# アプリ

## フォームの設定の取得

### フィールドの一覧を取得する
https://developer.cybozu.io/hc/ja/articles/204783170#anchor_getform_fields

```get_app_fields.rb
require 'rubygems'
require 'bundler/setup'
require 'dotenv/load'
require 'net/http'
require 'uri'
require 'json'
require 'base64'
require 'pp'

url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/form/fields.json"
uri = URI.parse(url)
pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}")

req = Net::HTTP::Get.new(uri.path)
req['Content-Type'] = 'application/json'
req['X-Cybozu-Authorization'] = pass_auth
req.body = JSON.generate({"app" => "100"})
Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

## アプリのプロセス管理の設定の取得

https://developer.cybozu.io/hc/ja/articles/216972946

プロセスにはAPIトークン認証は使えません。代わりにパスワード認証を使います。

```status.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/status.json"
uri = URI.parse(url)
req = Net::HTTP::Get.new(uri.path)
pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}")
req['X-Cybozu-Authorization'] = pass_auth
req['Content-Type'] = 'application/json'
req.body = JSON.generate({"app" => "100", "lang" => "ja"})

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

* クエリ文字列

結果は同じです。

```status_url.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/app/status.json?app=100&lang=ja"
uri = URI.parse(url)
pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}")

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.get("#{uri.path}?#{uri.query}", {'X-Cybozu-Authorization' => pass_auth})
  res.each_header do |name, val|
    puts "name=#{name}, val=#{val}"
  end
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

---

# スペース情報の取得
https://developer.cybozu.io/hc/ja/articles/202166200

スペース情報の取得は[APIトークン認証](https://developer.cybozu.io/hc/ja/articles/201941754#step7)が使えません。
代わりにパスワード認証を使ってください。

```space.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/space.json"
uri = URI.parse(url)
req = Net::HTTP::Get.new(uri.path)
pass_auth = Base64.strict_encode64("#{ENV['UID']}:#{ENV['PASS']}")
req['X-Cybozu-Authorization'] = pass_auth
req['Content-Type'] = 'application/json'
req.body = JSON.generate({"id" => "1"})

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```

## API情報

### API 一覧の取得
https://developer.cybozu.io/hc/ja/articles/201941934

認証情報は必要ありません。

```apis.rb
url = "https://#{ENV['SUBDOMAIN']}.cybozu.com/k/v1/apis.json"
uri = URI.parse(url)
req = Net::HTTP::Get.new(uri.path)

Net::HTTP.start(uri.host, uri.port, :use_ssl => true) {|http|
  res = http.request(req)
  case res.code.to_i
  when 200
    pp JSON.parse(res.body)
  else
    pp %Q(#{res.code} #{res.message})
    pp JSON.parse(res.body)
  end
}
```


---

# 環境

* macOS 10.13.6
* ruby 2.5.0

# リンク

* [Ruby ドキュメント](https://www.ruby-lang.org/ja/documentation/)
* [標準添付ライブラリ紹介 【第 7 回】 net/http](https://magazine.rubyist.net/articles/0013/0013-BundledLibraries.html)
* [Ruby-Doc.org](https://ruby-doc.org/)
* [kintone REST API一覧](https://developer.cybozu.io/hc/ja/articles/360000313406)

# 雑記

やってみたら、まあ普通にできた。
やっぱりRubyいいな。