OmniAICreator/Qiita-1.07M huggingface dataset:
【Laravel×graphql(lighthouse)】1対多（ポリモーフィック）の値の取得方法について

## 記事の目的
ポリモーフィックについて学習した際の備忘録

## テーブル定義
```php: table
users
    id - integer
    name - string

admins
    id - integer
    name - string

comments
    id - integer
    comment - string
    commenter_id - integer ##hogehoge_idにするとモデル定義のリレーション定義が自動でされるっぽい
    commenter_type - string ##hogehoge_typeにするとモデル定義のリレーション定義が自動でされるっぽい
```

## モデル定義
```php:Models/Comment.php
## 関数名をhogehoge, IDのカラムをhogehoge_id, typeのカラムをhogehoge_typeとすると、laravelが勝手に解釈してくれるっぽい
function commenter(){
    return $this->morphTo();
}
```
```php:Models/User.php
function comments(){
    return $this->morphMany(Comment::class, 'commenter');
}
```
```php:Models/Admin.php
function comments(){
    return $this->morphMany(Comment::class, 'commenter');
}
```

## type定義
```graphql: User.graphql
type User{
    id
    name
    "リレーション"
　　　　　　　　comments: [Comment] @morphMany
}
```
```graphql: Admin.graphql
type Admin{
    id
    name
    "リレーション"
　　　　　　　　comments: [Comment] @morphMany
}
```
```graphql: Comment.graphql
type Comment{
    id
    name
    "リレーション"
    commenter: Commenter @morphTo
}

union Commenter = Admin | User
```

## query
```graphql: queries
extend type Query {
    admins: [Admin] @all
}

extend type Query {
    users: [User] @all
}

extend type Query {
    comments: [Comment] @all
}

```

## リクエスト
```graphql:リクエスト
## 親から取得する場合は通常のリレーションと変わらない
query{
   admins{
     comments{
       id
       comment
       ・・・
     }
   } 
  comments{
    ## それぞれのtypeを定義しておくと対象のレコードに対応したデータセットが返却される
    ## commenter_typeがApp\Models\Adminの場合はAdminの型で返却される
    commenter{
      ...on Admin{
        name
      }
      ...on User{
        name
      }
    }
  }
}
```

## 参照
- https://readouble.com/laravel/8.x/ja/eloquent-relationships.html
- https://lighthouse-php.com/
【個人開発】ITエンジニアの経歴書

# 作ったもの

ITエンジニアの経歴書を作成するWebツールを作りました。
登録お待ちしております。
まだ、テスト中でバグだらけですが、たくさんの方にお使いいただけると嬉しいです。


