2023年5月31日水曜日

Cozy Web/エンティティ更新

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

ここまで、エンティティの作成についてみてきました。

今回はエンティティの更新についてみていきます。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われており、エンティティの作成を行うことができます。エンティティの作成では、アプリケーションが定義したビューを使用するようになっています。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/_create_">Create</a></li>
	    <li><a href="product/_update_">Update</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成されます。

このエンティティ作成シナリオによって、エンティティの作成オペレーションが可能になったことを前々回、前回に確認しました。

エンティティの更新オペレーションも同様にエンティティ作成シナリオによって可能になります。

エンティティの更新には以下の2種類があります。

  • 更新するエンティティのIDを更新画面から入力
  • 更新するエンティティのIDを更新開始時に指定

今回は前者の更新エンティティIDを更新画面から入力するシナリオを実行します。

実行

それではエンティティの更新を実行してみましょう。

エンティティ更新ページ

以下のようにリソース名の後ろに「_update_」をつけてアクセスします。

$ curl http://localhost:8080/web/HelloResource/product/_update_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">
              <input type="text" name="name" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">
              <input type="text" name="price" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
    </form>
  </body>
</html>

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">300</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティ作成のための次の画面に遷移します。

結果ページ

登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">1</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Apple</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">100</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="1"/>
      <input type="hidden" name="name" value="Apple"/>
      <input type="hidden" name="price" value="100"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;update-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;update-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;update-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
      <li>
        <a href="product/_update_">Update</a>
      </li>
    </ul>
  </body>
</html>

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにオブジェクトID 1のAppleの値段が100に変更されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">100</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/4.html">
          <td class="">4</td>
          <td class="">Banana</td>
          <td class="">250</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

リソースの作成に続いて、今回はリソースの更新の基本形について説明しました。

次回も引き続きリソースの更新について説明します。

諸元

Cozy
0.0.13

2023年4月30日日曜日

Cozy Web/エンティティ作成ビュー

Cozy Webはモデル駆動開発の基盤となるWebフレームワークです。リソースのモデルを定義することで、ノンプログラミングでWeb上のリソースをアクセスできる機能について説明を進めています。

前回はHelloResourceを用いてエンティティの作成操作を実現方法について説明しました。

エンティティのモデル定義をすることでエンティティ作成のオペレーションが可能になりましたが、エンティティ作成画面はCozy Webのデフォルト画面が使用されます。

今回はエンティティ作成用のビューを定義することで、エンティティ作成画面をカスタマイズする方法について説明します。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われているのでそのままエンティティの作成を行うことができます。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてindex.htmlを作成し、プロジェクトのトップページに配置します。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/create">Create</a></li>
	</ul>
    </body>
</html>

エンティティ操作シナリオ

エンティティのモデル定義を行うとエンティティ作成シナリオが自動的に作成され、このエンティティ作成シナリオによって、エンティティの作成オペレーションが可能になります。

この時、画面はエンティティ作成シナリオのデフォルトのビューが用いられます。

アプリケーションでカスタマイズした画面を使用するためには、エンティティ作成シナリオ用のビューを登録します。

エンティティ作成シナリオ用のビューの格納場所は、エンティティ名+「.entity」ディレクトリです。エンティティproductの場合は「product.entity」です。

エンティティ作成シナリオでは以下のビューを使用します。

  • エンティティ作成
  • 登録データ確認
  • 結果

それぞれカスタマイズした画面を登録していきます。

エンティティ作成

エンティティ作成画面として以下のHTMLを、product.entity配下に「create__input.html」という名前で作成します。

「create__input」の「create」が作成画面を、「input」が入力画面であることを示しています。

Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product作成/入力</title>
  </head>
  <body>
    <h1>Product作成/入力</h1>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">
              <input type="text" name="name" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">
              <input type="text" name="price" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value=""/>
    </form>
  </body>
</html>

登録データ確認

エンティティ作成の登録データ確認画面として以下のHTMLを、product.entity配下に「create__confirm.html」という名前で作成します。

