LoginSignup
6
10

More than 1 year has passed since last update.

kintone devCamp Step3 復習コンテンツ

Last updated at Posted at 2020-05-29

こちらは ステップで学ぶ kintone カスタマイズ勉強会」 kintone devCamp Step3 ~kintone REST API~ の復習コンテンツです。
devCamp_kintone_horizontal_RGB.png
2.png

🍙 はじめに

Step3 ではアプリ間でのデータ操作や他サービス連携で使える kintone REST API の概念と書き方を勉強しました!この記事では、Step3 の講義中に出てきた 用語基本構文 のおさらいができるプチ用語集/問題集となっています。

🍙 目次

  • 重要用語
  • 理解度 Check!
  • 演習問題
    • 問題① (難易度:⭐)
    • 問題② (難易度:⭐⭐)
    • 問題③ (難易度:⭐⭐⭐⭐)
  • ステップアップ情報

🍙 重要用語

Step3 で出てきた重要な用語になります。これらの意味・用途はきちんと抑えておきましょう!

  • REST API
  • kintone.api()
    • URL
    • メソッド
    • リクエストパラメータ
    • 成功時の処理/失敗時の処理

REST API

Webシステムを外部から利用するためのルールの1つ

kintone 関係なく一般的な Web システムのルールです。RESTful API と呼ばれることもあります。

Webシステムを外部から利用するためのプログラムの呼び出し規約(API)の種類の一つで、
RESTと呼ばれる設計原則に従って策定されたもの

引用元: IT用語辞典 e-Words

:small_blue_diamond:REST API に対応したサービスの例:small_blue_diamond:

※ 他にも様々な Web サービスが REST API に対応しています。

kintone.api()

kintone 上から kintone REST API を実行するための kintone JavaScript API

kintone JavaScript カスタマイズで kintone の REST API を実行したい場合に利用します。
ものすごくややこしい部分なので、ここは丁寧に説明します。

※ 以降 kintone JavaScript API は kintone JS API と記載します。

前提

そもそも REST API はいろいろなプログラミング言語から利用できます。

  • JavaScript
  • Python
  • C#

当然、kintone REST API も Python 等から利用することも可能です。

JavaScript で REST API を実行する

JavaScript で kintone REST API を実行したい場合、JavaScript に備わっている標準の実行方法が利用できます。
ただ、kintone はそもそも JavaScript でカスタマイズできるようになっており、そのための便利機能 (kintone JS API) もいくつか用意されています。
kintone カスタマイズで kintone REST API を実行するのであれば、専用の kintone JS API があった方が便利ということで用意されたものが kintone.api() となります。

kintone.api() を使った例

getRecordData.js
const body = {
  app: 100,
  id: 1
};

kintone.api(kintone.api.url('/k/v1/record.json', true), 'GET', body, callback, error_callback); // callback, error_callback という関数を作っておく

kintone.api() を使った方がプログラムがシンプルに書けます。(やっていることは同じです)
プログラムが短く書けるということはそれだけバグ(タイプミス等)もなくなるので、kintone 上から kintone REST API を実行するのであれば kintone.api() を使いましょう!

URL

扱いたいデータの宛先・ジャンル

REST API では扱いたいデータの宛先を URL (URI) で指定します。
詳細はサービスにより異なりますが、大まかなデータごとに宛先が決まっていてそこにリクエストするイメージです。

:small_blue_diamond:URLの例:small_blue_diamond:

※ その他のURLは一覧をご確認ください。

▼ kintone REST API 一覧
https://developer.cybozu.io/hc/ja/articles/360000313406

kintone.api.url()

kintone カスタマイズの場合、URL用に用意されている kintone.api.url() という URLを短縮する kintone JS API が利用できます。この kintone JS API を用いることで、

とURLを省略することができます。
また、それだけでなく「サブドメイン」をプログラム上に記載しなくて済むため、
JavaScript ファイルを他の環境へ適用する際にプログラムの修正が最低限で済む といったメリットもあります。

