テーブル定義書をWebでぽちぽちしながら作れるやつ作ったんやで

# テーブル定義書創るの面倒じゃね？
テーブル定義書書いて、そこからSQL起こして……
あーめんどう！

なので、Webでぽちぽちすると、SQLとテーブル定義書の元が作れるやつつくりました。
以下、ソースコード
https://github.com/nnahito/create_crud_table

デモ
https://tsumari.zapto.org/crud/


# 使い方

ページにアクセスして色々入力するだけ。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/63338/b95bb1e5-41ef-1984-ec19-87ee1d19af18.png)


# 改良案とかあったら教えてね！
教えてね


# 無理矢理感がすごいソース

```html
<!DOCTYPE html>
<html lang="ja">

<head>
    <title></title>
    <meta charset="UTF-8">

    <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>

    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">



</head>

<body>

    <div class="container">

        <div class="row">
            <div class="col s8 offset-s2 input-field">
                <label for="table-name">テーブル名</label>
                <input id="table-name" type="text" class="table-name sql_parts">
            </div>


            <div class="col s12 input-field center-align">
                <button id="add_button" class="waves-effect waves-light btn"><i class="material-icons left">add</i>行を増やすボタン</button>
                <button id="remove_button" class="waves-effect waves-light btn"><i class="material-icons left">remove</i>行が減るボタン</button>
            </div>

        </div>
    </div>



    <div class="row">
        <div class="col s10 offset-s1">
            <table class="bordered striped responsive-table centered">
                <thead>
                    <tr>
                        <th>No.</th>
                        <th>項目名</th>
                        <th>論理名</th>
                        <th>型</th>
                        <th>長さ</th>
                        <th>少数</th>
                        <th>自動増加</th>
                        <th>符号なし</th>
                        <th>ゼロ埋め</th>
                        <th>初期値</th>
                        <th>必須</th>
                        <th>INDEX</th>
                        <th>主キー</th>
                        <th>備考</th>
                    </tr>
                </thead>

                <tbody id="crud">

                    <tr>
                        <td>1</td>

                        <td>
                            <input type="text" placeholder="項目名" class="sql_parts">
                        </td>

                        <td>
                            <input type="text" placeholder="論理名" class="sql_parts">
                        </td>

                        <td>
                            <input type="text" placeholder="型" class="sql_parts">
                        </td>

                        <td>
                            <input type="text" placeholder="長さ" class="sql_parts">
                        </td>

                        <td>
                            <input type="text" placeholder="少数" class="sql_parts">
                        </td>

                        <td>
                            <input id="a_t" type="checkbox" value="AUTO_INCREMENT" class="sql_parts">
                            <label for="a_t"></label>
                        </td>

                        <td>
                            <input id="UNSIGNED" type="checkbox" value="UNSIGNED" class="sql_parts">
                            <label for="UNSIGNED"></label>
                        </td>

                        <td>
                            <input id="ZEROFILL" type="checkbox" value="ZEROFILL" class="sql_parts">
                            <label for="ZEROFILL"></label>
                        </td>

                        <td>
                            <input type="text" placeholder="デフォルト" class="sql_parts">
                        </td>

                        <td>
                            <input id="NOT-NULL" type="checkbox" value="NOT NULL" class="sql_parts">
                            <label for="NOT-NULL"></label>
                        </td>

                        <td>
                            <input id="INDEX" type="checkbox" value="INDEX" class="sql_parts">
                            <label for="INDEX"></label>
                        </td>

                        <td>
                            <input id="PRIMARY-KEY" type="checkbox" value="PRIMARY KEY" class="sql_parts">
                            <label for="PRIMARY-KEY"></label>
                        </td>

                        <td>
                            <input type="text" placeholder="備考" class="sql_parts">
                        </td>
                    </tr>
                </tbody>

            </table>
        </div>

        <div class="input-field col s8 offset-s2">
            <textarea id="sql" class="materialize-textarea"></textarea>
            <label for="sql">SQL出力結果</label>
        </div>

    </div>




    <script>
    // 行の追加
    $('#add_button').on('click', function(){
        // 現在の行数を取得
        let rows_num = $('#crud tr').length;
        // tbodyにtrを追加
        $('#crud').append('<tr>' + '</tr>');
        // テーブルの最初の行のセルをコピーして、追加していく
        let cells = $('#crud tr:first td');
        for( var i = 0; i < cells.length; i++) {
            // 要素を取得
            let cell = cells.eq(i);
            if ( i === 0 ) {
                $('#crud tr:last').append('<td>' + (rows_num + 1) + '</td>');
            } else {
                // コピーした行が、checkboxか、input_textか
                if ( cell.find('input').attr('type') === 'checkbox' ){
                    // checkboxなら、idに番号を追加する処理をする
                    let id_name = cell.find('input').attr('id');
                    // コピー元のデータを持っておく
                    let orign_id = cell.find('input').attr('id');
                    let orign_for = cell.find('label').attr('for');
                    // コピー先のデータを書き換えて出力
                    cell.find('input').attr('id', id_name + rows_num);
                    cell.find('label').attr('for', id_name + rows_num);
                    $('#crud tr:last').append('<td>' + cell.html() + '</td>');
                    // コピー元の情報を元に戻す
                    cell.find('input').attr('id', orign_id);
                    cell.find('label').attr('for', orign_for);
                } else {
                    // それ以外ならそのまま
                    $('#crud tr:last').append('<td>' + cell.html() + '</td>');
                }
            }
        }
    });
    // 行の削除
    $('#remove_button').on('click', function(){
        if( $('#crud tr').length > 1 ) {
            $('#crud tr:last').remove();
        }
    });
    $(document).on('change', '.sql_parts', function(){
        // SQLの基盤
        let sql = 'CREATE TABLE `' + $('.table-name').val() + '` (';
        // tableの行数を取得
        let rows = $('#crud tr');
        // 各行分ループする
        for (var i = 0; i < rows.length; i++) {
            // その行のすべてのセルを取得
            let cells = rows.eq(i).children();
            // 要素を振り分けるための配列を定義
            let arr = [];
            // tdの個数だけループする
            for (var j = 0; j < cells.length; j++) {
                // 要素を取得
                let cell = cells.eq(j).find('.sql_parts');
                // checkboxか、inputで格納する方式を変える
                if ( $(cell).attr('type') === 'text' ) {
                    // inputの場合
                    arr.push( $(cell).val() );
                } else if ( $(cell).attr('type') === 'checkbox' ) {
                    // checkboxの場合
                    if ( $(cell).prop('checked') ) {
                        // チェックされていれば、値を取得
                        arr.push( $(cell).val() );
                    } else {
                        // チェックされていなければ空文字を入れる
                        arr.push( '' );
                    }
                }
            }
            // もし、ループが2回目以降であれば、カンマを入れる
            if ( i >= 1 ) {
                sql += '\n,  ';
            } else {
                sql += '\n  ';
            }
            // 論理名
            sql += '`' + arr[1] + '` ';
            // 型と長さ
            if ( arr[2] !== '' && arr[3] !== '' ) {
                sql += arr[2] + '(' + arr[3] + ')' + ' ';
            } else if ( arr[2] !== '' ) {
                sql += arr[2] + ' ';
            }
            // 符号なし
            if ( arr[6] !== '' ) {
                sql += arr[6] + ' ';
            }
            // ゼロ埋め
            if ( arr[7] !== '' ) {
                sql += arr[7] + ' ';
            }
            // 必須
            if ( arr[9] !== '' ) {
                sql += arr[9] + ' ';
            }
            // 初期値
            if ( arr[8] !== '' ) {
                sql += 'DEFAULT \'' + arr[8] + '\' ';
            }
            // 自動増加
            if ( arr[5] !== '' ) {
                sql += arr[5] + ' ';
            }
            // 主キー
            if ( arr[11] !== '' ) {
                sql += arr[11] + ' ';
            }
            // 備考
            if ( arr[12] !== '' ) {
                sql += 'COMMENT \'' + arr[12] + '\' ';
            }
            // INDEX
            if ( arr[10] !== '' ) {
                sql += ', INDEX(' + arr[1] + ')';
            }
        }
        // SQLの終わり
        sql += '\n);';
        // textareaに出力
        $('#sql').val(sql);
        $('#sql').trigger('autoresize');
    });
    </script>


</body>
</html>
```