「create__confirm」の「create」が作成画面を、「confirm」がデータ確認画面であることを示しています。

Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。

<html>
  <head>
    <title>Product作成/データ確認</title>
  </head>
  <body>
    <h1>Product作成/データ確認</h1>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value=""/>
    </form>
  </body>
</html>

結果

エンティティ作成の登録データ確認画面として以下のHTMLを、product.entity配下に「create__show.html」という名前で作成します。

「create__show」の「create」が作成画面を、「show」がデータ結果表示画面であることを示しています。

Input要素のvalue属性はエンティティ操作シナリオが補完するので空欄にしています。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product作成/データ確認</title>
  </head>
  <body>
    <h1>Product作成/データ確認</h1>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value=""/>
    </form>
  </body>
</html>

実行

それでは実行してみましょう。

エンティティ作成ページ

最初にエンティティ作成を行うためのデータ入力ページを表示します。

以下のようにリソース名の後ろに「_create_」をつけてアクセスします。

$ curl http://localhost:8080/web/HelloResource/product/_create_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

product.entityにcreate__input.htmlとして登録したビューが使用されています。

Input要素のvalue属性はエンティティ操作シナリオが補完しています。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product作成/入力</title>
  </head>
  <body>
    <h1>Product作成/入力</h1>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">
              <input type="text" name="name" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">
              <input type="text" name="price" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
    </form>
  </body>
</html>

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。

product.entityにcreate__confirm.htmlとして登録したビューが使用されています。

Input要素のvalue属性はエンティティ操作シナリオが補完しています。

<html>
  <head>
    <title>Product作成/データ確認</title>
  </head>
  <body>
    <h1>Product作成/データ確認</h1>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティ作成のための次の画面に遷移します。

結果ページ

登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。

product.entityにcreate__show.htmlとして登録したビューが使用されています。

Input要素のvalue属性はエンティティ操作シナリオが補完しています。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;create-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
    </ul>
  </body>
</html>

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のようにカスタムのビューを使った場合も、無事リソースが追加されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/4.html">
          <td class="">4</td>
          <td class="">Banana</td>
          <td class="">250</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

今回はリソースの作成ビューの使用方法について説明しました。

次回はリソースの更新、削除の操作の作成鳳凰について説明します。

諸元

Cozy
0.0.12

2023年3月31日金曜日

Cozy Web/エンティティ作成

Cozy Webはモデル駆動開発の基盤となるWebフレームワークです。リソースのモデルを定義することで、ノンプログラミングでWeb上のリソースをアクセスできる機能について説明を進めています。

前回はHelloResourceを用いてエンティティの参照について説明しました。

今回は引き続きHelloResourceを用いてエンティティの作成について説明します。

HelloResource

ここまで作成したHelloResourceは、モデルの定義が行われているのでそのままエンティティの作成を行うことができます。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。これをベースに開発を進めます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

トップページ

トップページとしてindex.htmlを作成し、プロジェクトのトップページに配置します。

<html>
    <head>
	<title>HelloResource</title>
    </head>
    <body>
	<ul>
	    <li><a href="product">List</a></li>
	    <li><a href="product/create">Create</a></li>
	</ul>
    </body>
</html>

実行

それでは実行してみましょう。

エンティティ作成ページ

最初にエンティティ作成を行うためのデータ入力ページを表示します。

以下のようにリソース名の後ろに「_create_」をつけてアクセスします。

$ curl http://localhost:8080/web/HelloResource/product/_create_

次のようにエンティティ作成に必要なデータを登録するためのFORMの画面が表示されました。

まだビューの定義はされていないので、Cozy Webのデフォルト入力画面が表示されます。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">
              <input type="text" name="id" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">
              <input type="text" name="name" value=""/>
            </td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">
              <input type="text" name="price" value=""/>
            </td>
          </tr>
        </tbody>
      </table>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Input"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;input&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{}}"/>
    </form>
  </body>
</html>