メソッド

行いたい操作

REST API ではどんな操作を行いたいかをメソッドとして指定します。

:small_blue_diamond:メソッド一覧:small_blue_diamond:

  • GET (取得)
  • POST (登録)
  • PUT (更新)
  • DELETE (削除)

kintoneではこの4つのメソッドに対応しています。URLによって対応しているメソッドが異なるので、都度上記の kintone REST API 一覧を確認しましょう。

リクエストパラメータ

API を実行するために必要な情報

API を実行するためにより具体的な情報をオブジェクト形式で指定します。
例えば URL が kintone.api.url('/k/v1/record.json')、メソッドが GET の場合、

レコード1件を取得する

という命令になりますが、まだこれだけでは API を実行することができません。
kintoneの場合、どのアプリから? / どのレコード番号のレコードを? という情報が必要になり、それらを リクエストパラメータ で指定します。

:small_blue_diamond:リクエストパラメータの例:small_blue_diamond:

// アプリID: 100, レコードID: 10 のレコード
const params = {
  app: 100,
  id: 10
};

// アプリID: 200, 絞り込み条件: ラジオボタン(radio)の値が「Cybozu」のもの
const params = {
  app: 200,
  query: 'radio in ("Cybozu")'
};

※ リクエストパラメータに何を記載すれば良いかは、URL/メソッドの組み合わせによって異なります。
※ 絞り込み条件 query の書き方は以下をご確認ください。

▼ レコードの一括取得(クエリで条件を指定)
https://developer.cybozu.io/hc/ja/articles/202331474#step2

成功時の処理/失敗時の処理

API 実行に成功/失敗したときに実行される関数

API を実行した結果に紐づく処理を関数で指定します。例えば レコード1件取得 する処理の場合、

・成功時にはレコードデータ等をオブジェクト形式で受け取ることができます。
success.png

・失敗時にはエラー内容等をオブジェクト形式で受け取ることができます。
fail.png
リクエストが失敗する要因には、URLが正しくない/メソッドが正しくない/リクエストパラメータが正しくない等のプログラム上のミスの他に、外的要因(権限がない、ネットワークが繋がっていない等)もあります。

※ 成功時の処理と失敗時の処理は 省略 することも可能です。

🍙 理解度 Check!

Step3 講義の理解度を確認するための簡単な問題を用意しました。
頭の中でどんなプログラムを書けばよいかぱっと思いつくことができればOKです!

kintone.api() の括弧の中身

kintone.api() の括弧の中に記載すべき項目は・・・

※ 順番も大事です
※ プログラムではなく日本語でOKです

答え(ここをクリックすると表示されます)

  • URL
  • メソッド
  • リクエストパラメータ
  • 成功時の処理
  • 失敗時の処理
kintone.api(URL, メソッド, リクエストパラメータ, 成功時の処理, 失敗時の処理);

URLの確認

レコードコメントの投稿 のURLは・・・

答え(ここをクリックすると表示されます)

https://sample.cybozu.com/k/v1/record/comment.json

または、URLを短縮する kintone JS API を使って、

kintone.api.url('/k/v1/record/comment.json')

リクエストパラメータの確認

日付フィールド(フィールドコード: 日付) の値が今日以降のレコードデータを全て取得する API を実行するときに必要なリクエストパラメータは・・・

答え(ここをクリックすると表示されます)

const params = {
  app: XXXX,
  query: '日付 >= TODAY()'
};

🍙 演習問題

講義中に触れた内容に近い演習問題を用意しました。
これらの問題を難なく解くことができれば、Step3 の理解はもうばっちりです!

※ 演習問題③はかなり難しめになっていますが、ぜひチャンレンジしてみてください!

問題① (難易度:⭐)

案件管理アプリにて、
新規レコード追加画面を開いたときに、同アプリのレコードを全て取得してコンソール上に表示させる

step3_1.gif

