vte.cxによるバックエンドを不要にする開発(6.採番)

前回=>[vte.cxによるバックエンドを不要にする開発(5.データの一貫性)](https://qiita.com/stakezaki/items/522a8ab5b6196ad9c142)

今回はデータ登録における採番の方法について説明します。

## 自動採番

前回作成したホテル予約サイトでは、キー(link.___href)に、``/hotel/101``や``/hotel/102``といった値をセットしていましたが、これを省略することで自動採番とすることができます。以下のように実際にinitdataのエントリでlink項目を省略して実行してみましょう。

```index.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { useState } from 'react'
import axios from 'axios'

const App = () => {

  const [rooms, setRooms] = useState<VtecxApp.Entry[]>([])

  const initdata: VtecxApp.Entry[] = [
    {
      room: {
        name: '101',
        reserved: false
      } // link項目の省略
   },
   {
    room: {
      name: '102',
      reserved: false
    } // link項目の省略
   }
  ]

  const putrooms = async (req:VtecxApp.Entry[]) => {
    try {
      axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
      await axios.put('/d/hotel',req)
      getrooms()
    } catch (e) {
      alert('error:'+e)
    }
  }

  const getrooms = async () => {
    try {
      axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
      const res = await axios.get('/d/hotel?f')
      setRooms(res.data)
    } catch (e) {
      alert('error')
      console.log(e)
    }
  }

  const showrooms = () => {
    return rooms.map((entry,index) => {
      if (entry.room&&!entry.room.reserved) {
      return (
				<div key={index}>
					<p>{entry.room.name}　
					<button
						onClick={() => {
							reserve(entry)
						}}
					>
						予約
					</button>
          </p>
				</div>
      )
    }
  })
}

const reserve = async (entry:VtecxApp.Entry) =>{
  if (entry.room) {
    entry.room.reserved = true
    putrooms([entry])
  }
}

  return (
    <div>
      <button onClick={() => { putrooms(initdata) }}>
       初期化
      </button>
      <button onClick={() => { getrooms() }}>
       一覧
      </button>
      <br/>
      {showrooms()}
    </div>
  )

}

ReactDOM.render(<App/>, document.getElementById('container'))
```

これらの項目を、エンドポイント``/d/hotel``に対してPUTすると、その配下にエントリが登録され、キーが``/hotel/1``というように自動的に番号が採番されます。

<img width="575" alt="スクリーンショット 2019-09-10 14.57.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17472/dbe55b54-2077-a954-519b-3177cf9a95b9.png">

## 採番カウンタを利用して独自の採番を行う

自動採番ではなく、ホテルの部屋番号101,102のようにユーザが決めた値で採番したい場合もあるでしょう。その場合は、採番カウンタ機能を利用します。``_setids``で採番カウンタの設定が行え、``_addids``で採番カウンタの加算が行えます。
例えば、以下のサンプルのように、``PUT /d/hotel?_setids=100``とすると、/hotelをキーとする採番カウンタは100になります。また、``PUT /d/hotel?_addids=1``で101にカウントアップされます。(採番カウンタはキーごとに管理されます。ここでは/hotelがキー）

採番に関する詳しい説明は、[ドキュメント](https://vte.cx/documentation.html#index06)を参照してください。

```index.tsx
import * as React from 'react'
import * as ReactDOM from 'react-dom'
import { useState } from 'react'
import axios from 'axios'

const App = () => {

  const [rooms, setRooms] = useState<VtecxApp.Entry[]>([])

  const initrooms = async () => {
    try {
      // 採番の初期値を設定
      axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
      await axios.put('/d/hotel?_setids=100')
    } catch(e) {
      alert('error:'+e)
    }
    const req : VtecxApp.Entry[] = []
    for (let i = 0; i < 5; i++) {
      try {
        // カウントアップしてエントリにセット
        axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
        const res = await axios.put('/d/hotel?_addids=1')
        const entry : VtecxApp.Entry = {}
        entry.room = {
            name : res.data.feed.title,
            reserved: false
        }
        entry.link = [{
          ___href : '/hotel/'+res.data.feed.title,
          ___rel : 'self'
        }]
        req.push(entry)
      } catch(e) {
        alert('error:'+e)
      }
    }
    // エントリをまとめて更新
    putrooms(req)
  }

  const putrooms = async (req:VtecxApp.Entry[]) => {
    try {
      axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
      await axios.put('/d/hotel',req)
      getrooms()
    } catch (e) {
      alert('error:'+e)
    }
  }

  const getrooms = async () => {
    try {
      axios.defaults.headers['X-Requested-With'] = 'XMLHttpRequest'
      const res = await axios.get('/d/hotel?f')
      setRooms(res.data)
    } catch (e) {
      alert('error')
      console.log(e)
    }
  }

  const showrooms = () => {
    return rooms.map((entry,index) => {
      if (entry.room&&!entry.room.reserved) {
      return (
				<div key={index}>
					<p>{entry.room.name}　
					<button
						onClick={() => {
							reserve(entry)
						}}
					>
						予約
					</button>
          </p>
				</div>
      )
    }
  })
}

const reserve = async (entry:VtecxApp.Entry) =>{
  if (entry.room) {
    entry.room.reserved = true
    putrooms([entry])
  }
}

  return (
    <div>
      <button onClick={() => { initrooms() }}>
       初期化
      </button>
      <button onClick={() => { getrooms() }}>
       一覧
      </button>
      <br/>
      {showrooms()}
    </div>
  )

}

ReactDOM.render(<App/>, document.getElementById('container'))
```

上記コードを実行して初期化ボタンを押すと５件のroomが表示されるかと思います。

それでは、今日はここまでです。
お疲れさまでした。

次回=>[vte.cxによるバックエンドを不要にする開発(7.サーバサイドJavaScript)](https://qiita.com/stakezaki/items/d596afd085988d76983c)