URL はこちらに変更になりました => https://keirekisyo.com/introduction
## 経歴書の作成例
経歴書の作成例リンクは [こちらから](https://keirekisyo.com/users/7)

- スクショ
![経歴書スクショ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/91978/83f24455-20a2-1816-dd5d-dc7adfbfd85e.png)


# 作った経緯

今月で勤めている会社を退職することになり、次の職場を探すにあたりスキルシートを書いていたんですが中々良いフォーマットがなくて困ってました。
それなら、ついでに作ってしまおう! ということで作ってしまいました。

# 使った技術

## フロントエンド
- 言語
  - TypeScript
- メインフレームワーク
  - React
  - Next.js
- デプロイ環境
  - AWS × Amplify
## バックエンド
- 言語
  - Ruby
- メインフレームワーク
  - Rails
- データベース
  - PostgreSQL
- デプロイ環境
  - AWS
    - ECR
    - ECS Fargate
    - RDS

# 良かった点
色々勉強になったこと。

# 今後の展開
このサービスを求人サービス化したい。

# おねがい
とにかく、ユーザー登録をお待ちしてます! 

そして、どんどん改善、機能追加していきたいのでフィードバックをいただけると嬉しいです。

# 最後に

サービスを作っていく中でアウトプットしたい技術がたくさん出てきました。
また、Qiitaに記事書いていきます!

お読みいただきありがとうございます。
【Rails】javascriptで入力フォーム(textarea)の高さを自動で変えたい

# はじめに
textareaの高さが固定の場合、改行していくと前の文章が埋もれていってしまい、かなりUXが悪い。
これを改善するために、Javascriptを導入し、改行に合わせて高さが自動で変わるようにしていく。
意外と一連の流れを記載している記事が少なかったため、かなり殴り書きだが投稿する。ただし、自身が実施した流れのため環境によって要不要がある。
使用環境は以下の通りである。
| No |    項目     |   内容    |
|---:|-------------|------------|
| 1  |      OS       |   Mac     |
| 2  |       Ruby      |   2.6.3   |
| 3  |       rails      |      6.0.4 |
| 4  |     turbolinks|      5.2.0 |
| 5  |      webpacker      |      4.0.7 |

**変更前(右のスクロールバーが出る)**
![gif2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/0e6db8fe-be3d-3a13-2f17-aa0332d7055f.gif)

**完成イメージ（スクロールバーで遡らなくても高さ自体が変わるため見やすい）**
![gif1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2684787/7ddff053-bdbd-1c2d-fd47-245f09e556f6.gif)

ちなみに上のフォームのコードは下記のように実装している。
```言語名:app/views/shared/_micropost_form.html.erb
# @micropostは一覧表示したい投稿データを渡す
<%= form_with(model: @micropost, local: false) do |f| %>
  <%= render 'shared/error_messages', object: f.object %>
  <div class="field">
    <%= f.label :title, '投稿タイトル' %>
    <%= f.text_field :title, class: 'form-control' %>
　　　　　　　　# 以下が該当のコード
    <%= f.label :content, '投稿文' %>
    <%= f.text_area :content %>

  </div>
  <%= f.submit "Post", class: "btn btn-primary" %>
<% end %>
```

# 事前準備
下記のコードを書くことで、全てのページにjavascriptが読み込まれるようになっている。
```html:app/views/layouts/application.html.erb
<%= javascript_pack_tag 'application', 'data-turbolinks-track': 'reload' %>
```
app/javascript/userディレクトリ、app/javascript/user/custom.jsファイルを作成する。
```:ターミナル
$ mkdir app/javascript/user
$ touch app/javascript/user/custom.js
```
また、下記のコードを書くことで、app/javascript/user/custom.jsを読み込むことを明示する。
※packの配下にcustom.jsを作らない。
```js:app/javascript/packs/application.js
// app/javascript　を起点に記載
require ('user/custom')
```

# 実装
custom.jsにtextareaの高さ自動調整用のコードを記載する。
```言語名:app/javascript/user/custom.js
// textarea の高さ自動調整

$(function() {
  var $textarea = $('#micropost_content');
  var lineHeight = parseInt($textarea.css('lineHeight'));
  $textarea.on('input', function(e) {
    var lines = ($(this).val() + '\n').match(/\n/g).length;
    $(this).height(lineHeight * lines);
  });
  console.log($textarea)
});
```
もう一度WEBページを開いてみると、改行によって高さが変わるようになった。
ちなみにWEBページの検証ツールでHTMLを見てみると、変更後にはstyleが追加され、改行するたびに数値が大きくなる、
```言語名:生成されたHTML（変更前）
<textarea name="micropost[content]" id="micropost_content"></textarea>
```
```言語名:生成されたHTML（変更後）
<textarea name="micropost[content]" id="micropost_content" style="height: 178px;"></textarea>
```
# 【追記_20220807】一度リロードしないとjsが反応しない
[一度リロードしないとjsが反応しない](https://qiita.com/vaza__ta/items/44ef4e09fe6967836665)
上記記事で後で発覚したjsが反応しないことの対策を行ったので、参照いただきたい。
簡単に言うと、今回のtext_areaのページに飛ぶリンクタグに`"turbolinks" => false`を追加し、turbolinksを殺すことで、jsの関数を発火させることができた。

# 参考文献
https://qiita.com/ampersand/items/ceaa5066d44990d30df3

https://nobunobu1717.site/?p=1292#i
S3の用語要点まとめ２（自分用メモ

・クロスリージョンレプリケーション
S3のデータを自動的に異なるリージョンに保存したい場合に利用。クロスリージョンレプリケーションを設定すると、別のリージョンにあるバケットへ自動的にオブジェクトをコピーする。コピー先のリージョンは指定することができ、コピーは非同期で実行される。


・署名付きURL
非公開設定されたオブジェクトに対して有効期限のついたURLを発行することで、AWSアカウントを持っていないユーザーでも一時的にアクセスが可能になる機能。（署名付きURLには非常に長いランダムな文字列が入るため、URLを知らない人が推測することはほぼ不可能）
署名付きURLを利用することで、S3のデータを特定のユーザーに期限付きでアクセスさせることができます。しかしユーザー認証機能はないため、URLが漏洩すると誰でもアクセスができてしまうので注意。


・S3 Transfer Acceleration
S3上のデータをAWSネットワーク内から最速で通信できるルートを経由して転送させる機能。S3が所属しているリージョンから地理的に遠い場所へデータを転送する際に、転送速度を高速化できる。


・静的Webサイトホスティング
バケットに保存している静的コンテンツをWebサイトとして公開できる機能。サポートしているコンテンツには、JavaScriptなどクライアント側で実行されるスクリプトも含むが、PHP、JSP、ASP.NET などサーバー側で実行されるスクリプトは含まない。Webサイトとして公開したい静的コンテンツのあるバケットは「静的Webサイトホスティング」を有効にし、バケットをパブリックに読み取り可能になるよう設定。

・S3のアクセス制御方法
S3上のバケットやオブジェクトは、デフォルトではバケットやオブジェクトを作成したAWSアカウント（S3リソースの所有者）だけがアクセスできます。権限を制限されたIAMユーザーや、他のAWSアカウントからS3リソースへアクセスできるようにするには、S3リソースの所有者であるAWSアカウントでオブジェクトやバケットへのアクセス制御を行う。

・バケットポリシー
バケット単位でアクセス権限を設定する機能。自AWSアカウントのIAMユーザーや他のAWSアカウントのユーザーに対して、S3リソースへのアクセス権限を設定する。また、アクセス元のIPアドレスやドメイン名によるアクセス制御もできる。

【バケットポリシーはアクセス権限の設定の他にも機能がある】
１、バケットに対して「サーバー側の暗号化」を強制できる
バケットポリシーはバケットに対して後述する「サーバー側の暗号化（Server-Side Encryption:SSE）」を強制できます。これによりバケットには、暗号化されたデータのみアップロードできるようになります。

２、オブジェクトアップロード時にフルコントロール権限をバケットの所有者に設定することを強制できる
S3のオブジェクトはアップロードしたAWSアカウントが所有権を持つ。バケットを複数のAWSアカウントで共有している場合も、バケットの所有者とは違うAWSアカウントがアップロードしたオブジェクトの所有権はアップロードしたAWSアカウントが持つので、バケットの所有者はオブジェクトに対してフルコントロール権限がありません。

・ユーザー（IAM）ポリシー
IAMユーザー単位でアクセス権限を設定する機能。自AWSアカウントのIAMユーザーやグループ、ロールに対して、S3リソースへのアクセス権限を設定できる。バケットポリシーとは違い、他のAWSアカウントには設定できない。
ユーザー（IAM）ポリシーによるアクセス権限は、バケットポリシーと同じくアクセス元のIPアドレスやドメイン名によるアクセス制御もできる。

・ACL（アクセスコントロールリスト）
AWSアカウント単位でアクセス権限を設定する機能。他のAWSアカウントに対して、オブジェクトもしくはバケットへの読み取り/書き込みを許可

S3のデータ暗号化方法】
コンプライアンス対応などで、クラウド上にデータを保存する際に暗号化が必要になる場合があります。S3は保存するデータの暗号化に対応しています。S3のデータ暗号化には「サーバー側の暗号化」と「クライアント側の暗号化」の2種類の方法があります。

・サーバー側の暗号化（Server-Side Encryption:SSE）
データがS3に保存されるタイミングで、S3が暗号化を行う。データを取り出す際にもS3がデータを復号して、ユーザーに渡す。

サーバー側の暗号化には、３種類の方法がある。
○S3が管理している鍵を使用する (SSE-S3)
○AWS KMS（AWS Key Management Service）に保存されているCMK（カスタマーマスターキー）を使用する (SSE-KMS)
○ユーザーが管理している鍵を使用する (SSE-C)

また、S3バケットのオプションには、サーバー側の暗号化をバケット単位で利用できる「デフォルト暗号化」がある。
デフォルト暗号化は、S3へデータを保存する時に「サーバー側の暗号化」を自動で適用する機能。デフォルト暗号化で使用する鍵は「SSE-S3」か「SSE-KMS」のどちらかを選択


・クライアント側の暗号化
データをS3に保存する前にクライアント側で暗号化する方法です。データをS3へ保存する前にクライアント側で暗号化を行い、暗号化したデータをそのままS3に保存します。データを取り出す際にも、暗号化したデータをS3からダウンロードした後、クライアント側で復号

クライアント側の暗号化には、2種類の方法がある。
○AWS KMS（AWS Key Management Service）に保存されているCMK（カスタマーマスターキー）を使用
○クライアント側に保存したルートキーを使用
Laravel UI登録画面で画像保存処理を実装

<!-- 発端や概要を記載 -->
# 概要
Laravel UI導入後に登録画面に画像保存処理を実装したので記録します。
![スクリーンショット 2022-06-23 23.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2724488/5592c7d7-e3f2-6e0a-dd89-97ea319a6f85.png)


<!-- タイトルとアンカー名を編集 -->
1. [バージョン](#Chapter1)
1. [View](#Chapter2)
1. [Controller](#Chapter3)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# バージョン
Laravel Framework 9.6.0
PHP 8.1.0 
Laravel UI 8.5.19
bootstrap導入済み
シンボリックリンク作成済み

<a id="#Chapter2"></a>
# View
formタグにenctype="multipart/form-data"を追記

```PHP:redister.blade.php
...省略...
<div class="card-body">
    <form method="POST" action="{{ route('register') }}" enctype="multipart/form-data">
    @csrf
    {{-- アイコン画像 --}}
    <div class="row mb-3">
        <label for="icon" class="col-md-4 col-form-label text-md-end">{{ __('アイコン') }}</label>
        <div class="col-md-6">
            <input id="icon" type="file" class="form-control" name="icon_image_path">
        </div>
    </div>
...省略...
```

<a id="#Chapter3"></a>
# Controller
icon_image_pathがあればstorage/app/public/imgにそのまま保存させ、なければnullとする。

```PHP:RegisterController.php
...省略...
　　　　　　　　　　/**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\Models\User
     */
    protected function create(array $data)
    {
        if (isset($data['icon_image_path'])) {
            $icon_image_path = $data['icon_image_path']->store('img', 'public');
        } else {
            $icon_image_path = null;
        }

        return User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
            'icon_image_path' => $icon_image_path // Usersテーブルにicon_image_pathカラム追加済み
            ...省略...
        ]);
    }
```
Databricks で MLflow 使ってみる - 概要編 -

# はじめに
Databricks で MLflow を使う機会があったのでまとめてみました。
本記事では、Databricks で MLflow を利用する方に向けて、解説をしていきます。
詳細については以下の内容です。

- MLflow 概要
- MLflow 導入のメリット
- MLflow コンポーネント概要

実際に Databricks 上で MLflow を使ってみるパートは近日公開します。

# MLflow 概要
機械学習ライフサイクルを管理するためのオープンソースプラットフォームです。
MLflow は、以下の4つのコンポーネントから構成されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/fc5cbdd5-d765-aeea-675f-231e9acf36d9.png)

# MLflow 導入のメリット
機械学習モデルを開発するにあたって、以下のような問題が発生することがあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/a97c82ef-1451-6335-7ad7-9333f7520a64.png)

**→この問題を解決し、機械学習モデルの管理などをやりやすくしてくれるオープンソースプラットフォームが、MLflow です。**

# MLflow コンポーネント概要
## MLflow Tracking
- 機械学習コードの実行時にパラメーター、コードバージョン、メトリック、および出力ファイルをログに記録し、後で結果を視覚化するためのAPIおよびUIです。
- Python、REST、R API 、およびJavaAPIを使用して実験をログに記録してクエリを実行できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/b3728f52-6e2f-7578-8192-a651c7309e2a.png)

## MLflow Projects
- 機械学習を実行するための情報を、MLflow Projects というファイルにパッケージ化することで、機械学習モデルの実験を再現しやすくできます。
- MLflow Projects ファイルには実行するコマンドや実験実行環境設定ファイルなどが記述してあります。
- 実験実行環境設定ファイルには、依存するライブラリの情報などを記載することで、実行時にその環境が再現できるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/cd261f61-26cf-482a-69d2-c73d6519af1e.png)

## MLflow Models
- 学習済み機械学習モデルを MLflow Models でパッケージ化することによって、複数プラットフォームのモデルを統一的に扱えるようにできます。
- REST API を介したリアルタイム推論や Apache Spark でのバッチ推論、Azure MLへのデプロイなどが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/b1c900d3-c709-ce98-8a95-a593a570ff48.png)

## MLflow Registry
- MLflow モデルのライフサイクル全体を共同で管理できるようになります。
- モデルのバージョン管理、ステージング管理などが可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/07971632-b8de-76f6-9898-3a7dbbb947f5.png)

# MLflow コンポーネントのまとめ
機械学習ライフサイクルを管理するためのオープンソースプラットフォームです。
MLflow は、以下の4つのコンポーネントから構成されています。
このコンポーネントを利用し、機械学習モデルの管理をしていきます。
コンポーネントの詳細は以下です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1091796/38a6cadc-6195-da0a-b920-1034ac16e258.png)
Power Pages 試用版の取得 を有償ライセンスが無い状態でやってみた