考え方

  • イベントは何か
  • REST API の実行に必要な項目は何か
    • URL
    • メソッド
    • リクエストパラメータ
  • 成功時、失敗時の処理は何か

ヒント

ヒント(ここをクリックすると表示されます)

  • イベントは何か
    • レコード追加画面を開いたときなので app.record.create.show となる
  • REST API の実行に必要な項目は何か
    • URL
      • レコードを全て なので ~/k/v1/records.json となる
    • メソッド
      • レコードを全て 取得 なので GET となる
    • リクエストパラメータ
      • ~/k/v1/records.jsonGET のときに必要なリクエストパラメータは app (必須項目)
        • 同アプリ なので、直接アプリIDを数字で指定するのではなく kintone JS API の kintone.app.getId() を利用する (APIドキュメント)
  • 成功時、失敗時の処理は何か
    • 成功時
      • コンソール上に表示 なので取得したデータを console.log() で表示する
    • 失敗時
      • 明記されていないので省略、または window.alert('取得に失敗しました。') 等を書く

答え

答え(ここをクリックすると表示されます)

正解.js
(() => {
  'use strict';

  const getRecords = (event) => {
    const getUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId(); // アプリIDは決め打ちではなく kintone JS API を使いましょう
    const getParams = {
      app: appId
    };
    const successHandler = (resp) => {
      console.log(resp);
    };
    kintone.api(getUrl, 'GET', getParams, successHandler);
  };
  kintone.events.on('app.record.create.show', getRecords);
})();

成功時の関数(successHandler)はイベントの関数(getRecords)の外で定義することもできます。

正解.js
(() => {
  'use strict';

  const successHandler = (resp) => {
    console.log(resp);
  };
  const getRecords = (event) => {
    const getUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId();
    const getParams = {
      app: appId
    };
    kintone.api(getUrl, 'GET', getParams, successHandler);
  };
  kintone.events.on('app.record.create.show', getRecords);
})();

問題② (難易度:⭐⭐)

案件管理アプリにて、
新規レコード追加画面で案件名を入力したときに、案件名が他レコードと重複していたらアラートを表示する

Step3_2.gif

標準機能の 重複禁止 設定でも似た実装は可能ですが、標準機能では「保存ボタンを押した時」に重複しているか判断してエラーを出すため、入力中にすぐ判断してほしい という場合はカスタマイズをする必要があります。

考え方

  • イベントは何か
  • REST API の実行に必要な項目は何か
    • URL
    • メソッド
    • リクエストパラメータ
  • 成功時、失敗時の処理は何か

ヒント

ヒント(ここをクリックすると表示されます)

  • イベントは何か
    • 新規レコード追加画面で案件名を入力したとき
      → 新規レコード追加画面で案件名を 変更 したときなので app.record.create.change.案件名 となる
  • REST API の実行に必要な項目は何か
    • URL
      • 他レコードと重複していたら
        → 他レコードを全て取得して重複しているか確認するため ~/k/v1/records.json となる
    • メソッド
      • 取得 して確認なので GET となる
    • リクエストパラメータ
      • ~/k/v1/records.jsonGET のときに必要なリクエストパラメータは app (必須項目)
        • 同アプリ なので、直接アプリIDを数字で指定するのではなく kintone JS API の kintone.app.getId() を利用する (APIドキュメント)
      • 今回は 案件名が他レコードと重複していたら と条件がある
        • 条件をつけて取得すればあとの処理が楽になる
        • query を利用する
  • 成功時、失敗時の処理は何か
    • 成功時
      • 取得したデータが1以上なら window.alert() でアラートを表示する
      • 取得したデータが0なら console.log() でメッセージを表示する
    • 失敗時
      • window.alert('取得に失敗しました。') 等を書く

queryの使い所

query を記載しなくても 全件レコードを取得したあとに1つ1つ重複しているか条件分岐を使って確認 する方法でもできますが、query を使うことで そもそも取得するレコードを絞り込める ため、重複しているかの確認処理がとても楽になります。