このページでは以下のボタンが表示されています。

Input
データ登録
Cancel
キャンセル Inputボタンを押下するとエンティティ作成のための次の画面に遷移します。

Cancelボタンを押下するとトップページに戻ります。

登録データ確認ページ

データ登録画面でInputボタンが押されたので、登録データ確認画面が表示されます。

<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Back"/>
          </td>
          <td>
            <input type="submit" name="$submit" value="Cancel"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;confirm&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;input\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Input&quot;}}"/>
    </form>
  </body>
</html>

画面に入力したデータが表示されます。この結果を確認した上で、以下のいずれかのボタンを押下します。

OK
確認OK
Back
入力画面にモデル
Cancel
キャンセル

Okボタンを押下するとエンティティ作成のための次の画面に遷移します。

結果ページ

登録データ確認画面でOKボタンが押されたので、エンティティの作成が行われ、作成されたエンティティの情報表示ページに移ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <form action="" method="POST">
      <table class="">
        <tbody>
          <tr class="">
            <th scope="row" class="">Id</th>
            <td class="">5</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Name</th>
            <td class="">Banana</td>
          </tr>
          <tr class="">
            <th scope="row" class="">Price</th>
            <td class="">250</td>
          </tr>
        </tbody>
      </table>
      <input type="hidden" name="id" value="5"/>
      <input type="hidden" name="name" value="Banana"/>
      <input type="hidden" name="price" value="250"/>
      <table>
        <tr>
          <td>
            <input type="submit" name="$submit" value="Ok"/>
          </td>
        </tr>
      </table>
      <input type="hidden" name="$scenario" value="{&quot;name&quot;:&quot;create-entity&quot;,&quot;state&quot;:&quot;show&quot;,&quot;entity&quot;:&quot;product&quot;,&quot;schema&quot;:{&quot;columns&quot;:[{&quot;name&quot;:&quot;id&quot;,&quot;datatype&quot;:&quot;token&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;name&quot;,&quot;datatype&quot;:&quot;string&quot;,&quot;multiplicity&quot;:&quot;1&quot;}, {&quot;name&quot;:&quot;price&quot;,&quot;datatype&quot;:&quot;int&quot;,&quot;multiplicity&quot;:&quot;1&quot;}]},&quot;data&quot;:{&quot;name&quot;:&quot;Banana&quot;,&quot;$scenario&quot;:&quot;{\&quot;name\&quot;:\&quot;create-entity\&quot;,\&quot;state\&quot;:\&quot;confirm\&quot;,\&quot;entity\&quot;:\&quot;product\&quot;,\&quot;schema\&quot;:{\&quot;columns\&quot;:[{\&quot;name\&quot;:\&quot;id\&quot;,\&quot;datatype\&quot;:\&quot;token\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;name\&quot;,\&quot;datatype\&quot;:\&quot;string\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;},{\&quot;name\&quot;:\&quot;price\&quot;,\&quot;datatype\&quot;:\&quot;int\&quot;,\&quot;multiplicity\&quot;:\&quot;1\&quot;}]},\&quot;data\&quot;:{\&quot;name\&quot;:\&quot;a\&quot;,\&quot;$scenario\&quot;:\&quot;{\\\&quot;name\\\&quot;:\\\&quot;create-entity\\\&quot;,\\\&quot;state\\\&quot;:\\\&quot;input\\\&quot;,\\\&quot;entity\\\&quot;:\\\&quot;product\\\&quot;,\\\&quot;schema\\\&quot;:{\\\&quot;columns\\\&quot;:[{\\\&quot;name\\\&quot;:\\\&quot;id\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;token\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;name\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;string\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;},{\\\&quot;name\\\&quot;:\\\&quot;price\\\&quot;,\\\&quot;datatype\\\&quot;:\\\&quot;int\\\&quot;,\\\&quot;multiplicity\\\&quot;:\\\&quot;1\\\&quot;}]},\\\&quot;data\\\&quot;:{}}\&quot;,\&quot;price\&quot;:\&quot;10\&quot;,\&quot;id\&quot;:\&quot;5\&quot;,\&quot;$submit\&quot;:\&quot;Input\&quot;}}&quot;,&quot;price&quot;:&quot;250&quot;,&quot;id&quot;:&quot;5&quot;,&quot;$submit&quot;:&quot;Ok&quot;}}"/>
    </form>
  </body>
