OmniAICreator/Qiita-1.07M huggingface dataset:
KotlinのNULL安全

Kotlinはプログラムの実行時にNullPointerExceptionが発生する可能性を極力排除するように働きかけてくれます。
Null参照についての構文が厳しく設定されいます。守られていない場合はコンパイルエラーになるようになっています。
KotlinはNull参照に厳しいです。

<h2>非Null型とNull可能型</h2>
Kotlinには「非Null型」と「Null可能型」があり、
Null参照を保持できない型とNull参照を保持できる型を区別し、KotlinはNull安全を保証しています。
<br>・非Null型：Int、String、Boolean、自分で作ったクラスなど

        var noNull: String = "abc"
        noNull = null //ここでコンパイルエラー

・Null可能型：String?、Int?、Boolean?、自分で作ったクラス?など

        var okNull: String? = "abc"
        okNull = null //ここでコンパイルエラーにならない

<br>上記を見てわかるとおり、Null可能型にするには型のあとに「?」を付けます。
<br>意識せずに宣言した変数は必ずnullが保持できないことになるので、
普通に宣言した変数やメソッドなどにアクセスする際にNullPointerExceptionが発生しないことを保証します。意図的に?を書かない限りは思わぬnull参照を防いでくれます。

<h2>!! 演算子</h2>
あまりないかもしれませんが、NullPointerExceptionを発生させたい!!といった時には「!!演算子」を使用します。

        val okNull: String? = null
        val length = okNull!!.length
<br>「!!演算子」は、Null可能型のオブジェクトがnullでなければそのまま値を返却します。もしnullならNullPointerExceptionをthrowします。
NullPointerExceptionを発生させたい時は、「!!演算子」を使用することでNullPointerExceptionを拾うことが可能です。「!!演算子」を使用する場合はcatchをしっかりしましょう。

<h2>NullPointerExceptionが発生する場面</h2>
　・明示的にNullPointerExceptionをthrowする呼び出し方(!!演算子)
<br>　・外部コードでのNullPointerExceptionの発生した場合
<br>　・コンストラクタ内で利用可能だが初期化されていないオブジェクトが存在する場合
Procodile の process に HUP/USR1 等のシグナルを送信してもログファイルは reopen しません


## はじめに

Ruby には [Foreman] や [God] 等 process を管理してくれるツールがあり [Procodile] もその 1 つです。
今回 [Procodile] が出力する ログファイル が logrotate 時 reopen されていなかったため動きについて調査したので簡単にまとめました。

https://github.com/adamcooke/procodile

https://github.com/ddollar/foreman

https://github.com/mojombo/god

## 先に結論

[Procodile] が開いた logfile を reopen する方法は現時点存在しません。
[Procodile] (supervisor を含め) そのものを `stop`, `start` する必要があります。

```sh
$ bundle exec procodile stop --procfile path/to/Procfile --stop-supervisor
Stopped xxxxxx.1 (PID: xxxx)
Supervisor will be stopped when processes are stopped.
$ bundle exec procodile start --procfile path/to/Procfile
```

## Procodile とは

[Procodile] は Foreman に少し似た library です。

[Procodile] は background で動作するように設計されており（foreground も OK）。
process を監視する supervisor を持っており、対象の process が kill された場合はそれらを respawn します。

https://github.com/adamcooke/procodile

[Procodile] を start すると、 [Procodile] の supervisor が起動し、 `Procfile` に記載された process を起動・監視してくれます。

## Procodile の ログファイルについて

[Procodile] は `Procfile.options` に指定した `log_path` の path に、起動した process が出力したログを吐くことが出来ます。

```yml:Procfile.options
# The absolute path to the application (optional but useful when working
# with symlinks)
root: /absolute/path/to/app

# The directory that all PIDs will be stored in (default is 'pids')
pid_root: tmp/procodile-pids

# The path to the log file where the procodile log will be stored. By default
# this will be `procodile.log` in the root of your application.
log_path: log/procodile.log
```

https://github.com/adamcooke/procodile/wiki/Configuration

上記のような設定をしていた場合 `/absolute/path/to/app/log/procodile.log` にログが出力されます。

## Procodile の process 管理について

[Procodile] の wiki には、 process を restart する方法について記載されています。
こちらの記述は、 [Procodile] が起動した process restart に関するもので、 [Procodile] の process restart についての記述ではありません。

https://github.com/adamcooke/procodile/wiki/Restart-Modes

また、 `Procfile.options` にも `restart_mode` を記載することが出来ますが [Procodile] が起動した process restart に送信する signal を定義できるだけです。

```yml:restart_mode を term-start から usr2 に変更する場合
# Per-process configuration options
processes:
  web:
    # The mode that should be used when restart this process (default
    # is term-start)
    restart_mode: usr2
```

https://github.com/adamcooke/procodile/wiki/Configuration

[Procodile] が開いた logfile を reopen するには、[Procodile] (の supervisor を含め) `stop`, `start` する必要があります。

```sh
$ bundle exec procodile stop --procfile path/to/Procfile --stop-supervisor
Stopped xxxxxx.1 (PID: xxxx)
Supervisor will be stopped when processes are stopped.
$ bundle exec procodile start --procfile path/to/Procfile
```

logrotate したいときは上記を考慮し logrotate の設定ファイルを記述する必要があります。

## References