全件取得した場合のやること

  1. 取得したレコードの数を確認する
  2. 取得したレコードの数だけ以下を繰り返す
    1. レコードの「案件名」を確認する
    2. 案件名が被っていたらアラートを出して終了、被っていなければ 2-1 に戻る

queryで「案件名が "入力された値" を同じもの」と条件をつけて取得した場合のやること

  1. 取得したレコードの数が0なら終了、1以上ならアラートを出して終了

となります。query を使うことで無駄な処理を減らすことができるので、なるべく利用するようにしましょう!

答え

答え(ここをクリックすると表示されます)

正解.js
(() => {
  'use strict';

  const successHandler = (resp) => {
    if (resp.records.length === 0) {
      console.log('案件名は重複していません。');
    } else {
      window.alert('案件名が重複しています。');
    }
  };
  const errorHandler = (err) => {
    window.alert('データの取得に失敗しました。');
    console.log(err); // コンソールにエラー内容を表示しておくとエラーの原因追求がしやすくなります
  };

  const checkProjectName = (event) => {
    const projectName = event.record.案件名.value;

    const getUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId();
    const query = `案件名 = "${projectName}"`;;
    const getParams = {
      app: appId,
      query: query,
    };
    kintone.api(getUrl, 'GET', getParams, successHandler, errorHandler)
  };

  kintone.events.on('app.record.create.change.案件名', checkProjectName);
})();

また、リクエストパラメータに totalCount: true と指定することで、レコードの数 を totalCount として取得することもできます。

正解.js
(() => {
  'use strict';

  const successHandler = (resp) => {
    if (resp.totalCount === 0) { // totalCount の数で条件分岐ができる
      console.log('案件名は重複していません。');
    } else {
      window.alert('案件名が重複しています。');
    }
  };
  const errorHandler = (err) => {
    window.alert('データの取得に失敗しました。');
    console.log(err);
  };

  const checkProjectName = (event) => {
    const projectName = event.record.案件名.value;

    const getUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId();
    const query = `案件名 = "${projectName}"`;
    const getParams = {
      app: appId,
	  query: query,
	  totalCount: true // totalCount を true にする
    };
    kintone.api(getUrl, 'GET', getParams, successHandler, errorHandler)
  };

  kintone.events.on('app.record.create.change.案件名', checkProjectName);
})();

問題③ (難易度:⭐⭐⭐⭐)

案件管理アプリのレコード一覧画面にて、
日付を選択し実行ボタンを押すと、全ての既存レコードの「受注予定日」フィールドの値がその日付に更新される

Step3_3.gif

JavaScriptファイル

今回の本質ではない日付選択や実行ボタンを生成する JavaScript はあらかじめ用意してあります。
// この関数の中身を考えてください の部分を記述してください。

(() => {
  'use strict';

  // この関数の中身を考えてください
  const executeBtn = () => {

  };

  // 以下は修正する必要はありません
  const showExtraElement = () => {
    // テキスト入力用の要素を作成 & 見た目調整
    const input = document.createElement('input');
    input.id = 'date';
    input.type = 'date';
    input.style.height = '42px';
    input.style.width = '192px';
    input.style.marginRight = '8px';
    input.style.float = 'left';

    // 実行ボタン用の要素を作成 & 見た目調整
    const button = document.createElement('button');
    button.innerText = '実行する';
    button.id = 'executeButton';
    button.style.height = '47px';
    button.style.width = '96px';
    button.style.fontWeight = 'bold';
    button.style.color = '#ffffff';
    button.style.backgroundColor = '#3498db';

    // kintone の一覧画面のメニュー右部の空白要素を取得して、上で作成した要素を埋め込む
    const headerSpace = kintone.app.getHeaderMenuSpaceElement();
    headerSpace.appendChild(input);
    headerSpace.appendChild(button);

    // 実行ボタンのクリックイベントと executeBtn 関数を紐づける
    document.getElementById('executeButton').addEventListener('click', executeBtn);
  };

  kintone.events.on('app.record.index.show', showExtraElement);
})();