</html>

作成したエンティティのデータが表示されます。この結果を確認した後に、OKボタンを押下するとトップページに戻ります。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>HelloResource</title>
  </head>
  <body>
    <ul>
      <li>
        <a href="product">List</a>
      </li>
      <li>
        <a href="product/_create_">Create</a>
      </li>
    </ul>
  </body>
</html>

確認

確認のためにリソースproductの一覧を表示してみましょう。

$ curl http://localhost:8080/web/HelloResource/product

以下のように無事リソースが追加されました。

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/4.html">
          <td class="">4</td>
          <td class="">Banana</td>
          <td class="">250</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

Cozy Web上でエンティティのモデル定義をすることで、Web上でのリソースアクセスをノンプログラミングで行う方法についてみています。

今回はリソースの作成について説明しました。

今回はビューを登録していないので、エンティティ作成の入力画面、出力画面はデフォルトの画面となっています。次回はビューを登録することでアプリケーションで用意した入力画面、出力画面を使用する方法について説明します。

諸元

Cozy
0.0.12

2023年2月28日火曜日

Cozy Web/エンティティ表示

前々回に作成したHelloResourceでは、Cozy Webでモデル定義をすることでWeb上のリソースとしてアクセスすることができることを説明しました。

前回はデモモードを使って、デモ時のみメモリDBにデータ投入する方法を紹介しました。

今回はHelloResourceを使って、モデルで定義したリソースをデザイン化した画面で表示する方法を説明します。

HelloResource

前々回作成したHelloResourceにエンティティの情報を表示するビューを追加します。

HelloResourceではビューは定義されていないので、エンティティのデフォルトの表示画面で表示されます。これをデザイン化した表示画面にすることが目的です。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceが作成されています。ここにビューを追加していきます。

モデル

WEB-INF/models/model.orgにアプリケーションで使用するモデルが定義されています。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを定義しています。

これがWebのリソースproductとなります。

ビュー

リソースproductの表示ビューとして以下のHTMLをプロジェクトルートにproduct.htmlとして配置します。

<html>
    <head>
	<title>Product List</title>
    </head>
    <body>
	<c:table />
    </body>
</html>

タグ c:table の場所にエンティティ一覧のモデルの内容が表示されます。それ以外の部分は通常のHTMLとして装飾できます。

また c:table の表示に関してもカスタマイズができますが、詳細は今後取り上げていく予定です。

product.htmlの代わりにproduct.jadeとして以下のJadeファイルを配置しても同じ振る舞いになります。

html
  head
    title Product List
  body
    c:table

実行

それではHelloResourceを実行してみましょう。

モデルとして定義したリソースのproductの一覧取得は以下になります。

WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。

$ curl http://localhost:8080/web/HelloResource/product

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <title>Product List</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

今回データとして投入した4つのエンティティに対応する情報が表示されています。

詳細表示

次はエンティティの詳細表示ビューです。

ビュー

リソースproductの詳細表示を行うビューとして以下のHTMLを用意します。

<html>
    <head>
	<title>Product Detail</title>
    </head>
    <body>
	<c:detail />
    </body>
</html>

タグ c:detail がエンティティの詳細表示を行うタグです。この場所にエンティティの詳細情報が表示されます。それ以外の部分は通常のHTMLとして装飾できます。

また c:detail の表示に関してもカスタマイズができますが、詳細は今後取り上げていく予定です。

このHTMLファイルをプロジェクトルート配下のproduct.entityディレクトリ配下に配置します。