- [Home · adamcooke/procodile Wiki](https://github.com/adamcooke/procodile/wiki)
- [Restart Modes · adamcooke/procodile Wiki](https://github.com/adamcooke/procodile/wiki/Restart-Modes)

[Foreman]: https://github.com/ddollar/foreman
[God]: https://github.com/mojombo/god
[Procodile]: https://github.com/adamcooke/procodile
VSCodeでpip installしたパッケージが参照出来ない時の解決方法

# VSCode上でpip installしたパッケージが参照出来なかった…

ふとしたきっかけでdiscordのbotを作る事になったので、
bot開発環境のため`python`の導入を進めてみた所、掲題の部分でハマったお話。。。

その際、`Pip Manager`というVSCode上でpipでインストールしたパッケージの
参照・管理まで解決してくれる拡張機能を見つけたので事例も兼ねて紹介します。

※discordのbot開発の手引きはこちらを参考にしました
https://www.freecodecamp.org/japanese/news/create-a-discord-bot-with-python/

## 記憶を頼りにpythonのインストールと環境設定
- [Python.org](https://www.python.org/downloads/)から取り合えず最新版をDL
　　→ インストーラに言われるまま設定

- VSCodeの拡張機能の[Python](https://marketplace.visualstudio.com/items?itemName=ms-python.python)をインストール

- Python拡張機能の導入手順を見ながらpy.exeにPathを通す
  → <ユーザディレクトリ>\AppData\Local\Programs\Python\Python311

## とりあえずHelloWorld
※venvでCreateした
```py
print("Hello World!")
```
 → 成功

## pipでdiscord.pyをインストール

```powershell
# discord.pyをpipでインストール
> py -3 -m pip install -U discord.py
~エラー無し~

# パッケージ追加の確認
> py -3 -m pip list
Package            Version
------------------ -------
aiohttp            3.8.3
aiosignal          1.3.1
async-timeout      4.0.2
attrs              22.2.0
charset-normalizer 2.1.1
discord.py         2.1.0
frozenlist         1.3.3
idna               3.4
multidict          6.0.4
pip                22.3.1
setuptools         65.5.0
yarl               1.8.2
```
OKっぽい

## botのサンプルコードをVSCodeから実行してみる ※[コード引用元](https://www.freecodecamp.org/japanese/news/create-a-discord-bot-with-python/)
```py
import discord
import os

client = discord.Client()

@client.event
async def on_ready():
    print('We have logged in as {0.user}'.format(client))

@client.event
async def on_message(message):
    if message.author == client.user:
        return

    if message.content.startswith('$hello'):
        await message.channel.send('Hello!')

client.run(os.getenv('TOKEN'))
```

すると。。。
```
(.venv) PS C:\Users\XXXXX\project\XXXXX> & c:/Users/XXXXX/project/XXXXX/.venv/Scripts/python.exe c:/Users/XXXXX/project/XXXXX/main.py
Traceback (most recent call last):
  File "c:\Users\XXXXX\project\XXXXX\main.py", line 1, in <module>
    import discord
ModuleNotFoundError: No module named 'discord'
```

`discordのモジュールが見つからないよ`、と
解決方法を探す旅が始まる・・・

# 解決編
## VSCode拡張機能で良い感じにpipの管理してくれる物が見つかった

前章でpip installしたパッケージの参照を解決する方法を見つける前に、
VSCode上でpipの管理も完結できる拡張機能が見つかったのでそちらを導入

・Pip Manager
https://marketplace.visualstudio.com/items?itemName=slightc.pip-manager

- Pip ManagerのSearch packageで`discord.py`をインストール
  ※左：discord.pyインストール前　右：インストール後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120338/b0a04aeb-bb65-51c6-8f02-e2f74eb89f6d.png)

・今度はdiscord.py参照出来てそう！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120338/35fd19b1-6999-e0ec-5d50-081024ce321f.png)

- 実行 → 無事に動作しました！

# 結論
`Pip Manager`はVSCode上でpipインストールしたパッケージの参照・管理を完結出来るので便利そうでした！
input type="file"の未選択時はnullではなく空文字列""になる！

# input type="file"未選択時は…
## 例
``` html
<input type="file" name="hoge_imagefile">
```
上記で画像ファイルを選択しなかった場合は、PHP側で既存の画像をS3に保存しようとしました。
ですのでPHP側の該当箇所記述は下記かなと思って…
``` PHP
// リクエストに画像が存在しない場合
if(is_null($request->hoge_imagefile))
{
    $request->hoge_imagefile = $fuga->image;
}
// S3、DBへの保存アクションが以降で実装される
```
つまり、リクエスト画像が存在しない場合はすでに保存されている画像のパスをそのまま使用する、という形になっています。
(実装方法があまりよろしくないとは思いますが、本記事の趣旨とは異なるので無視)
いずれにせよリクエストが無くても従来画像が保存されると思ったのですが、思い込みとは恐ろしいもので…

## どうなったのか？
``` PHP
// $image_pathは上記の$request->hoge_imagefile
// S3へのアップロードメソッド
private function uploadImage(string $image_path)
{
    $path = Storage::disk('s3')->putFile('s3folder', $image_path, 'public');
    $url = Storage::disk('s3')->url($path);
    return $url;
}
```
上記の`$path = Storage::disk('s3')->putFile('s3folder', $image_path, 'public');`
の部分でLaravelから「$image_pathが無いぞ」って怒られます…
「なんでや！is_null()使ったやろ！」悩むこと1時間…

## 原因
__公式ドキュメントを読みましょう。エラーの内容を読みましょう。__
まずエラーですが、The file 〜 does not existです。(中学生でもわかる簡単英語ですね)
要するに該当のファイルが無いのです。肝心なのはnullどうのこうのより、ファイルが存在しないのです。
次にMSDNを眺めてみると…ありました！
https://developer.mozilla.org/ja/docs/Web/HTML/Element/input/file
なになに…
> ファイルが選択されていない場合は、値は空文字列 ("") になります。

__空文字列("")になります__(nullではない、そうnullではないのです…)

## 結論
__とにかく公式ドキュメントとエラー内容を確認!!!__

## おまけ
…C#のIsNullOrEmpty()がPHPにもありませんか？…そう、無いですか…おっ！
偉大な先人がいますね！

https://qiita.com/hirossyi73/items/6e6b9b3ff155a8b05075
WordPressで独自テーブルにフォームデータを格納する。バリデーションや非同期通信もやってみる。

## ■背景

仕事のため、必要だったため。
あまり記事もなく、調査が面倒だった。
自分共有用として。

mysqlのテーブル作成は記載していない。

## ■概略

処理の流れは以下

1. フォームの送信ボタンをクリック時に、javascript起動（バリデーション、送信前の確認メッセージ、非同期で自身の固定ページにpost送信）

2. 自身の固定ページにpost送信するので、配置しているショートコードがキック

3. 使用しているテーマのメソッドがキック

   

## ■固定ページ

### html

```html
<h2>アンケート</h2>
<form action="" name="survey_form">
  氏名：<input id="full_name" name="full_name" required="" type="text" />
  →注意：wordpressはname属性に「name」とすると、post送信時にエラーとなる
  
  〜その他フォームなど〜
  
  <button id="survey_form" type="submit" onclick="manageSurvey_form();">送信</button>
</form>
```



### javascript（送信ボタンクリック時に呼び出される）

```javascript
<script>
  function manageSurvey_form() {
    /* 送信前のバリデーションをする */
    const full_name = document.getElementById('full_name').value;

    validation_msgs = checkSurvey_form(full_name);

    if(validation_msgs !== "") {
      alert(validation_msgs);
      return false;
    }

    // 確認メッセージを生成する
    confirmMessage =  '以下の内容で送信します。\n'
                        + '氏名：' + full_name;
  
    // 確認メッセージを表示する
    if (window.confirm(confirmMessage)) {
      // formdata作成
      const id = document.getElementById('survey_form');
      const form_data = new FormData(id);
      form_data.set('full_name',full_name);
			
      // 送信処理
      submitSurvey_form(form_data).catch(alert);
    }
  }

  // アンケートの入力値をチェックする
  function checkSurvey_form(full_name, company, mail) {
    /* バリデーション*/
    let validation_msgs = [];

    if(full_name === ""){ 
      validation_msgs.push('氏名を入力してください'); 
      
      〜他　バリデーション〜
    }
    
    return formated_validation_msgs;
  }

  // 非同期でアンケートをpost送信する
  async function submitSurvey_form(form_data) {
    // 自分自身の固定ページにデータを送信することで、同じ固定ページに配置したショートコードをキックする
    const response = await fetch("", {
        method: 'POST',
        body: form_data
    });

    if (response.ok){
     　// post送信成功時の処理
    } else {
      throw new Error(response.status);
    }
  }
</script>
```

### ショートコード

```
[store_survey]
```



## ■使用しているテーマの：funcitons.php

```php
//　ファイルダウンロードログをDBに格納する
function storeSurvey) {
  if(isset($_POST) 
      && !empty($_POST)
      && !empty($_POST['file_name'])){

    // DB接続情報取得
    global $wpdb;
    // テーブル名にはプレフィックス（wp_）は記載しない
    $tableName = $wpdb->prefix . "テーブル名";
    
    $wpdb->insert($tableName,
      array( 'file_name' => $_POST['file_name'] ),
      array( '%s' )
    );
  }
}
add_shortcode('store_survey', 'storeSurvey');
```
C#でnull 許容参照型を使ってみる


# 1. はじめに
* Javaで使用するOptionalをC#でも同じように使用したい
* 変数をする前にnullかどうかをチェックしてヌルポににならないようにしたい

# 2. 開発環境

* Visual Studio 2022
* C# 8.0
* .NET6
* Windows10

# 3. null 許容参照型とは

* 値型の型名の後ろに ? を付けることで、元の型の値または null の値を取れることを明示的に示す

* C# 8.0で新しい機能として追加された

  ```csharp:
  int? x = 123;	// nullの可能性あり
  int x = 123;	// nullの可能性なし
  ```

# 4.  null 許容参照型の書き方

## 4.1. 変数の宣言 (?)

```csharp:
int? x = null;		// Nullable<int> x; と同じ
```

## 4.2. nullの判定 (HashValueプロパティ)

```csharp:
bool result = x.HashValue;		// null以外:ture, null:false
```

## 4.3. 値の取得 (valueプロパティ)

```csharp:
var z = x.Value;	// valueプロパティで値を返却、InvalidOperationException例外あり
var z = x;				// 上記と同じ結果になる
```

## 4.4. null 合体演算子 (??)

* 値がnullかどうかを判定して、nullの場合に別の値を割り当てることができる

```csharp:
var z = x ?? y;		// xがnull以外：x, xがnull: y
```

## 4.5. null 合体代入 (??=)

```csharp:
x ??= 100;			// if (x==null) x=...と同じ
```



# 5. 参考文献

https://ufcpp.net/study/csharp/sp2_nullable.html
POST送信（通常／javascriptで制御／動的にフォームを作って送信）

## ■通常

何も制御する必要がない場合はこちら。

```html
<form method="POST" action="" onSubmit="return check()">
  なんらかのフォーム
  <input type="submit" value="送信" />
</form>
```



## ■javascriptで制御する場合

javascriptで制御するので、バリデーションなどの処理をはなむことができる。

```html
<form method="POST" action="" onSubmit="return check()">
  なんらかのフォーム
  <input type="submit" value="送信" />
</form>
```

```javascript
<script>  
  function check() {
      if (window.confirm('実行しますか？')) {
        return true;
      } else {
        return false;
      }
  }
</script>
```



## ■動的にフォームを作って送信（Formを使わない）する場合

動的にフォーム作成し、post送信することで、フォームを用いずにちょっとしたデータをpost送信できる。

```javascript
<script>
  // ダウンロードしたファイル名を送信する
  function sendDownloadedFileName(file_name){
    const file_name = element.id;
    
    /* post送信する */
		const form = document.createElement('form');
    form.action = '';
    form.method = 'post';
		// 送信データ作成
    // 下記のように動的にフォームを作る
  　// もちろん複数フォームを作成することもできる　
    const data1 = document.createElement('input');
    data1.value = file_name;
    data1.name = 'file_name';
    form.appendChild(data1);
  
    document.body.appendChild(form);

    form.submit();
  }
</script>
```
CircleCI 公式のデプロイ用 Docker イメージ cimg/deploy

CircleCI でカスタマーサクセスをしている鈴木です。椎間板ヘルニアに悩んでいます。一日1万2000歩を超えると腰の痛みが足に現れるので、Fitbitを見なくても大体の歩数がわかるようになってきました。

CircleCI が用意している CircleCI のジョブの実行環境で利用する Docker イメージをコンビニエンスイメージと呼んでいます。コンビニエンスイメージは各言語やフレームワークごとに CI/CD で必要なツールやパッケージがインストールされています。現在、Docker Hub の[cimg/](https://hub.docker.com/u/cimg) に20種類ほどのイメージを確認できます。

本記事では比較的最近[^1]公開された cimg/deploy というコンビニエンスイメージと、それをベースにした主要クラウドサービス別のイメージを紹介します。

cimg/deploy は名前からも想像できるように継続的デリバリーやデプロイでの利用を念頭においていて、kubectl や terraform などがインストールされています。さらに AWS CLI が必要であれば、cimg/deploy をベースにした cimg/aws が、gcloud CLI が必要であれば cimg/gcp が用意されています。 

例えば、AWS CLIを使いたい場合、これまでのベストプラクティスはCircleCIが用意している aws-cli Orbを利用することでした。.circleci/config.yml には以下のように記述します。

```
version: '2.1'
orbs:
  aws-cli: circleci/aws-cli@3.1.4
  
# 省略

jobs:
  install_cli:
    executor:
      name: cimg/base:2023.01
    steps:
      - aws-cli/install
```

Orbを呼び出す代わりに、executor に cimg/aws を指定する記述は以下です。

```
version: '2.1'

# 省略

jobs:
  install_cli:
    executor:
      name: cimg/aws:2022.11
    steps:
      - aws-cli/install
```

コード量としては大きな差がありませんが、cimg/aws を使うほうがインストールの時間を省くことができます。
と書いてみたものの、AWS CLIのインストールぐらいでは時間短縮はほとんど見られませんでした。（むしろ cimg/aws イメージの pull に時間が。。）
また、aws-cli Orb のほうが、AWSのクレデンシャルを設定する [setup コマンド](https://circleci.com/developer/ja/orbs/orb/circleci/aws-cli#commands-setup)もあるので Orb のほうが実用的かもしれません。Orb 便利ですね。

さて、気を取り直して cimg/deploy イメージにどんなツールがインストールされているのか確認したいと思います。このイメージを作成している Dockerfile は CircleCI のパブリックな GitHub リポジトリの [CircleCI-Public/cimg-deploy](https://github.com/CircleCI-Public/cimg-deploy) で確認できます。

cimg/deploy イメージはほぼ毎月更新されていくとのことで、cimg/deploy:2023.01 のように年月でタグが付けられています。リポジトリ上ではこの年月別にディレクトリが分けられています。
![](https://storage.googleapis.com/zenn-user-upload/8fb73b809311-20230126.png)

2023.01 ディレクトリを見てみると Dockerfile がありました。[^2]
![](https://storage.googleapis.com/zenn-user-upload/3a7ccebff0ad-20230126.png)

[Dockerfile の中身](https://github.com/CircleCI-Public/cimg-deploy/blob/main/2023.01/Dockerfile)を確認すると、
python3-pip, rsync, ansible, kubectl, nfpm, packer, salt-master, terraform がインストールされていることがわかりました。

これらのツールのインストールに時間がかかっている場合はお試しください。


[^1]: 2022年4月のベータ公開を経て、2022年11月に正式公開されました。リリース時のCircleCIのアナウンスは[こちら](https://discuss.circleci.com/t/circleci/46027)です。
[^2]: node ディレクトリも見えますが、cimg/deploy イメージは cimg/deploy:2023.01-node といったタグもあり、そちらには Node.js と yarn がインストールされています。
マルスパム とは

## 勉強前イメージ

スパムっぽいよね。
普通のスパムと何が違うの

## 調査

### マルスパム とは

Malspamと英語で書き、悪意とスパムメールをあわせた造語になり
意味としては悪意を持って配信されるスパムメールのことをマルスパムって呼びます。
攻撃者側が大量のユーザの感染させたい場合に行うことが多いものになります。

悪意を隠して、普通のスパムメールを装います。
それで反応したユーザには [スピアフィッシング](https://qiita.com/miyuki_samitani/items/ee41e90eeb37940eebb1) や [ホエーリング](https://qiita.com/miyuki_samitani/items/1667c61979e78e818dff) などで攻撃を行います。

2021年に流行したEmotetはマルスパムの一部になります。

対策としては他の攻撃も同様ですが、
怪しい添付ファイルは開かないことや、マクロの実行はしないこと。
また関係者からのメールでもセキュリティスキャンは行う必要はあります。

## 勉強後イメージ

スパムって基本的には悪意あるんじゃない？って思ってたけど
マルウェアなどを大量に感染させたいときに引っ掛けたユーザは逃さない的な感じやと思ってる。

## 参考

- [マルスパムとは【用語集詳細】](https://www.sompocybersecurity.com/column/glossary/malspam)
- [マルスパムとは? - JA](https://sensorstechforum.com/ja/what-is-malspam/)
wordpress関数をjsファイルで扱えるようにする

ワードプレスである便利な関数をjsでも扱えるようにする方法のメモです。
今回は`home_url()`関数を使えるようにしてみます
~~~ php 
function custom_enqueue() {
  $tmp_path_arr = array(
    'home_url' => home_url(),
  );
  wp_enqueue_script('my_js', get_stylesheet_directory_uri() . '/js/script.js', array(), date("ymdHis", filemtime(get_stylesheet_directory() . '/js/script.js')));
  // home_url()関数をjsで使えるようにする
  wp_localize_script('my_js', 'tmp_path', $tmp_path_arr);
}
add_action('wp_enqueue_scripts', 'custom_enqueue');
~~~
`functions.php`に上のコードを記述します。
~~~ js 
  const wp_home_url = tmp_path.home_url;
~~~
上のコードを使いたいファイル先（`script.js`）に記述します。
以上、便利に使いまわせてお得だね〜

#### 参考
https://kubogen.com/web-wordpress-072/
Laravel CRUDについて

## はじめに
アプリケーションを作る際に基本的な機能となる`CRUD`を説明していく。

## CRUDとは
CRUDとは、下記のステップの頭文字をとったもの。
|Create  |作成  |
|---|---|
|Read  |読み出し  |
|Update  |更新  |
|Delete  |削除  |

CRUDとは、データを使ったシステムで共通して行う４つの処理を表現した言葉を言う。

## LaravelでCRUDを作成する
LaravelではリソースコントローラというCRUDを簡単に作成することができる機能をもっています。
CRUDの処理はコントローラーに記述していくことになりますが、下記コマンドでまとめて作成することができます。
```
php artisan make:controller TestController –resource
```

上記コマンドを打ち込むことで一般的にWEBアプリケーションを作成する上で必要となってくる7つのアクションメソッドを自動で作成することができます。

|作成されるメソッド  |  |
|---|---|
|index  |一覧表示  |
|create  |作成  |
|store  |作成したものを保存  |
|show  |個別ページ  |
|edit  |編集  |
|update  |編集したものを保存  |
|destroy  |削除  |

といったような7つのメソッドを自動で作成してくれます。

### ルートを設定する
LaravelだけでなくWEBアプリケーションを作成するうえでほぼ必ずルーティング設定をすることになります。
一般的にリソースコントローラを使わずにルート設定をする場合下記のような感じで記述することとなります。
※バージョンによって書き方が違うため、公式を確認するようお願いします
```web.php
// 一覧
Route::get('post', [PostController::class, 'index']);
// 作成
Route::get('post/create', [PostController::class, 'create']);
// 保存
Route::post('post', [PostController::class, 'store']);
// 表示
Route::get('post/{post_id}', [PostController::class, 'show']);
// 編集
Route::get('post/edit/{post_id}', [PostController::class, 'edit']);
// 更新
Route::put('post/{post_id}', [PostController::class, 'update']);
// 削除
Route::delete('post/{post_id}', [PostController::class, 'destroy']);
```

これをリソースコントローラで書くと下記一文で済んでしまいます。
```web.php
Route::resource('posts', PostController::class);
```
非常に楽ですね。

ただメソッド名を変えたい場合などはこのような書き方ではかけないため、1つずつルート指定をしてあげる必要があります。
場合によって適宜変えていきましょう。

以上です。
ActiveSupport::Duration で経過した月数を計算する

```pry
[1] pry(main)> now = Time.current
=> Thu, 26 Jan 2023 19:07:20 JST +09:00

[2] pry(main)> past = Time.current.ago(6.months)
=> Tue, 26 Jul 2022 19:07:22 JST +09:00

[3] pry(main)> ActiveSupport::Duration.build(now - past).parts
=> {:months=>6, :days=>1, :hours=>9, :minutes=>5, :seconds=>22.157833217}

[4] pry(main)> ActiveSupport::Duration.build(now - past).parts.dig(:months)
=> 6
```
AWS ECS上でRails上で動作するバッチをスケジューリングする

whenever+cronを使ってRails上のバッチを定期的に処理を行なっていたのだけど、
マネージドな環境に移したくなった。

# 手順
## railsをdockerに詰める
普通にsrc詰めて、bundle installする

## cmd
cmdにrails runnner Hoge::moge を設定する

## ECRへpushする

## ECSタスク定義を設定する
↑のECRを設定する
Fargateを指定する
ポートは指定しなくて良い

### テスト実行
cli run-taskコマンドで試してみる。
```
aws ecs run-task --launch-type FARGATE \
    --cluster #{cluster-arn} \
    --task-definition #{task define arn} \
    --network-configuration #{vpc config}
```

## ECSタスクスケジュールへ登録
ECSクラスター => タスクスケジュールへタスク定義を登録する
実行間隔をcronとかで設定可能


# 補足
railsをapiサーバとして使っている場合、dockerコンテナ・ECRは共用出来そう
apiサーバの場合cmdが puma とかになってると思うので、
タスク定義で、cmdをrails runnerで上書きしてあげる。
【SAA資格勉強】Direct Connectについて

## Direct Connectとは
AWS認定SAA資格勉強時にまとめたものです。
AWSとオンプレミス環境を専用線で接続するプライベートネットワークサービスです。

![](https://storage.googleapis.com/zenn-user-upload/40064d0b6b5f-20230112.png)

## AWS VPNとの違い
インターネットを経由せず接続することができるので、高いセキュリティレベルを保持したまま安定した速度でデータの送受信などを行うことができる。

## メリット
- セキュリティが高い
- 安定した通信速度
- データ転送料金が割安

## デメリット
- 初期コスト高

## 専用接続とホスト接続
### 専用接続
AWS Direct Connect location（中継地点）まで、事業者が物理ケーブルを直接繋ぎに行くイメージ。1Gbps以上の広帯域で専用のネットワークを構築したい場合や、１つの接続の中で複数のVIFを利用する可能性の高い企業などは専用接続が向いている。

### ホスト接続
AWS Direct Connect location（中継地点）まで既にいくつかケーブルが繋がっており、そのケーブルから必要な分を論理的に分割して提供するようなイメージ。選択できる帯域幅の数が多い。小規模での利用の場合に専用接続タイプと比べてコストを抑えることができる。


**例題**
[無料WEB問題集＆徹底解説 問7](https://aws-exam.net/saa/saa_q.php?q_id=20&q_num=7&category=%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A8%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E9%85%8D%E4%BF%A1)
[無料WEB問題集＆徹底解説 問10](https://aws-exam.net/saa/saa_q.php?q_id=40&q_num=10&category=%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF%E3%81%A8%E3%82%B3%E3%83%B3%E3%83%86%E3%83%B3%E3%83%84%E9%85%8D%E4%BF%A1)

**参考資料**
[公式ドキュメント](https://aws.amazon.com/jp/directconnect/)
[AWS Direct Connectとは？](https://atbex.attokyo.co.jp/blog/detail/9/)
App Service 証明書を Azure Key Vault にいれたまま Application Gatewayで利用する

# 目的

Application Gateway では Key Vault に保存されたシークレットを利用することができます。
https://learn.microsoft.com/ja-jp/azure/application-gateway/key-vault-certs#supported-certificates

> Key Vault 証明書を使用するように Application Gateway を構成すると、そのインスタンスによって Key Vault から証明書が取得され、TLS 終端のためにその証明書がローカルにインストールされます。 インスタンスによって 4 時間ごとに Key Vault がポーリングされ、証明書の更新バージョン (存在する場合) が取得されます。 更新された証明書が検出されると、HTTPS リスナーに現在関連付けられている TLS または SSL 証明書が自動的にローテーションされます。

https://learn.microsoft.com/ja-jp/azure/application-gateway/key-vault-certs#supported-certificates

Application Gateway で App Service 証明書を Key Vault を使えば  「[App service 証明書をエクスポートしてパスワードを設定し、他の Azure サービスにインポートする方法 \- Japan PaaS Support Team Blog](https://jpazpaas.github.io/blog/2020/09/23/how-to-export-appservice-certificate.html)」 に書いてある~~やたらとめんどくさい~~手順を実行しなくて済みそう。

# 問題

だがしかし、ポータルからの操作だと出て来ないのではまった。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4914/b570ba05-dc2b-21f9-9514-78e5b9474518.png)

# 回避策

先のリンクのドキュメントをよく読むと書いてありました。

> Azure portal では、シークレットではなく Key Vault 証明書のみがサポートされます。 Application Gateway は引き続き Key Vault からのシークレットの参照をサポートしますが、PowerShell、Azure CLI、API、Azure Resource Manager テンプレート (ARM テンプレート) など、ポータル リソース以外を使用している場合のみに限られます。

ということで　CLI を使うと無事インポートできました。



```bash
az network application-gateway ssl-cert create \
-g $resourcegroup \
--gateway-name $gatewayname \
--name $certName \
--key-vault-secret-id $keyVaultSecretIdWithoutVersion
```

https://learn.microsoft.com/ja-jp/cli/azure/network/application-gateway/ssl-cert?view=azure-cli-latest#az-network-application-gateway-ssl-cert-create

App Service 証明書を自動更新にしておけば証明書更新を気にしなくて良い[^1]構成ができそうです。
[^1]:ドメイン検証には要注意 https://jpazpaas.github.io/blog/2022/08/26/2022-08-25-App-Service-Certificate-Renewal.html
【Flutter】PageViewを使ったシンプルなチュートリアルページの実装

# はじめに
下記記事のように、かっこいいチュートリアル作れるパッケージはいくつかありますが、
依存関係を増やしたくない方や、とりあえずシンプルでいいという人向けに、シンプルなチュートリアルページの実装を記事にしようと思います。

https://qiita.com/tokkun5552/items/5848d4d0c8ab4eb11993

# 画面構成
説明する部分は、画像、タイトル、内容という構成で、その下に現在ページとトータルのページ数を表すインジケータ、次のページに進むためのボタンを表示しています。

![test00.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475427/0651b808-c13c-605c-13da-4897f5032d01.gif)


# ソースコード
動かしてみたい方は下記にリポジトリを置いておきます。

https://github.com/AppDeveloperMLLB/sample_simple_tutorial

# ポイント解説
チュートリアルの実装の大事な部分は、スワイプやボタンの押下で画面が切り替わっていく部分ですが、
それは`PageView`というWidgetで作成しています。
`PageView`を使うと、スワイプでの切り替えを実装することなく、使用できます。

また、ボタンによる遷移は`PageView`に渡す`PageController`で制御します。

```dart
pageController.nextPage(
  duration: const Duration(milliseconds: 600),
  curve: Curves.easeInOut,
);
```

詳しくは公式のページを見るのがいいと思います。

https://api.flutter.dev/flutter/widgets/PageView-class.html


ドットのインジケーターは自前で実装しましたが、以下のような便利なパッケージもあるみたいです。

https://pub.dev/packages/dots_indicator
Kria K26にPYNQ3.0を入れようとしたらハマった

## ハマりポイント

- Kria K26でPYNQ3.0を動かすにはUbuntu22.04が必要。
- Kria K26の工場出荷時のファームウェアではUbuntu22.04が動かない。
- ファームウェアを更新するにはブラウザがFirefoxでないといけない。

## PYNQ3.0の導入手順

### 1. Kria K26 SOMのファームウェアをアップデートする
[XilinxのWiKi](https://xilinx-wiki.atlassian.net/wiki/spaces/A/pages/1641152513/Kria+K26+SOM#Boot-Firmware-Updates)を参考にしながらファームウェアをアップデートします。`xmutil`コマンドの使用が推奨されていますが、使い方が分からなかったため、`Stand-alone FW Update & Recovery Utility`のセクションを参考にしました。
1. PCに`BOOT_xilinx-k26-starterkit-v2022.1-09152304_update3.BIN`をダウンロードします。
1. PCとKria K26をLANで直繋ぎします。
1. Kria K26の`FWUEN`ボタンを押しながら12V電源を繋ぎます。
1. PCのネットワークの設定でIP等を以下のように設定します。
    - IP: 192.168.0.100
    - MASK: 255.255.255.0
    - Router: 192.168.0.1
1. 必ずFirefoxを使って http://192.168.0.111/ にアクセスします。
1. Image Aに`BOOT-***.BIN`をアップロードします。
1. 電源を切ります。

### 2. Ubuntu22.04のイメージをSDカードに焼きます。
- https://ubuntu.com/download/amd-xilinx
- 特に注意点はないです。

### 3. PYNQ3.0.1をインストールします。
- https://github.com/Xilinx/Kria-PYNQ/tree/v3.0#2-install-pynq
- 特に注意点はないです。

## その他
- 正攻法のFWアップデート法は[こちら](https://qiita.com/ikwzm/items/4e5e954eabc988bd78d5)とかかなと思います。
- 9V電源でも安定して動いているのですが問題ないんですかね。いつか壊れますか？
悪魔の双子攻撃 とは

## 勉強前イメージ

2つで一つみたいな攻撃？

## 調査

### 悪魔の双子攻撃 とは

英語でEvil Twinと言われていて、APフィッシングとも言われています。
偽のwifiアクセススポットを設置し、接続してきたユーザの通信を盗聴したりする攻撃になります。
フィッシング詐欺の一つになります。

なりすましのwifiもありますが、これはなりすましより巧妙で
正規のwifiと同様のネットワーク名で設置されていることが多く接続時の認証なども本物そっくりにされているケースがあります。
正規のwifiというのはコーヒーショップやショッピングモールなどのwifiを指し、それと瓜二つということで悪魔の双子と言われています。
挙動しては本物のwifi同様ネットワークへの中継は行いますが、攻撃者によって中身が盗聴されていて
クレジットカードの情報やサービスのIDやパスワードなどが盗まれてしまいます。

### 対策として

悪魔の双子攻撃の対策としては、基本的には怪しいwifiには繋がないこと。
またSSLの証明書エラーが出ていたりとかURLが違うなど違和感があるときは停止しましょう。
また、暗号化していても盗み見られるため個人情報のやり取りはしないようにしましょう。

## 勉強後イメージ

確かにハンバーガやさんとか無料wifiあるけど
名前同じだったらつなげてしまいそうなのもわかる

## 参考

- [野良Wi-Fi、なりすましWi-Fi（偽Wi-Fi）、悪魔の双子って？　フリーWi-Fiと何が違うの？　～危険性と対策](https://www.ntt-bp.net/column/blog/2021/07/post-50.html)
- [Evil Twin【エビルツイン】悪魔の双子攻撃 / Wiフィッシング / Wi-phishing](https://e-words.jp/w/Evil_Twin.html)
evision 0.1.27 の破壊的変更について

## はじめに

evision は Elixir で画像処理をするためのモジュールです

https://github.com/cocoa-xu/evision

私の記事でも度々使っています

https://qiita.com/RyoWakabayashi/items/f7960ba642dfbaa05a9c

https://qiita.com/RyoWakabayashi/items/ab9857ddd79cbbcf6506

https://qiita.com/RyoWakabayashi/items/0d6d3d37a9a8b05641c2

2023/1/23 から 2023/1/25 にかけて、 evision のバージョンが 0.1.25 から　0.1.28 まで更新されました

その更新内容に破壊的変更（使用しているコードを修正しないとエラーになる変更）が含まれているので、その変更内容と対応方法を残しておきます

## 変更内容

evision 0.1.27 において、定数を `Evision` から `Evision.Constant` に移動しています

- 0.1.25 以前

  `Evision.cv_IMREAD_ANY`

- 0.1.27 以降

  `Evision.Constant.cv_IMREAD_ANY`

また、破壊的ではない変更ですが、プリコンパイル済バイナリでも OpenCV contrib　の機能と、 CUDA が使えるようになりました

## 対応方法

`Evision.cv_` で始まる evision の定数を全て `Evision.Constant.cv_` に置換する必要があります

```diff_elixir
- Evision.cv_IMREAD_ANY()
+ Evision.Constant.cv_IMREAD_ANY()
```

もしくは以下のように Evision.Constant　を import するようにします

```diff_elixir
+ import Evision.Constant
- Evision.cv_IMREAD_ANY()
+ cv_IMREAD_ANY()
```

## 0.1.27 で発生したエラーについて

実は 0.1.27 時点で動かしたところエラーが発生したのですが、私が Issue を上げたところ一瞬で対応して 0.1.28 に上げてくれました

https://github.com/cocoa-xu/evision/issues/174

Thank you, [cocoa-xu](https://github.com/cocoa-xu)!

## おわりに

私のリポジトリーは一通り更新しました

https://github.com/RyoWakabayashi/elixir-learning

Qiita の記事も可能な範囲で更新しておきます
【2023年1月版】Ubuntu20.04でfluentdのクライアントインストール

# はじめに

- ubuntu22.04 でも fluentd で auth.log とかログ流ししたい

# インストール

- fluentdの本家を参照
    - [Install by DEB Package (Debian/Ubuntu)](https://docs.fluentd.org/installation/install-by-deb)

- 以下のスクリプトを実行

- Ubuntu 20.04の場合はfocal
```terminal
$ curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-focal-td-agent4.sh | sh
```

- Ubuntu 22.04の場合はjammy
```terminal
$ curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-jammy-td-agent4.sh | sh
```
# 設定

- /etc/td-agent/td-agent.conf を編集する

# さいごに

かんたんでしたね
ニフクラ mobile backendを拡張するNCMBプロキシ（監査ログ）

ニフクラ mobile backendでは認証やデータストア（クラウドデータベース）、ファイルストア（ファイルストレージ）、プッシュ通知など様々な機能があります。そして、サーバーレスで拡張できるスクリプト機能もあります。

しかし、実際のアプリ要件は多彩で、場合によっては他にも様々な機能が望まれます。すべての需要を満たすのは困難な場合もあります。そこで、NCMBのフロントとして動作するプロキシソフトウェアを開発中です。

このプロキシを使うことによって、小さなニーズはプロキシ側で実装できるようになります。今回紹介する機能はシステムログに使えるであろう監査ログを収集する機能です。

## 追加する機能（予定）

現状は透過的なプロキシでしかありませんが、以下のような機能を実装する予定です。

- 認証をJSON Web Tokenに
- GitHub認証
- ソーシャル認証（標準ではサーバー認証が必要ですが、プロキシだけで認証できるように）
- Webhooks

他にもデータストアの集計機能、GraphQL機能なども追加できると便利そうです。なお、Webhooksなどの機能はプロキシ経由でしか実現できませんので注意してください（管理画面で操作しても実行されません）。

## インストール

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)のリポジトリをクローンします。

```
git clone git@github.com:NCMBMania/ncmb-proxy.git
```

ライブラリをインストールします。

```
npm i
```

## 設定の編集

`setting.example.yml` をコピーして `setting.yml` を作成します。そして、ファイル内にあるアプリケーションキー、クライアントキーをそれぞれお持ちのものに書き換えてください。

```
applicationKey: YOUR_APPLICATION_KEY
clientKey: YOUR_CLIENT_KEY
```

## サーバーを起動

サーバーを起動する際には、以下のコマンドを実行します（まだ開発中なので、開発用サーバーが立ち上がります）。

```
npm run dev

```

例えばローカルの場合、 `http://localhost:3000` にてサーバーが立ち上がります。

## 使い方

監査ログを利用する場合には `setting.yml` にて `ncmb.audit` を `true` にしてください。デフォルトは `false` です。

```yaml
ncmb:
  applicationKey: YOUR_APPLICATION_KEY
  clientKey: YOUR_CLIENT_KEY
  domain: mbaas.api.nifcloud.com
  version: 2013-09-01
  audit: false # true にします
```

## コードについて

今回はJavaScript SDKでの使い方です。実際に利用するアプリケーション側でJavaScript SDKを初期化する際に、以下のように指定します。以下の例で分かるように、認証やデータストアとスクリプトは同じプロキシサーバーで提供されます。

```javascript
const ncmb = new NCMB("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY", {
	fqdn: "localhost",
	scriptFqdn: "localhost",
	protocol: "http",
	port: 3000
});

```

この `fqdn` や `protocol` 、 `port` を実際に運用するサーバーのものに書き換えて利用できます。本番運用できるレベルになったら、 `protocol` や `port` は不要でしょう。恐らく以下のようになるはずです。

```javascript
const ncmb = new NCMB("YOUR_APPLICATION_KEY", "YOUR_CLIENT_KEY", {
	fqdn: "example.com",
	scriptFqdn: "example.com",
});
```

これでJavaScript SDKは直接ニフクラ mobile backendにはリクエストせず、 `example.com` へリクエストするようになります。

## 監査ログについて

データストアの `_auditLogs` クラスにログが集積されます。データは次のようになっています。

| カラム | 内容 |
| --- | --- |
| method | リクエストしたHTTPメソッド |
| requestUrl | リクエストしたURL |
| query | リクエストしたクエリー |
| body | リクエストしたボディ（POSTまたはPUTの場合） |
| headers | リクエストしたHTTPヘッダー |
| response | レスポンス内容（JSONやバイナリ） |
| responseContentType | レスポンスのHTTPヘッダー |

これらがリクエストごとに記録されていきます。

![0653 console.mbaas.nifcloud.com - 0126183044.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/b900e4e6-1088-6ca9-8ab9-ea4f66245db0.jpeg)


### アクセス管理

`Administrator` というロールに対して読み書き権限を付与しています。このロールを作成し、そのロールに所属するユーザーはSDK経由でアクセス可能になります。よりセキュアにする場合は `_auditLogs` クラスのクラスパーミッション設定より、外部からの読み書きを不可にするなどの対応をしてください。もちろん管理画面からはいつでも読み書きできます。

## 注意点

リクエストごとに記録されるので、1回のAPIリクエストに対して2回APIリクエストが消費されます。将来的に記録する内容を絞り込めるようにする予定です。

ファイルストアのHTTPS公開を有効にした場合、そのリクエスト（HTTPS経由でのリクエスト）は記録されません。あくまでもプロキシを経由したAPIリクエストのみ記録されます。

現状、認証時のパスワードが平文で記録されます。将来的にマスキングします。

## まとめ

ニフクラ mobile backendは便利なmBaaSですが、企業要件によってはよりセキュア、安全に使いたいという声もあるでしょう。監査ログ機能を付けることで、セキュリティインシデントに対して予防措置が取れるようになるので、より安全に活用できます。

開発はまだまだこれからですが、ぜひご期待ください。

[NCMBMania/ncmb-proxy](https://github.com/NCMBMania/ncmb-proxy)
アプセトネデブ

### 1層　物理層
    いわゆるコンピュータ同士がデータをやりとりする際に使うケーブルなどを指す
    コネクタの形状であったりケーブルの種類であったり

    データをを物理的な電気信号に変換し、目的のコンピュータに届ける役割  

### 2層　データリンク層
    MACアドレス(Media Access Control address)
    ネットワークにつながるすべての機器に割り当てられている
    データ転送対象の機器の判別、直接接続され機器同士の通信の役割
### 3層　ネットワーク層
    IPアドレス（インターネットプロトコルアドレス）など
    インターネットに接続できる機器すべてにIPアドレスが割り当てられている

    インターネット空間による宛先を管理する規定

    データを最終的な目的地まで送り届ける機能
### 4層　トランスポート層
    ポート番号、TCO,UDP
    コネクションの確立や切断処理
    https://net-skills.net/intro-menu1/communication-tcpudp/
### 5層  セッション層
    SSL接続
    コネクションの確立、データ転送に関する管理
### 6層  プレゼンテーション層
    データの表現形式の差異を吸収する役割
### 7層　アプリケーション層
    ユーザーが実際に利用するソフトウェアの中でネットワーク通信にかかわる部分
Pleasanterのリンクで自テーブルにリンクする

# 前置き
Pleasanterにはテーブル間の親子関係をしていする、[リンク](https://pleasanter.org/manual/table-management-choices-text-link)という機能があります。

通常は、2つ以上のテーブルにおいての連携を指定するのですが、自テーブルにもリンクが設定できます。一見使いどころが無さそうですが、ちょっとマニアックな利用例です。

# 作るもの
見積もりの工数を管理するテーブルを作ってみます。イメージは以下。

親／見積もりテーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/b5d73665-8ced-62c2-9770-f43d12a4a5a6.png)

子／見積明細テーブル
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/f6813aae-1754-b330-b700-b194d4944c0e.png)

ベースとなるアプリの構成としては、明細を束ねる親／見積もりテーブルと、タスクごとの見積明細を管理する子／見積明細テーブルです。

なお、見積もりテーブルと見積明細テーブルのリンクは通常のリンク設定をしています。

# 見積明細の仕様

明細を切り出します。(Excel)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/ae8b4a8e-c7ec-5a69-c10d-73efbd506871.png)
合計については、子／見積明細テーブルから親／見積もりテーブルへの[サマリ機能](https://pleasanter.org/manual/table-management-summary)で簡単に実現は可能です。

明細の、「５．テスト実施の項目」について以下のような要件であったとします。

```text
開発作業合算 × 0.3
```

示した明細例だと、開発作業は１．テーブル基本設定～４．一覧表示設定までの合算 × 0.3 つまり、
(16h + 23h + 24h + 8h) × 0.3 = 24h
となります。

Excelの関数で実現すると以下のとおり
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/60d71336-8113-f98f-dde6-65ee11b1401e.png)

これを、Pleasanterで実現します。

# Pleasanterの設定

見積明細テーブルの詳細画面です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/922382/0989cb06-a155-6f39-7343-b5faf4bad665.png)
「対象明細」に自分自身のサイトに対するリンクを設定しています。自レコードまで含めた自テーブルの内容が選択肢一覧に表示されます。

リンクの設定は以下のとおり(テーブルの管理>エディタ>項目「対象明細」の選択肢一覧の設定内容)
```json
[
  {
    "SiteId": 314967,
    "View": {
      "Id": 0,
      "ColumnFilterExpressions": {
        "ClassA": "[@ClassA]"
      },
      "ColumnFilterSearchTypes": {
        "ClassA": "ExactMatch"
      },
      "ApiColumnKeyDisplayType": 0,
      "ApiColumnValueDisplayType": 0,
      "ApiDataType": 0
    }
  }
]
```
特に難しいことは無く、リンクするサイトIDに自分自身のサイトIDを指定しています。また、親／見積もりテーブルに紐づく明細のみを表示させるため、[選択肢一覧を他の項目で絞り込む](https://pleasanter.org/manual/table-management-choice-json-column-filter-expressions)機能で、絞り込みをします。ClassAに親サイトのリンクを設定しているため、この記述で”親サイトが自分のレコードを同じも出絞り込む”ことができます。

こうすることで、親／見積もりテーブルに紐づく明細が選択肢一覧から選択できるようになります。

選択した情報をもって、テスト実施の工数を計算し「作業工数(h)」へ設定します。(サーバスクリプト)
```javascript
try{
    //対象明細(ClassB)に選択がある場合、計算対象
    if(model.ClassB){
        let idList = JSON.parse(model.ClassB);
        let total = 0;
        if(idList.length > 0){
            //選択肢をループして、各レコードの工数(NumA)を合算
            for (let id of idList) {
                let result = items.Get(id);
                if(result.Length > 0){
                    total += result[0].NumA;
                }               
            }
            model.NumG = total;
            //合算値に工数割合(NumF)をかけて作業工数を算出
            model.NumA = total * model.NumF;
        }    
    }
}catch{
    context.Log(e.stack);
}
```

# おわり
あまり、利用シーンは多くないかもしれませんが、こういった使い方もできる、という一例として投稿してみました。
Ubuntuの主要ログファイルメモ

# はじめに

すぐに忘れてしまうUbuntuの主要ログファイルリストのメモ

# 主要ログファイル 

## 認証周り

| 場所 | 説明 | 形式 |
|:-----------------|:------------------|:------------------|
| /var/log/wtmp | ログインユーザーおよび利用時間、システムのリブート情報(last)。 |バイナリ|
| /var/log/btmp |パスワード認証の失敗など不正なログイン履歴(lastb)。 |バイナリ|
| /var/log/lastlog | ユーザー単位で最終ログイン情報(lastlog)。 |バイナリ|
| /var/log/auth.log | システムへのログイン履歴情報 |テキスト|

## システム関連

| 場所 | 説明 | 形式 |
|:-----------------|:------------------|:------------------|
| /var/log/syslog | システムログ |テキスト|
| /var/log/kern.log | カーネルログ |テキスト|
| /var/log/boot.log | 起動ログ |テキスト|
| /var/log/dmesg |起動時のカーネルログ|テキスト|
| /var/log/apt/history.log | aptのログ |テキスト|

## メール関連

| 場所 | 説明 | 形式 |
|:-----------------|:------------------|:------------------|
| /var/log/maillog |メールログ|テキスト|

# 参照

- `/etc/rsyslog.conf`
- `/etc/rsyslog.d/*.conf`

# さいごに

すぐに忘れる
Dockerイメージのビルドの際にはapt-get updateの結果がキャッシュされないようにしよう

# 事象

aptパッケージをDockerfileに追加してビルドするとエラーが出た

```Dockerfile
RUN apt-get update
RUN apt-get install -y build-essential ~~some_packeges~~ vim ← vimを追加した
```

```
E: Failed to fetch http://deb.debian.org/debian-security/pool/updates/main/libk/libksba/libksba8_1.3.5-2+deb10u1_amd64.deb  404  Not Found [IP: 151.101.110.132 80]

E: Unable to fetch some archives, maybe run apt-get update or try with --fix-missing?
```
以下から探してみると確かに存在しない
http://security.debian.org/debian-security/

エラーメッセージによると`apt-get update`するか`--fix-missing`オプションをつければいいらしい

が、Dockerfileではすでに`apt-get update`している

# 原因
`apt-get update`の結果がキャッシュされていたため、すでに存在しない古いパッケージをインストールしようとしていたのが原因
```
Step 3/32 : RUN apt-get update
---> Using cache
```
今まではインストールするパッケージ一覧に変更がなかったため、`apt-get install`においてもキャッシュを使っていたので問題にならなかったが、今回はvimを追加したため、Dockerがキャッシュを使わずにインストールしようとする
にも関わらず、`apt-get update`の結果は引き続きキャッシュを使うので、古いパッケージを探しにいった結果当該パッケージが見つからずにエラーになったようだ

# 解決
`apt-get update`と`apt-get install`を同一の`RUN`で行うようにDockerfileを以下のように修正

```Dockerfile
RUN apt-get update \
  && apt-get install -y build-essential ~~some_packeges~~ vim
```
これで`apt-get install`の内容に変更があると`apt-get update`もキャッシュを破棄して実行するようになる
毎回キャッシュを破棄するとビルド時間が悪化するので、変更があったときだけキャッシュを破棄するようにした

Dockerイメージのビルドキャッシュの効率的利用や軽量化、高速化については突き詰めだすと際限がないので、最終的なイメージサイズ、ビルド時間が許容範囲であれば、属人化しないように可読性を優先すべきだと思うこの頃です
Azure Reposでブランチ名を変更する

# はじめに
GitHubではブラウザ上でブランチ名の変更ができるのですが、Azure Reposではブラウザ上からは直接ブランチ名の変更ができません。
そのためAzure Repos上でブランチ名を変更するためには、変更したいブランチをベースに新しいブランチを作成することで任意の名前を設定することができます。

# 手順
#### シナリオ
今回の手順ではデフォルトブランチのブランチ名を変更したい場合を想定し説明致します。

#### フロー概要
1. デフォルトブランチをベースに新規ブランチの作成
1. 新規ブランチの作成で任意の名前を設定
1. 上記の新規ブランチをデフォルトブランチに設定する


#### 手順詳細

ここではmainブランチをproductionに変更したいとします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/0c532d82-97a6-7363-66e1-6016f49d9ba9.png)


New branchで新規ブランチを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/397d89ed-23fe-41de-13bb-a4dcac99868f.png)

Nameに任意の名前を入力し、Based onにブランチ名を変更したいブランチを選択します。
今回はproductionに変更したいので、Nameにproduction、Baseにmainブランチを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/520ae599-78ca-b7cd-cd02-3c6b766aa942.png)

これで名前がproductionのmainブランチの複製ができました。
次にproductionブランチをデフォルトブランチに変更します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/e4c6e6ed-c21c-c505-de06-7049a281ac04.png)


productionブランチの右側の三点リーダーを選択し、「Set as default branch」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/1e80988d-817a-0d87-1616-07dbb9c91023.png)

productionブランチがデフォルトブランチになっていること確認できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1293404/99ac76c8-1707-5f5d-42ba-1ba56ee77b6f.png)


# まとめ
Azure Reposでは一度作成してしまったブランチの名前を現時点ではポータル上からは直接変更ができないようでした。
そのため、変更したいブランチをベースに複製して名前を変更する手順について説明しました。
サクラエディタのgrep機能

windowsフォルダを網羅的に検索できる機能。
かなり軽くてとても使いやすいです。
サクラエディタを開いてctrl+gで使えます。

おすすめ機能として、

grep条件にaaa
ファイルに *.* !*.zip
と書くと、"aaa"という文字列をzipファイル以外の全ファイル（ファイルの中身まで）検索してくれます。
[FAQ] 「'react-scripts' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。」の対処

# 事象
`npm start`あるいわ`yarn start`コマンドで以下のエラーが発生する。
※ yarn とは 2016 年にFacebookがリリースした npm と互換性のあるパッケージマネージャー

```console
PS C:\myproject> npm start

> myproject@0.1.0 build
> react-scripts build

'react-scripts' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
```

# 解決方法
```console
npm install react-scripts
```
※ npm 5.0.0 以降からは install 時にデフォルトで `package.json` の `dependencies` に追加してくれるので `--save` や `-S` オプションを指定する必要はない。
Laravel(PHP8) RefreshDatabaseが使えない!?

# 概要
RefreshDatabaseをPHP8系で利用するとエラーになり、ユニットテストができないようです。
対処方法はいくつか考えられますが、おすすめの2パターンを紹介します。
プロジェクトやテスト内容に応じて、お好きな方をお使いいただければと思います。
もし、この方法がいいよ、などあればコメントにて教えてください。

# 環境
- PHP 8.0.9
- Laravel Framework 8.83.27
- PHPUnit 9.5.28

# RefreshDatabaseを使うと遭遇するエラー
RefreshDatabaseを使うと以下のエラーに遭遇します。

```shell
PDOException: There is no active transaction

/var/www/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:279
/var/www/vendor/laravel/framework/src/Illuminate/Database/Concerns/ManagesTransactions.php:254
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/RefreshDatabase.php:105
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:246
/var/www/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:158
```

このエラーについては、[[8.x] Fix error PDOException: There is no active transaction ](https://github.com/laravel/framework/pull/35988)でも議論されているようです。


# 解決策
## 1. Traitを`RefreshDatabase`から`DatabaseMigrations`に変える

### 変更内容

```diff_php:コード
namespace Tests\Unit;

- use Illuminate\Foundation\Testing\RefreshDatabase;
+ use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;

class SampleTest extends TestCase
{
-     use RefreshDatabase;
+     use DatabaseMigrations;
```

エラーは出なくなりますが、DatabaseMigrationsは`migrate:fresh`を都度行います。
`migrate:fresh`コマンドは、データベースからすべてのテーブルを削除したあと、migrateコマンドを実行します。そのため、処理に時間がかかります。

### 実行結果

```shell
./vendor/bin/phpunit tests/Unit/SampleTest.php
PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

......                                                              6 / 6 (100%)

Time: 00:36.298, Memory: 22.55 MB

OK (6 tests, 6 assertions)
```

## 2. `setUp()`で`migrate`と`truncate`を行う

### 変更内容
ユニットテスト内で`setUp()`をオーバーライドして、`migrate`の実行とテストに必要なテーブルの`truncate`を行います。

```php
namespace Tests\Unit;

use App\Models\Sample;
use Tests\TestCase;

class SampleTest extends TestCase
{
    public function setUp(): void
    {
        parent::setUp();
        $this->artisan('migrate');
        Sample::truncate();
    }
```

`migrate`は未処理のマイグレーションのみ実行します。
テーブルの初期化をする必要がある場合は対象となるテーブルのみ`truncate`しましょう。

`※ 処理済みのマイグレーションファイルを編集など行なった場合にもマイグレーションの再実行はされないので注意が必要です。`

### 実行結果

```shell
./vendor/bin/phpunit tests/Unit/SampleTest.php
PHPUnit 9.5.28 by Sebastian Bergmann and contributors.

......                                                              6 / 6 (100%)

Time: 00:12.223, Memory: 22.55 MB

OK (6 tests, 6 assertions)
```

1.のDatabaseMigrationsを利用した場合と比較すると約3倍早いですね。。。

# まとめ
個人的には、開発初期段階や比較的小さいプロジェクトであれば`DatabaseMigrations`を利用する方法で良いと思います。しかし、中規模以上のプロジェクトでマイグレーションするテーブルやファイルが多い場合、ユニットテストに時間がかかり過ぎてしまいかなり非効率です。この辺りはプロジェクトに応じてご検討いただければと思います。

# 参考文献
- [【Laravel8・PHP8】PHPUnitのテストケースの中でseedingするとPDOException](https://zenn.dev/y640/articles/qiita-20210807-1db7786d2db36cfabe05)
Bashでビンゴゲーム

# はじめに
Bashで配列の扱い方とWhile Do ～ Doneの扱い方を学ぶのにちょうどいいものを探した結果、ビンゴゲームを作るという課題を思いついた。

## 注意
ビンゴカードを配って、ビンゴカードの数字と出たボールの数字をチェックし、BINGOとする処理は省いてます。


# コード

```bash:BingoGame.sh
#!/bin/sh

# ビンゴゲームに入れるボールを宣言
bingogame=(0 1 2 3 4 5)
history=()

# 条件を満たすまで無限ループ
#while:
do

# ゲーム操作の入力
read -p "Are You Ready? ( START / END / HISTORY):" operation

# ゲーム処理
case $operation in
  "START")

  # ビンゴゲームの中のボールが空になったらゲーム終了
  if [ ${#bingogame[@]} -eq 0 ]; then
    echo "Game Over !!"
    exit 0
  fi

  # ビンゴゲームをぐるぐる回してボールを出した
  element = $((RANDOM % ${ #bingomane[*] } ))

  # ボールを読み上げる
  getball={$bingogame[$element]}
  echo $getball

  # ボールを再抽選させない箱に放り込む  
  history+=getball

  # 取り出したボールをビンゴゲームに戻さない
  unset bingogame[$element]
  # インデックスを完全に削除してその分を詰める
  bingogame=( ${bingogame[@]} )
  ;;

  # 任意のタイミングでビンゴゲームを終わらせる
  "END")
  echo "Game Over !!"
  exit 0
  ;;

  # 今まで排出されたボールを読み上げる
  "HISTORY")
  echo ${history[@]}
  ;;

  # デバッグ用。ビンゴゲームの中にある数字を読み上げる
  "NOKORI")
  echo ${bingogame[@]}
  ;;

esac

done

# お終い
exit 0
```


# 参考

https://syutaku.blog/bash-array-unset-note/

https://qiita.com/satoshi-baba-0823/items/aed201ded17679dddaea
【Laravel】イミュータブルにCollectionのN番目の要素を取り出す

# ゴール
- 元のCollectionの値を変えずにCollectionのN番目の要素を取得する
- `Undifined Index`, `Undifined Offset`を発生させない

以下5番目の値を取得する場合の方法を記載する

# 方法1

```php:OK１
$item = $collection->values()->get(4);
```

`get()`の引数はindexで指定する。

https://stackoverflow.com/questions/24443949/how-to-access-the-nth-object-in-a-laravel-collection-object


https://gist.github.com/vielhuber/cf35a39fcbd7115c1e94a25e0d9fc491


https://readouble.com/laravel/8.x/ja/collections.html#method-values


# 方法2

```php:OK2
$item = $collection->skip(4)->first();
```

`skip($n)`は`$n`個分先頭から要素を削除した新しいcollectionを作成する。

https://readouble.com/laravel/8.x/ja/collections.html#method-skip

# 方法3

```php:OK3
$collection->slice(4, 1)->first();
```

`slice(開始index, 取得する個数)`

https://readouble.com/laravel/8.x/ja/collections.html#method-slice

# 方法4

```php:OK4
$collection[5] ?? null;
// 5番目の要素がない場合はnullを返す
```

https://wiki.php.net/rfc/isset_ternary

# NG1

```php:NG1
$item = $collection[4];
// 要素が5つ未満の場合エラーが発生する
// => Undefined offset: 4
```

# NG2

```php:NG2
$collection = collect([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
$item = $collection->shift(4)->last(); // 5

// $collection自体を書き換えてしまう
$collection->all(); // [6, 7, 8, 9, 10]
```

https://readouble.com/laravel/8.x/ja/collections.html#method-shift
Redshiftでよく使う「先月月初」「今月月初」をユーザー定義関数(UDF)に置き換えてみた

## はじめに
RedshiftのUDFを使ったことがなかったのでその備忘録になります。

## シチュエーション例
Redshiftで、先月のデータを取得したい、みたいな要件が多々あります。
でも毎回先月月初、今月月初を書くのが大変。

```sql
/**
 * 先月生成されたデータを取得
 */
SELECT * FROM table_name
WHERE
     created_at >= DATE_TRUNC('month',ADD_MONTHS(CONVERT_TIMEZONE('JST', GETDATE()), -1)) -- 先月月初から
AND  created_at < DATE_TRUNC('month',CONVERT_TIMEZONE('JST', GETDATE())) -- 今月月初未満
```

「先月月初」「今月月初」みたいなよく使う定義を
ユーザー定義関数(UDF)にしてみたらどうかな...と思いやってみます

## 対応
### 今月月初
```sql
CREATE FUNCTION f_first_day_of_this_month ()
  RETURNS datetime
STABLE
AS $$
  SELECT DATE_TRUNC('month',CONVERT_TIMEZONE('JST', GETDATE()))
$$ LANGUAGE sql;  
```

### 先月月初
```sql
CREATE FUNCTION f_first_day_of_last_month ()
  RETURNS datetime
STABLE
AS $$
  SELECT DATE_TRUNC('month',ADD_MONTHS(CONVERT_TIMEZONE('JST', GETDATE()), -1))
$$ LANGUAGE sql;  

```

使用例
```sql
/**
 * 先月生成されたデータを取得
 */
SELECT * FROM table_name
WHERE created_at >= f_first_day_of_last_month()
AND created_at < f_first_day_of_this_month()
```

## まとめ
UDFでちょっとだけ楽になりました。
ただ、、、僕自身が使い慣れていないので今後活用していくかは様子を見ていきます。


## 文献
https://docs.aws.amazon.com/ja_jp/redshift/latest/dg/udf-creating-a-scalar-sql-udf.html
【GAS】ログの色を変更したい

# はじめに
インターン先でGASを使用して社内ツールを作成する機会がありました。
ログが見にくいなと思い、ログに色をつけることはできないか調べたところ方法があったので記録しておきます。

# やりかた
```javascript
// 白
console.log("白色です")
// 黄
console.warn("黄色です")
// 赤
console.error("赤色です")
```

# おわり
ログが見やすくなりました！
制作したばかりのホームページでGoogleインデックス登録をするまで

# 自社ホームページを制作してみたが数日経っても社名Google検索に引っかからないので調べてみた

### Google(グーグル)公式のSEOガイドライン10項目
Googleが公式に発表している [検索エンジン最適化（SEO）スターター ガイド](https://developers.google.com/search/docs/fundamentals/seo-starter-guide?hl=ja)　で以下が項目として記載されている。

- Google がコンテンツを見つけられるようにする
- クロール対象外のページを Google に指示する
- Google（とユーザー）がコンテンツを理解できるようにする
- Google 検索結果での表示を管理する
- サイトの階層を整理する
- コンテンツを最適化する
- 画像を最適化する
- サイトをモバイル フレンドリーにする
- ウェブサイトを宣伝する
- 検索のパフォーマンスとユーザーの行動を分析する

大まかに以下に分かれるが
**Google側で必要な打ち手**
**自社コンテンツで必要な打ち手**
今回はGoogleでコンテンツを見つけて貰えていない可能性が高いため、
Googleが提供している [Google Search Console](https://search.google.com/search-console/welcome) を利用して、ホームページの状況確認を行うことにした。

### Google Search Consoleを利用するまで

1\.　[Google Search Console](https://search.google.com/search-console/welcome)へアクセスすると、最初にプロパティタイプの選択が求められる
※今回は **ドメイン** を選択してWebページ管理者の登録を行う。
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120185/6acbfda6-c787-8bc4-1646-d9381a717d25.png">

2\. 登録に際してDNSレコードの登録が求められるので、ナビゲーションに従って公開サーバーのDNSに記載のDNSレコードを追加
※自社ホームページはAWSで構築しています
※DNSレコードの追加後、反映までに多少の時間が必要です

3\. DNSレコード追加後、しばらくして **続行** を押下すると Google Search Console のトップページへ遷移する

### Google Search Consoleで試したこと

Google Search Console にアクセスすると添付の表示になっていた。
※インデックス登録がされていない状況であることを確認
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120185/235af3d4-08d8-d076-e7bb-5cf622a070ef.png">

インデックス登録のためにsitemap.xmlファイルを作成して公開環境へ配置して**新しいサイトマップの追加**を実施。
※sitemap.xmlファイル作成用のgeneratorは複数存在しているが、今回は[このサイト](https://www.mysitemapgenerator.com/)を利用
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120185/2fb48459-327e-8990-8d8b-d81d7d70b0c5.png">
※何度か失敗しているが、最終的にステータスが「**成功しました**」になっている

その後**URL検査**に戻り「**インデックス登録をリクエスト**」を実施。
反映には数日かかるため、数日後に改めて状況を確認する必要がある。
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3120185/5e38752c-cb7a-99cd-0cde-de54bdd1720c.png">

***

ここまでが今回試した内容。
Goodleでのインデックス登録完了後もSEOの状況を判断してコンテンツ内のコード調整が必要になる認識だが、ひとまずはGoogle検索ができるようになること願って様子をみてみることとする。
Excelの元号がどこまで入るのか試してみた

# 概要

Excelは日付フォーマットで元号を指定することができます。
元号はどこまで対応しているのか疑問になったので実際に試してみました。

## Excelの日付フォーマット

日付列のフォーマットは「yyyy/mm/dd」に設定します。

![ScreenShot-2023-01-26-16.52.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/bc96a4da-b545-ae6d-5054-565400521e0e.png)

元号列は「=A2」とA列の値を参照するようにして、日付フォーマットを「和暦」のスタイルに設定します。

![ScreenShot-2023-01-26-16.52.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/ca6da8a0-e021-5576-58c1-2071b3de42f4.png)

結果として１９００/1/1から対応していました。
元号の区切りでなく、年の区切りだったみたいです。

![ScreenShot-2023-01-26-16.53.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/81113/5b054184-a9f1-ee82-b21a-496d98ea00a8.png)
macのvscodeでpdfを開くと応答なしになる

もしかしてyabaiを使っていませんか？
私の環境では，yabaiを停止したところ何の問題も起きなくなりました．

ちなみに，focus follow mouse機能を使用したいだけの場合，[AutoRaise](https://github.com/sbmpost/AutoRaise)が使えます．
今の所，このアプリの使用中にpdfを開いても何も問題が起きません．