[先日投稿した Power Pages 試用版の取得方法](https://qiita.com/yamad365/items/3e1c374fa61448d6ecb2) の末尾で思わせぶりにした件です。

「Power Apps、Power Automate の有償ライセンスを保持していない状態」つまり”デフォルトの環境のみ” で試したらどうなるんだろう？と思ったので、実際にやってみた。

# 今回の環境情報
今回、Power Pages の試用版取得を試した環境は下記です。

　- Microsoft 365 Business Premium ※試用ライセンス

![画像1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/96f3c01f-76ba-4288-92e9-b3213f1d5279.png)
スクリーンショットには Power Automate の Free も含まれていますが、いつ追加されたのか覚えてない（汗
この状態では Power Platform の環境は追加できません。つまり、デフォルトの環境のみ = for M365 の範囲内ですよ、です。

# Power Pages 試用版を追加する
取得手順は前回の記事で案内しています。そちらを確認してください。

https://qiita.com/yamad365/items/3e1c374fa61448d6ecb2#power-pages-%E8%A9%A6%E7%94%A8%E7%89%88%E3%81%AE%E9%96%8B%E5%A7%8B%E6%89%8B%E9%A0%86

当記事ではポイントとなる箇所だけ記載します。

## Power Pages 試用版の開始
今回は公式サイトの［無料で試す］から開始してみました。
![画像2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/dabeb92d-1ffe-598c-b89e-7b5f93d168a2.png)

やはり、同じブラウザーでテナントへサインインしていてもメールアドレスの入力を求められます。
![画像7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/e460443b-d647-74aa-6d68-0c8adf1ac921.png)
開始する、の画面まで辿り着いたら途中までボタンぽちぽちーです。
![画像3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/7b3be9f8-1f0a-8aaa-324e-3e9f50ad8cd7.png)

## サイト情報の入力
この画面、よくみると
　・新しい試用版環境を作成する
　・既存の環境を選択する
という選択肢があります。
![画像4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/197423e8-d1fd-7be2-58ee-06656655e53d.png)
今回、検証しているテナントは既存の環境しかありませんし、ライセンスが不足しているため環境の追加は不可能です。なので［既存の環境を選択する］を選んでも正しく動作しません。（スクショを取り忘れました・・・汗）

環境が作成できない状態のテナントは［新しい試用環境を作成する］を選ぶしかありません！

## 完成？？？（ホントに？
おめで・・・いや、ちょっと待て。画面をよく確認してみましょう。前回の記事だと、このタイミングで Power Pages が選択したテンプレートで提供された状態の画面になったハズです。
ですが、今回は「サイトがありません」になっています。なん・・・だと・・・！？！？
![画像5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/2b0d9bf5-a8bc-5e10-b11c-ec6dcea868bf.png)
はい、これをネタにしたくて前回の記事を書いたようなモンです（ﾈﾀﾊﾞﾚ。
不謹慎かもしれませんが、チョッとオモシロい現象ですよね。

Power Apps、または Power Automate の有償ライセンス（試用版でも可）が無いテナント＝環境が追加できない状態の場合、記事投稿時点で Power Pages 試用版を追加すると初期サイトの作成に失敗しちゃうみたいです。ちなみに、検証とは言え何個も試用ライセンスを取得するのは心苦しいので検証回数は僅かです。なので、for M365 のライセンス範囲でもうまく想定通りの動作をする場合も・・・あるのかなぁ🤔🤔🤔

ちなみに、上記画面の［サイトを作成する］から再度テンプレートを選択して処理を進めると Power Pages サイトが追加されます。

## 環境の確認
保持しているライセンス状況では環境の追加ができないテナント状態であっても、Power Pages の試用版用環境は追加されています。このため、前述どおりサイトを作成することができるんでしょうね。
![画像6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/6639ea3a-b23a-28eb-a0fc-9f5374371b95.png)
(´ω`)。○○（ってことは、この Pages にある Datavarse 使えるってコトですよね…ほほぅ）

※前回の記事よりも前に検証した結果のスクリーンショットを利用しているので、前回記事スクリーンショット内の日付が前後していますがスルーしてください（汗
# まとめ
- Power Apps、Automate の有償ライセンスを保持していなくても Power Pages は試用可能
- Power Pages 試用版ライセンスもチャンと追加される
- Power Pages 試用版の Power Platform 環境も追加される
- でも、初回のサイト作成はうまくいかないぽい
    - 手動で追加すれば OK

検証を開始するテナント状態によって差異が発生しますよ、ですね。Power Pages を試す場合は利用する M365 テナントのライセンス状況などを確認したうえで実施するのが良さそうです。

それでは、皆さま、素晴らしい Power Platform Life を！
【Ruby】何度も繰り返してしまったエラー「undefined method `+' for nil:NilClass (NoMethodError)」

## 概要
Ruby初心者の私が、ここ最近勉強中に何度も発生させてしまったエラーについて書きました。
難しいエラー内容ではないかと思いますが、なんか前もこのエラー出たな。。。となったので、備忘録として残すことにしました。

### エラー再現コード
```rb
numbers = 1..5

numbers.each do |number|
  # 1~5まで順に足しあげながら繰り返し処理する
  sum += number
  puts sum
end
```

### エラー内容
「+」 メソッドは、nilクラスに定義されていませんという意味のエラーメッセージ。
```rb
$ undefined method `+' for nil:NilClass (NoMethodError)
```
「-」の場合も発生しました。
```rb
$ undefined method `-' for nil:NilClass (NoMethodError)
```
### 原因と解決策
- 原因
eachメソッドのブロック内の変数sumを、メソッド外で定義していないため。

- 解決策
eachメソッド外部で、変数sumの初期値を0として定義してあげる。
```diff_ruby
numbers = 1..5
+ sum = 0

numbers.each do |number|
  # 1~5まで順に足しあげながら繰り返し処理する
  sum += number
  puts sum
end
```
```実行結果.rb
1 # 0 + 1
3 # 1 + 2
6 # 3 + 3
10 # 以下省略
15
```
変数の定義が必要なら、ブロック内に記載すれば良いのではないか？と考えました。
しかしながら、その方法では繰り返し処理をする毎にsumが0になるため、足し上げ不可能となりました。
```失敗.rb
numbers = 1..5

numbers.each do |number|
  # 1~5まで順に足しあげていく
  sum = 0
  sum += number
  puts sum
end
```
```実行結果_失敗.rb
1
2
3
4
5
```
### 終わりに
eachメソッドに限らず、同じクラス内のメソッドにて足し上げ処理を書こうとした際、変数の定義・初期化のし忘れをしてしまい、今回と同様のエラーに再会しました…
その時に、あ〜これ前もやったやつだと気付き、無事解決することができました。
同じ状況になっている方の参考になれば幸いです。
パラメータ数が多くても過学習しない！？～二重降下～

# はじめに
従来の考えでは、パラメータ数を多くすると過学習につながると言われていました。
しかし、近年**パラメータ数を多くしても過学習しない現象（二重降下）が発見されました。**
今回は二重降下に関連する論文である、
"[High-dimensional dynamics of generalization error in neural networks](https://arxiv.org/abs/1710.03667)"を紹介します！

本記事は[Qiita Engineer Festa 2022](https://qiita.com/official-events/97ae2edf9e1a01bde1fe)への投稿です。

# 目次
* 二重降下とは
* パラメータ数と過学習の関係
* 二重降下が生じる理由
    * Eigen gap
    * Frozen subspace
* まとめ

# 二重降下とは
まず、二重降下を紹介します。
二重降下については別の論文（[Reconciling modern machine learning practice and the bias-variance trade-off](https://arxiv.org/abs/1812.11118)）の図が分かりやすいので、そちらを引用します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629975/5337da0d-72d3-2e72-0bf9-cda3017d1ed2.png)
左の図は過学習に関する従来の考えを図にしたものです。
学習を進めていくと学習誤差/汎化誤差ともに下がっていきますが、
ある時を境に汎化誤差が上がっていってしまいます。これが過学習です。

次に二重降下です。
右の図のように、一度上がってしまった汎化誤差がover-parameterized時に下がっています！
つまり、パラメータ数がデータ数より多くても過学習はしないということです。
この不思議な現象が「**二重降下（Double Descent）**」です。
今回紹介する[論文](https://arxiv.org/abs/1710.03667)は、この現象が生じる理由をデータ数とパラメータ数の関係から説明しています。

# パラメータ数と過学習の関係
パラメータ数と過学習の関係をまとめた図が下記の図です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629975/bfa7542d-1dee-09f4-0c25-6ac611006ec9.png)
αは「サンプル数(P)/パラメータ数(N)」を表しています。
（Pがサンプル数ってややこしいですね）
これらの内容を整理します。
* 「α=2（サンプル数>パラメータ数）」の時、最も汎化性能が高い。
* 「α=1（サンプル数=パラメータ数）」の時、汎化性能が徐々に悪化している（過学習）。
* **「α=1/2（サンプル数<パラメータ数）」の時、過学習は起きていない（悪化しない）。**

従来の考え通り、パラメータ数が少ないときが最も良い汎化性能を出していますね。
一方α=1のときは、徐々に汎化誤差が悪化しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629975/29a32c85-933f-45ba-0275-feefc9e3c6cd.png)

さて、本題の「α=1/2（サンプル数<パラメータ数）」ではどうでしょうか？
**「α=2」の時より汎化性能は劣りますが、「α=1」のように汎化性能は悪化していません。**
つまり、パラメータ数がデータ数よりも多いときでも、過学習は起きていないのです！
なぜこのようなことが起きるのでしょうか？

# 二重降下が生じる理由 
論文の筆者はこの現象を"Eigen gap"と"Frozen subspace"で説明しています。

## Eigen gap
Eigenとは固有値（eigen value）のことで、この**固有値の分布**が重要です。
なぜなら固有値が過学習に大きな影響を与えるからです。
それを理解するため、下記の式をご覧ください。
これは「学習回数とともに変化する誤差関数」を表す式です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629975/993173f6-44e8-2b0e-2dd8-45ce4f294230.png)
2行目のΣ内の第二項は**Overfit noise**を表しており、分母には固有値λがあります。
**固有値λの値によってOverfit noiseの大きさ、そして全体の誤差の大きさが決まる**ことが分かります。
<br>
それでは、サンプル数とパラメータ数の関係ごとに固有値分布を確認しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/629975/44b4a4d2-d631-fbcd-e61e-55d45f89e344.png)

* 「α=1」の固有値分布（過学習が生じるときの分布）
「α=1」の分布では0に限りなく近い値を多くとっています。
これにより先ほどのOverfit noiseが大きくなり、過学習につながったのです。

* 「α=2」の固有値分布（最も汎化性能の高くなるときの分布）
λ=0付近をよく見ると、横棒が見えると思います。
**これは固有値λが0に限りなく近い値を取っていない（gapがある）ことを表します。**
つまり、「サンプル数>パラメータ数」の時はEigen gapがあり、固有値λが0に近い値をとらず、
Overfit noiseが大きくなりにくかったため、汎化性能が高くなっているのです。


## Frozen subspace
最後に、本題の「サンプル数<パラメータ数（α=1/2）」の固有値分布を確認しましょう。
* 「α=1/2」の固有値分布
    * **Eigen gapがある**
    * **固有値λが0を取っている。**

固有値が0を取ると、学習中に学習が進まないことがあります。
**学習が進まないということは、汎化性能はよくならないし、悪くもなりません。**
この「学習が進まない」というFrozen subspaceが汎化性能の悪化を防いでいると、筆者は考えています。

# まとめ
以上より、パラメータ数がデータ数よりも多いときに過学習が起こらない理由は、
**「Eigen gap」と「Frozen subspace」が働いているから**と言えます。
この発見は、パラメータ数が増大しやすい画像データなどを扱うときに役立ちそうですね！

本記事はここまでです。
お読みいただきありがとうございました。

P.S. 
内容に誤りがございましたら、お手数ですがご指摘いただけますと幸いです。
ブラウザ上のGithubで他人のpublicレポジトリを間違えてcommitしちゃった?


# やらかしたことと経緯
　本当に右も左もわからぬGit初心者だったころにやらかしたことです。

　ある人の書いたソースコードをお借りしたいと思い、そのレポジトリを複製した上で自分で名前を付けて新しいレポジトリをprivateで作りました。

　そしてちょいちょい自分用にそのレポジトリを書き換えて、元になった方のレポジトリと見比べながらブラウザ上でちまちま編集していたところ……
　なんと間違えて元になった方のレポジトリ（他人様のレポジトリ）を直接ブラウザでいじってしまったのです！

　複製したばかりだったので、コード編集画面がそっくりで編集した時には気づかなかったのですね。
　そのまま緑色のCommit Changesボタンを押して、あっ……！と直後に気が付きました。自分は今、他人様のレポジトリで編集してしまったのではないかと！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125283/c576132f-7264-454d-8548-cf78b198f909.png)
　画面上には　自分のユーザ名 Update .gitignore　が表示されてしまっています。
　しかもprivateで編集していたはずなのに、publicになっちゃってる……！