考え方

  • イベントは何か
  • REST API の実行に必要な項目は何か
    • URL
    • メソッド
    • リクエストパラメータ
  • 成功時、失敗時の処理は何か
  • 日付選択の値をどうやって取得するか

ヒント

ヒント(ここをクリックすると表示されます)

  • イベントは何か
    • 自作したボタンのクリックイベント。すでにexecuteBtn関数と紐づける処理が記述されているので今回は何もやらなくて良い
  • REST API の実行に必要な項目は何か
    • URL
      • レコードを全て なので ~/k/v1/records.json となる
    • メソッド
      • レコードを全て 更新 なので PUT となる
    • リクエストパラメータ
      • ~/k/v1/records.jsonPUT のときに必要なリクエストパラメータは APIドキュメント を確認してください
      • 同アプリ なので、直接アプリIDを数字で指定するのではなく kintone JS API の kintone.app.getId() を利用する (APIドキュメント)
      • 更新するそれぞれのレコード情報を配列で記載して、records に指定する
  • 成功時、失敗時の処理は何か
    • 成功時
      • window.alert() でメッセージを表示する
      • location.reload() で画面の再読み込みをする
    • 失敗時
      • 明記されていないので省略、または window.alert('取得に失敗しました。') 等を書く
  • 日付選択の値をどうやって取得するか
    • date というidを使って、document.getElementById('date').value で値が取得できます

for文

処理を繰り返したいときの JavaScript の記法

同じ処理繰り返し行いたいときに利用します。if文と同じくこちらも頻出の記法なのでここで覚えてしまいましょう!

for文の基本形は、

for (初期化; 繰り返し条件; 処理後の処理) {
  // 繰り返したい処理
}

となります。例えば コンソール上に こんにちわ と100回表示させる場合は、

for (let i = 0; i < 100; i++) {
  console.log('こんにちわ');
}

となります。例えば コンソール上に 値は0, 値は1, 値は2 ... 値は9 と一部可変するように表示させる場合は、

for (let i = 0; i < 10; i++) {
  console.log('値は' + i);
}

となります。
i を初期化部分で 0 と定義し、繰り返し条件の 10 になるまで処理後の処理の 1ずつカウントアップ する」ようになっています。
→ 結果、0から9までの計10回繰り返すことになります。

今回の演習問題だとリクエストパラメータの records の指定部分でfor文をうまく使うとプログラムの量がかなり短く書けます。

答え

答え(ここをクリックすると表示されます)

・for文を利用しない場合

正解.js
(() => {
  'use strict';

  // この関数の中身を考えてください
  const executeBtn = () => {
    // 日付を取得して変数に入れる
    const dateValue = document.getElementById('date').value;

    // REST APIに必要な情報を用意する
    const putUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId();
    const putParams = {
      app: appId,
      records: [
        {
          id: 1,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 2,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 3,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 4,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 5,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 6,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 7,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 8,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 9,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        },
        {
          id: 10,
          record: {
            受注予定日: {
              value: dateValue
            }
          }
        }
      ]
    };

    const successHandler = (resp) => {
      window.alert('更新に成功しました。');
      location.reload();
    };
    const errorHandler = (err) => {
      window.alert('更新に失敗しました。');
      console.log(err);
    };
    kintone.api(putUrl, 'PUT', putParams, successHandler, errorHandler);
  };

  // 以下は修正する必要はありません
  const showExtraElement = () => {
    // テキスト入力用の要素を作成 & 見た目調整
    const input = document.createElement('input');
    input.id = 'date';
    input.type = 'date';
    input.style.height = '42px';
    input.style.width = '192px';
    input.style.marginRight = '8px';
    input.style.float = 'left';

    // 実行ボタン用の要素を作成 & 見た目調整
    const button = document.createElement('button');
    button.innerText = '実行する';
    button.id = 'executeButton';
    button.style.height = '47px';
    button.style.width = '96px';
    button.style.fontWeight = 'bold';
    button.style.color = '#ffffff';
    button.style.backgroundColor = '#3498db';

    // kintone の一覧画面のメニュー右部の空白要素を取得して、上で作成した要素を埋め込む
    const headerSpace = kintone.app.getHeaderMenuSpaceElement();
    headerSpace.appendChild(input);
    headerSpace.appendChild(button);

    // 実行ボタンのクリックイベントと executeBtn 関数を紐づける
    document.getElementById('executeButton').addEventListener('click', executeBtn);
  };
  kintone.events.on('app.record.index.show', showExtraElement);
})();