product.entityディレクトリはリソースproductに対してエンティティ操作のシナリオに対するビューを格納するためのディレクトリです。サフィックスのentityが「エンティティ操作のシナリオに対するビュー」を示しています。

この配置を行うことにより「product/3」といったリソースproductのID 3のエンティティに対する表示のためのビューとして利用されます。

実行

それではHelloResourceを実行してみましょう。

$ curl http://localhost:8080/web/HelloResource/product/4

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>Product Detail</title>
  </head>
  <body>
    <table class="">
      <tbody>
        <tr class="">
          <th scope="row" class="">Id</th>
          <td class="">4</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Name</th>
          <td class="">Berry</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Price</th>
          <td class="">450</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

今回はモデルとして定義されたエンティティをリソースとして操作する際に、参照ビューを定義する方法について説明しました。

次回はエンティティ・リソースの更新についてみていきます。

諸元

Cozy
0.0.12

2023年1月31日火曜日

Cozy Web/動作モード

Cozy Webでは開発中や製品版といった動作モードでアプリケーションの振る舞いを調整することができます。

今回は動作モードを使用して、開発時の初期データやデモ時に使用するデータの初期投入を行う方法について説明します。

モード

Cozy Webでは以下の動作モードがあります。

developモードで開発を行い、製品リリース時にproductionモードにします。

develop
開発モード(デフォルト)
production
製品モード
test
テスト・モード
demo
デモ・モード

test用途、デモ用途にはそれぞれtestモード、demoモードを使用します。

HelloResource

前回作成したHelloResourceに対して、デモ実行時に埋め込みDB上に初期化データを投入する設定を行います。

準備

前回の作業でcozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceができています。このHelloResourceを使用します。

ビュー

HelloResourceでは、Web画面を記述するビュー(*.html, *.jadeなど)は定義していません。リソースの表示はデフォルトのビュー機能によって自動的にレイアウトされます。

これは前回と変わりません。

モデル

WEB-INF/modelsでアプリケーションで使用するモデルを定義します。以下のモデル定義をmodel.orgとしてWEB-INF/modelsに格納します。

これも前回と変わりません。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

初期化データ

WEB-INF配下に動作モード名のディレクトリを作成し、そこに各種定義ファイルを配置することで動作モード固有の定義を行うことができます。

今回はデモ時にデータの初期投入を行ってみます。

デモ・モードを示すdemoディレクトリをWEB-INF配下に作成し、そこにモデル定義のファイルmodels/model.orgを配置します。

WEB-INF/demo/models/model.orgの内容は以下になります。

* data-store
** product
  
*** data
1,Apple,300
2,Orange,350
3,Peach,400
4,berry,450

DBのprodutテーブルに4レコードを作成します。

実行

それではHelloResourceを実行してみましょう。

一覧

まず一覧取得です。

モデルとして定義したリソースのproductの一覧取得は以下になります。

WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。

$ curl http://localhost:8080/web/HelloResource/product

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">4</td>
          <td class="">Berry</td>
          <td class="">450</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

今回データとして投入した4つのエンティティに対応する情報が表示されています。

詳細

$ curl http://localhost:8080/web/HelloResource/product/4

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <table class="">
      <tbody>
        <tr class="">
          <th scope="row" class="">Id</th>
          <td class="">4</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Name</th>
          <td class="">Berry</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Price</th>
          <td class="">450</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

まとめ

データベースを使用するシステム開発を行う場合、開発を進める実行環境上でのDBの構築が煩雑な作業となっています。今回はCozy Webのデータ移入機能とモードを組み合わせて対処する方法を紹介しました。

次回はビューを定義して、デザイン化された画面でエンティティ情報の表示を行ってみる予定です。

諸元

Cozy
0.0.11

2022年12月31日土曜日

Cozy Web/HelloResource

Cozy Webの目的の一つはモデル駆動開発とWeb開発を接続することにあります。

モデリングによって定義したモデルが、そのままWebアプリケーションのアプリケーション・ロジックとして動作し、Web画面をデザインするだけでWebアプリケーションが作成できるのが理想形です。