　その時、私はめちゃくちゃ焦りました。なぜなら、当時のセキュリティ意識がガバガバな私はAPI keyをそのままの形で埋め込んでCommitしていたからです。（アホ）
　やばい……！　私のAPI keyが公開されたうえ、コソコソと世界の片隅で開発しているだけの私の存在が全世界に知られてしまう……！

# 解決への道

　その時大変焦っていた私はQiitaの質問板にまでお邪魔してCommitを取り消す方法などを聞いたりなどしていたのですが、まあ、もちろん無事解決しました。

　Githubのブラウザ上において、他人のレポジトリを編集した場合それはforkしたものとして扱われます。
　すなわち、自分が編集した変更はそのままで、publicなレポジトリとして自分の配下に作られるということですね。
　なので当然自分のレポジトリという扱いになるので、そのレポジトリを消すもprivateにするも自分の自由です（SettingからDeleteを押すだけです）。
　消せばもちろんそれ以降誰の目に触れることもありません。

　しかし当時の私は「Fork＝なんじゃそりゃ、Commit＝編集の確定」みたいな感じだったので、編集確定しちゃった！どうしよう他人のレポジトリなのに！　となってしまったのですね。
　そもそもブラウザ上で直接ガリガリ編集を書き加えていたところで大分やっちゃってますしね。

# 終わりに

　ろくに使い方も分かっていなかった初心者だったから仕方がないとはいえ、当時はとても焦りました。
　ちなみに公開してしまったAPI keyはLINE Notifyのやつなので、流出して使われてしまっても「通知がうるさいなあ」となるだけだったのですがねｗ

　最近Gitを操作するのに詰まったことがあり、ふとそういえばあんなことがあったなと思い出してこの記事を書きました。（※ちなみに、git初期化をしないでcommitしようとしていました。いつまで経ってもこんなミスばかりしています）

　私みたいな早とちりのおっちょこちょいがそうそう世の中にいるとは思えませんが、もし困っていたら検索かなにかでこの記事にたどり着いてくれると嬉しいですね。

　ところで最近からなのか知りませんが、Publicな他人のレポジトリに変更を加えようとすると以下のような文章が出てくるらしいです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2125283/dff0e06f-e020-c849-8eac-d4a4e735ed3e.png)
　ひょっとして、割と自分のレポジトリと間違えて操作しちゃう人多いのか……？
gvim ColorColumnで色を変えられない【解決法】

# gvim ColorColumnで色を変えられない(赤色で固定される)問題の解決法

## 解決策

結論から書きます。

例えば、文字色を白、背景色を黒としたいときは下記のような設定をvimrcに記述します。

`highlight ColorColumn guifg=#ffffff guibg=#000000`

設定値はHTMLカラーコードのようです。

以降、蛇足です。

## 解決に至った経緯

### 問題を認識

vimでの設定と同じようにして特定の行の文字色/背景色を設定するつもりでいたので下記のような設定をしていました。
(この投稿に検索エンジンから辿り着く人も、このような設定でうまくいかずに検索してきたのではないでしょうか。)

`highlight ColorColumn ctermfg=0 ctermbg=0`

結果は、どのような値を設定しても色が変わらず、背景色も赤色で固定されたままでした。

### 解決策の発見

なかなかそのものズバリな解決策が検索ではヒットしませんでした。

そんな中、RedditのQAから有力な情報を得ました。質問のタイトルは、"ColorColumn staying in one color (red)"です。
リンク先URLを書けずすみません。書いたところエラーメッセージが表示されて記事投稿ができなかったので割愛させていただきました("リンク先に投稿禁止の内容が含まれています"というメッセージがでました)。

質問タイトル的には今読んでいただいているこの投稿タイトルとほぼ同じでした。

ただし、私の場合の解決策とはなりませんでした。
人によっては、私の投稿のやり方ではなく、その質問に投稿された解決策を実行することで解決するかもしれません。

それはともかく、結局役に立ったのはこの質問への解答にあった`verbose`というコマンドでした。
具体的には下記のコマンドです。
`:verbose highlight ColorColumn`
このコマンドの出力から、ColorColumnに実際にどんな設定キーと設定値が割り当てられているのかを知ることができました。

設定キーの内でもguifg/guibgというキーが気になりました。
vimで出来てgvimで出来ないことが問題だったので、gui関連の設定が問題と言うのはありそうなことでした。

そこでこのキーの値を変えてみたところ解決となりました。

gvimの場合の設定なので、gvimrcに記述する方が良いのかもしれません。

## あとがき

`verbose`コマンドは今後もお世話になりそうです。
やはり、調査・デバッグ関連のコマンドは設定トラブルシューティングにおいて真っ先に知っておきたいものの一種かもしれません。
検索で見つかる情報には限界がありますから。

以上、いつも通りの作業ログ兼忘備録でした。
Bokehで作ったグラフをWebAPIで取得してReactで描画する

