OmniAICreator/Qiita-1.07M huggingface dataset:
JavaScriptでMapのキーにオブジェクトを使う際の注意点と解決方法

JavaScriptの`Map`は、キーと値のペアを保持するための便利なデータ構造です。

しかし、キーとしてオブジェクトを使用する場合には注意が必要です。

以下のコードが`undefined`を出力する理由とその対策について説明します。

```js
const map = new Map();
map.set({a: 1}, "foo");
console.log(map.get({a: 1})); // "undefined"と表示される
```

## 問題の原因
上記のコードでは、mapにオブジェクト`{a: 1}`をキーとして値`foo`をセットしています。

同じ形状のオブジェクト`{a: 1}`を使って値を取得しようとすると、`undefined`が表示されます。

これは、JavaScriptではオブジェクトが参照によって比較されるためです。`map.set`で使用したオブジェクトと`map.get`で使用したオブジェクトは異なるメモリ参照を持つため、同じキーとは認識されません。

## 解決方法
この問題を解決するための方法をいくつか紹介します。

### 1. 同じオブジェクト参照を使用する
```js
const map = new Map();
const key = {a: 1};
map.set(key, "foo");
console.log(map.get(key)); // "foo"と表示される
```

同じオブジェクト参照を使用することで、期待通りの結果が得られます。

### 2. プリミティブ値をキーとして使用する
```js
const map = new Map();
const key = JSON.stringify({a: 1});
map.set(key, "foo");
console.log(map.get(JSON.stringify({a: 1}))); // "foo"と表示される
```

オブジェクトを文字列に変換してキーとして使用します。同じ構造のオブジェクトは同じ文字列になるため、意図した通りに動作します。

### 3. WeakMapの使用
```js
const map = new WeakMap();
const key = {a: 1};
map.set(key, "foo");
console.log(map.get(key)); // "foo"と表示される
```

`WeakMap`を使用することで、オブジェクトがガベージコレクションの対象になります。キーとしてオブジェクトを使用し、同じ参照を保持する場合に有効です。

以上が解決方法となります。

## 最後に
実装でハマってしまい、学んだはいいものの、すぐに忘れてしまいそうなので記事に残しました。
PlantUMLのspriteを使いこなす