現時点ではその理想形にはまだまだ距離がありますが、部分的には実現できているところもあります。今回はエンティティをWebのリソースとしてアクセスする処理をモデルベースで実現する方法について説明します。

HelloResource

モデル駆動開発を指向した、モデルを使用したWebアプリケーションとしてHelloResourceを作成します。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloResourceを作成します。

ビュー

HelloResourceでは、Web画面を記述するビュー(*.html, *.jadeなど)は定義していません。リソースの表示はデフォルトのビュー機能によって自動的にレイアウトされます。

モデル

WEB-INF/modelsでアプリケーションで使用するモデルを定義します。以下のモデル定義をmodel.orgとしてWEB-INF/modelsに格納します。

* entity  
** product
*** features  
table=product
*** attributes  
| Name  | Type   | Multiplicity |
|-------+--------+--------------|
| id    | token  |            1 |
| name  | string |            1 |
| price | int    |            1 |

エンティティproductを以下の通りに定義しています。

  • feature項で格納するテーブル名をproductと定義
  • 属性としてid, name, priceの3つを定義

モデルはCozy Webのスクリプト言語であるCozy Scriptの基盤となっているKaleidoxの提供するモデル駆動機能をベースとしています。

Kaleidoxの提供するモデル駆動機能は以下で説明しています。

モデルの定義、データベースとの接続、状態機械の定義、状態機械によるイベント駆動といった機能を提供しています。

これらの機能をCozyではWebアプリケーションから使用することができるようになります。

実行

それではHelloResourceを実行してみましょう。

一覧

まず一覧取得です。

モデルとして定義したリソースのproductの一覧取得は以下になります。

WebアプリケーションのURL http://localhost:8080/web/HelloResource の直下にリソース名productを指定しています。

$ curl http://localhost:8080/web/HelloResource/product

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
    <title>product</title>
  </head>
  <body>
    <table class="">
      <caption class="">product</caption>
      <thead class="">
        <tr class="">
          <th scope="col" class="">Id</th>
          <th scope="col" class="">Name</th>
          <th scope="col" class="">Price</th>
        </tr>
      </thead>
      <tbody class="">
        <tr data-href="product/1.html">
          <td class="">1</td>
          <td class="">Apple</td>
          <td class="">300</td>
        </tr>
        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>
        <tr data-href="product/3.html">
          <td class="">3</td>
          <td class="">Peach</td>
          <td class="">400</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

tableタグで3つのエンティティに対応する情報が表示されています。

詳細

$ curl http://localhost:8080/web/HelloResource/product/2

この結果、以下のHTML文書が返されます。(読みやすいようにxmllintで整形しています。)

<?xml version="1.0"?>
<!DOCTYPE html>
<html>
  <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
    <meta name="keywords" content="TBD"/>
    <meta name="description" content="TBD"/>
    <meta name="robots" content="noindex,nofollow"/>
    <meta name="author" content="TBD"/>
  </head>
  <body>
    <table class="">
      <tbody>
        <tr class="">
          <th scope="row" class="">Id</th>
          <td class="">2</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Name</th>
          <td class="">Orange</td>
        </tr>
        <tr class="">
          <th scope="row" class="">Price</th>
          <td class="">350</td>
        </tr>
      </tbody>
    </table>
  </body>
</html>

一覧表示のidが2の部分は以下になります。

        <tr data-href="product/2.html">
          <td class="">2</td>
          <td class="">Orange</td>
          <td class="">350</td>
        </tr>

このエンティティが詳細情報として表示されているのが分かります。

まとめ

HelloResourceでは、必要最小限の構成要素としてモデル定義のみを作成しました。HTMLなどのビューは作成していません。

モデル定義を記述したmodel.orgを作成し、WEB-INF/modelsに配置するのみで、エンティティの内容が一覧画面、詳細画面として表示できることが分かりました。ビューの定義がない場合は、Cozy Webのデフォルト画面を使ってエンティティ情報が表示されました。