Pythonの[Bokeh](http://docs.bokeh.org/en/latest/)で作ったグラフをWebアプリ化する話です。バックエンドで作ったグラフを、フロントエンドからWebAPIで呼び出してReactで描画します。

Bokehサーバーという選択肢もありますが、フロントエンドの技術でレイアウトするのもまた一興だと思います。ニッチすぎでしょうか？？

# APIの用意

バックエンドサーバーはいまどきっぽい[FastAPI](https://fastapi.tiangolo.com/ja/)で作ります。
以下の例はFastAPIである必要性は全くないですが、リクエストが来たらBokehでグラフを作ってjson化して返すモジュールです。

```python
import json

from fastapi import FastAPI
from starlette.middleware.cors import CORSMiddleware

import bokeh
from bokeh.plotting import figure

app = FastAPI()
# cors対策
app.add_middleware(
    CORSMiddleware,
    allow_origins=['*'],
    allow_credentials=True,
    allow_methods=['*'],
    allow_headers=['*'],
    )

@app.get('/plot')
def get_plot():
    x = [1, 2, 3]
    y = [5, 2, 4]
    p = figure(width=500, height=300)
    p.line(x, y)
    return json.dumps(bokeh.embed.json_item(p)
```
ファイル名はmain.pyで保存します。
これでAPI用のモジュールができたので、サーバーを立ち上げます。ホストやポートはお好みで。

```bash
uvicorn main:app --reload --host 0.0.0.0 --port 8000
```

# フロントエンドの用意

フロントエンドの環境は無数にありますが、今回はViteで作ります。
ViteでReactのテンプレートを使って、その後bokehjsも入れます。
準備ができたら、ウェブサーバーを立ち上げます。

```bash
yarn create vite my-app --template react
cd my-app
yarn
yarn add @bokeh/bokehjs
yarn dev --host 0.0.0.0 --port 3000
```

このままだと、Viteが用意したトップページのままなので、src/App.jsxを書き換えます。
以下はボタンが配置されただけのページです。

```react
import * as Bokeh from '@bokeh/bokehjs'

export default function App() {
  const handleClick = () => {
    fetch('http://YOUR_IP_ADDRESS:PORT/plot').then(res => res.json())
      .then(data => {
        Bokeh.embed.embed_item(JSON.parse(data), 'testPlot')
      })
  }

  return (
    <>
      <button onClick={handleClick}>send</button>
      <div id='testPlot' className='bk-root'></div>
    </>
  )
}
```

以上でいけそうかと思ったのですが、ブラウザでエラーがでていました。
JQUERYがないとのメッセージがでていたのですが、どうもbokehjs内部での呼び出し方が適切でないようでしたので、index.htmlのheadでCDNからjqueryを読み込みます。

```html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.0.3/jquery.min.js"></script>
```

これで私の環境では無事動きました。

![output.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2591762/34725ebe-e9f1-9c59-5ae2-2e68d476aee6.gif)

sendを叩くとビスケットではなくプロットが増えます。
【batch】Qiitaへの記事投稿の準備を自動化した

# はじめに
Qiitaに記事投稿をする際、毎回記事のもととなるテンプレートの記事を探して内容を開いてコピーし、新規投稿のページを開いて、コピペする。
この手順が面倒だったので、バッチファイルにて自動化したので、共有する。

# 内容
windowsの.batファイルにて、コマンドを記載していった。内容は単純なので、batchファイルを書いたことがない人にもわかりやすく順番に解説していく。
ちなみに、このバッチファイルが配置されているファイルには記事のテンプレートとなるテキストファイルを配置する必要があるので、準備いただきたい。
```batch:postQiita.bat
@ECHO OFF

REM 文字コードをUTF8に設定
chcp 65001

REM 記事投稿テンプレート文字列をコピーする
type Qiita_template.txt | clip

REM Qiitaを開く
start https://qiita.com/drafts/new
```
## 1. 初期処理
```batch
@ECHO OFF
```
まず初めに`@ECHO OFF`を設定する。.bat形式のファイルはダブルクリックで実行した後、コマンドプロンプトが開き処理が実行されていく。
その際、処理内容がすべてコマンドプロンプトに表示されていくのだが、この`@ECHO OFF`を設定しておくと処理が表示されなくなる。（処理はきっちり裏で動いているのでご安心を。）

## 2. 文字コードの設定
```batch
REM 文字コードをUTF8に設定
chcp 65001
```
次に、文字コードの設定を行う。コマンドプロンプトでは文字コードはSHIFT-JISとなっているのだが、記事投稿用テンプレートのテキストファイルで使用している文字コードがこれとあっていない場合、合わせるよう設定する必要がある。（でないと後で面倒なことになってしまうので）
今回は`chcp`コマンドにて文字コードをUTF8に設定した。（詳しい設定の方法は割愛する。）

## 3. 記事投稿用の内容をコピー
```batch
REM 記事投稿テンプレート文字列をコピーする
type Qiita_template.txt | clip
```
`type`コマンドは、指定したファイルの内容を画面に出力するコマンドである。`clip`コマンドは指定された文字列をクリップボードにコピーする。そのコマンドをパイプライン`|`にて続けて記載し、連続で実施している。
つまり、記事投稿用のファイルの内容を出力し（実際には`@ECHO OFF`が設定されているので画面には出力されない）、それをクリップボードにコピーしている。

## 4. 記事投稿ページを開く
```batch
REM Qiitaを開く
start https://qiita.com/drafts/new
```
`start`コマンドにて、指定したURLのページ（ここではQiitaの記事投稿ページ）を、指定のブラウザで開く。
`start`コマンドは、実際は指定したプログラムをコマンドプロンプトとは独立して呼び出すコマンドだが、URLを指定すると、デフォルトで設定されたブラウザで開くらしい。
ちなみに、好きなブラウザで開きたい場合は、ブラウザの実行ファイルを指定するとよい。
```batch
start "C:\Program Files\Internet Explorer\iexplore.exe" https://qiita.com/drafts/new
```
後は各自`Ctrl + v`などで貼り付けを行えば、準備完了ということになる。

# まとめ
いかがだっただろうか。もしかしたら大した短縮にはならないかもしれないが、私と同じような手間をかけて記事投稿をしているようであれば、ぜひ役に立ててほしい。
もちろん、ここに記載している内容は自由に使っていただいて構わない。自由に複製なりカスタマイズなりして、上手に作業を簡略化していただければと思う。
djangoのWebアプリがherokuへのpushで失敗する（requested runtime (Python-x.x.x) is not available for this stack ）

# djangoのWebアプリがherokuへのpushがエラーになり失敗する。pushできない
（requested runtime (Python-x.x.x) is not available for this stack ）

```
> git push heroku master
```
すると
requested runtime (Python-x.x.x) is not available for this stack 
となってPUSH失敗する。

原因は、
runtime.txt の記述を
Python-3.9.2
↓
python-3.9.2
に修正したら解決しました。
RSpecのbefore

時間固定などbeforeを使う機会が多々あるのですが、引数を渡すことで実行タイミングを変更できると知らなかったのでメモです。

具体的に言うと、これまで以下のように書いていたのですが、
```
before do
  travel_to(Time.zone.local(2022, 7, 1, 0, 0, 0)) }
end
```

以下の3パターンで変更ができます。 ※afterも同様です
1. before(:suite)
RSpecの実行時に呼び出される。
2. before(:all)
context/describeブロックの実行時に呼び出される。`before(:context)`とも書ける。
3. before(:each) ※デフォルト
itの直前に毎回呼び出される。冒頭に記載したように引数を指定しないとこのパターンになる。`before(:example)`とも書ける。

あくまでイメージですが、コードで見るとよりわかりやすいかと思います。
```ruby
RSpec.describe Sample do
  before(:all) do
    puts 'all'
  end
  before(:suite) do
    puts 'suite'
  end
  before(:each) do
    puts 'each'
  end

  describe 'sample1' do
    puts 'sample1'

    it 'do test1' do
      puts 'do test1'
    end
    it 'do test2' do
      puts 'do test2'
    end
  end

  describe 'sample2' do
    puts 'sample2'
    
    it 'do test3' do
      puts 'do test3'
    end
  end
end

# 結果
all
suite
sample1
each
do test1
each
do test2
suite
sample2
each
do test3
```
Rails備忘録 #1 「undefined local variable or method」エラーが解消できない

Railsの勉強を開始して、テキスト通りのプログラムを構築する中で、
slimを使用しているが、

<b>インデント</b>がとても重要とのこと。。。

きちんとしたインデントでないとエラーが出るのでご注意を。

Railsで引っかかった初めてのエラーで困ったので備忘録までに。

「undefined local variable or method」エラーが解消できない、、、
何も間違っていないと思ったら、インデントを確かめてみよう。
laravelにてcomposer installを実行したらpsr-4に違反しているからautoloadできない警告がでた

# 概要

- laravelにて開発中のコードのvendor直下を削除して`$ composer install`を実行したところautoloadの警告が出たので解決方法をまとめる。

# 警告

- `$ composer install`を実行したところ下記の警告が出た。

    ```
    Class namespace\class名 located in ディレクトリ/classが含まれるファイル名 does not comply with psr-4 autoloading standard. Skipping.
    ```

# 解決方法

- よく見たら当該クラスのnamespaceの最後のフィールドの頭文字が大文字が正しいのに小文字になっていた。
    - 誤

        ```php
        namespace Xxx\Yyy\zzz;
        ```

    - 正しい

        ```php
        namespace Xxx\Yyy\Zzz;
        ```

# 参考文献

- [https://qiita.com/inouet/items/0208237629496070bbd4](https://qiita.com/inouet/items/0208237629496070bbd4)
GCSにバックアップしたデータをBigQueryにcloud functionsで転送

GCSにバックアップしたデータをBigQueryにcloud functionsで転送したときのメモ
cloud functionsはpythonを使ってます

●GCSのバケット情報を把握
バケットはbucket_nameという名前とします。このバケット配下には毎日バックアップデータが生成されます。本日のバックアップデータのみをBigQueryにコピーします
```
bucket_name/
  2022-07-12T14:00:05_37464/
    all_namespaces/
      data1/
        all_namespaces_data1.export_metadata
        output-0
        output-1
  2022-07-11T14:00:06_24950/
    all_namespaces/
      data1/
        all_namespaces_data1.export_metadata
        output-0
        output-1
```

●cloud functionsでやること
・GCSバケット配下のファイルのリストを取得
・リストから最新のバックアップデータの日付を取得
　(例では2022-07-12T14:00:05_37464)
・バックアップデータのURIを取得
　(例ではgs://bucket_name/2022-07-12T14:00:05_37464/all_namespaces/data1/all_namespaces_data1.export_metadata)
・上記データをBigQueryのデータセット(dataset_name)のテーブル(table_name)に転送

●GCSバケット配下のファイルのリストを取得と、バックアップデータの日付を取得
[公式ページの例](https://cloud.google.com/storage/docs/samples/storage-list-files?hl=ja)を参考に、list_blobsを使います。prefixとdelimiterが設定できます。prefixに本日の日付を指定することで、最新のファイルのみのリストを取得します。delimiterは今回は使いませんでした
```python
    storage_client = storage.Client()
    blobs = storage_client.list_blobs(
        'bucket_name', prefix=datetime.now().strftime('%Y-%m-%d'), delimiter=None)
    for blob in blobs:
        time = blob.name[:25]  #2022-07-12T14:00:05_37464の部分を取り出す
        break
```

●BigQueryにコピーするバックアップデータのURIの取得
all_namespaces_data1.export_metadataが対象になります。URIは下記
gs://bucket_name/2022-07-12T14:00:05_37464/all_namespaces/data1/all_namespaces_data1.export_metadata
(上記の日付の部分は、さきほどの処理で取得)

●BigQueryにコピー
今回はDatastoreからGCSにバックアップされたデータが対象なので、SourceFormatはDATASTORE_BACKUPを選択
WRITE_TRUNCATEは上書きのことです
ちなみにBigQueryにテーブルがないとコピーに失敗するので、事前に作っておきます(DATASTORE_BACKUPの形式で)
```python
    bq_client = bigquery.Client()
    dataset = bq_client.dataset('dataset_name')
    jobconfig = bigquery.LoadJobConfig(
        autodetect=True,
        source_format=bigquery.SourceFormat.DATASTORE_BACKUP,
        write_disposition=bigquery.WriteDisposition.WRITE_TRUNCATE)

    uri = 'gs://bucket_name/' + time + '/all_namespaces/data1/all_namespaces_data1.export_metadata'
    job = bq_client.load_table_from_uri(
        uri,
        dataset.table('table_name'),
        job_config=jobconfig)
    job.result()
```
Rails on Ruby テーブルをupからdownにする方法

※Rails 6.1.6 
## rails db:migrate:statusでテーブルがupかdownかを確認できる。
```
Status   Migration ID    Migration Name
--------------------------------------------------
   up     20220355345534  Devise create customers
   up     20220353343534  Devise create admins
```

## 今回はcustomersテーブルをdownにします。
```
rails db:migrate:down VERSION=20220355345534
```

## もう一度db:migrate:statusで確認すると....
```
Status   Migration ID    Migration Name
--------------------------------------------------
  down    20220355345534  Devise create customers
   up     20220353343534  Devise create admins
```

## まとめ
#### rails db:migrate:down VERSION="downにしたいテーブルのMigration IDをここに入れる"　これでupからdownにできます。
Laravel プロジェクトをDockerを使用し作成。また、既存プロジェクトをDockersail up する方法

Dockerを使用してLaravelプロジェクトを作成し、実行する
1,Docker Desktopをインストール
2,Windows Subsystem for Linux 2（WSL2）がインストール
3,curl -s https://laravel.build/example-app | bash
```powershell
curl -s https://laravel.build/example-app | bash
```

4,cd example-app
```powershell
cd example-app
```

5,./vendor/bin/sail up
```powershell
wsl
./vendor/bin/sail up
```


6,http://localhost


クローンした既存LaravelプロジェクトのDocker環境構築
1,git clone プロジェクト名
```powershell
git clone プロジェクト名
```
2,cd プロジェクト名
```powershell
cd プロジェクト名
```
3,cd docker-composeファイルのあるディレクトリ

4,venderディレクトリがないのでcomposer updateを実行
```powershell
composer update
```
5,composer installを実行
```powershell
composer install
```
6,cp .env.example .envを実行
```powershell
cp .env.example .env
```
7,wslターミナルで./vendor/bin/sail upを実行（初回はコンテナが立ち上がるまで８分ほどかかる場合もある）
```powershell
wsl
./vendor/bin/sail up
```
【Swift】複数のトレイリングクロージャー

# 1.はじめに
初投稿です。
会社の後輩がSwiftUIのチュートリアルにあったこれで躓いた時、きちんと答えることができなかったので、復習を兼ねて記事にしました。

この記事では
* トレイリングクロージャー
* 複数のトレイリングクロージャー

について書いていきます。

# 2.トレイリングクロージャー
そもそもトレイリングクロージャーって何？

↓↓↓これです↓↓↓
```swift: 引数が１つだけの場合
/// クロージャー引数をもつ関数の宣言
func doHoge(fuga: () -> ()) {
    fuga()
}

/// 普通に引数にクロージャーを渡して、関数を呼び出す
doHoge(fuga: {
  print("fuga")
})

/// これがトレイリングクロージャー
doHoge {
  print("fuga")
}
```
```swift: 複数の引数のうち、最後がクロージャーの場合
/// クロージャー引数をもつ関数の宣言
func doHoge(fuga: Int, piyo: () -> ()) {
    print("\(fuga)")
    piyo()
}

/// 普通に引数にクロージャーを渡して、関数を呼び出す
doHoge(fuga: 1,
       piyo: {
         print("piyo")
       })

/// これもトレイリングクロージャー
doHoge(fuga: 1) {
  print("piyo")
}
```
[公式サイト](https://docs.swift.org/swift-book/LanguageGuide/Closures.html#Trailing%20Closures)ではこれだ！って書き方がなかったので、自分なりに解釈をした言葉で言うと

トレイリングクロージャーとは
_「クロージャーの引数が末尾の時に使えるシンタックスシュガー」_

もう少し細かく言うと
_「クロージャーの引数が末尾のメソッドを呼び出す際に、引数ラベルや括弧を省略できる記法」_
と認識しています

※「引数の最後がクロージャーの時に使える記法」という認識だと、後述で「？」となってしまいます

# 3.複数のトレイリングクロージャー
本題。
複数のトレイリングクロージャーって何？

↓↓↓これです↓↓↓
```swift: 関数宣言
func doHoge(fuga: () -> (), piyo: () -> ()) {
    fuga()
    piyo()
}
```

クロージャーの引数が複数ありますね。
これのトレイリングクロージャーが↓です。
```swift: これもトレイリングクロージャー
doHoge {
    print("fuga")
} piyo: {
    print("piyo")
}
```

これは最近見たことある人いるんじゃないでしょうか。
そう、~~最近林檎が勝手に書き換えやがった~~SwiftUIのチュートリアルです。
ここで後輩がやられました。
↓件のSwiftUIのチュートリアル。「Building Lists and Navigation 第6節のステップ6」で登場します。
https://developer.apple.com/tutorials/swiftui/building-lists-and-navigation

ちなみに、英語では「Multiple Trailing Closures」と呼ばれているみたいです。
これでggると色々な記事が出てきますね。日本語だとわかりやすい記事が出てこなかったです……

# 4.いつの間に実装されてたの？
[ここ(2020-09-16)](https://docs.swift.org/swift-book/RevisionHistory/RevisionHistory.html)によると、Swift5.3の時に追加された記法らしいです。
実際、Swift公式の[Closures](https://docs.swift.org/swift-book/LanguageGuide/Closures.html#Trailing%20Closures)でも記載はあります。（ちょっと見落としがちではありますが）

# 5.どのXcodeで使えるの？
余談ではありますが、Xcodeのバージョンによって使用できるSwiftのバージョンは異なります。
[Download Swift](https://www.swift.org/download/#releases)ではSwift5.3のPlatformがXcode12とあるので、12以降なら使えるみたいですね（筆者は11以前で試したことはないです）

# 6.まとめ
トレイリングクロージャーには複数の書き方がある。
* doHoge {}
* doHoge(fuga: x) {}
* doHoge {} piyo: {}

最初誤植かと思ったよ……精進せねば。
他にも、間違いの指摘だけでなく、SwiftやiOS開発の小ネタ等あればコメントよろしくお願いします。
レガシー企業にいるとよく出会う「Excelあるある」

レガシー企業にいるとよく出会う「Excelあるある」


よくつかう言葉として、「えくせるつかえますか？」があります。

でも、蓋を開けてみるとできることはバラバラ。
「できます」「できません」のレベルが全く違います。
分類すると下記のような感じでしょうか。

「Excel」使えます。
関数はもちろん、VBAも理解できます。

「エクセル」使えます。
VLOOKUPを使ったり、グラフ化できます。

「えくせる」使えます。
四則演算、SUM程度。

たまにいらっしゃる、セルに数字を入れられるだけで「えくせるできます！」っていう方はちょっとご遠慮いただきましょう。
基本情報（プリンタ）

処理結果をプリント（印刷）する装置だからプリンタ。代表的な出力装置のひとつです。
ディスプレイがRGBに対してプリンタはCMYK(Cyan:シアン、Magenta:マゼンタ、Yellow:イエロー、black:ブラック)という４色の色を再現します。

## プリンタの種類と特徴
プリンタは、その印字方式によって様々な種類に分かれます。
代表的な次の3種類を記述します。

|   |説明  |
|---|---|
|ドットインパクトプリンタ  |印字ヘッドに多数のピンが内蔵されていて、ピンでインクリボンを打ち付けることによってインするプリンタ。複写式の伝票印刷に使用できる唯一のプリンタであるため、事務処理能力分野で重宝されている。  |
|インクジェットプリンタ  |印字ヘッドのノズルから、用紙に直接インクを吹き付けて印刷するプリンタです。インクの滲みなど印字先の紙質に左右される面もありますが、基本的に静かで高速。個人用途のプリンタとして普及しています。CMYKだけでなく、ライトシアンなどを加えた多色表現を可能としてモデルが出ており、写真並みの高画質印刷を可能としています。  |
|レーザプリンタ | レーザ光線を照射することで感光体上に１ページ分の印刷イメージを作成し、そこに付着したトナー（顔料などの色粒子からなる粉）を紙に転写することで印刷するプリンタ。基本的にコピー機と同じ原理。ページ単位で印刷するため非常に高速で、音も静か。粉を定着させる方式であるため、インクがにじむようなこともなく、高品質な印字結果を得ることができる。

## プリンタの性能指標
プリンタの性能は、印字品質とその速度によって評価することができる

### プリンタの解像度
印字品質をはかる指標が解像度です。プリンタの場合は、「１インチあたりのドット数」を示すdpi(dot per inch)を用いて表します。
この数値が大きいほどきめの細かい表現ができるので、高精細な印字結果を得ることができます。

１インチという距離の中に
１インチ（2.54cm）の300個のドットが描かれれば300dpiとなる。

### プリンタの印字速度
印字速度を表す指標は「１秒間に何文字印字できるか」を表すcps(character per second)と「1分間に何ページ印刷できるか」を表すppm(page per minute)の２つがある。
プリンタの印字方式により、いずれか最適な方を用いて表す。

## まとめ
プリンタは重要
batch使ってファイル中の文字列を全部取り出して変数に渡す




```batch
rem *****バッチ実行
java -cp some command 2>exception.log
rem エラー時はエラー処理へ
IF ERRORLEVEL 1 goto ABEND
rem 成功処理
省略...
exit /b 0


rem エラー処理
:ABEND
setlocal enabledelayedexpansion
rem ファイル中の文字列を全部を取り出す
set text=
rem tokens=* 行ごとにループ、text変数にわたす
for /f "tokens=*" %%i IN (exception.log) do set text=!text!%%i
rem エラー文字列をイベントビュアーに登録
eventcreate /ID 999 /L Application /T ERROR /D "%text%"
endlocal
rem *****異常終了（コード＝１）
exit /b 1
```
## eventcreate について

eventcreate (Computer) /ID EventID (option) /T Type /D Description

登録内容確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/736127/94e8ddc3-56b3-6980-4c0c-57d355f88b7e.png)
Qualtricsのオンラインヘルプを検索するのに便利な方法

## はじめに

Qualtricsのオンラインヘルプは日本語化されていますが、~~まだ検索窓が実装されていません。~~
~~ですが、実は英語版の検索窓から検索すると日本語のヘルプのコンテンツも検索することができます。~~
※日本語版のページにも検索窓が付きました！　ただ、こちらの記事でご紹介する方法を使うと素早く検索ができますので、よければ試してみてください。

Qualtricsを活用する場合にヘルプページにはかなりお世話になりますので、今回はヘルプページを素早く検索するための2つの方法を紹介します。

## 方法1. Google Chromeの「サイト内検索」機能を使う
Google Chromeのアドレスバーに任意の文字列を打つと、検索できる方法。
![Screen Recording 7-13-2022 at 9.39 PM.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/7aa061eb-ee8c-7c89-0b78-602469afb63c.gif)

こんな感じで、自分が決めた任意のキーワードをアドレスバーに入れてから、検索したい語句を打つと、クアルトリクスのヘルプから検索することができます。
日本語の語句も検索可能です。

### 設定方法

1. Google Chromeの設定を開き、「検索エンジン」のメニューを選択し、「検索エンジンとサイト内検索を管理する」をクリックする。
1. 「サイト内検索」の項で「追加」ボタンをクリック
![スクリーンショット 2022-07-13 21.43.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/b3c4b4ef-57a5-5563-d0f3-3146ea76d8fa.png)
1. 以下のように設定する。
「ショートカット」の部分は好きな文字を入れてください。この文字をアドレスバーに入れるとクアルトリクスのオンラインヘルプから検索できるようになりますので、覚えやすくて打ちやすい文字が良いです。
「検索エンジン」のところも好きな名前を入れてください。
<img width="400" alt="d23309c9-e639-7f1f-cc62-86d3f75da1f6.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/d23309c9-e639-7f1f-cc62-86d3f75da1f6.png">

使用するURLは以下の通りです。

```
https://www.qualtrics.com/support/search/?q=%s
```

完成！早速試してみてください。






## 方法2. Bookmarkletを使う
次に、Bookmarkletという方法を使って、アドレスバーに検索用のボタンを作ってしまう方法があります。

使い勝手はこんなイメージです。
![Screen Recording 7-13-2022 at 9.40 PM.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/52208b3c-2bf6-a646-f3ef-d2773df848be.gif)

### 作り方
1. 適当なブックマークをブックマークバーに作る
1. ブックマークを右クリックし、編集する
1. URLを下記のコードに入れ替える

```
javascript:(function()%7Bvar val%3Dprompt("検索したいキーワードを入力してください","")%3Bvar val%3DencodeURIComponent(val)%3Bvar val%3D"https://www.qualtrics.com/support/search/%3Fq%3D%3F"%2Bval%3Bif(val)window.open(val)%3B%7D)()
```
こんな感じです。
<img width="300" alt="389a217f-4121-1418-4beb-7a80c27a5dd0.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/490870/389a217f-4121-1418-4beb-7a80c27a5dd0.png">

完成！ 早速使ってみましょう。


## 最後に
いかがでしたでしょうか？
今回ご紹介した方法を使うと、調べ物でのストレスが軽減されて作業効率も良くなりますので、
より作り込む方に集中して取り組むことができるのではないでしょうか。
ぜひ活用してみてください！

## 追記
たくさん検索をしているとまれに"400 Bad Request"となり、個別の記事が開けなくなることがありますが、
この場合はCookieが肥大化してしまっていることがありますので、Cookieを削除して再度アクセスしてみてください。
【#28 エンジニア転職学習】DB入門　持続性とパフォーマンス維持

# はじめに
富山県に住んでいるChikaといいます。
毎日投稿を目標に、バックエンドエンジニア転職に向けた学習内容をアウトプットします。

DBの入門をざっくり学習していきます。

バックエンドエンジニアになるまでの学習内容は以前投稿した以下の記事を基にしています。


https://qiita.com/Chika110/items/ef54dddd565a0193ef44

# 本日の学習内容
本日はDBMSの持続性とパフォーマンスに関して学習しました。

* テーブルのER図
* **持続性とパフォーマンス　←Topics!!**

# DBMSの持続性とパフォーマンス
DBMSでは、ACID特性の1つである「COMMITされたデータの永続性保証」と、実用パフォーマンスの両立として3つの仕組みが用いられている。
1. ログ先行書き込み
    * 変更をログとして記述して、同期する
1. データベースバッファ
    * データファイルへの入出力をデータベースバッファに一本化する
1. クラッシュリカバリ
    * ロールフォワードによって、クラッシュ時までにコミットされた最新状態まで戻す


使用している教材はこちら↓


https://www.amazon.co.jp/%E3%81%8A%E3%81%86%E3%81%A1%E3%81%A7%E5%AD%A6%E3%81%B9%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E3%83%99%E3%83%BC%E3%82%B9%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E3%83%9F%E3%83%83%E3%82%AF-ebook/dp/B00TTRZFDC/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=1657112653&sr=8-1


# おわりに
最後までお読みいただきありがとうございました。
アドバイス・応援コメント等いただけますと幸いです。
汚物は消毒だ！（不要なコードは消しましょう）

独学でも一年ほど勉強しましたが、それでも実務に入って新しく学んだことも多いです。アウトプットの意味も込めて、ここに書いていこうと思います。
技術記事としては、初学者の方向けです。エンジニア転職を目指して頑張っている方の参考になればよいと思います。

汚物は消毒だ！！

はい、不要なコードは消しましょうという話です。

改めて書くと当たり前なのですが、私が独学の頃に作成したポートフォリオの時は、全くできていませんでした。LaravelというPHPのフレームワークを使っているのですが、Laravelはコマンドをいくつか入力するだけで、ログイン機能などを自動的に作成してくれます。そこから独自に開発を進めていたのですが、使わないコードも残していました。メールアドレス認証などは使わなかったのですが、それらのコードをLaravelが自動的に作成してくれていました。

不要なコードを消すという、一見簡単そうに見えることでも、以下の能力が必要になると思います。
１．技術的な負債をなるべく減らそうという姿勢
２．フレームワークに対する理解

まず一つ目についてですが、これは他人が自分のコードをみて理解できるかです。先の例だと、メールアドレス認証のコードを残していれば、ほかの人がそれを見たとき、
「あれ、メールアドレス認証のための記事があるぞ。アプリにメールアドレス認証機能ってついていたかな？（カチカチ...）やっぱり認証機能は見当たらないな。（再度、コードをチェック...)あっ、このコードは使ってないのか。（それなら消しておいてくれよ。無駄な時間使ってしまった...）」となってしまいます。整理整頓してあるコードは、他者が見たときに分かりやすくなります。

次に二つ目についてですが、不要なコードを削除しようと思うと、一つ一つファイルの中身を確認していく必要があります。その過程で、「このコードは何をしているのだろうか？削除してしまっても問題ないか？」と考えるようになり、フレームワークが裏でどのような処理を行ってくれていたのかを深く理解できるようになります。今後、難しい機能を実装するときの助けになると思います。
Rails link_toで関数を渡す

# 背景
レシピ共有アプリ制作にて以下のような問題がありました

```ruby:モデル
class User < ApplicationRecord
has_many: recipes
has_one: list
end

class Recipe < ApplicationRecord
belongs_to: user
has_many: ingredients
end

class Ingredient < ApplicationRecord
belongs_to: recipe
end

#これは買い物リストのモデルで、追加したいレシピの材料をリストテーブルに保存します
class List < ApplicationRecord
belongs_to: user
end
```

買い物リストにレシピの材料を追加するときに、

パラメーターの中にレシピの情報を追加したかったのですが、

親子関係ではないのでルーティングのネストをせずに実現したい。。。

迷った末見つけた方法をここに残します

```ruby:ルーティング
post '/lists', to: 'lists#create', as: 'create_list'
```
```ruby:コントローラー
 def create
    #レシピのidを整数に変換
    num = (params[:format]).to_i
    @recipe = Recipe.find(num)
    #レシピの材料を全て取り出す
    @ingredients = @recipe.ingredients
    list = List.new
    @ingredients.each do |ingredient|
      list = List.new(ingredient_name: ingredient.name, ingredient_quantity: ingredient.quantity, user_id: current_user.id)
      list.save
    end
    flash[:notice] = 'リストを追加しました'
    redirect_to "/users/#{current_user.id}"
  end
```
```erb:ビュー
<%= link_to "追加", create_list_path(x), method: :post %>
<!--xにはレシピの情報が入っています-->
```
この方法だとエラーが発生したときにエラーハンドリングができていません。

ストロングパラメータもないので良くないですが、とりあえずデータベースに保存するための基盤を作りました。

# ポイント
ポイントは`lists#create`アクションに行くときに`recipe`の情報をパラメーターに含めたかったので、

`<%= link_to "追加", create_list_path(x), method: :post %>`この形を取りました。

`"/lists"(x), method: :post`とかでできないかとやってみましたが、できなかったので、

`post '/lists', to: 'lists#create', as: 'create_list'`
この記載で`create_list`というprefixを作りました


初学者が足掻いて試した結果なので、もっといい方法などありましたら教えてください。

この記載でストロングパラメーターをつけるとしたらどうすればいいか現在調べてます。
SORACOM LTE-M Button for Enterprise から PowerAutomate を実行する

## はじめに
ボタンは準備する・したが、クラウド(AWS,GCP,Azure,etc...)はよくわからない。
そんな人へ贈る記事です。
いつも使ってるMicrosoft Officeとも親和性の高いPowerAutomateでコードを書かずに連携してみましょう

MSアカウントやADとも連係できるのがPowerAutomateの強み
そのため内部への踏み台を用意せずに自分のメールアドレスから送ったり、Teamsへ投げたり！

## 用意するもの
* PowerAutomateが使えるMicrosoftアカウント
* LTE-M Button for Enterprise もしくは LTE-M Button Plus
    * 今回はLTE-M Button powered by AWSは不可

## 設定手順
### 送信先URLの作成
PowerAutomateの画面を開いて置いてください。

1. [インスタンスクラウドフロー]を選択
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/2b8f73d3-6b69-a6d0-1f3b-f3792ff2eebd.png)
2. [HTTP 要求の受信時]を選択
  (執筆時点では一番最後 
  ![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/9fe7bdec-efe6-4486-c946-b00919de2e5a.png)
3. 開くと以下のようになっているのでバーをクリック
  ![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/4dde132b-fe67-d6e8-5dd8-3a06f7a582f3.png)
4. 「要求本文のJSONスキーマ」へ「[JSONスキーマ][JSONスキーマ]」をコピペ
  ![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/7e2e1f68-94a1-0f1a-41d1-2a57a30b952b.png)
5. やる予定のアクションを設定して一旦保存
6. 再度開く URLがあるのでコピー
  ![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/102e42da-856a-4866-437a-3545cd4edf5c.png)
7. スキーマを設定しているので、クリックタイプなどが使えるようになっているので、お好みでアクションに使用する。
  ![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/b259450e-b37c-401f-a269-fa930b7bed4b.png)


### 送信の設定
※正直、[ボタンからBeam][beam]のマニュアルで事足りる。
SORACOM ユーザーコンソール を開いて置いてください。

1. ボタンを設定したSIMグループを選ぶ
1. 「SORACOM Air for セルラー設定」でバイナリーパーサーを有効にする。フォーマットは```@button```![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/4fb328b6-be9b-8ff8-beac-49b7ec4e72a3.png)

1. Beamのメニューから「UDP→HTTP/HTTPSエントリーポイント」を選ぶ
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/01b91bf8-ba10-093e-5d4a-7319469d7236.png)
1. 「送信先URLの作成」で作成したURLを以下のように分解して入れる
  パスは省略していますが、元の全部入れてください。
  ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141402/8435f1c6-30dd-2386-fcd1-ae903181a923.png)

## 参考文献
[beam]: https://users.soracom.io/ja-jp/guides/soracom-lte-m-button-series/lte-m-button-enterprise/beam/
[JSONスキーマ]: https://gist.github.com/tac-yacht/bac5c298f0c627d0d35ac4f43025c139
* [[PowerAutomate]HTTP要求の受信時 仕様](https://docs.microsoft.com/ja-jp/azure/connectors/connectors-native-reqres)
* [[SORACOM]ボタンクリック時のデータを SORACOM Beam でサーバーへ転送する][beam]
* [[SORACOM]送信されるデータフォーマット](https://users.soracom.io/ja-jp/guides/soracom-lte-m-button-series/lte-m-button-enterprise/payload/)
* [JSONスキーマ][JSONスキーマ]

## 余談
よりセキュアにだと、署名ヘッダを付与をSORACOMで行い、PowerAutomateで検証すれば、SORACOMからだけにできるが、PowerAutomateでやるのは辛そう。。。
DB設計の属性の基本。

個人開発でDB設計を行なった際に調べた内容をまとめます。


①文字列を扱うデータ型。

char型、(例)char(30)

()の中の数字は格納できる桁数(文字列）を指定する。
格納するデータが指定した桁数に満たない場合その分だけ空白が埋められる。＝固定長文字列

varchar型、(例)vachar(30)
()の中の数字は格納できる桁数(文字列）を指定する。
格納するデータが指定した桁数に満たない場合データの大きさはchar型とは異なり
空白を保存せずそのデータの大きさのまま登録される。（可変長文字列）

②数値を扱うデータ型。
ini型(整数)
整数の数値データを格納する場合はint型を指定する。

float型double型
1.4など、少数点を含む数値はfloat型、もしくはdouble型を使用する。
これらは浮動小数点型とよばれ、概数値（おおよその数）を扱うものとなっているので、
金額などより正確な値を扱う必要がある場合は後述する「固定少数型」を採用する必要がある。

decimal型(固定少数型)、(例）decimal(5,2)
小数点の中でも金額データなどより正確な数値が求められる場合はdecimal型を採用する。

例の場合少数部分が2桁、合計で5桁の値を格納することが出来る。
※-999.99から999.99 の範囲を格納可能となる

③時間、日付を扱うデータ型。
date型（日付）
時間以外の年月日の値を‘YYYY-MM-DD’ 形式で扱う。

time型（時間）
時間の値を‘HH:MM:SS’ 形式で扱う

datetime型、timestamp型（日時）
日時（日付と時刻）を記録する場合、datetime型もしくは、timestamp型を使用する。
YAMLで複数行を記述するときに使うブロックスカラーのサンプル

YAMLの書き方にブロックスカラーというのがある。
`|`（パイプ記号、縦棒記号） または `>`（大なり記号） に、 `+` や `-` を組み合わせた、複数行に渡った値の書き方だ。[^ref]

[^ref]: `|` と `>` を[ブロックスタイルインジケータ（Block Style Indicator）](https://yaml.org/spec/1.2.2/#812-literal-style)、`+` と `-` を[ブロックチョンピングインジケータ（Block Chomping Indicator）](https://yaml.org/spec/1.2.2/#8112-block-chomping-indicator)というらしい。日本語だとなんだろう、ブロック型指定子、ブロック末改行指定子、といったところか。


毎回書き方のサンプルをGoogle先生に聞いているような気がするので、ここにメモります。[^parser]

[^parser]: パーサにはRubyのYAMLライブラリを使いました。

## `|`

`|`は複数行を改行コードで繋げる。

```yaml:単純な複数行
- |
  hoge
  fuga
# ["hoge\nfuga\n"]
```

```yaml:途中のインデント（段下げ）のスペースは反映される
- |
   hoge
   fuga
     boo
     poo
   piyo
   piyo
# ["hoge\nfuga\n  boo\n  poo\npiyo\npiyo\n"]
```

```yaml:ブロックの最後の複数改行は１つの改行にまとめられる
- |
  hoge
  fuga

# ["hoge\nfuga\n"]
```


## `|+`

```yaml:単純な複数行は"|"と同じ
- |+
  hoge
  fuga
# ["hoge\nfuga\n"]
```

```yaml:ブロックの最後の複数改行は保持される
- |+
  hoge
  fuga

# ["hoge\nfuga\n\n"]
```

## `|-`

```yaml:単純な複数行ではブロック最後の改行は削除される
- |-
  hoge
  fuga
# ["hoge\nfuga"]
```

```yaml:ブロックの最後に複数改行がある場合も全て削除される
- |-
  hoge
  fuga

# ["hoge\nfuga"]
```

## `>`

`>` は改行をスペースに変換する。

```yaml:単純な複数行では改行はスペースに置き換わり、ブロックの最後の改行は残る
- >
  hoge
  fuga
# ["hoge fuga\n"]
```

```yaml:ただしインデント（段下げ）が変わると改行で分けられ、段下げ分のスペースも活かされる
- >
  hoge
  fuga
    boo
    poo
  piyo
  piyo
# ["hoge fuga\n  boo\n  poo\npiyo piyo\n"]
```

```yaml:ブロックの最後の複数改行は１つの改行にまとめられる
- >
  hoge
  fuga

# ["hoge fuga\n"]
```

## `>+`

```yaml:単純な複数行は">"と同じ
- >+
  hoge
  fuga
# ["hoge fuga\n"]
```

```yaml:ブロックの最後の複数改行は保持される
- >+
  hoge
  fuga

# ["hoge fuga\n\n"]
```

## `>-`

```yaml:単純な複数行では改行はスペースに置き換わり、ブロック最後の改行は削除される
- >-
  hoge
  fuga
# ["hoge fuga"]
```

```yaml:改行はスペースに置き換わり、ブロックの最後の複数改行も削除される
- >-
  hoge
  fuga

# ["hoge fuga"]
```

## その他

YAMLのブロックスカラーの動作確認をできるページがあるようなので共有です。

https://yaml-multiline.info/