# 試した環境
dockerhubの[plantuml/plantuml-server:v1.2024.5](https://hub.docker.com/layers/plantuml/plantuml-server/v1.2024.5/images/sha256-1e78335d6d5c129387936c74a817b78c0274b3d48b9974ace64a9b0d24cd97b1?context=explore)

# 動機
PlantUMLではsprite(二次元のビットマップ画像)をテキスト中やステレオタイプに指定することができます。

[スプライトの定義と使用](https://plantuml.com/ja/sprite)や[PlantUML 標準ライブラリ](https://plantuml.com/ja/stdlib)をよく読めばわかるのですが自分の備忘録のためにもspriteの見つけ方と使い方を記載しておこうと思います。

# 利点
サーバーを表現するときは
```plantuml
@startuml
node XXServer
@enduml
```

とかとりあえずnodeで記載したりするのですが
```plantuml
@startuml
!include <logos/apache>
node XXServer <<$apache>>
@enduml
```
とか
```plantuml
@startuml
!include <logos/nginx>
node XXServer <<$nginx>>
@enduml
```

で視覚的にわかりやすくなります。


# 見つけ方

```text
@startuml
listsprite
@enduml
```

と入力すれば

```plantuml
@startuml
listsprite
@enduml
```

と一覧が表示されます。しかしこれはデフォルトで規定されているArchiMateの一覧です。

```text: 注:動かないです
@startuml
!include <archimate/Archimate>

listsprite
@enduml
```

の省略形です。(だと思います)
他のspriteの一覧を見たい場合はincludeを記載する必要があります。

## office

```text
@startuml
!include <office/all>
listsprite
@enduml
```

```plantuml
@startuml
!include <office/all>
listsprite
@enduml
```

## azure

```text
@startuml
!include <azure/all>
listsprite
@enduml
```

```plantuml
@startuml
!include <azure/all>
listsprite
@enduml
```

## include指定文字列の見つけ方

じゃあincludeに何を記載すれば見られるのかという話ですが、

[plantuml-stdlib](https://github.com/plantuml/plantuml-stdlib/tree/master)を見に行けばわかります。



たとえばofficeの一覧を見たい場合、サイトを見に行くと[office/all.puml](https://github.com/plantuml/plantuml-stdlib/blob/master/office/all.puml)があるので

```text
@startuml
!include <office/all.puml>
listsprite
@enduml
```

と入力すれば一覧を表示してくれます。puml拡張子はなくても大丈夫です。
all.pumlがない分類もあるのでその際は一個ずつみるかweb上でみるしかないと思います。

```text:参考としてapache
@startuml
!include <logos/apache>
listsprite
@enduml
```

```plantuml
@startuml
!include <logos/apache>
listsprite
@enduml
```

### とりあえず画像一覧が見れる場所

* [gilbarbara-plantuml-sprites](https://github.com/rabelenda/gilbarbara-plantuml-sprites/blob/master/sprites-list.md)

# 使い方

## 文章中に埋め込む

**<$名称>** をダブルクォーテーション中に入れれば表示されます。

```text
@startuml
!include <office/Servers/web_server>
node "文章の中に<$web_server>web_serverを埋め込む"
@enduml
```

```plantuml
@startuml
!include <office/Servers/web_server>
node "文章の中に<$web_server>web_serverを埋め込む"
@enduml
```

includeの指定はallがあればall指定でもいけました。
```text
@startuml
!include <office/all>
node "文章の中に<$web_server>web_serverを埋め込む"
@enduml
```

## ステレオタイプに埋め込む

ステレオタイプの中に **$名称** を入れれば表示されます。
```text
@startuml
!include <office/Servers/web_server>
node "ステレオタイプに表示する。" <<$web_server>>
@enduml
```

```plantuml
@startuml
!include <office/Servers/web_server>
node "ステレオタイプに表示する。" <<$web_server>>
@enduml
```

ステレオタイプにspriteと文字を同時には指定できないかもです。
方法わかる方いればご教示願います。

## ArchiMateの場合
デフォルトに設定されているせいか少し書き方が違いました。

```text
@startuml
node "device" <<$archimate/device>>
@enduml
```

```plantuml
@startuml
node "device" <<$archimate/device>>
@enduml
```

# 終わりに
公式サイト以外にあんまり解説しているサイトを見つけることが出来なかったため、書いてみました。
誰かの一助になれば幸いです。
ffmpeg 複数のmovファイルをコマンドでまとめて連結させる

## 目的

特定のディレクトリにある40個の動画ファイルを連結させたかった

## 準備

- ffmpeg のインストール
  - https://ffmpeg.org

## コマンド

```shell-session
$ ls -1v *.mov | sed 's/^/file /' > filelist.txt
$ ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mov
```

## 補足

```shell-session
$ ls -1v *.mov | sed 's/^/file /' > filelist.txt
```

- `ls -1v *.mov`: .mov ファイルを名前順にリスト表示
- `sed 's/^/file /'`: 各ファイル名の前に `file` を追加
- `> filelist.txt`: リストを `filelist.txt` に保存

```text:filelist.txt
file aaa.mov
file bbb.mov
file ccc.mov
```

```shell-session
$ ffmpeg -f concat -safe 0 -i filelist.txt -c copy output.mov
```

- `-f concat`: 連結モードを指定
- `-safe 0`: ファイル名にスペースが含まれている場合でも安全に処理
- `-i filelist.txt`: 入力リストファイル
- `-c copy`: エンコードせずにコピー
- `output.mov`: 出力ファイル名
PHPで画像ファイルのバイト数を取得する方法

## 目次
1. 画像ファイルの存在確認
2. 画像ファイルのバイト数を取得

## 1. 画像ファイルの存在確認

まず、画像ファイルが指定したパスに存在するかどうかを確認する必要があります。
これには、`file_exists` 関数を使用します。

```php
<?php
// 画像ファイルのパス
$imagePath = 'path/to/your/image.jpg';

// 画像が存在するか確認
if (file_exists($imagePath)) {
    echo '画像ファイルが存在します。';
} else {
    echo '画像ファイルが存在しません。';
}
?>
```

### `file_exists` 関数の解説
`file_exists` 関数は、指定されたファイルまたはディレクトリが存在するかどうかを調べます。
ファイルやディレクトリが存在する場合は `true` を返し、存在しない場合は `false` を返します。
これにより、ファイルの存在を事前に確認することができ、存在しないファイルを操作しようとしてエラーが発生するのを防ぎます。

## 2. 画像ファイルのバイト数を取得

次に、画像ファイルのバイト数を取得します。
これは `filesize` 関数を使用します。`filesize` 関数は指定したファイルのサイズをバイト単位で返します。


```php
<?php
// 画像ファイルのパス
$imagePath = 'path/to/your/image.jpg';

// 画像が存在するか確認
if (file_exists($imagePath)) {
    // 画像のバイト数を取得
    $fileSize = filesize($imagePath);
    
    // バイト数を表示
    echo '画像のバイト数: ' . $fileSize . ' bytes';
} else {
    echo '画像ファイルが存在しません。';
}
?>
```


### `filesize` 関数の解説
`filesize` 関数は、指定されたファイルのサイズをバイト単位で返します。
ファイルサイズが必要な場合、例えばファイルのアップロード制限をチェックする場合やディスク使用量を計算する場合に便利です。
ただし、ファイルが存在しない場合や読み取り権限がない場合にはエラーが発生する可能性があるため、事前に `file_exists` 関数でファイルの存在を確認することが推奨されます。

以上
AWSのRDSの復旧方法について

# デーべベースでDELETEを実行してしまった。

先日本番のデータベースの作業を行っているときに誤ってDELETEを実行してしまい、データベースの一部を削除してしまいました。無事復旧でしたので手順を残しておきます。

# はじめに

**まずは落ち着いてください！！**

これが一番重要です。どうにかなります。
タバコでも吸うなり、飲み物を飲むなりして落ち着いてください。(味はしない)
焦って作業を行うと二次災害を起こしかねません。

# バックアップから新たなデータベースを作成
1. AWSのRDSから自動バックアップを選択します。
2. 対象のデータベースインスタンスを選択して、アクションから特定地点の復元を選択します。
3. カスタム日時を選択して、DELETEする前の日時を選択します。
4. 元のデータベースの情報を見ながら、設定を行っていきます。(接続の設定を同じにしないと接続できなかったりするので注意)
5. 必要な項目を選択したら特定時点への復元を押下します。
6. 数十分したらバックアップからデータベースが作成できるかと思います。

# dumpを作成
1. データベースの作成が完了したらターミナルからdumpを行います。
`mysqldump -u ユーザー名 -pパスワード -h エンドポイント --hex-blob DB名 テーブル名 --where="条件" > 任意のファイル名.sql`
※ここで接続できない場合は、データベースの作成時の設定に不備があるので、セキュリティグループなどの確認してみてください。
1. 作成したdumpファイルに不備がないか、エディタで確認します。

# リストア
以下のコマンドでリストアを行います。
`mysql -u ユーザー名 -pパスワード -h エンドポイント DB名  < 任意のファイル名.sql`

# 終わりに
報告書を書きました😭
少しでも参考になれば幸いです。
Vue Devtools の活用

Vue.js は、そのシンプルさと強力な機能で多くのプロジェクトで使用されています。しかし、開発過程をさらにスムーズに進めるためには、適切なツールを活用することが不可欠です。Vue Devtools は、開発者の時間を大幅に節約し、効率的な開発ができるためその使い方を確認していきます。

**Vue Devtools は、ブラウザの開発者ツールに統合される拡張機能**

* **コンポーネントツリーの可視化:** Vue.js アプリケーションのコンポーネント階層を視覚的に確認できます。各コンポーネントのプロパティ、メソッド、データ、イベントなどの詳細情報も確認できます
* **データの検査:** 各コンポーネントのデータの状態をリアルタイムで確認できます。データの変更履歴も追跡できます
* **イベントの監視:** コンポーネントで発生するイベントを監視し、デバッグを容易にします
* **タイムトラベルデバッグ:** アプリケーションの過去の状態を遡って確認し、バグの原因を特定できます
* **パフォーマンス分析:** アプリケーションのパフォーマンスを分析し、ボトルネックを発見できます

**Vue Devtools の活用例:**

* **コンポーネントの構造とデータの確認:** コンポーネントのツリー構造を確認し、データの状態をリアルタイムで監視することで、コンポーネント間のデータのやり取りを理解することができます
* **イベントハンドラのデバッグ:** イベントが発生した際に、関連するコードをステップ実行し、イベントハンドラの動作を検証できます
* **バグの特定:** タイムトラベル機能を使用することで、アプリケーションの過去の状態を遡って確認し、バグの原因を特定できます
* **パフォーマンスの改善:** パフォーマンス分析機能でボトルネックを特定し、コードを最適化することで、アプリケーションのパフォーマンスを向上できます

**Vue Devtools のインストール:**

Vue Devtools は Chrome と Firefox で利用できます。Chrome ウェブストアまたは Firefox アドオンストアから簡単にインストールできます。

**Vue Devtools の使用方法:**

Vue Devtools は、ブラウザの開発者ツールに統合されています。開発者ツールの「Vue」タブを選択すると、Vue Devtools のインターフェースが表示されます。

**まとめ:**

Vue Devtools は、Vue.js アプリケーションの開発を効率化する強力なツールです。筆者の私もVueで開発をする上で欠かせないツールになっています。
Windows PythonとBLEAKを使ってESP32とBLE通信してみました

以前作ったESP32のBLE通信ソフトですが僕にとっては必要十分だったみたいで、
気が付けば2024年の今でも同じソースコードで使っています。
そこで以前WindowsC＃で挫折したBLE接続ですが最近PythonのBLEAKで使える様に
なったそうなので挑戦してみる事にしました。


#実行に必要なリソース
　　ESP32とArduinoIDE開発環境（以前作った奴です）
　　Windows機とPython開発環境（Bleakをインストールしてください


#機能
　　ESP32とSerial通信ぽい事をします（サンプルプログラムミみたいな感じです


#使い方
　　ESP32側もコンパイルして動作させておきます
  　Windows機からは「ESP32_BLE_SERVER」に接続して通信を行います。
    通信するだけのソフトなので、後はお好きな様にどーぞ

#問題点
　　接続・切断テストを行っていますが、全ての条件が網羅できていない様です。
　　私はあまりPythonの事をよく判っていません。

```py:WindowsBLE.py:
import asyncio
import bleak
from bleak import BleakClient
import time
import threading

async def run1(CONNECTNAME):
    global hitDevice
    print( "BLE search [" + CONNECTNAME + "] start" )
    devices = await bleak.BleakScanner.discover()
    for d in devices:
        if d.name ==CONNECTNAME :
            hitDevice = d
            print( "BLE hit [" + CONNECTNAME + "]" )
            
def BLEreceivecallback( self, data ):
    print(data.decode())

async def run2( address, loop ):
    global BLEsendMessage, BLELoop, hitUUID
    async with BleakClient(address, loop=loop) as client:
        for service in client.services:
            for c in service.characteristics:
                if( service.description=='Vendor specific' ):
                    print(f"{service.uuid}: {service.description}: {f'{c.properties},{c.uuid}' }")       
                    hitUUID = c.uuid
        if hitUUID==None :            
            return
        print( "BLE connect [" + hitDevice.name + "]" )
        await client.start_notify( hitUUID, BLEreceivecallback)
        while BLELoop:
            if BLEsendMessage!=None :
                await client.write_gatt_char( hitUUID, BLEsendMessage)
                BLEsendMessage = None
            await asyncio.sleep(0.0001)
            x = await client.is_connected()
            if x!=True :
                print("BLE disconnect")
                return
        await client.stop_notify(hitUUID)

def send_thread():
    global threadLoop, BLEsendMessage
    count = 0
    while threadLoop:
        msg = f"{count}"
        print( msg )
        BLEsendMessage = bytearray()
        BLEsendMessage.extend( map(ord, msg+"\x00" ) )
        count = count + 1
        time.sleep(1)
        
threadLoop = True
BLEsendMessage = None
thread = threading.Thread(target=send_thread)
thread.start()

BLELoop = True
while BLELoop:
    hitDevice = hitUUID = None
    loop1 = asyncio.get_event_loop()
    loop1.run_until_complete(run1( 'ESP32_BLE_SERVER' ))
    if hitDevice!= None :
        loop2 = asyncio.get_event_loop()
        loop2.run_until_complete(run2( hitDevice.address, loop2))
threadLoop = False
print( "end" )
```

あとがき
　以前WindowsのC＃でBLE通信に挑戦したのですが挫折しました。
　今回Pythonで何とか通信できましたのでBLE/UDPの通信ブリッジを作って、
　UDPのPC内通信で.Net C#に繋いでＧＵＩプログラムを作ろうと思います。
誰でもわかる！VAEの動きと役割

# この記事の作成にあたって
情報系学部学生のsunです。この記事はVAEを抽象的に捉えることを目標としております。
コードや数字に頼らず、言葉のみでまとめてみようと思います。
間違いがあれば指摘していってください！

# VAE
## 1.中身
VAEの中身はこのようになってます。

![IMG_0580.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674061/570aa229-a7f5-7b65-0936-4aaaf4d5f75f.jpeg)
[前記事](https://qiita.com/sun_5103/items/8b11d3b309eaa81b15be)(VAEとEMアルゴリズムの違いについて)より画像を持ってきましたが、数式には触れません。
文字と動きを見返すためにはってます。
これらの役割について具体例を出してみましょう。

## 2.具体例

皆さんは、美味しい物を食べた時、もしくは飲んだ時、この料理のレシピが知りたいなぁと考えたことはありますか？
それが美味しければ美味しいほど「再現」をしたくなりますよね！

何の話かわからない人もいるかもしれませんが、この再現こそVAEの目的と言っても過言ではないんです。
実際にカレーを例にあらわしてみたいと思います。
## エンコーダー
![IMG_0590.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674061/dc3aad83-16d8-1aa1-27db-c3cc19edd57c.jpeg)

:::note info
カレーを食べて、レシピを推測することがエンコーダーの役割です。
:::

料理全般言えることですが、レシピはかなり複雑なので、食べた味をこの動きだけで再現することはエンコーダーだけでは難しいです。
そこでデコーダーを使います。
## デコーダー
![IMG_0592.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674061/1634de3d-70aa-98a7-381e-9e27d775fd2b.jpeg)

:::note info
エンコーダで推測したレシピを実際に作ってみること（再構成すること）がデコーダーの役割です。
:::

## 平均・分散

もちろん、具材の種類やそれを入れる量などを考えるとレシピ自体のバリエーションはかなりあるとおもいます。

:::note info
その中でも標準的なレシピを平均
そのレシピがどれだけばらつくかを分散とします。
:::

![IMG_0593.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3674061/c571722b-40ed-a866-51c4-8f3d32b257fa.jpeg)
カレーだと辛さや、甘さや、具材で別れたりしますよね。
これらのレシピのバリエーションがあればあるほどばらつきは大きくなっていき、元のカレーを再現することが難しくなってます。
## 損失関数について
VAEは二つの誤差を足し合わせた形を損失関数として扱います。
つまり、誤差が少なくなればなるほど元のカレーの味に近づくことがわかりますね。
#### KLダイバージェンスについて
この平均が0分散が1に従うようにする役割があります。

:::note info
極端なばらつきをなくすという役割があります。
:::
要するに変なレシピになることを防止する役割を待ってます。

#### 再構成誤差について
デコーダーの役割で再構成をしたカレーと、元々食べたカレーの味を比較して、誤差を出します。
つまり、これが小さいと再現が上手く行ってることになります。

#### バックプロパゲーションについて
損失を最小化するようにエンコーダーとデコーダーのパラメータが更新されます。
これによって、潜在変数が正規分布つまり、極端にならないような動きをし、デコーダーが入力データを再構築する能力が向上します。

これらの動きにより、画像生成したり、異常を検知したりできるわけです。

# 最後に
今回は一般的に理解が難しく、説明も難しいVAEについてできるだけ簡単に説明してみました。
できるだけ噛み砕いて書いたため、必要なものや、逆に不必要なものもあるとは思いますが、皆さんの機械学習のことを知る初めの一歩として伝えられたらなと思います。
エンジニアと夢、二足の草鞋

## 「夢」お持ちですか？
突然ですが、今あなたに夢はありますか？
『あんな夢　こんな夢　いっぱいあるけど』
みんなみんな叶えてくれる人はいないし、全部は叶わないです。

もうそんなものはないよ、と擦り切れた人も、
現実だけで精一杯手一杯だよ、と考えられない人も、
主題の通り、夢を目指している人も、
いろんな人がいると思います。

私はどちらかと言えば変わり者の部類でしょうし、
本記事ではあえて別角度を狙って、
「エンジニアと夢、二足の草鞋」を考えていきたいと思います。
先に断っておきますが、もちろん正しい答えなんてありません。

## どうして「エンジニアと夢、二足の草鞋」を考えたのか
偶然、何十年も持ち続けられる夢があって、
成り行きでエンジニアになったからです。

あとは、周りにそういった二足の草鞋を履いている人がいたり、
世間一般的に「夢」と言われるものを叶えた人や、
日本屈指、世界有数な知り合いがたまたま身近にいるのもあります。

## 大多数の「エンジニア」に二足の草鞋は難しいはず
エンジニアと言っても、いろんなタイプのエンジニアが居ると思います。
ただ、そのほとんどは「仕事に加えて日々勉強が必要なエンジニア」だと思ってます。
「仕事+勉強」と、あとは生活に必要な諸々の時間をいれたら、
24時間は使い切っちゃいますよね。
「ワークライフバランス」ですら難しいって話があるのに、
「ワークライフドリームバランス」なんて、もっと難しいです。

## どうやって二足目の草鞋を履くか
だからそもそも、物理的に時間が足りないですよね。
ということは、まず時間を確保したいところですね。
どう時間を捻出しましょう。

### 健康を犠牲にする
これ一番簡単ですよね。
**睡眠時間を削る。**
ほとんどの人ができるお手軽解決方法です。
でも、もちろん体を壊しちゃいます。
体だけじゃないものも壊れちゃいそうです。

あとは、健康に気を使っている人とかだと、
それらに割いている時間を、
つまり運動やジムに行くのをやめる、とかですかね。

いずれにしても、寿命を縮めそうで、とりたくない手段です。

### 心を犠牲にする
趣味や気分転換、遊びに行く時間を、
すべて費やすようにする方法です。
これも嫌ですよね。
ただでさえ土日じゃ休みが足りないのに、
さらに減らすのも辛いです。

### 仕事を犠牲にする
「仕事+勉強」の勉強を削ったり、
残業をなるべくしないようにしたり、
というワークライフバランスと同じ手段です。
でも、これを取るならまずはライフに回したいですよね。

### 生活基盤の強化
端的に言えば「お金で時間を買う」です。
特に家事の領域は、伸び代があると考えています。
+ 洗濯機をドラム式にして干す時間を減らす
+ シワになり辛い服を揃えてさらに省力化
+ ルンバの導入
+ 朝ご飯をプロテインバー固定
+ 弁当で毎食済ます
+ 作り置きをする
+ 家を駅近など利便性の高い場所にする

など、お金で解決していきます。
日々効率化できる時間は30分など短いですが、
基本的に時間はお金で買えないので、良い買い物かもしれません。

私は最近ドラム式洗濯機を買いましたが、
あれは良いものです。

### 気分転換の趣味≒夢
やはり、何も犠牲にせず負担少なく続けられるのは、
この項目を差し置いて考えられません。
好きこそものの上手なれ、趣味が高じて、です。

しかし、時折「趣味が仕事になると辛い」という話も耳にします。
これも最善手ではないのかもしれません。

### 仕事≒夢
めちゃくちゃ数が少ないですが、この方式もあります。
エンジニアと夢が近しいケースだと、
UIUXとデザイナーなどでしょうか。
ゲーム系エンジニアも、そうかもしれません。

## 夢じゃないけど、すごいものに繋がる
夢を叶える一つの要素に、運があると思ってます。
逆説的に、運によって意図せず、
夢とは違うが良い結果が転がり込むこともあります。
直近、そんな話を聞いたので挙げました。
ただやはり「あとは運が良ければ」の段階には、
至っておく必要があります。
Qiitaに投稿することがその一助にならないか、
私はそう期待して筆を取っている面もあります。

## 二足目の草鞋がエンジニアになる人
逆のパターンもあると思っています。
昨今、「プログラミングをする」という行為は、
何か他のことをしていても身に着くケースがあるはずです。
ロボット工学、マインクラフト、何かの統計を取るためにExcelをいじったり……
そういった他の畑から、エンジニアに参入する人々もいるでしょうし、
今後も増えていくかもしれません。
そういった方々のライフプランも、どうなっているのか気になりますね。

## 「エンジニアと夢、二足の草鞋」を省力的に実現するには
前述のことを考えると
+ 生活基盤に投資して時間を増やし
+ エンジニアのスキル周りと連携する部分を攻める

といった感じであれば、体を壊さずに二足の草鞋を履けそうですね。

## 「夢のカケラ」、最近見つけましたか？
『あんなこといいな　できたらいいな』
は、日々あります。

本を読んでるとき。
喫茶店に立ち寄ったとき。
動画を流し見してるとき。

「いいなぁ」「羨ましい」「楽しそう」は、
夢に育つ小さなカケラです。
そこで考えを打ち切ったり、
見ないようにしたり、
否定したり、してませんか。
もしかしたらその思いつきが、
何かに繋がるかもしれません。

まぁ、私はよく目をそらしてますが。
ただ、前述した通り、半ば運や機会を待つため、
こうして筆を取っている次第です。
QiitaのOrganizationに記事を投稿すると自動でDiscordに通知させる

IFTTTを使用する方法もあるのですがこちらは有料になるので、今回はGoogleAppScriptを使用してこのプロセスを自動化します。
# 必要なもの
1. Googleアカウント
1. DiscordのWebhook URL
1. QiitaのRSSフィード

# RSSとは？
ニュースやブログなど各種のウェブサイトの更新情報を配信するための文書フォーマットの総称である。（[参照](https://ja.wikipedia.org/wiki/RSS)）

要するに記事情報を取得するためのフォーマットだと思います。（間違っていたらすみません）

# Webhookとは？
Webhookとは、Web アプリケーションやサービスなどの更新情報を他のアプリケーションへ特定のイベント等が発生した際にリアルタイムで HTTP プロトコルを使用して通知するシステム。
（[参考](https://circleci.com/ja/blog/webhook-explained/)）

# Webhookを取得
1. Discordを開く
1. サーバー設定の連携サービスを開く
1. 「新しいウェブフック」ボタンから作成しURLを取得する

# RSSフィードを取得する
組織のURLの最後尾に「/activities.atom」を付けたものが組織のRSSフィードになります。
```
https://qiita.com/organizations/<組織名>/activities.atom
```

# GoogleAppScriptの作成
### 手順1
GoogleDriveを開く。
### 手順2
新規をクリックし、その他から新しいGoogleAppScriptを作成します。
### 手順3
以下のコードを入力してください。

```ruby:QiitaToDiscordNotifier.gs
const DISCORD_WEBHOOK_URL = 'Discordで取得したWebhookを入力';
const RSS_FEED_URL = 'RSSフィードを入力';

function checkQiitaFeed() {
  try {
    const response = UrlFetchApp.fetch(RSS_FEED_URL);
    const xml = response.getContentText();
    const document = XmlService.parse(xml);
    const root = document.getRootElement();
    
    Logger.log('Root element: ' + root.getName());

    const namespace = XmlService.getNamespace('http://www.w3.org/2005/Atom');
    const entries = root.getChildren('entry', namespace);
    Logger.log('Number of entries: ' + entries.length);

    const lastCheck = PropertiesService.getScriptProperties().getProperty('lastCheck');
    const lastCheckDate = lastCheck ? new Date(lastCheck) : new Date(0);

    entries.forEach(entry => {
      const publishedDate = new Date(entry.getChild('published', namespace).getText());
      if (publishedDate > lastCheckDate) {
        const title = entry.getChild('title', namespace).getText();
        const link = entry.getChild('link', namespace).getAttribute('href').getValue();
        sendDiscordNotification(title, link);
      }
    });

    PropertiesService.getScriptProperties().setProperty('lastCheck', new Date().toISOString());
  } catch (e) {
    Logger.log('Error fetching or parsing RSS feed: ' + e.message);
  }
}

function sendDiscordNotification(title, link) {
  try {
    const payload = {
      content: `新しいQiita記事が投稿されました: ${title} ${link}`
    };
    const options = {
      method: 'post',
      contentType: 'application/json',
      payload: JSON.stringify(payload)
    };
    UrlFetchApp.fetch(DISCORD_WEBHOOK_URL, options);
    Logger.log(`Notification sent: ${title} - ${link}`);
  } catch (e) {
    Logger.log('Error sending Discord notification: ' + e.message);
  }
}
```
### 手順4
トリガーを設定します。
左のタブからトリガーを選択し、
右下のトリガーを追加をクリックしてください。
![スクリーンショット 2024-06-20 170614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524352/3fa039d4-8935-b066-bab2-5790e37e2bba.png)
開いたら以下のように設定してください。
チェックを行う時間間隔はお好みで設定してください。
![スクリーンショット 2024-06-20 171614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524352/58c5d385-7e2b-6de8-e5b5-8ff92fab4ef5.png)
# 終わり
これでスクリプトが定期的に実行され、Qiitaの組織に新しい記事が投稿されると自動的にDiscordに通知されるようになりました。
SnowflakeでArrayのみでループを回したいとき使える技

同じような名前のテーブルを作りたい時に配列をforループで回して作りたいってとき時々ありますよね？
それもSQLだけでやってしまいたい時って結構ないでしょうか。
今回はそれをLATERAL FLATTENを使ってシュッとやる方法をご紹介します。

```sql
EXECUTE IMMEDIATE $$
DECLARE
 table_names CURSOR FOR SELECT t.value || '_table' table_name
    FROM LATERAL FLATTEN(INPUT => ['a', 'b', 'c', 'd']) t;
BEGIN
FOR t in table_names DO
    -- なんかテーブルを使ってやりたい処理
END FOR;
END;
$$;
```

簡単な流れとしては
1. LATERAL FLATTENでArrayを展開したものをクエリするCURSORを定義
1. forループを回す
1. やりたい処理を書く

以上です！

これをやりたい場面がいつかきっと来ると思います。
それでは！
[解決済み]php.iniを開いても空白

**[解決しました](#解決20240624)**

```:環境
PHP8.3.7
OS: macOS Sonoma14.4
エディタ:　Cursor
ターミナル:　Warp
ツール: Homebrew
```
# 目的
Cursorで`php.ini`を編集したい。
# 問題
教材に習って`cursor /opt/homebrew/etc/php/8.3.7/php.ini`で開くと何も書かれていない空白の`php.ini`が開かれる。
# 多分…
単純に開くパスが間違えているのでは。と予想…。
もしくは正しく開けているし、空白なのが普通？と思ったがPHPの設定がなにも書かれていないなんてこと無いと思うし、教材にはズラーーーっと文字が並んでいたので違うハズ。

# 余談（問題とは関係無し）
ちょっとずつPlanckのオリジナルキーマップとyabai+skhdにも慣れてきて調子が出てきた。
これ完全に慣れて感覚で操れるようになったら効率爆上げだ。よく聞く生産性ってのもモリモリになれる。

俺は自室を片付けられない人間なのだが、これまでパソコン内の整理はこまめにできていたし得意だった。
しかし最近パソコン内、特にデスクトップ画面がごっちゃごちゃなのである…。
windowsならアイコンが整っていてまだ良いが、macだとアイコンが自由配置なのでさらにゴチャ&ゴチャ。

気持ちが前向きになり運動や勉強ができるようになった代わりに整理整頓ができなくなったのであった。オワリ。

# 解決(2024/06/24)
`php -i | grep php.ini`で出てきたパスを使ってシェルコマンド打ってみたら普通にできた。

やはりただ単にパスが間違えていただけだったようだ。
そして空白だったのは、新たにファイルを作ろうとしていたために空白だった様子。
適当に`cursor /Desktop/piyo.ini`でも空白のファイルが開かれた。

ちなみに最終的なシェルコマンドは`cursor /usr/local/etc/php/8.3/php.ini`
…
homebrewでも8.3.7でもねえじゃん！！
はじめにhomebrewでPHPを入れた記憶あるし、`brew list`で調べた時に確かにphpがあったし、PHPのバージョンを調べると8.3.7だし…考えが凝り固まっていたな。プログラミングをする上であらゆる考えと試行をしてみるもんだなあ。みつを

参考にさせていただいた記事 &raquo; [siba4848 - php.iniの場所を調べる](https://qiita.com/siba4848/items/adad797c536667f0545f)
[Qiita初心者必見!!]マークダウンの書き方のはじめ

# はじめに
みなさん，おはこんにちばんは！！！
今回は，自分も忘れがちなマークダウンの書き方について書いていきます．
全て見たいなら [Qiita公式](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)をみるのが一番いいですが，よく使うものだけこちらに残しておこうと思います．

# 目次
- 見出し
- リスト
- 強調
- リンクと画像
- コードブロックとインラインコード
- 引用
- 表

# 見出し
 `# `の数でレベルが決まります。
 `#`が多いほど小さい見出しになります。
 `#`5こが最小になります。
``` header.md
# h1
## h2
### h3
#### h4
...
```
出力
# h1
## h2
### h3
#### h4

# 数字なし,ありリスト
番号なしリストは-、*、あるいは+を使います。
番号付きリストは数字にピリオドをつけます。

``` list.md
- one
- two
- three
    - 3-1 
    - 3-2
        - 3-2-1
            - 3-2-1-1 
```
出力
- one
- two
- three
    - 3-1 
    - 3-2
        - 3-2-1
            - 3-2-1-1  


``` numList.md
1. あ
1. い
1. う
    1. あ
    1. い
```
出力
1. あ
1. い
1. う
    1. あ
    1. い

# 強調
### 文字の強調
イタリックは`*`または`_`で囲みます。
ボールドは`**`または`__`で囲みます。
ボールドイタリックは`***`または`___`で囲みます。
``` intence.md
*イタリック*
_イタリック_

**ボールド**
__ボールド__

***ボールドイタリック***
___ボールドイタリック___
```
出力
*イタリック*
_イタリック_

**ボールド**
__ボールド__

***ボールドイタリック***
___ボールドイタリック___

## 補足や警告
Qiitaでは，色をつけて細く説明や警告を強調して示すことができます．
```
:::note
インフォメーション
:::

:::note warn
警告
:::

:::note alert
より強い警告
:::
```

:::note
インフォメーション
:::

:::note warn
警告
:::

:::note alert
強い警告
:::

# リンクと画像
リンクは`[表示テキスト](URL)`で作成します。
画像は`![代替テキスト](画像URL)`で挿入します。
``` link.md
[Googleへのリンク](https://www.google.com)
![代替テキスト](画像URL)
```
[Googleへのリンク](https://www.google.com)
![代替テキスト](画像URL)

# コードブロックとインラインコード
インラインコードはバッククォート ` で囲みます。
複数行のコードブロックは3つのバッククォートで囲み、必要に応じて言語を指定します。

入力
```インラインコード.md
これは`インラインコード`です。
```
出力
これは`インラインコード`です。
入力
```バッククォート.md
```python.py
# Pythonコードを示す場合
print('Hello, Python!')
```>
```
出力
```python.py
# Pythonコードを示す場合
print('Hello, Python!')
```

# 引用

引用は `>` を行の始めに置くことで作成します。
入力
```引用.md
> これは引用文です。
> 引用文は複数行にわたることができます。

>空白で離れる
>>2行にも行ける
>>>3行も

>>先に2行すると
>後ろも2行以上となる
```
出力
> これは引用文です。
> 引用文は複数行にわたることができます。

>空白で離れる
>>2行にも行ける
>>>3行も

>>先に2行すると
>後ろも2行以上となる

# 表
`nxm`を入力すると`テーブル挿入する`というボタンが表示され，n行m列の表のmdが作られます

例
``` 
3x2
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3748983/5333bab8-ec88-cf91-b587-5bae0d35aaad.png)

```
| 1 | 2 | 3 |
|:-:|:-:|:-:|
|   |   |   |
|   |   |   |
```

表示
| 1 | 2 | 3 |
|:-:|:-:|:-:|
|   |   |   |
|   |   |   |

# 終わりに
今回はよく使うマークダウン言語だけをまとめてみました！マークダウン言語は，QiitaだけでなくNotionでも使えたり，GitのREADMEとかでも使います．色々なところで使うので，ぜひ使いこなしてください！！
それでは，みなさんよいエンジニア生活を〜👋
EventBridgeを使用しS3へのファイルアップロードをトリガーにLambdaを動かす

# はじめに
本記事ではAmazon EevntBrige使用し、S3バケットへファイルをアップロードしたことをトリガーにしてLambdaを実行させてみます。


# EevntBrige とは？

AWSのサービスやSaaSで発生するイベントをトリガーとしてワークフローを動かすことができるサービス。
EevntBrigeを使用すればイベント駆動型アーキテクチャを簡単に構築する事ができる。

https://aws.amazon.com/jp/eventbridge/

# ゴール

S3へのファイルアップロードをトリガーとしLambdaを実行させる。

# 環境
python 3.12


# S3

対象のバケットのプロパティを選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/d1e7eb73-9e07-ed11-0283-22492bcd9158.png)

イベントの通知からAmazon EventBridgeの「編集」を選択し、通知をオンに変更。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/f2247446-b26c-210e-4bdb-d34c22039f46.png)



# Lambda

実行されたことの確認のため `Hello Lambda` と出力されるLambda関数を準備します。

```python:lambda_function.py
import json

def lambda_handler(event, context):
    print('Hello Lambda')
    return 
```

# EventBrige

ルールを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/2e0ac89e-e4f5-470d-e63d-56953cb768ad.png)

イベントパターンには以下の内容で設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/ee8374cf-64cf-8813-4667-74feadf029d1.png)


```json:イベントパターン
{  
  "source": ["aws.s3"],  
  "detail-type": ["Object Created"],  
  "detail": {  
    "bucket": {  
      "name": ["test-s3-eventbrige"]  
    },  
    "object": {  
      "key": [{  
        "prefix": ""  
      }]  
    }  
  }  
}
```

ターゲットとしては実行するLambdaを選択します。
今回は先ほど作成した「test-s3-lambda」関数を選択し、あとはデフォルトの設定で進みルールを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/ec93ffde-d555-fe42-cc0e-bba48cf27796.png)

ここまでできたらS3バケットに任意のファイルをアップロードし、Lambdaが実行されるか確認します。

# 実行 & 結果
S3バケットにファイルをアップロードすると、Lambdaが実行されCWのログが吐かれている事を確認できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247619/404e709f-f421-12a8-c7f6-966b37bdf758.png)



# 参考

https://aws.amazon.com/jp/eventbridge/

https://dev.classmethod.jp/articles/lambda-trigger-eventbridge-s3/
iLO5やiDRAC9を使用したサーバのリモート管理

# まえがき
おつかれさまです。mochiです。
今回は私の実業務で触っているiLO5について少し書こうかと思います。
# 普段の業務について
私は普段、医療機関に設置されているオンプレミス環境のサーバや仮想環境のサーバを遠隔保守する業務に就いています。そこではすでに稼働しているサーバの稼働時間やDBサーバのバックアップ取得ジョブが正常に行われているか、物理環境の場合であればハードウェアのヘルスチェックも実施します。
# ハードウェアのヘルスチェックはどう行う？
オンプレの場合、ハードウェアは病院内に保持して自分たちで管理しなければいけません。ですが私は全国の病院をかなりの数保守しなければならないため、リモートでハードウェアの管理を行います。そこで使用されるのがHPEのiLO5やSMH(System Management Homepage)です。これらはサーバのヘルスチェックを遠隔で行うことができ、リモート管理をスムーズに実施することができます。
私はHP製のサーバを保守している為、DELLのiDRACやOMSAは研修で触ったことがある程度です。
# iLO5とは？
iLO5（Integrated Lights-Out 5）は、HPE（Hewlett Packard Enterprise）が提供するサーバー管理技術の最新バージョンです。ですがiLO6がリリースされ始めたようです。この技術は、HPE製サーバーのリモート管理を可能にし、物理的にアクセスが難しい場所からでもサーバーの運用や保守を効果的に行うことができます。

https://ascii.jp/elem/000/004/072/4072660/
### 機能について
・仮想コンソール
GUIベースで管理するサーバのコンソール画面にアクセスすることができます。これにより、リモートでサーバの操作や設定変更をリアルタイムで行うことができます。

・仮想メディア
iLO5は仮想メディア機能を備えているため、リモート環境でCD/DVDドライブやUSBデバイスをサーバに接続することができます。これによってOSインストールやファームウェアのアップデートなんかも行うことができます。

・パフォーマンス監視
iLO5はサーバーのハードウェアリソースやパフォーマンスを監視し、リアルタイムでのモニタリングとレポート作成を行うことができます。障害の早期発見や問題のトラブルシューティングを支援します。

・アラートや通知
システムの異常や重要なイベントが発生した際には、iLO5が自動的にアラートや通知を送信します。管理者は迅速に対応することができ、サーバーの可用性を高めることができます。ハードウェアに何か障害が発生した場合、イベントログも抽出することができる為、詳細に状況を把握し、トラブルシューティングに役立ちます。

実際に私が行っている業務では、iLO5のマネジメントコンソール画面にログインし、システムインフォからRAIDディスクの正常性、FANに問題はないか、アレイコントローラに異常がないか等の基本的なステータスを一元管理してチェックしています。
GUIで操作できるため、ブラウザベースでストレスなくチェックできます。
# 研修でDELLのiDRACやOMSAを触ってみた
会社の物理サーバに実際にRAID設定からOSのインストールまでを行う研修があり、そちらに参加した際の感想です。正直、『DELLめっちゃ良くね！？』と思いました。何がいいかって、まず監視ツールのコンソール画面にログインした時の視認性が非常に高いです。ログインしたらすぐの画面に必要な情報がまとめて入ってくることが大きな利点かと思います。

比較用のコンソール画面置いておきます。

![image.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726585/52c22bbe-0038-e404-0a2a-6ac6774cf659.jpeg)
👆iLO5のホーム画面

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726585/c18446b1-f102-8b4b-fe41-2ef85514e962.png)
👆iDRAC9のホーム画面
# OMSAって何？
OMSA（OpenManage Server Administrator）は、Dell Technologiesが提供するサーバー管理ソフトウェアです。これは、Dell製のサーバーおよびストレージ装置の管理を容易にするために設計されています。
##### 機能について
・リモート管理
OMSAを使用することで、物理的にアクセスが難しいサーバーにリモートでアクセスし、管理や運用を行うことができます。リモートからの電源のオン/オフ、BIOS設定の変更、システムの監視などが可能です。

・複数サーバの一元管理
大規模なデータセンター環境において、複数のサーバーやストレージデバイスを一元管理するための機能を提供します。これにより、運用の効率化とコスト削減を図ることができます。

https://japancatalog.dell.com/c/isg_blog_openmanage_server_administrator/
# 所感
普段の業務では対象のサーバがHPE製であるため、iLO5やSMHを使用してサーバ保守を行っています。ですが、自社での研修でDELL製サーバを実際にRAID構成からOSのインストールまでを行ってみた結果、管理ツールがとにかく扱いやすく、病院サーバも全てDELLにしてくれ！！と思いました（笑）

リモートでのサーバ保守をしている際、病院側にはNASや冗長構成されたDBサーバやGWサーバなども存在しており、複数のサーバを行ったり来たりしながら保守しています。
こういった時、複数のサーバを一元的にまとめて管理したい為OMSAのような一元管理機能は使ってみたいと思いました。
# 最後にオンプレとクラウドの比較
オンプレミスを知ってクラウドがいかに優秀かという点についても同時にひしひしと感じました。例えばAzureの場合、サーバをひとつ稼働させたいと考えた時にAzure PortalからVMを作成するのにわずか5分ほどで稼働させることができます。ですが物理サーバの場合、まずハードウェアを用意するのに時間がかかりますし、RAIDを組んでOSも自分でインストールさせる必要があります。

やはりリモート保守をしている際、iLO5のようなリモート管理は楽で良いですが、もっと良いのはやはりクラウドでの開発と運用です。今後は医療機関でも物理的なサーバの管理はクラウドベンダーに任せたいところです。セキュリティ的に医療機関などは難しいのかもしれませんが、その重い腰を上げるのを助けてあげるのもIT業界の人間の役目だと思います。
今後もっとクラウドについて理解を深め、自分の市場価値を上げていきます🔥
【メモ】Microsoft Fabric Sparkでの 他クラウドデータレイクへの書き込み

## はじめに

他クラウドとのショートカットは読み取り専用なんで、書き込みのサンプルを載せます。

ネットワークレベルのアクセスポリシーはなしの状態でやってるので、エンプラ的には厳しそうですが、Managed vnet → Privatelink service 的な流れで多分ネットワークの問題も解消できる気がしますが、それはまた別機会で。

https://qiita.com/whata/items/042b5cfd50091d63ff83


## GCS

Fabric spark runtimeにはコネクタが入ってます。

[Runtime 1.2](https://learn.microsoft.com/ja-jp/fabric/data-engineering/runtime-1-2)

[ライブラリの一覧](https://github.com/microsoft/synapse-spark-runtime/blob/main/Fabric/spark3.4/Official-Spark3.4-Rel-2024-05-08.8-rc.1.md)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/77409f87-71fa-8541-d646-0793ddc62968.png)



※https://github.com/GoogleCloudDataproc/hadoop-connectors


### 準備

サービスアカウント作成後、キーファイルを出力し、権限付与

権限：ストレージオブジェクト管理者

キーファイル：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/6cd43977-1d10-074a-fe27-8d899e96ca42.png)


### 実行

1. Fabric ノートブックリソースにキーファイルアップロード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/3c0d2591-70eb-6ebc-499f-5ef84aa62502.png)
2. spark 実行
```spark:spark

data = [("John", "Doe", 30), ("Jane", "Doe", 25), ("Mike", "Jordan", 50)] 
df = spark.createDataFrame(data, ["FirstName", "LastName", "Age"])  

key_file_name="キーファイル名"
gcs_backet_name ="バケット名"

spark._jsc.hadoopConfiguration().set('fs.gs.auth.service.account.enable', 'true')
spark._jsc.hadoopConfiguration().set('google.cloud.auth.service.account.json.keyfile', f"{mssparkutils.nbResPath}/builtin/{key_file_name}")
## 環境使う場合は f"{mssparkutils.nbResPath}/env/{key_file_name}" 

gcs_route_path=f"gs://{gcs_backet_name}"
output_path = f"{gcs_route_path}/qiita-output/"
df.write.mode("overwrite").format("delta").save(output_path)

```  
3. 確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/b17023bc-197a-4011-f60d-ecaad5c0c8db.png)

## S3


### 準備

IAMユーザーとアクセスキーを作成して、権限付与
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/01162292-43b4-39ee-99b1-d3c86a1aa3e5.png)

権限：以下のようなポリシーで作成
```json:json
"Action": [
                "s3:PutObject",
                "s3:GetObject",
                "s3:ListBucket",
                "s3:DeleteObject"
            ]
```



### 実行

1. spark 実行
```spark:spark

data = [("John", "Doe", 30), ("Jane", "Doe", 25), ("Mike", "Jordan", 50)] 
df = spark.createDataFrame(data, ["FirstName", "LastName", "Age"])  


s3_backet_name ="バケット名"
access_key_id="アクセスキーID"
accecc_key_secret="アクセスキーシークレット"

sc._jsc.hadoopConfiguration().set("fs.s3a.access.key", access_key_id)
sc._jsc.hadoopConfiguration().set("fs.s3a.secret.key", accecc_key_secret)

s3_route_path=f's3a://{s3_backet_name}'
output_path = f"{s3_route_path}/qiita-output/"
df.write.mode("overwrite").format("delta").save(output_path)

```
2.  確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/281819/a6fda6dc-698f-90ab-0874-e4044f957d88.png)
愛用のソフトウェア・サービスを紹介する