次回はビューを定義して、デザイン化された画面でエンティティ情報の表示を行ってみる予定です。

諸元

Cozy
0.0.10

2022年11月30日水曜日

Cozy Web/HelloScript

前回はCozy Scriptの組込み関数を使用して、システムが提供するオペレーションをフォーム画面から呼出して使用する方法について説明しました。

今回はフォーム画面から入力したパラメタを引数にしてCozy Scriptを実行する方法について説明します。

HelloScript

フォームから使用できるアプリケーション・ロジックをCozy Scriptのスクリプトとして記述することができます。

Cozy scriptを用いたWebアプリケーションHelloScriptを作成します。

準備

cozyを起動するディレクトリのwebappsディレクトリに、アプリケーションのホームディレクトリとなるHelloScriptを作成します。

Formページ

フォームを使った入力画面として以下のページをindex.jadeとしてホームディレクトリに配置します。

-@val form: ViewForm
html
  head
    title HelloScript
  body
    form(method="POST" action={form.action})
      input(hidden="true" name="$scenario" value={form.scenario})
      input(name="arg1" value={form.arg1})
      input(name="arg2" value={form.arg2})
      input(name="arg3" value={form.arg3})
      button(type="submit" id="submitbutton" name="$submit" value="ok") Submit
      button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel

ViewFormオブジェクト

以下の宣言でフォームの設定に必要なViewFormを参照可能にします。

-@val form: ViewForm

Form/action

actionにViewFormオブジェクトのaction属性を設定します。

    form(method="POST" action={form.action})

今回の場合は空文字が設定されます。入力と同じページにフォームのPOSTが行われるということですね。

POST処理に必要な情報は後述する「$scenario」に設定されています。

Input/Hidden

Hidden属性のInputで入力する「$scenario」プロパティにViewFormオブジェクトのscenario属性を設定します。

      input(hidden="true" name="$scenario" value={form.scenario})

今回の場合は「{&quot;name&quot;:&quot;invoke-operation&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}」が設定されています。URLエンコーディングを解除した値は「{"name":"invoke-operation","state":"input","data":{}}」です。

Cozy Webがフォーム処理を行うために必要な情報が設定されています。

Inputデータ

Hidden属性のないInputでデータ入力を行います。

今回は以下の3行が対象です。

      input(name="arg1" value={form.arg1})
      input(name="arg2" value={form.arg2})
      input(name="arg3" value={form.arg3})

nameにarg1,arg2,arg3を指定しているので、arg1プロパティとarg2プロパティ, arg3プロパティの3つのプロパティの入力ということになります。値のデフォルト値としてViewFormオブジェクトのarg1属性とarg2属性の値を設定しています。今回のケースでは空文字が設定されます。

Input/Ok

OK用のサブミットボタンとして以下のButtonを設定しました。

      button(type="submit" id="submitbutton" name="$submit" value="ok") Submit

name属性に「$submit」、value属性に「ok」を指定しています。

Input/Cancel

キャンセル用のサブミットボタンとして以下のButtonを設定しました。

      button(type="submit" id="cancelbutton" name="$submit" value="cancel") Cancel

name属性に「$submit」、value属性に「cancel」を指定しています。

コントローラ

WEB-INF/controllersにindex.jade用のコントローラである以下のindex.jsonを配置します。

{
  "action": "script-scenario",
  "script0": "(+ 1 2 3)",
  "script": "(+ arg1 (* arg2 arg3))",
  "method": "POST",
  "successView": "index_complete",
  "errorView": "index_error",
  "parameters": [{
    "name": "arg1",
    "datatype": "int"
  },{
    "name": "arg2",
    "datatype": "int"
  },{
    "name": "arg3",
    "datatype": "int"
  }]
}

action

コントローラのアクションとしてscript-scenarioを指定しています。

  "action": "script-scenario",

script-scenarioは、フォームで入力したパラメタ入力を使ってスクリプトを呼び出し、その結果をビューに渡すモデルとして生成する処理を行うシナリオです。