・for文を利用した場合は、

正解.js
(() => {
  'use strict';

  // この関数の中身を考えてください
  const executeBtn = () => {
    // 日付を取得して変数に入れる
    const dateValue = document.getElementById('date').value;

    // REST APIに必要な情報を用意する
    const putUrl = kintone.api.url('/k/v1/records.json');
    const appId = kintone.app.getId();

    // 配列を用意する
    const records = [];

    // records配列の中に順番にオブジェクトを入れていく
    for (let i = 0; i < 10; i ++) {
      records[i] = {
        id: i + 1, // レコード番号は 1 からなので、i = 0 なら +1 する必要がある
        record: {
          受注予定日: {
            value: dateValue
          }
        }
      };
    }

    const putParams = {
      app: appId,
      records: records
    };

    const successHandler = (resp) => {
      window.alert('更新に成功しました。');
      location.reload();
    };
    const errorHandler = (err) => {
      window.alert('更新に失敗しました。');
      console.log(err);
    };
    kintone.api(putUrl, 'PUT', putParams, successHandler, errorHandler);
  };

  // 以下は修正する必要はありません
  const showExtraElement = () => {
    // テキスト入力用の要素を作成 & 見た目調整
    const input = document.createElement('input');
    input.id = 'date';
    input.type = 'date';
    input.style.height = '42px';
    input.style.width = '192px';
    input.style.marginRight = '8px';
    input.style.float = 'left';

    // 実行ボタン用の要素を作成 & 見た目調整
    const button = document.createElement('button');
    button.innerText = '実行する';
    button.id = 'executeButton';
    button.style.height = '47px';
    button.style.width = '96px';
    button.style.fontWeight = 'bold';
    button.style.color = '#ffffff';
    button.style.backgroundColor = '#3498db';

    // kintone の一覧画面のメニュー右部の空白要素を取得して、上で作成した要素を埋め込む
    const headerSpace = kintone.app.getHeaderMenuSpaceElement();
    headerSpace.appendChild(input);
    headerSpace.appendChild(button);

    // 実行ボタンのクリックイベントと executeBtn 関数を紐づける
    document.getElementById('executeButton').addEventListener('click', executeBtn);
  };
  kintone.events.on('app.record.index.show', showExtraElement);
})();

🍙 ステップアップ情報

お疲れ様でした!ラスト回、どうでしたでしょうか?
演習問題③はなかなか難しい内容になりましたが、「レコードを一括で承認したい」とか 一括で〇〇したい というカスタマイズのときにはよく使う方法になります!
すらすらっと JavaScript が書けるようになるには、あせらず地道に数こなすことが大事です!

他にも復習に使えるコンテンツを紹介します。ぜひチャレンジしてみてください!!

cybozu developer network はじめようシリーズ

はじめようstep3.png

cybozu developer network Tips

Tips step3-1.png - [レコード保存後に自動でステータス更新!](https://developer.cybozu.io/hc/ja/articles/214639003) Tips step3-2.png - [スペースのスレッドにアプリの集計データを投稿する](https://developer.cybozu.io/hc/ja/articles/212152403) Tips step3-3.png

Step1~3 までお疲れ様でした!!Enjoy kintone Customization!

6
10
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
6
10