# 共通

## バージョン管理ツール
[Git](https://www.git-scm.com/)
プログラムのバージョン管理に使うツールです。GitHubと組み合わせて使います。

## Gitクライアント
[Fork](https://git-fork.com/)
英語だけですが他のGitクライアントよりも軽量で見やすく使いやすいです。

## テキストエディタ
[Intellij IDEA](https://www.jetbrains.com/ja-jp/idea/)
Intellij 製品を一度使うともう抜け出せない...
名前空間の自動挿入とか便利すぎ。

## コード補完
[Github Copilot](https://docs.github.com/ja/copilot)
基本的にどのIDEでも使えるので、使ってみる価値はあると思います。
勉強目的でコード書いているときは使わないことをオススメします。

## 音楽
[Spotify](https://www.spotify.com/jp/)
作業中に音楽を聴くのに便利です。プレイリストも作れたり。
だけど音楽を聞きながら作業ができない人がいるかも...

## コミュニケーション
[Discord](https://discord.com/)
LINEみたいなチャットツールですがチャンネルやスレッドを作れたりするから大人数用。
サーバーを作って、コミュニティを作ることもできます。
自分はプログラミングのサーバーに入って、エンジニアさんと一緒に作業をしていたりします。
サーバーを見つけるのはここから[Disboard](https://disboard.org/ja)

# ゲーム開発
[Unity](https://unity.com/ja)
3Dゲームだけでなく、2Dゲームも作れるゲームエンジンです。UnityのC#は使いやすいです。
見た目も良いしプログラミングの学び始めには良いのかも。

[Unreal Engine](https://www.unrealengine.com/ja/)
3Dゲームを作るのに向いています。ブループリントが初心者向けと言われているけど、全くのPC初心者はきつそうな印象。そして情報量が少ないのが難点。
だけどそれ以上に綺麗なグラフィックスが作れたり、高品質なオンラインゲームを作れたりする強みがある。

# モバイルアプリ開発
[Flutter](https://flutter.dev/)
Google製のクロスプラットフォームアプリ開発フレームワークです。基本的に一回コードを書くだけで全部に出せちゃう。
言語は[Dart](https://dart.dev/)、一般的ではない言語だから使いにくい...。
でも短い時間で70点くらいのUIを作れるからオススメ。iOSで出すときはMacが必要です。


# Web開発
[React](https://ja.reactjs.org/)
Facebook製のJavaScriptライブラリです。メジャーだから情報量が多いです。
やはり勉強するには情報がいっぱいあるフレームワークがいいですよね。

# バックエンド開発
[Gin](https://github.com/gin-gonic/gin)
Golangで使えるWebAPIを作るためのフレームワークです。 
簡単な記述で早いAPIが作れるので、初心者にもオススメです。

## APIテスト
[Postman](https://www.postman.com/)
APIのテストに使うツールです。自動テストだったり、ドキュメント作成だったり、色々できます。

## 仮想化
[Docker](https://www.docker.com/)
デファクトスタンダードなコンテナ仮想化ツールです。コンテナを使えるようになると、デプロイがとっても楽になります。

## コンテナオーケストレーション
[Kubernetes](https://kubernetes.io/ja/)
前述のDockerを扱うツールです。この子はコンテナのヘルスチェックやスケーリングなど、色々な機能が使えます。 
各種クラウド(AWS, GCP, Azure)でサポートされているので、学習する価値はあると思います。ただし学習コストが高いです。

## クラウドサービス
[Firebase](https://firebase.google.com/)
Google製のバックエンドサービスです。基本的なアプリやゲームを作るのには十分な機能を揃えています。無料なのが嬉しいですね。
自分はこいつにサーバーサイドの楽しさを教えてもらいました。

[AWS](https://aws.amazon.com/jp/)
Amazon製のクラウドサービスです。サーバーやストレージ、つよつよオンラインゲーム構築など、色々なサービスが使えます。
無料枠があるので、学習にも最適です。**ただし円安の影響で料金が高いのが難点。**

## SSHクライアント
[RLogin](https://kmiya-culti.github.io/RLogin/)
SSHクライアントです。PuttyやTera Termよりも使いやすい印象。
先輩エンジニアさんに教えてもらいました。
テスト管理ツールのTestRailを触ってみた

:::note 
<details><summary>AI要約</summary>

- TestRailはテスト管理ツールで、テストケースの作成、整理、実行、追跡を効率的に行うためのプラットフォームです
- 自動テストツールではなく、テスト管理に特化しており、Excel管理よりも視認性が良いです
- テストスイートとテストランを作成し、異なるリリースやビルドに対して再利用可能です
- リアルタイムのダッシュボードとレポート機能があり、JIRAやGitHub、Jenkinsなどの開発ツールと統合できます
- コストと学習時間がかかりますが、チーム全体の生産性を向上させ、目視によるテスト管理もサポートします
</details>
:::


## はじめに
下記に便乗してテスト管理ツールのTestRailを触ってみました

https://qiita.com/official-events/5100659e9b4ffbcb941b

一時期Excel管理のテスターをしていたのである程度の知見はあるかなと思います

## 概要
TestRailは、テスト管理ツールとして、テストケースの作成、整理、実行、追跡を効率的に行うための強力なプラットフォームです
TestRailは、ソフトウェアテストプロセスを最適化し、テスト結果を詳細にレポートすることでチーム全体の生産性子を向上します

## 注意点
僕が勘違いしてましたが、TestRailは自動でテストを実行するツールではないということです
テスト管理に特化したツールで **プロジェクトのテスト管理画面** のような位置付けになるのではないかと思います

## 主な機能

### テストケースの管理
TestRailは、テストケースを簡単に作成、編集、整理のため管理ツールです
テストケースは、セクションやフォルダに整理でき、必要な詳細情報を追加することができます

### テストスイートとラン
テストスイートは、関連するテストケースのグループです
TestRailでは、テストスイートを作成し、特定のテスト計画に基づいてテストランを実行することができます
異なるリリースやビルドに対してテストケースを再利用することが容易になります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/3b197cad-b445-cab1-537c-85d5b344c94b.png)


### レポートとダッシュボード
TestRailは、テスト結果の詳細なレポートとリアルタイムのダッシュボードを提供します
これによりテストの進捗状況や品質を確認することができます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282722/705d968a-b85a-9645-f2f4-3e037f9fde4a.png)


### インテグレーション
TestRailは、JIRA、Github、Jenkinsなどの多くの開発ツールと統合できます
この統合により、バグトラッキング、リリース管理、CI/CDプロセスと連携して、シームレスなテスト管理を行うことができます

参考：

https://qiita.com/testTaro310/items/758c7bd712cd570e7935

## メリット
- テスト効率の向上
    - テストケースの管理やテスト実行を効率化し、テストサイクルの短縮を図れます
- 可視化
    - リアルタイムのダッシュボードとレポートにより、テストの進捗状況と品質を可視化します
- 一元管理
    - テストケースやテストランなどを一元管理できるため、全体の見通しだ良くなります
- チームコラボレーション
    - 複数のチームメンバーが同時に作業できるため、協力してテストプロセスを進めることができます
- 視認性の向上
    - CSVやExcelよりも視認性が良く、テストケースの整理や追跡がしやすくなります

参考（Excelとの比較）：

https://qiita.com/it_beginner/items/2a54a73c024cdf22b0d3


## デメリット
- コスト
    - 高機能なツールであるため、導入コストがかかります
- ある程度の学習コスト
    - 多機能なため、使いこなすには一定の学習時間が必要です
- テスト自動化とは共存しない？
    - もしプロジェクトでテストの自動化を導入していたらその結果やプロセスはTestRailで管理できない可能性があります

## 実際の仕様シナリオ
- 新機能のリリーステスト
    - 新しい機能が追加されるたびに、テスト計画を作成し、すべての関連テストケースを実行してリリースの品質を確認する際に使用されます
- 回帰テスト
    - テストコードによる自動テストとは別に、ユーザーが実行する目視によるテストを管理し、テスト結果を記録します
- 継続的インテグレーション
    - JenkinsやCircleCIなどのCIツールと連携し、コードの屁脳があるたびに自動でテストを実行し、結果をTestRailにフィードバックします

## まとめ
TestRailは、ソフトウェアテストのすべての側面を効率的に管理できる強力なツールです
特に、テストケースの整理、テストランの実行、詳細なレポート作成など、多くの機能を持っており、チーム全体の生産性を向上させます。
ただし、導入にはコストや学習時間がかかるため、これらの点を考慮して適切に導入することが重要になりそうですね

デモサイトがあるので是非１度試してみてはいかがでしょうか？

https://www.techmatrix.co.jp/product/testrail/demo_site.html
初心者にもわかる! クラスとオブジェクト指向の基礎①

## はじめに
みなさん、初めまして。エンジニア歴1.5年のエンジニアです。
最近、後輩からプログラミングの基礎的な質問をよく受けるようになりました。

「オブジェクト指向ってなに?」
「クラスってなんだよ?」

こういった質問に対して、分かりやすく説明できるよう自分なりにまとめようと思います。

では、レッツスタート:point_up:

## オブジェクト指向プログラミング（OOP）
オブジェクト指向プログラミング（OOP）は、効率的で再利用可能なコードを書くことを目的としています。
まずは、OOPの基本である「クラス」について説明していきますね。

## クラスとは?
クラスは、オブジェクトの設計図とよく言われます。
「設計図? なんやねんそれ」と思った方、落ち着いてください。
私たちは日常的に、人間を表現することがあります。
例えば、友人や家族の情報を他人に説明したり、新入社員の紹介文を書いたりする際です。
そんな時、クラスが役に立ちます。

クラスの中には、人間を表現するための項目(プロパティ)と、人間らしい動作(メソッド)が書かれています。

プロパティとは、オブジェクトの状態を表す値のことです。
人間なら名前や年齢、出身地といった情報がプロパティになります。

一方、メソッドとは、オブジェクトの振る舞いを表すものです。
人間なら挨拶したり自己紹介したり、趣味を話すような動作がメソッドに相当します。  

このプロパティとメソッドを組み合わせて、クラス(設計図)を作ります。そしてそのクラスからオブジェクト(実体)を作成できます。

具体例を見てみましょう。あなたの会社に、Aさんという人がいるとしましょう。

### 例
Aさんは、いつもプログラミングに夢中で人の話は聞きません。
仕事が終わるといつもお酒を飲みに行くようです。

#### Aさんのプロフィールを表現する

```php
class Person {
    // プロパティ(オブジェクトの状態)
    public $name; 
    public $birthPlace;
    public $job;
    public $hobby;
    public $favoriteFood;

    // コンストラクタ(インスタンス化時にプロパティを設定)
    public function __construct($name, $birthPlace, $job, $hobby, $favoriteFood) {
        $this->name = $name;
        $this->birthPlace = $birthPlace;
        $this->job = $job;
        $this->hobby = $hobby;
        $this->favoriteFood = $favoriteFood;
    }

    // メソッド(オブジェクトの振る舞い)
    public function introduce() {
        return "こんにちは、" . $this->name . "です。出身地は" . $this->birthPlace . "。職業は" . $this->job . "で、趣味は" . $this->hobby . "です。好きな食べ物は" . $this->favoriteFood . "です。";
    }
}

// Personクラスのインスタンスを作成し、プロパティを設定
$person_a = new Person("A", "北海道", "CTO", "飲酒", "鮭とば");

// introduceメソッドを呼び出し
echo $person_a->introduce();
// 出力: こんにちは、Aです。出身地は北海道。職業はCTOで、趣味は飲酒です。好きな食べ物は鮭とばです。
```

なんとここで、新入社員のBさんも入社することになりました。
Bさんはガジェット狂で、最新のガジェットを手に入れると夜通し遊んでしまうそうです。

#### Bさんのプロフィールを表現する

```php
$person_b = new Person("B", "大分県", "WEBエンジニア", "ガジェット", "ラーメン");
echo $person_b->introduce();
// 出力: こんにちは、Bです。出身地は大分県。職業はWEBエンジニアで、趣味はガジェットです。好きな食べ物はラーメンです。
```

このように、Personクラスを作成し、その中にAさんやBさんの情報を設定することで、簡単にオブジェクトとして表現できます。
そして、この設計図があれば何人分でも同様に表現することができます。
つまり、クラスを使えば何個でも新しいオブジェクトを作れるということですね。
クラスはこのように、モノを表現する際の設計図として活用できます。

さて、Aさん、Bさん、早く仕事終わらせて飲みに行きましょうか。

## 終わりに
続編に乞うご期待。

※登場人物はフィクションです:thinking:
[Docker Desktop for Windows]エンジンが起動しない対処

dockerデスクトップ画面の左下に下のようなアイコンで、起動を促すことができるときもある。

![スクリーンショット 2024-06-20 161938.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2759593/31696e19-3096-baf5-b51f-762f7f8fda1c.png)

以上。
[MySQL]起動エラーの対処

xammpコントロールパネル上で、MYSQL起動エラー終了する場合の対処法。

　※xammpフォルダの「MySQL」フォルダのバックアップをとる。

MySQLフォルダ⇒「data」内の次のファイルを削除する。
　・ibdata1
　・ib_logfile～で始まるファイル

これで復旧することが多い。

参考元サイト↓
https://qiita.com/gone0021/items/1240f857776c6bb620b6
ShiftJISからUTF-8 BOMにまとめて変換する方法

# 文字化けの原因
Windows環境でUnityを使用して新しくスクリプトを作成すると、デフォルトでShift_JISエンコードが使用されます。一方で、UnityのエディタやVisual Studioは、通常UTF-8が使われています。このエンコードの不一致が文字化けの原因となります。

:::note info
UTF-8 BOMとは
UTF-8 BOM（Byte Order Mark）は、ファイルの先頭に付加される特別なマークで、ファイルがUTF-8エンコードであることを示します。これにより、多くのテキストエディタやIDEが正しくファイルを認識し、日本語を含む多言語のテキストを適切に表示できます。
:::
# 解決方法
エンコードをUTF8-BOM有で一致させる必要があります。
方法はいくつかありますが今回は一括で変換できるソフトを紹介します。

# ZiiDetectorを使ったエンコード変換

1. [ZiiDetector](https://www.vector.co.jp/soft/winnt/util/se488922.html)のインストール
2. ダウンロードしたファイルを解凍する
3. exeを起動する
3. 起動すると以下のような画面が表示されるので、
ここにUnityのAssetsフォルダをドラック＆ドロップ
![スクリーンショット 2024-06-20 155840.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524352/613b7aa5-5c6e-4a5d-440c-5a5b7ae95399.png)
5. ここをUTF-8(BOM有)にして変換をクリックする
![スクリーンショット 2024-06-20 160012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524352/ce401ebf-d639-f62a-fd8e-85c99e88b91e.png)

# 結果
一瞬でまとめて変換できる。
自動で変換する方法もいくつかあるようだが過去にうまくいかなかった（やたらロードされたり変換されてなかったり、、、）ので、この方法で変換するに至った。
MacとWindowsの両環境を使用していると必ずこの問題にぶち当たるのでUnity側で何とかしてくれるようになってほしいと切実に思います。

# 参考

https://qiita.com/kumi0708/items/2f8dd2fc2ccb673ff12b

https://www.create-forever.games/unity-source-code-encode/
nuxt3から提供されるcomposableのmockの方法について

# はじめに

こんにちは、Gakken Leap のフロントエンドエンジニアの日下です。
この度、nuxt3 のテストを vitest で書く機会があったのですが、nuxt から提供される useFetch や navigateTo 等の関数のモックができずハマってしまいました。
公式ドキュメントや記事も調べたのですがなかなか情報が見つけられず、解決まで時間が取られてしまったため、備忘録も兼ねて解決策を書き残しておきたいと思います。

## ハマった部分

今回テストを書くにあたりリグレッションが発生したらすぐに検知できるようにというモチベーションがあったため、ページ単位で複数のコンポーネントを組み合わせた結合テストを書き始めました。

ページ全体での動きをテストする場合、api コールのための useFetch 関数や画面遷移のための navigateTo 関数のモックが必要になります。

[公式ドキュメント](https://vitest.dev/guide/mocking.html)によると以下のように mock が書けます。

```javascript
import { afterEach, describe, expect, it, vi } from 'vitest'

function getLatest(index = messages.items.length - 1) {
  return messages.items[index]
}

const messages = {
  items: [
    { message: 'Simple test message', from: 'Testman' },
    // ...
  ],
  getLatest, // can also be a `getter or setter if supported`
}

describe('reading messages', () => {
  afterEach(() => {
    vi.restoreAllMocks()
  })

  it('should get the latest message with a spy', () => {
    const spy = vi.spyOn(messages, 'getLatest')
    expect(spy.getMockName()).toEqual('getLatest')

    expect(messages.getLatest()).toEqual(
      messages.items[messages.items.length - 1],
    )

    expect(spy).toHaveBeenCalledTimes(1)

    spy.mockImplementationOnce(() => 'access-restricted')
    expect(messages.getLatest()).toEqual('access-restricted')

    expect(spy).toHaveBeenCalledTimes(2)
  })

  it('should get with a mock', () => {
    const mock = vi.fn().mockImplementation(getLatest)

    expect(mock()).toEqual(messages.items[messages.items.length - 1])
    expect(mock).toHaveBeenCalledTimes(1)

    mock.mockImplementationOnce(() => 'access-restricted')
    expect(mock()).toEqual('access-restricted')

    expect(mock).toHaveBeenCalledTimes(2)

    expect(mock()).toEqual(messages.items[messages.items.length - 1])
    expect(mock).toHaveBeenCalledTimes(3)
  })
})
}
```

vi.spyOn()関数を使うことで関数のモックができます。第一引数にオブジェクトを渡し、第二引数にメソッドを渡します。

モックを行うとテスト中に実際の関数の代わりに mock した関数が呼び出されるようになります。

上記の例では呼び出された回数を取得していますが、以下のように書くことで関数の中身を上書きすることもできます。api を mock するときはモックデータを返すように書きます。

```javascript
vi.spyOn().mockImplementation(() => {});
```

では useFetch 等の nuxt から提供される関数を mock する場合はどのようになるでしょうか。

第二引数に'useFetch'を渡すというところまではわかりやすいのですが、第一引数に何を渡せば良いのかという部分で詰まってしまいました。

nuxt3 では useFetch 等の nuxt から提供される関数は import 文を書かなくても利用できます。そのため、普段実装するときはあまり意識することは少ないかと思います。

明示的に書く場合は以下のように書きます。

```javascript
import { useFetch } from "#app";
```

しかし、第一引数に#app と書いても意味がありません。`#app` はエイリアスのようなもので実行時に nuxt 側で実際のパスに変換されるため、テスト環境ではこの方法で参照できません。

このパスが指し示すオブジェクトが何なのかという点がポイントなのですが結論としては以下のように書くことで解決できました。

```javascript
import * as nuxt from "nuxt/app";

vi.spyOn(nuxt, "useFetch");
```

`#app` が参照している nuxt オブジェクトを第一引数に渡すことが必要でした。

navigateTo 等の関数も同様の手段でモックできます。

## おわりに

振り返ってみれば単純なことなのですが、ネットに nuxt の情報が少ないということもありこの方法に行き着くまでにだいぶ時間がかかってしまいました。
同じように nuxt3 にテストを導入しようとしている方の一助になれば幸いです。

# エンジニア募集中

Gakken LEAP では教育をアップデートしていきたいエンジニアを絶賛大募集しています！！
ぜひお気軽にカジュアル面談へお越しください！！

https://gakken-leap.co.jp/recruit/
AppSheetを使って簡単な業務報告アプリを作成！その２

こんにちは、
地方のスーパーで製造部門の教育や指導をしているkuwaharaです。

前回の記事のアプリを様々な方に見てもらい、使用感と要望について聞き、修正してみました。
前回の記事はこちら

https://qiita.com/kuwaharada/items/391d8678b9f5ade9e716

**使用感と要望**
シンプルで使いやすい！
（前回の記事から）所々英語になっているので、日本語に！
白黒が多いので色が欲しい！
項目の文字は太字または大きくしてほしい
忙しい日は他の店舗の様子を見れないので良い！
店舗から写真を送るのは大変なので、楽になりそう

**修正**

①英語を日本語に修正しました。
AppSheetは自動で日本語表記にならないので、
UX⇒Locailizeで各項目を日本語に入力します。

![課題用50.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763115/fa7ad38a-1235-eba5-1f11-cf33fe7b26dd.jpeg)

②文字の大きさの修正
UX⇒Format Rulesから各項目のTextsizeで変更することが出来ます。
![課題用53.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763115/14982f73-149b-8d00-7cf8-8addc2221e0f.jpeg)

③デザインの修正
UX⇒Brandからテーマやアプリのロゴの修正をすることが出来ます。
![課題用54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763115/9eda41b0-e82a-df97-4cca-e8622e5255db.jpeg)

![課題用55.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3763115/44a0a1f3-1668-5788-874b-f6c3a6d81326.jpeg)

**今後の取り組み**

マニュアルの作成
店舗従業員の年齢層も上がっているので分かりやすく作成

自部門だけでなく他部門の方の使用感を確認してもらう

実際の業務へ取り入れる際の流れを確認しておく


今回は以上になります。
早く実装して欲しいとの声をまたもらいました。
頑張ろう！
GORMのトランザクションについて

## はじめに
GORMでDB操作していて、トランザクションをやりたかったので調べたときの備忘録です。細かいとこ間違っていたらすみません。

## トランザクションとは
データベースへの複数操作(レコードの読み書きなどの複数SQL文)を1つのステップにまとめるための仕組み。
トランザクションを開始し、レコードを書き換え、処理後にコミットするという流れで行われる。トランザクションに関わるデータはコミットするまでロックされる。
### トランザクションの特性
4つの特性があり、頭文字をつなげてACIDと呼ばれる。
1. 原子性(Atomicity)
トランザクション内で行われる処理はすべて成功するか、すべて失敗するかのどちらかになる。
処理の途中で失敗した場合、それ以前の成功は無かったことになり、すべて失敗したものとして一連の処理が終了する。
2. 一貫性(Consistency)
トランザクションの前後で、データベースの整合性や制約など、正常な状態が失われないことを保証する。
3. 分離性(Isolation)
並行して実行される複数のトランザクションは、お互いに干渉せずに実行でき、あたかも同時に実行されるトランザクションが存在しないように振る舞う。ただ、本当に同時に実行しないとなると処理速度が低下するため、分離レベルを弱くして対応する場合もある。
4. 永続性(Durability)
トランザクションがコミットされたとき、その状態が半永久的に保持されること。

※分離レベル(下ほど強い)
- 未コミット読み取り(read uncommitted)
最弱。ダーティリード(未コミットの他トランザクションの変更を読める)、ノンリピータブルリード(他トランザクションのコミットによって読み込む値が変化する)、ファントムリード(他トランザクションが追加/削除した場合、読み込むデータが変わる)をすべて許容する。
- コミット済読み取り(read committed)
ノンリピータブルリード、ファントムリードを許容し、ダーティリードを許容しない。
- 反復可能な読み取り(repeatable read)
ファントムリードのみを許容する。
- 直列化可能性(serializability)
最強。3つすべて許容しない。

## GORMでトランザクションを実装する
概ね、公式のリファレンスに書いてあります。

https://gorm.io/ja_JP/docs/transactions.html
```golang
db.Transaction(func(tx *gorm.DB) error {
  // トランザクション内でのデータベース処理を行う(ここでは `db` ではなく `tx` を利用する)
  if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
    // 何らかのエラーを返却するとロールバックされる
    return err
  }

  if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
    return err
  }

  // nilが返却されるとトランザクション内の全処理がコミットされる
  return nil
})
```

自分「あれ、分離レベルはどうするの...?」

## GORMでトランザクション(分離レベル付)を実装する
GithubでTransaction関数の実装を読んでみました。

https://github.com/go-gorm/gorm/blob/109f239fae95b310f64236bcc0fbe87bbfb1edfc/finisher_api.go#L620

それによれば、どうやら可変長引数*sql.TxOptionsがあるようです。
```golang
func (db *DB) Transaction(fc func(tx *DB) error, opts ...*sql.TxOptions) (err error) {
	panicked := true

	if committer, ok := db.Statement.ConnPool.(TxCommitter); ok && committer != nil {
// 以下略
```

つまり、分離レベルを使用したTransactionの実装はこのようになります。
```golang
import(
  "database/sql"
)

db.Transaction(func(tx *gorm.DB) error {
  // トランザクション内でのデータベース処理を行う(ここでは `db` ではなく `tx` を利用する)
  if err := tx.Create(&Animal{Name: "Giraffe"}).Error; err != nil {
    // 何らかのエラーを返却するとロールバックされる
    return err
  }

  if err := tx.Create(&Animal{Name: "Lion"}).Error; err != nil {
    return err
  }

  // nilが返却されるとトランザクション内の全処理がコミットされる
  return nil
}, &sql.TxOptions{Isolation: sql.LevelSerializable})
```

sql.Txoptionsはdatabase/sqlパッケージで定義されている構造体です。
```golang
type TxOptions struct {
	// Isolation is the transaction isolation level.
	// If zero, the driver or database's default level is used.
	Isolation IsolationLevel
	ReadOnly  bool
}
```
IsolationLevelで設定可能な分離レベルは以下の通りです。
```golang
const (
	LevelDefault IsolationLevel = iota
	LevelReadUncommitted
	LevelReadCommitted
	LevelWriteCommitted
	LevelRepeatableRead
	LevelSnapshot
	LevelSerializable
	LevelLinearizable
)
```

## おわり
GORMの公式ドキュメントの日本語版だけではなく、英語版にもこのことが書かれていないため、おそらく忘れられているのだと思います。多分、気が向いてオライリーの本を読まなければ、分離レベルの存在に気づかなかったので、オライリーの本様様といった感じです。

## 参考
database/sqlパッケージのドキュメント

https://pkg.go.dev/database/sql

オライリーの本こと詳説データベース。中々面白かったです。

https://www.oreilly.co.jp/books/9784873119540/
[AWS #11] Amazon Inspector

## はじめに
こんにちは
今回もセキュリティ分野に関する **「Amazon Inspector」** について紹介いたします。
:rolling_eyes:：Inspectorを和訳したら **「検査官」** と出てきました。
:upside_down:：EC2や、インスタンス、コンテナ、Lambdaなどの**ワークロードを自動的に検出**し、ソフトウェアの**脆弱性**を意図しないネットワークの**露出がないかをスキャン**します。なのでイメージは合っていますね。

初めにAmazon Inspectorの前提知識となる **「脆弱性診断」** について紹介いたします。
## 脆弱性診断
脆弱性診断は、ネットワーク・OS・ミドルウェアやwebアプリケーションなどに<font color=red>**脆弱性がないか診断する**</font>ことです。
![AWS11_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/9495f14b-8d28-07af-2acf-b98a7fc1bfcd.png)
脆弱性診断を実施し、セキュリティの現状を確認することで、**攻撃者からの悪意ある攻撃**や**情報漏えいの事故など**を**未然に防ぐことができます。**

:::note info
Amazon Inspectorとは、EC2に対する**脆弱性診断を行う**サービス
:::

## Amazon Inspector
Amazon Inspectorは、利用している**EC2インスタンスの脆弱性診断を安価に行ってくれるサービス**です。自動的に利用しているEC2インスタンスを評価し、**脆弱性がないか** 、ベストプラクティスに沿っているかを確認します。

:::note info
評価後は、評価結果のリストがAmazon Inspectorによって表示されます
:::
### 評価内容（ネットワーク評価とホスト評価）
Amazon Inspectorには、予め定義された個別の**セキュリティルール（評価基準）** があります。ルールパッケージと呼ばれており、**ネットワーク評価とホスト評価の2つ**があります。

それぞれ検出する内容が違うため簡単に紹介いたします。
**ネットワーク評価**
![AWS11_02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/e20ac537-fc6f-086b-0f68-71454bfb97f1.png)
アクセスの許可・拒否を確認することで、外部の攻撃者から**EC2インスタンスに不正なアクセスをされないか確認する**ことができます。

**ホスト評価**
![AWS11_03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3806875/68f177e0-c1f1-bfce-2e7e-9068dcbda2b6.png)
確認内容です。
**・EC2インスタンスに使用している「OS」に[パッチ](https://x.gd/4iIwp)が適用されているか**
**・既に脆弱性があるアプリケーションを利用していないか**
などを確認することがあります。

## おわりに
ちょっとしたまとめになります。

:::note info
Amazon Inspectorとは、利用しているEC2インスタンスの**脆弱性診断を自動で行うサービスです**
:::
:::note info
脆弱性診断とは、ネットワーク・OS・ミドルウェアやwebアプリケーションなどに**脆弱性がないかを診断すること**です
:::
このInspectorを利用することで、EC2インスタンスを含む環境に対して**自動的に脆弱性の評価ができる**ということが理解できました。また、この脆弱性を発見することで、**サイバー攻撃に対する早期施策も可能になる**と考えます。

最後までお読みいただきありがとうございました！

>日頃より活用している参考書です。
>> **「参考書」**
[AWS認定クラウドプラクティショナー改定第3版](https://x.gd/19i6N)
>
> **「AWS公式サイト」**
[Amazon Inspector](https://aws.amazon.com/jp/inspector/)
>
> **「参考元」**
[Amazon Inspectorとは？メリットや評価方法などを解説](https://x.gd/K8t9A)
>
> **「参考元」**
[Amazon Inspectorとは](https://www.wafcharm.com/jp/blog/amazon-inspector-for-beginners/)
>
> **「参考元」**
[Amazon Inspectorとは？EC2インスタンスに利用できる脆弱性診断のメリットや機能](https://business.ntt-east.co.jp/content/cloudsolution/column-211.html)
>
> **「Youtube」**
[【CLF-C02：AWSクラウドプラクティショナー】第14回 AWS Shield (セキュリティとコンプライアンス分野)](https://x.gd/JUitI)