フォーム入力にまつわるWebブラウザとサーバ間のインタラクションをシナリオに従って実現します。

script

実行するスクリプトをCozy Scriptで記述します。

  "script": "(+ arg1 (* arg2 arg3))",

method

メソッドはPOSTを指定しています。

  "method": "POST",

FormのメソッドがPOSTのものを受け付けます。

successView

successViewにはindex_completeを指定しています。

  "successView": "index_complete",

コントローラの処理が成功するとこのページに遷移します。

errorView

errorViewにはindex_errorを指定しています。

  "errorView": "index_error",

コントローラの処理が失敗するとこのページに遷移します。

parameters

フォームから入力されるパラメタとして、パラメタ名とデータ型を指定しています。

  "parameters": [{
    "name": "arg1",
    "datatype": "int"
  },{
    "name": "arg2",
    "datatype": "int"
  },{
    "name": "arg3",
    "datatype": "int"
  }]

パラメタは、パラメタ名arg1でデータ型int, パラメタ名arg2でデータ型int, パラメタ名arg3でデータ型intの3つです。

成功ページ

成功ページとして以下のindex_complete.htmlを用意します。コントローラのsuccessViewで指定したページです。

<html>
    <head>
	<title>Script Success</title>
    </head>
    <body>
	<h1>Script Success</h1>
	<c:model/>
    </body>
</html>

このページ内の以下のタグはコントローラの実行結果のモデルの内容を表形式で表示するものです。

	<c:model/>

今回の場合は、スクリプトの実行結果が出力されます。

エラーページ

成功ページとして以下のindex_error.htmlを用意します。コントローラのerrorViewで指定したページです。

<html>
    <head>
	<title>Script Error</title>
    </head>
    <body>
	<h1>Script Error</h1>
	<c:error/>
    </body>
</html>

このページ内の以下のタグはコントローラの実行時にエラーが発生した場合、そのエラーを表形式で表示するものです。

	<c:error/>

今回の場合は、スクリプトの実行結果がエラーとなる場合に出力されます。

実行

Formページ

curlコマンドによってローカルホストの8080ポート上の/web/HelloScript を取得します。

$ curl http://localhost:8080/web/HelloScript/

以下のHTML文書が返されます。

<!DOCTYPE html>
<html>
  <head>
    <title>HelloScript</title>
  </head>
  <body>
    <form action="" method="POST">
      <input value="{&quot;name&quot;:&quot;execute-script&quot;,&quot;state&quot;:&quot;input&quot;,&quot;data&quot;:{}}" name="$scenario" hidden="true" />
      <input value="" name="arg1" />
      <input value="" name="arg2" />
      <input value="" name="arg3" />
      <button value="ok" name="$submit" id="submitbutton" type="submit">Submit</button>
      <button value="cancel" name="$submit" id="cancelbutton" type="submit">Cancel</button>
    </form>
  </body>
</html>

OK

OKボタンの押下は以下のcurlに相当します。

$ curl http://localhost:8080/web/HelloScript/ -X POST \
--data-urlencode '$submit=ok' \
--data-urlencode 'arg1=3' \
--data-urlencode 'arg2=8' \
--data-urlencode 'arg3=5' \
--data-urlencode '$scenario={"name":"invoke-operation","state":"input","data":{}}'

OKボタン押下と同等の上記curlの結果、以下のHTMLが出力されました。

<!DOCTYPE html>
<html><head>
	<title>Script Success</title>
    </head><body>
	<h1>Script Success</h1>
	43
</body></html>

c:modelタグの場所に、スクリプト「(+ 3 (* 8 5))」の計算結果である43が出力されています。

まとめ

今回はフォーム画面から入力したパラメタを引数にしてCozy Scriptを実行する方法について説明しました。

次回はCozy Scriptに組み込まれたモデル駆動の機能を使用してリソースに対するアクセスを実現する方法について説明する予定です。

諸元

Cozy
0.0.9