OmniAICreator/Qiita-1.07M huggingface dataset:
TypeScript入門：型定義の基本と使い方

TypeScriptを勉強しだしたときにまず引っかかるのが型の導入だと思います。
様々なサイトやドキュメントもあるため、情報を容易に検索できるようになってきましたが、
簡単なサンプルのドキュメントが多かったり、
高度な内容程、サンプルが少ないなと思うことがあったので、
今回自分なりにまとめていこうと思います。

【目次】
1. TypeScript入門：型定義の基本と使い方（←いまここ）
1. [TypeScript実践1：ジェネリクスとデコレータの使い方](https://qiita.com/hanahagewanko/items/ab0f961f443d346d8fc1)
1. TypeScript実践2：高度なジェネリクスとデコレータの使い方
1. TypeScript実践3：インターセクション型とユニオン型
1. TypeScript実践4：コンディショナル型
1. TypeScript実践4：高度なデコレータの活用法

## 型定義の基本
TypeScriptでは、変数や関数の引数、戻り値などに対して、型を指定することができます。例えば、以下のように変数nameにstring型を指定することができます。

```typescript
let name: string = "John";
```
また、下記のように数値を代入するなど、
型推論により、変数に初期値を代入する場合は、型指定が不要です。

```typescript
let age = 20; // ageの型は自動的に`number`に推論される
```

## 型の種類
TypeScriptで使用できる主な型は以下のとおりです。

- `number`: 数値型
- `string`: 文字列型
- `boolean`: 真偽値型
- `any`: どのような型でも受け付ける型
- `void`: 戻り値がない場合の型
- `null` / `undefined`: 値が存在しない場合の型
- `object`: オブジェクト型
- `Array`: 配列型


## 型の使い方
型を使った変数の宣言や関数の引数、戻り値の指定方法を見ていきましょう。

### 変数の宣言
変数宣言時に __「変数名：型」__という書き方をします。

```typescript
let age: number = 20;
let name: string = "John";
let isStudent: boolean = true;
let person: object = {name: "John", age: 20};
let fruits: Array<string> = ["apple", "orange", "banana"];
```

### 関数の引数
引数の型は __function 関数名(引数名：引数の型)__ という指定をします。
```typescript
function sayHello(name: string): void {
  console.log(`Hello, ${name}!`);
}
```

### 関数の戻り値
引数の型は __function 関数名(引数名)：戻り値の型__ という指定をします。
以下のサンプルでは`number`を指定していますが、何も戻り値が無い場合は`void`になります。
```typescript
function add(a: number, b: number): number {
  return a + b;
}
```

## まとめ
TypeScriptの型定義の基本と使い方について紹介しました。
最近ではJavaScriptでフロントを書くプロジェクトがどんどん減少して、
TypeScriptを使う会社がどんどん増えているように思います。
基礎を掴んで、使いこなしていきましょう。

以上、初心者向けのTypeScript入門記事でした。
Gitlab CI/CD あれこれ


# やりたいこと

弊社内の活動の中で、Gitlab で、Azure Function Apps へのコードデプロイを自動化したので、その内容をまとめます。

# 前提

* 弊社の Gitlab サーバはオンプレです。
* そのため、ジョブを実行するためのコンピューティングリソースが必要です。
  * 今回は個人のローカルマシンでやってみました。
* 作業はすべて WSL 上で行っています。
  * WSL 上で Docker を使います。

# 大まかな手順

- [やりたいこと](#やりたいこと)
- [前提](#前提)
- [大まかな手順](#大まかな手順)
- [Gitlab CI/CD](#gitlab-cicd)
- [事前準備](#事前準備)
  - [WSL](#wsl)
  - [Docker](#docker)
- [ローカルのマシンでジョブを動かせるようにする](#ローカルのマシンでジョブを動かせるようにする)
- [デプロイのパイプラインを作成する](#デプロイのパイプラインを作成する)
- [ということで](#ということで)

# Gitlab CI/CD

Gitlab での CI/CD についてはここを参照

https://www.gitlab.jp/stages-devops-lifecycle/continuous-integration/

Gitlab-Runner というアプリケーションを利用して、ローカルのマシンでジョブを動かせるようにする。

https://docs.gitlab.com/runner/

# 事前準備

## WSL

以下を参考に環境をつくる。

https://qiita.com/fsdg-adachi_h/items/2aaa6579cb8e4fa1d874

## Docker

以下を参考に WSL 上にインストールする。

https://docs.docker.com/engine/install/ubuntu/

# ローカルのマシンでジョブを動かせるようにする

まずは、`gitlab-runner` のイメージからコンテナを起動する。以下のような感じ。

```sh
docker run -d --name gitlab-runner --restart always \
              -v /var/run/docker.sock:/var/run/docker.sock \
              -v /srv/gitlab-runner:/etc/gitlab-runner \
              gitlab/gitlab-runner
```

以下コマンドで、起動したコンテナに入る (表現正しい？)

```sh
docker exec -it gitlab-runner /bin/bash

(コンテナ内で)
gitlab-runner register
```

インタラクティブにいろいろ入力を求められるので、入力する。
参考: https://e-penguiner.com/build-gitlab-runner-with-docker/#register-runner-for-saas

* Enter the GitLab instance URL (for example, https://gitlab.com/):
  * Gitlab の URL
* Enter the registration token:
  * Runner を紐づけたいリポジトリのトークン
* Enter a description for the runner:
  * 任意。設定しなくても可
* Enter tags for the runner (comma-separated):
  * 任意。設定しなくても可
* Enter optional maintenance note for the runner:
  * 任意。設定しなくても可
* Enter an executor:
  * docker
    * 基本的に docker で OK
* Enter the default Docker image (for example, ruby:2.7):
  * 何らかイメージを指定する
  * Python:3.9 を使った

登録を解除する場合は、`gitlab-runner unregister --url {GITLAB_URL} --token {TOKEN}` で。
`gitlab-runner list` で登録内容を確認できる。

ここまでやると、Gitlab のプロジェクトページから、Settings → CI/CD のページを開き Specific Runners の下の方にさっき登録した Runner が表示されているはず。ステータスが緑になっていれば使用可能な状態。

# デプロイのパイプラインを作成する

ひとまず簡単なコマンドを実行させてみる。リポジトリのルートに、`.gitlab-ci.yml` を以下の内容で作成する。

``` .gitlab-ci.yml
job:
  script: echo "HelloWorld"
```

このファイルをリポジトリへ Push するとパイプラインが動き出す。`HelloWorld` と表示されるはず。

あとは、一般的なデプロイの手順を YAML ファイル内で定義していく。
YAML ファイルの書き方はここ。

https://gitlab-docs.creationline.com/ee/ci/yaml/README.html

すべて CLI で行う必要があるので、`Auzre Functions Core Tools` を使う。

https://learn.microsoft.com/ja-jp/azure/azure-functions/functions-run-local?tabs=v4%2Clinux%2Ccsharp%2Cportal%2Cbash#install-the-azure-functions-core-tools

基本的に上記の内容に沿って定義していけば大丈夫なはず。

# ということで

Gitlab での CI/CD の構築方法について大まかにまとめた。
Azure を提供している Microsoft は Github を買収したこともあり、そちらを今後は (というかすでに) 推していくと思うので、どこかのタイミングで Github Actions に移行したい。また、Azure との親和性という意味でも、Github Actions には簡易にデプロイできるアクションが用意されているが、Gitlab でのデプロイは1から構築することになり大変なので、そういう意味でも移行したい。
【AWS】CodePipelineからCodeBuildの環境変数を設定した場合の確認方法

# 概要
* 前任者が構成したAWS環境を確認していて、「CodeBuildの環境変数が設定されていないのに、ビルド履歴では環境変数がある...あれ、どこで設定してあるの!?」となったので、その問題の答えを備忘を兼ねて記します。

# 結論
* CodePipelineからCodeBuildの環境変数がされていました。CodeBuildの方をいくら見ても見つからないわけです。
* 以下リンクに詳しく記載がありますが、環境変数は以下のどちらでも設定ができます。今回は下記のうち、CodePipelineの方から設定されていたのでした。
    * CodePipeline
    * CodeBuild
* 参考：[CodePipelineからCodeBuildの環境変数が設定できるようになりました！](https://dev.classmethod.jp/articles/codebuild_envset_pipeline/)

# CodePipelineからCodeBuildの環境変数が設定ができる(2019/4-)
* CodePipelineからCodeBuildの環境変数が設定ができるようになったのは、2019年10月から。以下がAWS公式サイトのアップデート案内です。
    * 参考：[AWS CodePipeline で、AWS CodeBuild のビルドジョブにおける環境変数の設定が可能に](https://aws.amazon.com/jp/about-aws/whats-new/2019/10/aws-codepipeline-enables-setting-environment-variables-on-aws-codebuild-build-jobs/)

> パイプラインで CodeBuild のビルドジョブの環境変数を設定できるようになりました。これまでパイプラインのビルドジョブでは、ビルドプロジェクトの設定や buildspec ファイルで定義された環境変数のみを使用可能でした。今後は、別の環境やステージでビルドする場合でも、CodePipeline から直接、環境変数を設定できます。同じビルドプロジェクトを複数のアクションで再利用できるようになり、パイプラインのステージング環境や本番環境に向けたデプロイが簡略化されました。また、パイプラインの実行履歴から、ビルドで使用された環境変数やその他のアクション設定の詳細をすべて確認できます。

* つまり、以下のような変化・メリットがあるということですね。
    * 従来：環境ごとにCodeBuildプロジェクトを用意し、そのCodeBuildで環境変数を設定する必要があった（=環境変数が環境ごとに必要だった）
    * アップデート後：CodePipelineのCodeBuildに環境変数を設定し、このCodeBuildを汎用的に使い回すことができるようになった（=環境変数が複数環境で使えるようになった）
* そんな方法があったのか...知らなかった。

# 確認方法（設定手順）
* 実際の手順は以下の通りです。
* CodePipeline→CodeBuildがプロジェクトに入っている該当のパイプラインをクリック
* 右上の「編集」のボタンをクリック
* CodeBuildの右上にある「ステージを編集する」をクリック
* 以下の画像のように、鉛筆の編集マークが出てくるので、そこをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/8ee897fd-cd82-6de8-f322-37c6b96f7451.png)
* 「環境変数 - オプショナル」のところで設定・追加が可能です。
    * これから設定する場合は「環境変数の追加」をクリックします
* コンソール画面上ではこんな形になります。

### CodePipelineのCodeBuild
* 鉛筆マークの編集から入れば、CodePipelineのCodebuild設定画面なので、もちろん、環境変数や値が設定されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/4c3e2a4d-fe7a-94f1-cc55-64fcc3c6c01f.png)

### CodeBuild
* 先ほどの鉛筆マークのすぐ左にある「AWS　CodeBuild」から環境変数の編集画面に入ると、、、
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/68d472b1-0267-2275-43c3-934ba6a4b475.png)

↓
↓
↓

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2710373/5a730abe-cd35-a6b7-c635-c9c42a17bb92.png)

* こちらには何も設定されていません。当然、Pipeline側で設定しているからですね。

* ということで、くれぐれも「あれ、CodeBuildには環境変数が設定されていないのに！？」とならないように...どなたかの一助になればと思います（自分で設定していれば問題ないのでしょうが、他の方が構成したものを触るという機会はエンジニアは誰しもあると思いますので...）
ChatGPT APIキー取得までの手順

# はじめに
2023年3月2日、ついにChatGPT APIが公開されました！
値段も安くAPIに送信されたデータを学習に使用しないことが明言されているため、企業での利用なども加速していきそうですね。
>OpenAIは、お客様がこの目的のためにデータを共有することを明示的に決定しない限り、APIを介してお客様から提出されたデータを、モデルの訓練や改良のために使用することはありません。
>APIを通じて送信されたデータは、不正使用や誤用監視の目的で最大30日間保持され、その後削除されます（法律で定められている場合を除く）。

↑ [公式ページ](https://platform.openai.com/docs/data-usage-policies)から引用＆翻訳

今回はAPIキー取得から支払い情報の登録までの流れを書いていきます。

# 手順
### APIキー取得手順
まずは以下のリンクからOpenAI APIにアクセスします。

https://platform.openai.com/overview

右上の「Log in」からアカウントにログインします。
（まだアカウントを作っていない人は右上の「Sign up」からアカウント作成を行ってください。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/43c9dcf6-142d-71f0-41b9-ad28903009ee.png)

ログインしたら自分の右上のアイコンをクリックして「View API keys」をクリックします。
![Qiita1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/f2b02ed9-edff-f212-1aff-b783855e4f9a.png)

画面中央にある「+ Create new seacret key」をクリックするとAPIキーが生成されます。
![Qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/a7f21079-2a5b-cf28-06e1-c9791656e145.png)

その時に出てくるAPIキーをコピーしてコードなどに貼ります。
**※上の画面に表示されているSECRET KEY列に表示されている文字列は真ん中が省略されているため使えません。**

一度表示を消すと2度と見ることができない仕様になっていますが、削除してもう一度生成すれば問題ないです。

### 支払い情報の登録手順
このままAPIを使おうとするとエラーが出てしまいます。（下の記事参考）

https://qiita.com/kotattsu3/items/d6533adc785ee8509e2c

左側のタブから「Billing」をクリックします。
支払い設定の画面が出てくるので「Set up paid account」をクリックします。
![Qiita3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/a4a9e226-bdb2-2e59-2b8f-47678cd776c8.png)

個人開発であれば上の「I'm an individual」、企業で使うのであれば下の「I'm working on behalf of a company」をクリックし、
クレジットカード情報や住所などを入力して登録します。
![Qiita4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/d24ecb98-078a-b93b-4d5f-f1705da06995.png)

左タブの「Billing」下にある「Usage limits」をクリックし、赤丸で囲った部分に上限金額を入力します。
（デフォルトの$120は少し怖かったので自分は下げています）
入力したらその下の「Save」ボタンをクリックします。
![Qiita6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2497780/127d73a5-fd42-9949-4041-dbc5ac569e93.png)

ここまで行うことで先ほど生成したAPIキーが使えるようになります。

# おわりに
OpenAIはPythonだとライブラリも提供されているらしく、非常に簡単に実装ができるらしいので今後試していこうと思います。
【Docker】sed: couldn't open temporary file ./sedxxx: Permission denied 対処法【VirtioFS】

## 状況

Dockerでファイル共有にVirtioFSを使用してコンテナ内で`sed -i`を実行したところ以下のようなエラーが出ました。

```terminal
$ sed -i 's/example/EXAMPLE/' sample.txt
sed: couldn't open temporary file ./sedxxx: Permission denied
```

## 対処法

次のようにバインドマウントをしていないディレクトリにファイルをコピーします。
その後そのファイルに対して`sed -i`を実行しオリジナルのファイルにその内容をコピーして戻します。

```terminal
$ cp ./sample.txt /tmp/sample.txt
$ sed -i 's/example/EXAMPLE/' /tmp/sample.txt
$ cp -f /tmp/sample.txt ./sample.txt
```

または次のように`-i`オプションを使用しないようにします。

```terminal
$ sed 's/example/EXAMPLE/' ./sample.txt > ./sample.txt.tmp
$ mv -f ./sample.txt.tmp ./sample.txt
```

## 参考

https://forums.docker.com/t/sed-couldnt-open-temporary-file-xyz-permission-denied-when-using-virtiofs/125473
Pythonでお手軽音声合成が可能なgTTSモジュール

備忘録です。

# gTTSとは
gTTSはPythonで音声合成ができるモジュールです。
文字列を音声に変換できます。
ちなみにgTTSはGoogle Text-to-Speechの略です。

下記はColabで実行の想定です。

# インストール
```
!pip install gTTS
```

# import
```gtts_test.ipynb
from gtts import gTTS
import IPython.display
```

# 文字列を音声に変換
```gtts_test.ipynb
message = "こんばんは。テストです。"
tts = gTTS(message, lang='ja') 
tts.save('gTTS_test.mp3')
```

# 音声データを埋め込む
```gtts_test.ipynb
IPython.display.Audio('gTTS_test.mp3')
```
以上でお手軽に音声合成ができます。
とりあえず音声合成を使用したい時に便利です。

# 注意点
[ドキュメント](https://gtts.readthedocs.io/en/latest/index.html)を確認したところ、mp3しか作成出来ないみたいなので注意です(wav等は作成できません)。

# ちなみに
この記事は上記注意点を書きたかっただけみたいなところあります(wavファイルを作成している記事が見受けられたりしたので…)。
Python全く分からん自分のアウトプット　その8

8日目：今日はPythonコース5やっていくぞい！！…の前に
今回もgoogleColab使ってみた。仕事している時に一枚一枚画像のリサイズすんのめんどくせ〜って思ってた時にふと「こーれPythonで作れるワンチャンあります(ニュータイプ音)」って口に出てた。
そうと決まれば早速やってみるぜって感じのノリで調べ調べやってみた結果、パスとかが見つからないエラーが出たりしたけど形には出来た。
明日職場で一緒に仕事してる人に使ってみてもらって感想聞いてみるZE🌟

それじゃやっていくぜ！！！！！


◎以下調べたこと、疑問に思ったこととかのメモ◎

子クラス、親クラス・・・HTMLの親要素子要素みたいなもんか？

オーバーライド・・・親クラスにあるメソッドを子クラスで定義するとメソッドを上書きできる。オーバーライド！ドラゴニックオーバーロード・ザ・グレート！！みたいな感じ(突然のVG、好きなんですグレート)

戻り値は「return」←復習

super()・・・親クラスを呼び出せる。「super().メソッド名()」で親クラスに定義したインスタンスメソッドをそのまま利用できる。同じコードを何回も書かなくて済むからめっちゃ便利、らしい。


-------------------------------------------------------


ひとまずPythonコース1周目終わった。2周目に突入するぜ！！(フロムゲーか？)
今回1周目は結構時間かかったけど、2周目はもう少しスムーズに進められるようになってるといいなあじゃねえなるんだよ。
仕事に活かせるようなプログラムも思いつき次第メモして作ってみようと思う。
とりあえず1周目、お疲れ様でした！！！！！
配列のなかで、一番最初に見つけた要素を削除する関数を再帰で書いてみた

簡単に書くとこうなってほしい。

```TypeScript
const list1 = [1, 2, 3, 1];
const target1 = 1;
const result1 = removeFirstItem(list1, target1);
console.log(result1); // [2, 3, 1]

const list2 = ["a", "b", "c", "a"];
const target2 = "a";
const result2 = removeFirstItem(list2, target2);
console.log(result2); // ["b", "c", "a"];

```

```TypeScript
const removeFirstItem = <T>(list: T[], target: T): T[] => {
	/* この前教えてもらった技で補助関数にしてみた */
	const rec = (rest: T[], inspectedList: T[]): T[] => {
		/* この前教えてもらった技でheadとtailに分割してみた */
		const [head, ...tail] = rest;

		/*
		  head === undefined,つまり最後まで調べ終わったら検査済みを返す。
			(この場合、tailは空なのでたさなくても良いのだが2回if書くのがめんどいので足して返した)
			現在の検査対象(head)と与えられたもの(target)が一致したときは検査済み＋検査残りを返す。
		*/
		if (head === undefined || JSON.stringify(head) === JSON.stringify(target))
			return [...inspectedList, ...tail];

		/* 一致しなかったときは残り(tail)を返し、今回の検査対象(head)を検査済みリストに足す */
		return rec(tail, [...inspectedList, head]);
	};

	/* 補助関数のおかげで、removeFirstItem関数に要らん配列を渡さなくてよろしいのだ*/
	return rec(list, []);
};


```

findIndexで愚直にやるとこんな感じ。破壊的なのがなんだかなぁ。
spliceが非破壊的だったらいいのに。
```TypeScript
const removeFirstItem2 = <T>(list: T[], target: T) => {
	const fIndex = list.findIndex((x) => JSON.stringify(x) === JSON.stringify(target));
	if (fIndex === -1) return list;
	const nextList = [...list];
	nextList.splice(fIndex, 1);
	return nextList;
};
```

よく考えたらfilterでよろしいな
まあめっちゃ長い配列だと、index合致したやつの処理が終わったあとでもループがつづいてしまう気がする。
そういうときは再帰が有利か。
というかfindIndexとfilterで2回ループしてるか……。
```TypeScript
const removeFirstItem3 = <T>(list: T[], target: T) => {
	/* 同じ要素のindexを探す */
	const fIndex = list.findIndex((x) => JSON.stringify(x) === JSON.stringify(target));
	/* ないときはlistを返す。あったらfilterでindexが合致したものを取り除く */
	return fIndex === -1 ? list : list.filter((_, i) => i !== fIndex);
};
```
【エンジニア必須】Linuxについて。よく使うLinuxコマンド一覧！

# はじめに

こんにちは！今回はLinuxについて語っていきます！
自身の備忘録になるので、自分流の言葉でやっていきます。
それでは行きましょう！

# Linuxとは何ぞや？？
LinuxはOS（Operating System）といわれる基本ソフトウェアの一種です。
他の代表的なOSとしては、Windows、Macなどがあげられます。
このOSとはソフトウェアとハードウェアをつなげるもので、OSがあるからこそハードウェアを用いて様々なデータを取り扱うことができています。

Linuxは無料で使える事がメリットです。
こちらのペンギンがLinuxのマスコットです。
タックスという名前らしいです。可愛いですね。
![images.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2975065/aaf22e49-bf35-598f-a961-9f94d2149e7a.jpeg)

さて、Linuxの簡単な解説が終わったので、
よく使うコマンドを紹介します。

まずコマンドの前にGUIとCUIの意味を説明します。
パソコンのUI（操作画面）には、GUIとCUIの2種類があります。

GUIとは、メニュー、アイコン、ウィンドウなどが表示されているグラフィカル（絵画的）な操作画面のことで、WindowsやMacのパソコンはGUIです。

一方、CUIとは、メニューアイコンなどがない文字だけの操作画面のこと。Windowsに搭載されているコマンドプロンプトもCUIにあたります。
アイコンや画像をクリックして操作ができるGUIに対して、CUIではやりたいことをコマンド（命令文）で記述する必要があります。エンジニアっぽいあの画面ですね。
![download.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2975065/06e6e8bb-20d7-6b46-23f1-13f976065e4a.jpeg)

そのため、パソコン初心者にとっては難易度が高いのですが、キーボードだけで操作ができるため慣れてしまえばかなり操作を高速化することが可能です。
CUIを使いこなすことは処理の高速化や業務の効率化にもつながるため、エンジニアはLinuxを使ってCUIに慣れておくといいらしいです。

その時に使用するコマンドが少し独特なので、
今回解説したいと思います！では行きましょう！！

# Linuxコマンド一覧

|コマンド  |説明  |使用例  |
|---|---|---|
|cd   |ディレクトリ（フォルダ）に移動  |cd 移動したいフォルダ名  |
|ls  |フォルダの内容をリスト形式で表示する  |中身を見たいフォルダに移動して、ls  |
|mv  |ファイルを移動  |mv（移動元ファイル名/フォルダ名）（移動元ファイル名/フォルダ名）  |
|cp  |ファイルやフォルダをコピーする  |cp（移動元ファイル名/フォルダ名（移動先ファイル名/フォルダ名））  |
|clear  |消さずに画面をきれいにする  | - |
|mkdir  |フォルダを作成する  |mkdir フォルダ名  |
|touch  |ファイルを作成する  |touch ファイル名  |
|rmdir  |空のフォルダを削除する  |rmdir フォルダ名  |
|rm  |ファイルやフォルダを削除する  |rm ファイル名/フォルダ名  |
|pwd  |現在いる位置を表示する  |-  |
|find  |ファイルの検索をする  |find/-name ファイル名  |
|cat  |ファイルの内容を表示する  |cat ファイル名  |
|diff  |ファイルとファイルの内容の違いを表示する  |diff 旧ファイル名 新ファイル名  |
|grep  |指定した文字列がテキスト内に存在した場合その行を抽出する  |grep "検索したい文字"* ファイル名  |
|chmod  |ファイルやフォルダのアクセス制限を変更する  |chmod 権限ファイル名  |
|chown  |ファイルやフォルダのオーナーやグループを変更する  |chown 変更したいユーザー名 変更したいファイル名  |
|history  |コマンドの履歴を表示する  |-  |
|ln  |ファイルやフォルダにリンクを設定する  |ln リンク元ファイル名 リンク先ファイル名/フォルダ名  |
|man  |コマンドのマニュアルを表示する  |man コマンド  |
|apropos  |manページの内容を検索する  |apropos キーワード  |
|less  |テキストファイルを閲覧する  |less ファイル名  |
|more  |ライルをページ単位で閲覧する  |more ファイル名  |
|useradd/adduser  |ユーザーを新規作成する  | - |
|deluser  |ユーザーを削除する  | - |
|groupadd  |グループを新規作成する  |-  |
|chfn  |ユーザー情報を変更する  | - |
|free  |空きメモリや、使用中メモリを表示する  | - |
|last  |最近ログインしたユーザー名を表示する  | - |
|finger  |ユーザー情報を表示する  |-  |
|route  |ルーティングの表示や設定を行う  |-  |
|ftp  |ファイルをFTPで転送する  |-  |
|ssh  |sshでログインする  |-  |


ショートカットキーも併せて解説します！
|ショートカットキー  |説明  |
|---|---|
|↑↓ |コマンド履歴を順に表示  |
|tabキー  |フォルダやファイル名の予測変換  |
|Ctr(control) + a  |カーソルを先頭に  |
|Ctr + b  |カーソルを一文字戻す  |
|Ctr + f |カーソルを一文字進める  |
|Ctr + d  |カーソル位置の文字を消す  |
|Ctr + h  |カーソル位置の左側の文字を消す  |
|Ctr + w  |カーソル位置の左側の単語を消す  |
|Ctr + r  |コマンド履歴の中で検索する  |

# さいごに
Linuxの説明、コマンドの説明は以上になります！
参考にしていただければ幸いです！
ご視聴頂きありがとうございました！
Leetcode 1507. Reformat Date

https://leetcode.com/problems/reformat-date/description/



```java
class Solution {
    public String reformatDate(String date) {
        String[] dates = date.split(" ");

        HashMap<String, String> month = new HashMap<>();

        month.put("Jan", "01");
        month.put("Feb", "02");
        month.put("Mar", "03");
        month.put("Apr", "04");
        month.put("May", "05");
        month.put("Jun", "06");
        month.put("Jul", "07");
        month.put("Aug", "08");
        month.put("Sep", "09");
        month.put("Oct", "10");
        month.put("Nov", "11");
        month.put("Dec", "12");

        String day = "";
        if (dates[0].length() == 4) {
            day = dates[0].substring(0, 2);
        }
        if (dates[0].length() == 3) {
            day = dates[0].substring(0, 1);
            day = "0" + day;
        }
        return dates[2] + "-" + month.get(dates[1]) + "-" + day;
    }
}
```
ulタグに発生する左端の余白

ulタグはリストを作るためのタグであり、左側に余白が必然的に生じる。

# ulタグで左側に発生する余白をなくす方法
``
padding-left:0px
``

## 横並びのリストを中央寄せする方法

``
ul{
  display: flex;
  padding-left: 0px;
  justify-content: center;
}
``
Terraform の azapi を使ってみた


# やりたいこと

Azure で Terraform を使っていて、AzAPI なるものがあることを知ったので、調べた内容を備忘録も兼ねてここにまとめます。

# AzAPI とは

https://learn.microsoft.com/ja-jp/azure/developer/terraform/overview-azapi-provider

公式ドキュメントより
> AzAPI プロバイダーは、 Azure ARM REST API の上にある薄いレイヤーです。 AzAPI プロバイダーを使用すると、任意の API バージョンを使用して任意の Azure リソースの種類を管理できます。 このプロバイダーは、新しい Azure リソースとプロパティ (プライベート プレビューを含む) の管理を有効にすることで、AzureRM プロバイダーを補完します。

そもそも、Terraform は HCL (HashiCorp Configuration Language) という専用の記述言語で、作成すべきリソースを定義していく。
HCL は、Azure や GCP、AWS などが提供する[プロバイダー](https://developer.hashicorp.com/terraform/language/providers)を利用していて、その実体は、各クラウドの API を呼んでいるだけ (と思っている) なので、プレビュー段階のサービスはまだその API を Terraform から使えないことが多い。
AzAPI はそういったプレビュー段階のサービスも Terraform から作成できるようにするもの、というのが個人的な理解。Azure のリソースプロバイダー (AzureRM) よりさらに API に近い部分のラッパー的な位置づけ。

公式ドキュメント内では、以下の利点があると述べている。

> AzAPI プロバイダーには、次のような利点があります。
> * すべての Azure サービスをサポートします。
>   * プライベート プレビュー サービスと機能
>   * パブリック プレビュー サービスと機能
>   * すべての API のバージョン
> * 完全な Terraform 状態ファイルの忠実性
>   * プロパティと値は状態に保存
> * Swagger への依存関係なし
> * 一般的で一貫性のある Azure 認証

プレビュー段階の間は AzAPI プロバイダーを、正式リリースされれば AzureRM プロバイダーを使うことを推奨している。

# AzAPI の使い方

https://learn.microsoft.com/ja-jp/azure/developer/terraform/get-started-azapi-resource

基本的には一般的な Terraform の使い方と変わらないが、事前準備として、AzAPI を登録してあげる必要がある。
具体的には、`terraform` ブロック内のプロバイダー定義に `azapi` を以下のように追加する。その後、`terraform init` すれば、`terraform plan` や `terraform apply` できるようになる。

```terraform
terraform {
  required_providers {
    azapi = {
      source  = "azure/azapi"
      version = "=0.1.0"
    }
    azurerm = {
      source  = "hashicorp/azurerm"
      version = "=3.0.2"
    }
  }
}

```

ただし、実際のリソース定義は一般的な Terraform での書き方と少し異なる。
例として、以下。

```terraform
# Provision a Lab Service Account and a Lab that are in public preview
resource "azapi_resource" "qs101-account" {
  type      = "Microsoft.LabServices/labaccounts@2018-10-15"
  name      = "qs101LabAccount"
  parent_id = azurerm_resource_group.qs101.id

  body = jsonencode({
    properties = {
      enabledRegionSelection = false
    }
  })
}
```

AzAPI で作成するリソースについては、すべて `azapi_resource` にする。リソース名 (`"qs101-account"` の部分) は通常どおり。
`type` や `name` などは任意で指定するが、注意点として `type` には API のバージョンを指定する必要がある (`@2018-10-15` の部分)。プレビュー状態のものは、日付の後に `-preview` と付く。
各 AzAPI の仕様については、[ここ](https://learn.microsoft.com/ja-jp/azure/templates/)。

# ということで

リソースプロバイダーが未提供のリソースも Terraform で作成して管理できるようになった。AzAPI を知る前は、そういったリソースだけ手動でポチポチ作成していたので、だいぶ楽になった。
ただ、AzureRM で提供されるリソースとは種類が異なり、リソースから取得できるプロパティが限られているので、使いたい情報 (接続文字列など) を Terraform のコード内で完結できないことはある。
今回、そもそも Azure の Communication Services E-mail (プレビュー) を使いたかったが、プレビュー段階なので AzureRM が対応しておらず手動で作成していた。それを AzAPI で作成できるようにはなったが、作成されたドメインを Terraform のコード内で、Function Apps のアプリケーション設定に渡すことができなかった。というような手の届かなさはある。でもそれはプレビューなんだから当然！

以上です。
Dockerコンテナ上で立てた開発サーバに別端末でアクセスする方法

# はじめに

Dockerコンテナで開発サーバを立てた時、http\://localhost:3000とあるからスマホでhttp\://localhost:3000って入力してるのにアクセス出来ないよ！ となります。割と当たり前の話ではありますが、じゃあどうすればいいの？と後輩に聞かれた時のためのチートシートです。

# 要約

理論なんてどうでもいいから方法を教えろ！という方のために。

1. docker-compose.ymlの中のサービス名の中のportsオプションに`"ports":"8000:3000"`を指定する。(もちろん`"ports":"3000:3000"`でいいが、どのポートにどのポートが対応しているか分かりやすくするために今回は`"ports":"8000:3000"`を指定する。)
2. Windowsならshellで`ipconfig`、Macなら`ifconfig`を実行し、IPv4アドレスをコピーする。
3. Dockerコンテナ上で開発サーバーをhttp\://0.0.0.0:3000で立てる。
4. Dockerを起動したPCと同一ネットワーク上に接続されている別端末でhttp\://<2.で調べたアドレス>:8000をブラウザのURL欄に入力

# 対象読者

インフラ関係全然わからん、IPアドレスってネットの住所ってことくらいは知ってるよという人。

# 本文

タイトルはDocker関連の話ですが、本文はほとんどWebの基礎知識についての話題になります。先述したように、理論はどうでもいいという方は要約を読んでください。

ただし、Dockerネットワークについては結構踏み込んだ話題となり、少し長くなりすぎるのでここでは説明しません。あくまで目標はDockerのUbuntuコンテナで立てた開発サーバに、実機端末でアクセスすることとします。また、理解しやすいように一部簡略化しています。

ちなみに、[これ](https://qiita.com/amuyikam/items/0063df223aed40193ba9)を読むと全て解決します。

## 特別なIPアドレス

プライベートIPアドレスとグローバルIPアドレスの説明については省きます。よく分からない方は[このあたり](https://www.infraexpert.com/study/ip5.html)を読んでください。

ここで、プライベートIPアドレスの中で特別なものが存在し、0.0.0.0と、127.0.0.1の2つがあります。

### 0.0.0.0

基本的に無効なIPアドレスですが、開発サーバとしてhttp:\//0.0.0.0上に立てた場合に限り、**同一ネットワーク上にある全てのデバイスからアクセス可能**なサーバーになります。同一ネットワーク上のデバイス全てに対するネットワークインターフェースを持つ、と言ったりします。

つまるところ、同じWiFiに繋がっていれば、別端末でもアクセス可能になるということです。

しかし、その際にはホスト側のPCのIPアドレスに接続すべきで、0.0.0.0にアクセスするとOSによっては(というかWindowsの場合)アクセスできません。

### 127.0.0.1

このIPアドレスに馴染みがなくとも、localhostという単語に聞き覚えはあるのではないでしょうか。localhostを名前解決する(ドメイン -> IPアドレスへと変換することです。このことをDNSと呼びます。)と127.0.0.1となります。

そして、この127.0.0.1とは**ループバックアドレス**と呼び、自分 -> 自分へのアクセスを指すことになります。ループバック、という単語と意味の対応がしやすいと思います。だから、WindowsPC(Dockerではなく、本当にWindowsのローカル環境)で開発サーバをhttp\://localhostと立てた際には、同じWindowsPCでhttp\://localhostとアクセスすることで開発サーバにアクセスできるようになる、ということです。

そして、重要なのが127.0.0.1は同一ホスト内の通信しか許可しません(ネットワークインターフェースは自分のみ)。なので、開発サーバをhttp\://127.0.0.1で立てた場合、別端末からそのサーバにアクセスすることはできません。

---

## docker run -p 8000:3000の意味

そして、docker runの際に指定する`-p 8000:3000`はちょっと調べただけだと、「ポート開放」のためだとか、「ポートフォワーディング」のためだとか、分かっている人向けへの説明しかないですが、これは**ホストPCの8000番ポートへの通信は全てコンテナの3000番ポートへ流す**というオプションになります。

だから、ホストPCがhttp\://localhost:8000とアクセスすると、これはコンテナの3000番ポートへのアクセスへと流すということになります。

(内部的にはiptablesのテーブルを変更しています。が、冗長になるのでここでは説明しません。)

---

ここまで読めば、大体なぜ[要約](#要約)のようにすることで実機端末でアクセスできるか分かると思います。

最初の要約と対応させて以下の箇条書きを読んでください。

1. ホストPCの8000番ポートへのアクセスをコンテナの3000番ポートへのアクセスに流すオプションを付けてコンテナを起動。
2. ホストPCのIPアドレスを取得。
3. コンテナ側で0.0.0.0:3000でサーバを起動。
4. スマホでホストPCの8000番ポートへとアクセス -> コンテナの3000番ポートへとアクセスを流すことで開発サーバを確認できる

> 1. docker-compose.ymlの中のサービス名の中のportsオプションに`"ports":"8000:3000"`を指定する。(もちろん`"ports":"3000:3000"`でいいが、どのポートにどのポートが対応しているか分かりやすくするために今回は`"ports":"8000:3000"`を指定する。)
> 2. Windowsならshellで`ipconfig`、Macなら`ifconfig`を実行し、IPv4アドレスをコピーする。
> 3. Dockerコンテナ上で開発サーバーをhttp:\//0.0.0.0:3000で立てる。
> 4. Dockerを起動したPCと同一ネットワーク上に接続されている別端末でhttp\://<2.で調べたアドレス>:8000をブラウザのURL欄に入力

何か間違っている事があればコメントをお願いします…


# 参考文献

[0.0.0.0にはアクセスしないこと](https://qiita.com/amuyikam/items/0)
金融データ活用チャレンジに挑戦してみた。

# 〈はじめに〉
こんにちは、Data Science League エンジニアリング代表オオキ、エンジニア エザワです。
このたび、一般社団法人金融データ活用推進協会（FDUA）様が主催する《[第1回金融データ活用チャレンジ](https://signate.jp/competitions/841"第1回金融データ活用チャレンジ")》にDSLから支部を含め、4チームが参加させていただきました。

https://signate.jp/competitions/841

https://www.fdua.org/lp38.html

# 〈金融データ活用チャレンジとは〉
実際の金融機関保有データを模した、実データを基にAIアルゴリズムによって作成された架空のデータを用いて競うデータ分析コンペティションです。
今回の課題は「 **住宅ローン契約者の分析** 」でした。内容としては、「顧客の属性情報や銀行口座の入出金、預金残高などの金融データを用いて延滞の予測モデルを構築し、その顧客が3か月後から **連続して延滞するかどうかを予測する** 」というもので、評価指標はAUCです。

本コンペではDatabricksという統合データ分析基盤を使用します。データやチュートリアルはDatabricks上で取得できたので、「ダウンロード→アップロード」などの作業がなく楽でした。

# 〈予測までの流れ〉
ルールの実装方法に書いてある通り、以下のように行います。
##### 1. Preprocessing（前処理）
ここで日付データに直したり、特徴量を生成したりします。説明変数はATMの使用回数、振込入出金金額など銀行口座に関するデータが多く、チームメンバーが全員大学生だったこともありどのような特徴量を作成するべきか全然分かりませんでした。しかし、本コンペの公式Slackワークスペースがあり、銀行や金融系企業で働いている方々の考え方や、やりとりを見ることができてとても参考になりました。
##### 2. Learning（学習）
今回はLightGBMを使用しました。この文章を書いているエザワは初めてLightGBMの実装をしたのですが、精度が良すぎて驚きました。すごいです。
##### 3. Predicting（予測）
2.で学習をしたモデルを使用して予測結果を出力します。大抵このまま提出をしてしまうのですが、10回に1回くらい「提出した結果エラーだったよ」というメールが届き悲しくなります（提出が完了すると評価結果がメールで届きます）。見直しは大切ですね。


# 〈チュートリアルについて〉
本コンペでは5つのチュートリアルがありました。

* Databricksにおけるデータ操作
* Databricksにおける機械学習モデルの訓練
* 提出方法
* 分析例×２

Databricksは今回初めて使用したのですが、このチュートリアルと公式Slackのおかげで何とかなりました。
また、チュートリアルを全て終えると0.89くらいのスコアが出るので、初心者にとってはこれだけで嬉しく満足でした。

# <特徴量について>
今回、特徴量に振り回されています。
特徴量を工夫したら一度大幅にスコアが上がりとても嬉しくなったのですが、その後は下がる一方です。
給与振込口座として使用しているかどうか、などもやってみましたがそもそもが不均衡データなので極端にデータ数が少なくなってしまったこともあり上手くいかず。難しい。

# <参考にした記事・本など>
**1. 【FDUA】第一回金融データ活用チャレンジの戦い方を考える** 
コードが前処理・学習・予測と全て書いてあり、とても参考になりました。

https://takaito0423.hatenablog.com/entry/2023/02/03/212539


**2. 【FDUA】第一回金融データ活用チャレンジをやってみている**
Databricks上でのAutoMLの使い方がわからなかったのでとても参考になりました。

https://qiita.com/isanakamishiro2/items/477fa0df6c5b69c77a1b


**3. Kaggleで勝つデータ分析の技術**
今回は辞書的に使用しました。

https://gihyo.jp/book/2019/978-4-297-10843-4


# <その他・感想>
今回、初めてsparkを使用したのですが、データがどのような特性を持っているかを見る際に可視化されていてとても便利でした。欠損値の割合、ゼロの割合、分布などなど。
今まではまだ技術力がないことを言い訳にしてコンペに出ていなかったのですが、今回は勢いで参加しました。チュートリアルはとても親切で、Slackを見ればドメイン知識に長けた方々がいるという最高の環境でとても勉強になりました。あと数日間ですが最後の追い込みを頑張ろうと思います。
ROS2でPythonノードを作る(備忘録)【ROS2】

# 概要
PythonでしかROS2ノードを書けない筆者が残した備忘録です。

Zennで書いてしまいましたが、Qiitaの方が検索が引っかかるということで、Zennリンクだけ貼っておきます。

https://zenn.dev/mol0921/articles/f8b789d90abb35
SSL証明書の有効期限を調べるコマンド


プロジェクトのSSL証明書は`/etc/letsencrypt/archive`に保存されています。

証明書を更新するたびに証明書が増えて、`cert.pem`、`cert2.pem`、`cert3.pem`…と増えていきます。
（`/etc/letsencrypt/live/example.com/`には最新のものへのシンボリックリンクが保存される）
証明書の有効期限を知りたいことがありました。

その場合のコマンドをメモしておきます。
`cert3.pem`の有効期限を知りたい場合↓
```
[user@ip-172-8-0-10 example.com]$ cd /etc/letsencrypt/archive/example.com
[user@ip-172-8-0-10 example.com]$ openssl x509 -noout -subject -dates -in cert3.pem
subject= /CN=example.com
notBefore=Jan 14 17:32:01 2023 GMT
notAfter=Apr 14 17:32:00 2023 GMT
```

`notBefore`が有効になった日時、`notAfter`が有効期限の日時。

参考：

https://beyondjapan.com/blog/2022/09/how-opensslx509/#_openssl_x509_-noout_-subject_-dates
RubyでTokenizersを使う

ChatGPTが流行して、Rubyで[OpenAI API](https://github.com/alexrudall/ruby-openai)を呼び出したりするときに、Tokenが気になる人もいるかも知れない。
そんなときのために、バインディングをAnkaneさんがちゃんとGemを作ってくれている。

こちらは、[huggingface/tokenizers](https://github.com/huggingface/tokenizers) のRubyバインディングだ。

https://github.com/ankane/tokenizers-ruby

```ruby
s = "In a hole in the ground there lived a hobbit."
tokenizer = Tokenizers.from_pretrained("gpt2")
ids = tokenizer.encode(s).ids
tokenizer.decode(ids)
```

Tokenの数を数える。

```ruby
tokenizer = Tokenizers.from_pretrained('gpt2')
encoded = tokenizer.encode(prompt, add_special_tokens: true)
prompt_tokens = encoded.tokens.length
```

もうひとつ、blingfireというのもある。これはMicrosoftの[BlingFire](https://github.com/microsoft/BlingFire)のバインディングだ。

https://github.com/ankane/blingfire-ruby

```ruby
s = "In a hole in the ground there lived a hobbit."
encoder = BlingFire.load_model('gpt2.bin')
decoder = BlingFire.load_model('gpt2.i2w')
ids = encoder.text_to_ids(s)
decoder.ids_to_text(ids)
```

GPT-2のTokenとGPT-3とは互換であるようだ。

tokenizers-ruby はRust製だ。
blingfire-ruby はWindowsでも動く。

## tiktoken

最近はtiktokenというライブラリもあり、バインディングを開発する動きもいくつかある。

https://github.com/IAPark/tiktoken_ruby

```ruby
require 'tiktoken_ruby'

enc = Tiktoken.encoding_for_model("gpt-4")
enc.encode("hello world").length #=> 2
```

https://github.com/volition-co/tiktoken

この記事は以上です。
vimの基本操作について

エンジニアなら使えるようになりたいvimの基本操作についてまとめていきます。

# 基本動作
Insert Mode : `i`
Normal Mode : `esc`
Command Mode : `:`
↑に移動 : `k`
↓に移動 : `j`
←に移動 : `h`
→に移動 : `l`
次の文字からInsert Mode : `a`

# ファイルの保存
保存して終了 : `:wq`
保存しないで終了 : `:q!`
上書き保存 : `:w`
編集終了 : `:q`
viewモードで起動 : `view`

# 削除系
1文字削除 : `x`
1行削除 : `dd`
単語の削除 : `dw`
2行削除 : `2dd`
戻る : `u`
進む : `Control + r`

# コピー&ペースト
1行コピー : `yy`
2行コピー : `2yy`
下にペースト : `p`
現在の行にペースト : `P`
リピート : `.`

# 移動
10行目に移動 : `:10`
行末に移動 : `$(shift + 4)`
先頭に移動 : `0`
インテントに移動 : `^`
段落ごとに上に移動 : `{`
段落ごとに下に移動 : `}`
セクションごとに上に移動 : `[[`
セクションごとに下に移動 : `]]`

# 検索
wordを検索 : `/word`
次の検索結果に移動 : `n`
前の検索結果位に移動 : `N`
置換 : `R`
一括置換 : `:%s/search/replace/g`
確認しながら置換 : `:%s/search/replace/gc`

# Visual Modeやインテント
選択行の下に空白を入れ、インサートモード : `o`
選択行に空白を入れ、インサートモード : `O`
行に連結 : `J`
右にインテントを移動 : `>`
左にインテントを移動 : `<`
カーソル指定コピー : `i(Visual Mode)移動してからy(コピー)`
【Swift】アプリ内でSafariを起動する（SFSafariViewController）

アプリ内でSafariを起動する方法
# 環境
macOS Monterey バージョン 12.6.3
Xcode バージョン 14.2 

# コード
``` swift: ViewController.swift
import SafariServices
```
SafariServicesを忘れずに
``` swift: ViewController.swift
    func openSafari() {
        let url = URL(string: "https://qiita.com/")
        if let url = url {
            let vc = SFSafariViewController(url: url)
            self.present(vc, animated: true, completion: nil)
        }
    }
```

### Delegate
`SFSafariViewControllerDelegate` があります。
ユーザーがSafari内の共有ボタン（Action button）を触った時の共有アイテムも指定できそうです。

# 公式ドキュメント
[SFSafariViewController](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller "SFSafariViewController")
[保存版] AVAudioRecorderのAVFormatIDKeyの指定方法まとめ

以下は対応するAVFormatIDKeyとファイル拡張子の組み合わせです。
```swift
mp3: kAudioFormatMPEGLayer3
m4a: kAudioFormatMPEG4AAC
aiff: kAudioFormatLinearPCM
caf: kAudioFormatAppleLossless
wav: kAudioFormatLinearPCM
```

コード内で使用する場合は、以下のように記述します。

```swift
let fileExtension = "mp3"
let formatID: AVAudioFormatID

switch fileExtension {
case "mp3":
    formatID = kAudioFormatMPEGLayer3
case "m4a":
    formatID = kAudioFormatMPEG4AAC
case "aiff":
    formatID = kAudioFormatLinearPCM
case "caf":
    formatID = kAudioFormatAppleLossless
case "wav":
    formatID = kAudioFormatLinearPCM
default:
    formatID = kAudioFormatLinearPCM
}

// ここから先は formatID を使用して AVAudioRecorder を設定する処理が続く

```



このように、ファイル拡張子に対応するAVFormatIDKeyをswitch文で判別することで、それに対応したAVAudioRecorderを設定することができます。
ファイルメーカーのススメ+Ruby on Rails

# はじめに
- この記事は仕事で感じたファイルメーカーの良さ、苦手な部分についてと、Railsについての感想を書きました。

この記事は筆者のレベルアップと共に今後更新する可能性があります。

筆者：社内SE（休職中）,ファイルメーカー歴6年, 仕事でファイルメーカーを動かしている規模（同時接続200程）,Ruby on Rails 4ヶ月,プログラミングスクール卒業(2023/3現在)

# 目次
1. [こういうパターンならファイルメーカー](#Chapter1)
1. [ファイルメーカーの苦手な所](#Chapter2)
1. [Ruby On Railsの凄さ](#Chapter3)
1. [最後に](#Chapter4)

<!-- 各チャプター -->
<a id="#Chapter1"></a>
# こういうパターンならファイルメーカーがおすすめ
偉い人「社内で使用するアプリを作成して欲しい。とにかく短期間でお願い、機能は最低限でいい。とにかく早く始めたい。」
という無茶振りがあったとします。こんな時に威力を発揮するのがファイルメーカーです。

ファイルメーカーはapple子会社のクラリスが開発したデータベースソフトです。


https://www.claris.com/ja/

詳細は公式サイトを見て下さい。


今回のケースではオンプレミス（物理サーバーを設置）で　windowsサーバーにファイルメーカーサーバーをインストールし、クライアントはPCの場合ファイルメーカーproをインストール、ipadはファイルメーカーgoでアクセスするとします。


ファイルメーカーには次の特徴があります。
- ファイルメーカーサーバーでホストしている場合、マウントしているファイルは**停止せずにそのまま修正可能**
- **直感的**にアプリケーションを作成出来る
- 本番環境へのデプロイが容易（作成したファイルを本番環境で動かす事が簡単、ファイルメーカーサーバーがマウントするフォルダに置くだけ＋少しの設定）
- ローコードの為、習得が容易（プログラミンング言語に比べて）
- データのバックアップが容易、復元が容易い。
- ファイルメーカーサーバーの管理が容易（GUIでほぼ設定可能）
- 帳票などのレイアウトが作成しやすい（Excelでレイアウトを作成するのとほぼ変わらない）


以上の特徴から社内で小規模〜中規模で使用する場合は無類の強さを発揮します。特に直感的に作成出来る点、サーバーを停止する事なく修正を行える点（データベース構造が大幅に変わる場合は停めます。）は社内の支援ツールのような**変更の多いシステム**ではスピーディーに開発・修正対応が可能で保守を行う側からするとかなり使いやすいです。又ローコードの為、**内製化しやすく**0から教育しても短期間で習得可能な点が大きいです。



<a id="#Chapter2"></a>
# ファイルメーカーの苦手な所


スピード開発・修正が可能なファイルメーカーですが、次のような部分を考える必要があります。

- オンプレミスの場合、アクセスするだけでもライセンスが必要であり、**不特定多数に展開する**にはライセンスのコストを考慮しなければならない。ボリュームライセンスなし時の価格は1ライセンス買い切り版 6万円超 （2023/3現在）

＊不特定多数の場合ファイルメーカーcloudというものがあるが、サブスク的なコストが見合うかどうかは規模次第。


https://www.claris.com/ja/filemaker/cloud/


- ファイルメーカーに元々ない機能は、**プログラミング言語でプラグインを開発しなければならない**
- ファイルメーカーで**web連携したい場合**（例えばgooglemap等使いたい場合）レイアウトにwebビューワー（ブラウザみたいなもの）を埋め込む事は可能であるが、動作が安定しない。（クライアントのブラウザ依存になる為）
- webdirectというファイルメーカーをwebホストする機能があるが、制限がある（特定のスクリプトが動かない等）この形態を選択してもライセンス問題は解決しない。（費用が発生する）

以上の特徴からファイルメーカーは、**対象者と機能が限定されている場合にフットワーク重視で選択する**事が望ましいと思っています。（ガチガチに大規模で使っている所を否定している訳ではありません。私もファイルメーカーは大好きですので）




<a id="##Chapter3"></a>
# Ruby On Railsの凄さ

ファイルメーカーだけを触ってきた私（と言ってもそこまで深くはないと思いますが）にとってはRuby On Railsは衝撃的でした。Railsを選んだ理由は、ファイルメーカーで対応出来ない部分を解消出来ないかと考えた事、開発スピードが早いとネット記事で見た為でした。実際に学んでみて、ローコードと違って奥深い点、高い生産性、分かりやすい構造に魅力を感じています。

以下ファイルメーカー使用者から見た感想です。

- 規約に沿って書く必要はあるものの、少ないコード量でWEBアプリケーションが作成出来る
- ruby自体がスタイリッシュな為、表現がわかりやすい
- Webアプリケーションに特化している為、不特定多数で利用可能（webアプリだから当たり前か）
- 無料で開発出来る!　(これも何気に凄い)
- gemを使って色々拡張出来る！　← ファイルメーカーのプラグインは開発しないとない

<a id="##Chapter4"></a>
# 最後に

現在はファイルメーカーよりプログラミング全般に傾倒していますが、
ファイルメーカーとRailsを使って何か活用出来ないか考えています。思いついたら記事を書こうと思います。次はプログラミングスクールで作成した卒業課題(Rails×Vue.js)について記事を書きます。


ファイルメーカーに興味を持った方こちらのサンプルが面白いのでぜひ見て下さい

https://content.claris.com/jpapps
AVEncoderAudioQualityKey このキーの設定方法

AVEncoderAudioQualityKeyは、録音された音声の品質を指定するキーです。値としては、AVAudioQuality列挙型の値を指定します。

以下は、AVAudioRecorderの設定例で、音声品質をhighに設定しています。

```swift

let audioSession = AVAudioSession.sharedInstance()
do {
    try audioSession.setCategory(.playAndRecord, mode: .default, options: [])
    try audioSession.setActive(true)
    let settings: [String: Any] = [
        AVFormatIDKey: Int(kAudioFormatMPEG4AAC),
        AVSampleRateKey: 44100,
        AVNumberOfChannelsKey: 2,
        AVEncoderAudioQualityKey: AVAudioQuality.high.rawValue
    ]
    audioRecorder = try AVAudioRecorder(url: audioFilename, settings: settings)
} catch {
    print("Error setting up audio session or recorder: \(error.localizedDescription)")
}
```


AVEncoderAudioQualityKeyの値には、.min、.low、.medium、.high、.maxのいずれかが指定可能で、それぞれ以下のような品質に対応します。

.min: 最低品質
.low: 低品質
.medium: 中品質
.high: 高品質
.max: 最高品質
上記の例では、.highを指定しているため、音声品質が高くなります。ただし、高品質なほどファイルサイズが大きくなるため、目的に応じて適切な品質を選択する必要があります。

音声録音って重要な機能だから、しっかり覚えておきたいね！

さて、まずは音声録音の基礎を学ぼう！まずはAVAudioRecorderっていうクラスを使うんだ。これは音声の録音と再生を簡単に扱うことができるよ。AVAudioRecorderを使って録音するには、まず録音セッションの初期化を行う必要があるよ！ここでは、AVAudioSessionを使って録音セッションを初期化するよ！

そして、録音セッションを初期化したら、次はAVAudioRecorderのインスタンスを作成する必要があるよ！AVAudioRecorderを使って録音を開始するには、そのインスタンスを作成し、record()メソッドを呼び出す必要があるよ！

さらに、録音が終了したら、stop()メソッドを呼び出して、録音を停止する必要があるよ！

最後に、録音された音声データをファイルとして保存するには、AVAudioRecorderのインスタンスのfileURLプロパティに、保存先のファイルパスを指定する必要があるよ！

AVFormatIDKeyは、録音するファイルの形式を指定するキーだよ！mp3やm4a、wavなど様々な形式があるから、ファイル形式に合わせて指定してね！
AVEncoderAudioQualityKeyは、録音品質を指定するキーだよ！高品質にすると、ファイルサイズが大きくなっちゃうから、適度な品質に設定しよう！
AVSampleRateKeyは、サンプリングレートを指定するキーだよ！サンプリングレートが高いと音質が良くなるけど、ファイルサイズが大きくなっちゃうから注意してね！

次に、AVAudioRecorderで録音して、保存する方法を解説するよ〜！
まずは、録音するためのオブジェクトを作成するよ！そして、保存するためのパスを指定するよ！
録音が始まったら、ファイルを保存するよ！
これで録音と保存が完了したよ！簡単でしょ〜！



以上が、音声録音の基本的な手順だよ！音声録音は、慣れるまでちょっと難しいかもしれないけど、がんばって覚えよう！
5G Mobile routerにeSIMを入れる 

eSIM対応のWiFiルータが発売されたので買ってみて、Povo 2.0のeSIMにプロファイルをダウンロードして開通させてみました。
5G対応ルータWiFiルータ：富士ソフト　FS050W

https://twitter.com/nekokane/status/1631397559221764096?s=20


# 参考文献
[1]動作確認済 eSIM
　https://www.fsi.co.jp/mobile/plusF/confirmed/esim.html
[2]Povo　（auのサブブランド？） 
　https://povo.jp/
[3]5G対応ルータマニュアル
　https://www.fsi.co.jp/mobile/plusF/products/FS050W/index.html#download

## 前提
　物理SIMでFS050Wをオンラインにする。
　WiFi ON/インターネットOFFでアプリ経由でFS050Wにアクセス
　eSIMのダウンロード

## [1]動作確認済 eSIMを見てeSIMはPovo 2.0にしてみる。
　専用アプリをダウンロードして申し込み

## [2]Povo2.0を新規で、申し込みは専用アプリから。
・本人認証もeKYC(免許のコピーを送るのではなく、免許証を斜めにして厚みを見せて撮影したり、首を振ったりして本人確認するやつ）
・半日くらいで本人認証完了メールが届く
　・アプリにログイン
  ・eSIMの設定　QRコードをスクショ
　　SM＋DPアドレスは：SM-V4-012-A-GTM.PR.GO-ESIM.com
　　　go-esimっぽい。図は　https://www.esim-go.com/　より引用
　　　複数のSMDP＋サーバを管理するプラットフォームっぽい
　　　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/09e6739a-198b-0fc8-ac48-c8f5bca49140.png)

## [3]5G対応ルータマニュアルのeSIMのアクティベーション方法
　・FS050WとスマホをWiFiでつなぐ。
　・専用アプリ +FSmart APP起動
　・eSIM設定
　　・保存したPovoのQRコードをアプリに画像で読み込む
　　・失敗
　・色々して何とかeSIMダウンロードできた
　　・ファームウェアダウンロード
　　・何回かやってみる
　　・スマホのモバイル回線をOFF
　　・FS050Wに物理SIMを刺してみる
　・専用アプリで使用するSIMを eSIMに指定
　・無事開通！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2311625/136b4f88-eeec-06ff-ffad-cf3f2253264c.png)
いい加減にしたいSSHキー

# はじめに
最近なぜだかSSHキーを作る機会が多い。
その都度`'ed25519'`が思い出せず調べてるので見つけやすようにまとめておく。

# 参考

https://man.openbsd.org/ssh-keygen.1

# 本題

基本
```shell
ssh-keygen
```


タイプ指定
```shell
ssh-keygen -t [type]
```

type
```shell
#使わない
dsa
ecdsa
ecdsa-sk

#使う
ed25519
ed25519-sk
rsa
```

結局これ
```shell
ssh-keygen -t ed25519
```

ed25519無理ならこれ
```shell
ssh-keygen -t rsa -b 4096
```
`-b`はビット数の指定

## てか-skってなに(蛇足)

https://www.openssh.com/txt/release-8.2


>This release adds support for FIDO/U2F hardware authenticators to
OpenSSH. U2F/FIDO are open standards for inexpensive two-factor
authentication hardware that are widely used for website
authentication.  In OpenSSH FIDO devices are supported by new public
key types "ecdsa-sk" and "ed25519-sk", along with corresponding
certificate types.

Google様ぁ!!


>このリリースでは、FIDO/U2F ハードウェア オーセンティケータのサポートが
OpenSSH. U2F/FIDO は安価な 2 要素のオープン スタンダードです
Web サイトで広く使用されている認証ハードウェア
認証。OpenSSH FIDO デバイスでは、新しいパブリックによってサポートされています
キータイプ「ecdsa-sk」および「ed25519-sk」、および対応する
証明書の種類。

わからん!!
ChatGPT様ぁ!!
`ed25519とed25519-skの違いを教えてください!!`


>ed25519とed25519-skは両方とも、Edwards曲線を使用して構築された公開鍵暗号方式ですが、異なる目的に使用されます。
>
>ed25519は、暗号化や署名に使用される一般的なEdDSA（Edwards-curve Digital Signature Algorithm）の実装です。この方式は、高速で、安全で、シンプルな実装が可能であることが特徴です。ed25519は、RFC 8032で標準化されています。
>
>一方、ed25519-skは、ed25519のサブセットであり、セキュリティキーのみを提供します。これは、電子署名に使用されるのではなく、鍵派生のみに使用されます。この方法は、ブロックチェーン技術など、特定のセキュリティ要件を持つ分野で使用されます。SKは、「セキュリティキー（security key）」の略です。
>
>要約すると、ed25519は暗号化や電子署名に使用される一般的な実装であり、ed25519-skは、特定のセキュリティ要件を持つ分野で使用される鍵派生のためのサブセットです。


余計にわからんwww
`もっと簡単に教えて!!`

>ed25519とed25519-skは、どちらもEdwards曲線を使用して構築された暗号方式ですが、異なる目的に使用されます。
>
>ed25519は、一般的な電子署名に使用される方法で、高速で、安全で、シンプルな実装が可能です。
>
>一方、ed25519-skは、セキュリティキーのみを提供するサブセットで、電子署名に使用されることはありません。主に、特定のセキュリティ要件を持つ分野で使用される、鍵派生のための方法です。


こいつぁwww

### FIDO/U2F
Universal 2nd Factorなるものらしい。

https://wiki.archlinux.jp/index.php/Universal_2nd_Factor

>Universal 2nd Factor (U2F) はスマートカードと同様のセキュリティ技術に基づいて、専用の USB または NFC デバイスを使用した二要素認証 (2FA) を強化、簡素化するためのオープンスタンダードです。

さっきのやつに`FIDO/U2F hardware authenticators`って書いてたしハードで認証しちゃおうみたいな感じのやつですかね？

じゃあ結局`ed25519`でいいんですよね？！
誰かに怒られるまでは`ed25519`でいっちゃうよ？！

***おわり***
null, undefined, NaNの違い

TypeScript には「値がない」という状態の表現として `null` と `undefined`のふたつが存在します。
さらに、返す数値が存在しない表現として `NaN` があります。
これらの違いについてのまとめです。

## null とは

- TypeScript のプリミティブ[^1]のひとつ
    - ただし `typeof` では `object` を返す[^2]
        ```typescript
        console.log(typeof(null)); // "object"
         ```
- 値がないという状況
- プリミティブなので `null` という型も存在する
   ```typescript
    const x:null = null;
    ```

[^1]: プリミティブとは、TypeScript における基本的な値で、`string`, `number`, `boolean`, `bigint`, `null`, `undefined`, `symbol` がある
[^2]: [JavaScript の初期からの実装に基づく](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/typeof#typeof_null)

## undefined とは

- TypeScript のプリミティブのひとつ
    ```typescript
    console.log(typeof(undefined)); // "undefined"
    ```
- 値が未定義という状況
- プリミティブなので `undefined` という型も存在する
   ```typescript
    const x:undefined = undefined;
    ```

## NaN とは

- `NaN` は Number 型に存在する特殊な値
    ```typescript
    console.log(typeof(NaN)); // "number"
    ```
- 数値が必要な場面で数値が得られなかった場合に出現
- 数値を表すものではない
- `NaN` を含んだ等価演算式、比較演算子では必ず `false` を返す
    ```typescript
    const x = NaN;
    console.log(x === 100); // false
    console.log(x > 100); // false
    console.log(x < 100); // false
    // === で NaN を判定することもできない
    console.log(x === NaN); // false
     ```
-  `NaN` の判定するには `Number.isNaN()` を使用する
    ```typescript
    const x = NaN;
    console.log(Number.isNaN(x)); // true
    ```

## TypeScript では null と undefined のどちらを使うべきなのか？

TypeScript のコーディング・ガイドライン では `undefined` の使用を推奨しています。

- Use `undefined`. Do not use null.
- https://github.com/Microsoft/TypeScript/wiki/Coding-guidelines#null-and-undefined

## 参考

- [null - JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/null)
- [undefined - JavaScript - MDN Web Docs](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/undefined)
- [NaN - JavaScript - MDN Web Docs - Mozilla](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/NaN)
ECC 椭圆曲线加密算法(一)


## 椭圆曲线

椭圆曲线的一般表现形式：$y^2= x^3+ax+b$

椭圆曲线其实不是椭圆形的，而是下面的图形：
>![椭圆曲线 ](https://upload-images.jianshu.io/upload_images/47789-6aba5a7bfe100d19.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

Bitcoin 使用了 secp256k1 这条特殊的椭圆曲线，公式是：
$y^2=x^3+7$
这个东西怎么加密的呢？

## 群 (Groups)

19 世纪挪威青年 **尼尔斯·阿贝尔** 从普通的代数运算中，抽象出了加群（也叫阿贝尔群或交换群），使得在加群中，实数的算法和椭圆曲线的算法得到了统一。是什么意思呢？

**我们在实数中，使用的加减乘除，同样可以用在椭圆曲线中！
对的，椭圆曲线也可以有加法、乘法运算。**

数学中的群是一个集合，我们为它定义了一个二元运算，我们称之为“加法”，并用符号`+`表示。假定我们要操作的群用𝔾表示，要定义的`加法`必须遵循以下四个特性：

- 封闭性：如果 a 和 b 都是𝔾的成员，那么 a+b 也是𝔾的成员。

- 结合律：(a + b) + c = a + (b + c);

- 单位元：存在确切的一个值，称之为单位元，0 可以保证该等式成立 a+0=0+a=a

- 逆元。每个成员都有一个相反数：对于任意值 a 必定存在 b 使得 a+b=0

如果在增加第 5 个条件：
交换律：a + b = b + a

那么，称这个群为阿贝尔群。根据这个定义整数集是个阿贝尔群。

岔开一下话题，**伽罗瓦** 与 **阿贝尔** 分别独立的提出了群论，他们并称为现代群论的创始人，可惜两位天才都是英年早逝。

## 椭圆曲线的群定义

如上文所说，我们可以基于椭圆曲线定义一个群。具体地说：

- 元素都在椭圆曲线上
- 单位元是无穷 0 点
- 点 P 的逆元与 P 关于 X 轴对称
- 加法由下列规则给出：给定三个共线的非零点 P、Q、R，则 P+Q+R=0（无限远点）成立

## 椭圆曲线运算之加法

在椭圆曲线上有 **不重合且不对称的** A、B 两点，两点与曲线相交于 X 点，X 与`x轴`的对称点为 R，R 即为 `A+B`的结果。这就是椭圆曲线的加法定义。

**因为椭圆曲线方程存在 $y^2$项，因此椭圆曲线必然关于 x 轴对称**

 >![椭圆曲线加法运算](https://upload-images.jianshu.io/upload_images/47789-a8b1e2dd7e45ed21.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

## 椭圆曲线的群律

曲线：$y^2=x^3+5x+7$，
坐标：A=(2,5)，B=(3,7)
A、B 正好在曲线上，因为坐标满足曲线公式
$5^2=2^3+5*2+7=25$
$7^2=3^3+5*3+7=49$
那如何找到相交的第三个点呢？

通过 A、B 两点确定直线方程，
设直线方程：$y=mx+c$，m 为直线的斜率
$m=\dfrac{B_y-A_y}{B_x-A_x}=\dfrac{7-5}{3-2}=2$
进一步得到 c=1。

联立方程：

$$
\begin{equation}
  \left.\begin{aligned}
  y=2x+1\\
  y^2=x^3+5x+7\\
\end{aligned}\right\}
\Rightarrow   x^3-4x^2+x+6=0
\end{equation}
$$

X(-1,-1) 的 x 坐标 -1 代入方式正好满足方程，所以 A、B 两点所在直线与曲线相交于 X(-1,-1)，则点 X 的关于 x 轴的对称点为 R(-1,1)，即 A(2,5)+B(3,5)=R(-1,1)。

根据椭圆曲线的**群律 (GROUP LAW)**公式，我们可以方便的计算 R 点。

曲线方程：$y^2=x^3+ax+b$
当 A=(x1,y1)，B=(x2,y2) ，R=A+B=(x3,y3)，x1≠x2 时，
$m=\dfrac{y2-y1}{x2-x1}$，m 是斜率
x3=$m^2-x1-x2$
y3=m(x1-x3)-y1

A=(2,5), B=(3,7) , R=(-1,1) 符合上面的公式。

椭圆曲线加法符合交换律么？

先计算 (A+B)，在计算 A+B+C
> ![A+B+C](https://upload-images.jianshu.io/upload_images/47789-1e9c10d9c2836ab1.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

先计算 B+C，在计算 B+C+A
> ![B+C+A](https://upload-images.jianshu.io/upload_images/47789-32a1b568b9a87b59.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

看图像，计算结果相同，大家手动算下吧。

那 `A + A` 呢，怎么计算呢？

## 定义乘法运算

当两点重合时候，无法画出“过两点的直线”，在这种情况下，
过 A 点做椭圆曲线的切线，交于 X 点，X 点关于`x轴`的对称点即为`2A`，这样的计算称为“椭圆曲线上的二倍运算”。

![随着两点越来越靠近，过两点的直线逐渐趋近于曲线的切线。
](https://upload-images.jianshu.io/upload_images/47789-89144a802ecda8a7.gif?imageMogr2/auto-orient/strip)

下图即为椭圆曲线乘法运算：
> ![椭圆曲线乘法运算](https://upload-images.jianshu.io/upload_images/47789-1721c93a62fc9882.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

我们将在[ECC 椭圆曲线加密算法 (二)](https://www.jianshu.com/p/8fbd8cd84e1e) 介绍有限域，椭圆曲线的离散对数问题，椭圆曲线加密就是应用了离散对数问题。

---

参考：

https://eng.paxos.com/blockchain-101-foundational-math
https://eng.paxos.com/blockchain-101-elliptic-curve-cryptography
https://andrea.corbellini.name/2015/05/17/elliptic-curve-cryptography-a-gentle-introduction/
【SSL】「接続はプライベートではありません」でWebサイトが表示できなくなった

# はじめに
ConoHaWingでレンタルサーバーを借りてWebサイトを公開しています。
ふと自分のWebサイトを開こうとすると、、、
ん！？？
![IMG_2328.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/b8c2a5ab-5e3e-7b9e-b4fb-e866888462f1.png)

めちゃくちゃ治安悪いこと書かれてるじゃないですか。。。

これはめっちゃ困ります
修正した時の方法を記録しておきます。

# 修正方法
① 「サイト管理」を選択します
② 「サイトセキュリティ」を選択します
③ 「独自SSL」を選択します
④ 「無料独自SSL」を開きます
![スクリーンショット 2023-03-02 21.35.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/28e4720e-c876-8ffa-2578-2b7a27edf07a.png)

⑤ 「利用設定」をOFFにします
⑥ 「利用設定」をONにします
![スクリーンショット 2023-03-02 21.37.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/166f21af-4929-4b11-f99a-5ddd439dd6e6.png)

:::note warn
**注意**
オンオフはめっちゃ時間かかります
:::

# おわり
これは焦りました
とりあえず治ってよかったです
ユーザーと記事を紐付け③

<h2>migrationファイルの修正</h2>
ロールバックして、何もない状態！

db/schema.rb
をみると、まっさら👀

ということで、マイグレーションファイルを編集💨

まず、ユーザーがあって記事があるとという関係にしたい！
いまは、記事があってユーザーがある状態。

先にユーザーを作り、その後に記事があって、その記事の中にユーザーレファレンス
そうすることで、ユーザーidがないと絶対ここに保存できないよ！となる。

そのため、順番を入れ替える！
順番は、名前順になっている。
現在は、日付が古い順に並べられている。

そのためファイル名を変更！
前にやりたいファイルの名前を新しい数字にする。

db/migrate/20230206145433_create_articles.rb
変更後、このファイルに

    t.references :user
を追加
db/migrate/20230226221434_add_user_id_to_articles.rb
ここでやっていることを前のファイルで実行することになるので、このファイルは不要！
※referencesの意味：名言及；参照，参考文献

db/migrate/20230206145433_create_articles.rb
ここに、

    t.references :user, null: false
を追加。これは、ここのカラムには絶対値が入ってないとダメですよ！となる。
よって、ユーザーIDが入っていないと、絶対保存できませんとなる🔥

このアーティクルは、ユーザーIDが絶対紐づくことになる。

    t.string :title, null: false
    t.text :content, null: false
タイトルやテキストにも、つけることができる。

ターミナルに行きましょう。

    ＄rails db:migrate
DeviseCreateUsers→CreateArticles
となっているのが、確認できます。

db/schema.rb
articlesがあって、usersがある。
そして、user_idにnull: falseオプションがついている。絶対にユーザIDがないとダメだとなる。

ということで、改めて、サインアップ

これで、ユーザーidがないことは、なくなりました👍
目標達成！


ここで、nullオプションはバリデーションとなにが違うのか？

app/models/article.rb
で、validatesのArticleのpresence: trueとなっている。
これは、絶対にタイトルがないと保存しませんよという意味。
ただ、これはアクティブレコードが、そいつがここにないと保存しないよと言っているだけであって、
SQL自体は、保存する。
そのため、アクティブレコードを少しいじれば、validatesがついていても、保存される。
これだと少し不安！

データベースが側に、制限を加えるのがnullオプションである。

こうしておけば、データベースにこの値がないと、何がなんでも保存しない。

これで、安心することができる(^^)
CentosでMySqlが起動できないエラーが発生

# 経緯
Vagrantを使用してRailsの環境構築をしていました。rbenvやらrailsのインストールが終わって一通り立ち上げの準備ができたところでmysqlのサーバーを起動させようとしましたが起動せず...

#### 開発環境: centos/7  vagrant2.3.4  
````
~$ mysql.server start
ERROR! The server quit without updating PID file (/usr/local/var/mysql/MacBook-Pro-3.local.pid).
````

# 対策
以前、同じようなエラーが出た際**Centos**に**MariaDB**がデフォルトで入っており、それがmysql競合？？ してエラーが起きていたことを思い出しました！
そのときに調べていた記事を見つけたので、それを参考にMariaDBをアンインストールしました。

````
~$ rpm -qa | grep aria

     MariaDB-client-10.3.0-1.el7.centos.x86_64
     MariaDB-compat-10.3.0-1.el7.centos.x86_64
     MariaDB-server-10.3.0-1.el7.centos.x86_64
     MariaDB-common-10.3.0-1.el7.centos.x86_64

#sudo yum remove以降は上で表示されたバージョンをコピペして貼り付け 
~$ sudo yum remove MariaDB-client-10.3.0-1.el7.centos.x86_64    
~$ sudo yum remove MariaDB-compat-10.3.0-1.el7.centos.x86_64
~$ sudo yum remove MariaDB-server-10.3.0-1.el7.centos.x86_64
~$ sudo yum remove MariaDB-common-10.3.0-1.el7.centos.x86_64
````

MariaDBをアンインストールしてもう一度**mysql.server start**したら無事起動できました！

# 参考記事
https://glodia.jp/cent_mariadb_to_mysql
FiletoDBのバッチ処理に関する備忘録

駆け出しのSEです。

今回初めてバッチ処理の設計・実装に取り組みましたが、FiletoDBのバッチ処理において、ファイルからDBへデータが格納される流れを理解するにあたって少し混乱があったので、ここに書き留めておきます。

# 扱うファイルの構成について
ファイルの中身は、ヘッダレコード、データレコード、トレーラレコードなど、「レコード」という単位でデータ項目がグループ分けされています。
なお、ファイル自体は固定長改行無しのテキストファイルを意識していますが、そこからデータ項目を抽出していく過程については割愛します。
今回は、とある会員情報を題材とした以下のような1つのファイルを例に処理を説明します。
ここでは、レコードの種類はデータ区分という項目で識別します。

##### ヘッダレコード
| データ区分 | 会員番号 | 氏名 |
|:-:|:-:|:-:|
| 1  | 1111  | ﾀﾅｶｲﾁﾛｳ  |

##### データレコード
| データ区分 | 生年月日 | 電話番号 | メールアドレス |
|:-:|:-:|:-:|:-:|
| 2  | 20001231  | 11122223333  | aaa@example.co.jp  |

##### トレーラレコード
| データ区分 | 会員ランク | ポイント |
|:-:|:-:|:-:|
| 8  | GOLD  | 300  |

# DB登録後の状態
以下にDB登録後の状態を示します。
レコードには登録順に処理連番を振り、テーブル項目として追加するものとします。
なおここで、ファイルのレコード種類の「レコード」と、DBの行を表す「レコード」は区別するよう注意してください。

| 処理連番 | データ区分 | 会員番号 | 氏名 | 生年月日 | 電話番号 | メールアドレス | 会員ランク | ポイント |
|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|:-:|
| 1  | 1  | 1111  | ﾀﾅｶｲﾁﾛｳ  |   |   |   |   |   |
| 2  | 2  |   |   | 20001231  | 11122223333  | aaa@example.co.jp  |   |   |
| 3  | 8  |   |   |   |   |   | GOLD  | 300  |

上記のように、基本的にファイルのレコード種類をひとつの単位として処理し、対応する項目ごとに登録を行っていくことで、ファイルのレコード種類ごとにDBの1レコードとなります。（表で見ると階段状にデータが入るイメージ）
つまり、DBに登録した状態でも、「ヘッダレコード出身の行」「データレコード出身の行」が存在するイメージで、これ以降にDBtoDBの処理が続く場合も、この単位のまま精査などを行っていくのが一般的です。
なお、該当するレコード種類以外の行に絶対に格納しないかというとそうではなく、その必要がある際はインスタンス変数やセッションで持ち回ることで対応します。

私が設計書を読み始めたときは、なんとなく1ファイル分のデータは自動的にDBの1行として登録されるかのように思い込んでいたので、今回このように書き留めておくことにしました。


:::note warn
※このアカウントで発信する内容はあくまで私個人の意見であり、現在所属する会社の公式見解を示すものではありません。
:::
ChatGPTの活用法

## ChatGPTって何ができるの？

---

### 1. **対人のような会話**

まるで実際に誰かとチャットをしているようなやり取りが可能
![Untitled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/27cf448f-1531-d78c-11a1-c9b3948a29f7.png)


---

### **2.表計算ソフトの関数やプログラミング言語の記述**

私はメインでお世話になってます🤗

実装したい内容などを送ると実装手順からコードを教えてもらえる

![Untitled 1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/499a09c3-dbbb-e912-4e97-93a98b0d2d8f.png)


---

### **3.小説、脚本を書く**

これは初めて知った！

一定の情報を渡すだけで小説などを書くことが可能
![Untitled 2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/59701239-b3d7-d9ae-6932-1bae27b5061e.png)


---

### エンジニアに役立つ使い方３選🤚

---

### 1.****プログラミングのリファクタリングやバグのチェック****

コードを送ることでリファクタリングをしてくれます。

![Untitled 3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/c964769d-5ee9-1b91-9783-f79b8f70b973.png)


---

### 2. 学習計画を作ってもらう

転職や新しい技術を学ぶ場合にどのような手順で学べばいいかを提案してくれる

![Untitled 4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/78af1eb0-296f-5a61-3ce8-eccc170db0b3.png)


---

### 3. 設計のサポート

個人開発でのDB設計を実際に行ったが有能🥰

![Untitled 5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1957020/860f2df7-c6a3-738a-8fdc-cc9187663234.png)


---

### まとめ

- これからいろいろなところで活用される
- やりたいことのサポートとして使う
- 課題などをやってもらうなどの悪用厳禁🙅‍♂️