OmniAICreator/Qiita-1.07M huggingface dataset:
LPIC300のための勉強備忘録③

・Sambaの設定ファイル(smb.conf)において、"copy"の意味
ほかの共有の設定の設定を取り込む

・[homes]共有のbrowseable
通常の共有設定と異なる。各ユーザのホームディレクトリの実際の共有においてはhomesセクションのものではなく、globalセクションのものが使用される。
なお、ホームディレクトリ共有とはすべてのユーザは自分自身と対応付けられているホームディレクトリ共有にアクセスできる仕組みのこと。

・Sambaプリントサーバ上のプリンタの管理権限を表すもの
SePrintOperatorPrivilege

・Sambaの設定ファイル(smb.conf)において、パラメータ"create mask"を設定変更すると、Sambaサーバの共有上のファイルのパーミッション指定時にどのような効果があるか
ファイルのパーミッション指定時に指定されたパーミッションと"create mask"の値とのAND演算により、対象ファイルに設定されるパーミッションが決定される。
"create mask"で0に設定されているビットは常に0になる。
ex)"create mask"の値を666に設定し、ファイルのパーミッションに770を指定すると
所有者の権限: rw- (666) AND rwx (770) → rw-
グループの権限: rw- (666) AND rwx (770) → rw-
その他の権限: rw- (666) AND --- (770) → ---
"create mask"は「最大の制限」

・Sambaの設定ファイル(smb.conf)において、共有へのアクセスを制限するために使用できるパラメータ
write list
valid users
Sambaの設定ファイル(smb.conf)において、ユーザーがアクセス可能な共有上のファイルとディレクトリのみを表示するようにするパラメータ
"hide unreadable = yes"
言い換えるとSambaの共有フォルダにアクセスしたユーザーが、アクセス権限のない（つまり読み取りができない）ファイルやディレクトリを表示しないようにするための設定

・ファイルのアクセス制御リストを設定追加・削除するコマンド
setfacl　＝「set file access control lists」

・Sambaの設定ファイル(smb.conf)において、共有のデータの格納先（パス）を指定するパラメータ
path

・Sambaのコマンドで、Windows NT上のファイルやディレクトリの ACLである、REVISION、ACL、CONTROL、OWNER、GROUPなどの項目を表示するもの
"smbcacls" =Samba command Access Control Lists
表示だけでなく設定追加や削除も可能

・ls -l コマンドで表示されるパーミッションの意味
ACLを考慮せずに付与される最低限のパーミッションを示している

・DFS ＝分散ファイルシステム（Distributed File System）
「DFS名前空間」という仕組みによって、複数のファイルサーバーにある共有フォルダを一元管理できる。この仕組みにより、ユーザーは個々のファイルサーバーのIPアドレスや、サーバー名がわからなくても共通の名前を使用して各クライアントから共有フォルダへアクセスが可能になる。論理的なファイルやディレクトリの存在を ネットワーク上に現実に存在する位置から切り離す仕組み

・Sambaの設定ファイル(smb.conf)において、DFS共有として設定するためのパラメータ
"msdfs root = yes"

・Sambaサーバで共有プリンターを使用できる設定
設定ファイルに"[print$]"セクションを記述する。
予めSambaサーバでプリンタドライバの設定を行う必要があるためWindows端末から「プリンターの追加ウィザード」GUIツールを実行するか、Sambaツールのrpcclientコマンドを実行することで行う。
・"create mask"値の設定がない場合の規定値は"0744"
"force create mode"値とのOR演算を行う

・Sambaの設定ファイル(smb.conf)において、[homes]セクション内にパラメータ"browseable = no"を定義した場合
homes共有に直接アクセスするには、個別のUNCパスで開く
Sambaサーバの共有をブラウズしてもhomesという共有があるわけではない
UNCパス（Universal Naming Convention パス）とは、WindowsやSambaなどのネットワーク環境で、ネットワーク上の共有リソース（ファイルやプリンターなど）にアクセスするために使用される標準的なファイルパスの形式。以下の形式で表す。
\\サーバー名\共有名\パス

・[printers]共有に必須の設定はprintable = yes"

・RAW印刷とは「印刷対象のファイルはテキストや画像ではないバイナリファイルであってもディスク上のビット列のままプリンタに転送される」ことを言う

・Sambaの設定ファイル(smb.conf)において、"write list"とは
Linuxのファイルシステムのパーミッションで書き込み許可がある場合、write listに記載されているユーザーに共有への書き込みが許可される
俺用、範囲を判定するマクロ 成功0428


いろいろ、注意
----

- Arduino UNOでの　予定は、未定
- いろいろ、あって、完成(朝、ぎりぎり10分前から初めたので、一発で動くと思っていた。)
- 今回のポイントと、方向によって範囲を反転


プログラム
----

オンラインコンパイラpaiza

```c++


#define RE(A,B,C) (  (A<B)?( (C >= A) && (C <= B) ):( (C >= B) && (C <= A) )  )

#include <iostream>
using namespace std;
int main(void){
    // Your code here!
    
    
    for(int i=1;i<=7;i++){
        if( RE(3,6,i) ) {
            printf("RE(3,6,%d) YES\n",i);
        }else{
            printf("RE(3,6,%d) NO\n",i);
        }
    }
    printf("\n");
    for(int i=1;i<=7;i++){
        if( RE(6,3,i) ) {
            printf("RE(6,3,%d) YES\n",i);
        }else{
            printf("RE(6,3,%d) NO\n",i);
        }
    }
    
}



```


```

RE(3,6,1) NO
RE(3,6,2) NO
RE(3,6,3) YES
RE(3,6,4) YES
RE(3,6,5) YES
RE(3,6,6) YES
RE(3,6,7) NO

RE(6,3,1) NO
RE(6,3,2) NO
RE(6,3,3) YES
RE(6,3,4) YES
RE(6,3,5) YES
RE(6,3,6) YES
RE(6,3,7) NO


```
queryAllByRoleとgetAllByRoleの違い

# はじめに
名前が似てるようで、機能が異なる ```queryAllByRole``` と ```getAllByRole``` の違いについてまとめました。

# ```queryAllByRole``` と ```getAllByRole```の違い
### - queryAllByRole
```queryAllByRole``` はDOM上に要素が見つからなかった場合に空の配列 ```[]``` を返します。
つまり、要素が存在しない可能性がある状態をテストしたい場合はこちらを使用します。
```jsx
afterDeleteButtons = screen.queryAllByRole("button", {
    name: "削除",
  });
console.log(afterDeleteButtons); // []が表示される
```
### - getAllByRole
```getAllByRole``` はDOM上に該当する要素が見つからなかった場合 ```TestingLibraryElementError``` というエラーがスローされます。
これは、 ```getAllByRole``` ファミリーのメソッド（```getAllByRole```、```getAllByLabelText```、```getAllByText``` など）の設計によるものです。

これらのメソッドは、**1つ以上の要素が見つかることを期待しており、見つからなかった場合はテストが意図しない状態で進むのを防ぐためにエラーを発生させます。**
```jsx
afterDeleteButtons = screen.getAllByRole("button", {
    name: "削除",
  });
console.log(afterDeleteButtons); // エラーがスローされるのでテストが失敗する
```

# おわりに
Jestの関数は多すぎて、なかなか覚えられない（笑）
レトロPCのためのBASIC講座１０　シーケンシャルファイルの読書

# 前回のおさらい
前回は、グラフィック画面操作のプログラムをFor文やGOSUB命令を交えたプログラムで書いてみました。
[レトロPCのためのBASIC講座９](https://qiita.com/kawamo55/items/6298fb523e5eb804a4e0)

# BASICのファイル読書
BASICでは、シーケンシャルファイルとランダムアクセスファイルがあります。
シーケンシャルファイルは、１行ごと書込みます。
１行の長さが決まっていないので、１レコードの読書はできません。

# シーケンシャルファイルの書込み
N88BASICのディスクBASICでデータを読み書きする際の１つの手法が、シーケンシャルファイルの読書です。
以下は、シーケンシャルファイル（テキストファイル）の書込みmです。
``` WTTEXT.BAS
100 ' Datas
110 DATA "Test1",10,11,"Test2",19,29
120 '
130 '
140 '
150 OPEN "Test.txt" FOR OUTPUT AS #1
160 FOR I=1 TO 2
170 READ S$,I1,I2
180 WRITE #1 ,S$,I1,I2
190 NEXT
200 CLOSE #1
```
上記プログラムは110行目にあるデータを読みディスク上のTest.txtというファイルに書き込みます。
150行目でファイルを書込み用に開いて、180行目のWRITE文で書込み、200行目でファイルを閉じています。
170行目のREADは110行目のデータを読んでいます。
# シーケンシャルファイルを読む
``` RDTEXT.BAS
100
110 OPEN "Test.txt" FOR INPUT AS #1
120 FOR I=1 TO 2
130 INPUT #1,S$,I1,I2
140 WRITE S$,I1,I2
150 NEXT I
160 CLOSE #1
```
上記の例ではTest.txtに書込まれたデータを読取ります。
110行目で読込用にファイルを開いて、130行目でファイルから読み取り、160行目でファイルをクローズ

読書時に使っている♯1はファイルディスクリプターと呼ばれる番号

# 今回の動画
https://youtu.be/Z8A2KL1HM4s
ハッカーのギャル文字を学んで1337なチャットを送ろう

# はじめに
今年のゴールデンウィークは新婚旅行で海外に行きます。
社会人になってから英語から遠ざかっていたので、最近は英語の練習のために毎日適当なGitHubのリポジトリの`README.md`を音読してから眠るという生活を送っています。

そんな生活を送っていると、**英語圏のハッカー達が使う独特の単語が存在する**ことに気がつきました。いわゆる、ジャーゴン[^1]というものです。

私見ですが、ジャーゴンというものは自分が理解できない内は忌々しく感じて、一度理解できると自分でも使ってみたくなるという性質があると思います。
少なくとも私はそうです。

私はある程度調べて使ってみたくなるフェーズに入っているのですが、仕事のチャットでいきなり使うと引かれてしまいます。そのため、会社の同僚も読むであろうQiitaで解説記事を書くことにより、社内チャットでハッカーのスラングが飛び交うための土壌を醸成しようと思います。

:::note
本記事では、私が見つけたスラングを3つの分類に分けてご紹介します。
:::

# leetspeak
leetspeakとは、英単語の特定のアルファベットを特定の記号や数字に置き換えたものです。また、単語の綴り自体が変化する場合もあります。

leetspeakという言葉自体もleetspeakの一種です。
`leet`は、`elite`という単語を変化させたもので、`i`を`1`、`e`を`3`、`t`を`7`に置き換えて`1337`で`leet`(elite)と読ませることが多いようです。
日本のギャル文字[^2]と同じ発想ですね。

よくleatspeak表記されている単語としては、`hax0r` (hacker)、`u` (you)などがあります。

# 映画に登場する単語
leetspeakと違い私が独自で考えた分類ですが、映画からの引用もよく見かけます。
例えば、1995年公開のHackers(邦題:サイバーネット)に登場する架空のコンピュータである`gibson`はコンピュータという意味で使われています。
観たことがなかったので、最初は全く意味が分かりませんでした。

私は仕事中以外でプログラミングをするときはよく映画を流しながら作業するのですが、英語圏のハッカー達も同じなのかもしれませんね。

# 意図的な誤字
意図的に誤字を残している文章もよく見かけます。
例えば、`the`を`teh`と意図的に誤字させることが多いようです。
最初は単に誤字に気が付かないで残っちゃっているのかなと思いましたが、あまりにも同じ間違いをしている人が多いので調べてみたところそういう文化があるようです。

他にも、`own`を`pwn`と書いたり`cool`を`kewl`と書いたりするのが代表的な意図的な誤字です。
`own`を`pwn`にするのはキーボードで`o`と`p`が隣だからだと思いますが、`cool`を`kewl`とする感性は私にはwat[^3]という感じです。

# おわりに
皆さんもぜひ職場で使ってkewlなやつだと思われましょう。
最後に、**leetspeak**、**映画に登場する単語**、**意図的な誤字**が全て含まれた3p1c[^4]な文章を発見したので引用して終わりにします。

>Well, because some of us hackers that actually like to do fun and challenging things to expand our minds and make us think and aren't just out to hax0r up a gibson or two to show everyone who's teh 1337. Anyways, carrying on...
-- https://gist.github.com/roachhd/dce54bec8ba55fb17d3a

[^1]: 特殊な集団内でしか通用せず、部外者には意味がわからない言葉。
[^2]: ギャルが使うとされる独特の文字。例えば、[ギャル文字一括変換装置](http://www.gal-moji.com/moji/gyaru_moji_pc_org.asp#google_vignette)によると`ギャル文字`のギャル文字は`≠″ｬ｣ﾚ文字`。
[^3]: whatの意。
[^4]: epicの意。
【脱・課金】Cursor AI有料プラン不要！無料ツールだけで始めるAI駆動開発ガイド

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/212914/8ef9f105-e494-46cd-8292-dbf00d8e65a2.png)


## 1. はじめに：AI駆動開発の波とツールの選択肢 

AIによる開発支援、いわゆる「AI駆動開発」への関心が急速に高まっています。GitHub Copilotや、より強力な機能を持つCursor AIなど、選択肢も豊富です。しかしCursor AIは月額$20～と、コスト面で躊躇する声も。  
そこで本記事では、「有料プランに頼らず、無料ツールの組み合わせだけで、AI駆動開発をスタートする方法」を紹介します！  
実は、無料でも十分実践できるんです。

---

## 2. なぜCursor AI有料プランが「必須ではない」と言えるのか？

結論から言うと、**基本的なAI駆動ワークフローは無料ツールだけで実現できる**からです。

キープレイヤーは次の通り：

- **GitHub公式MCPサーバーの登場**  
  → AIがGitHubリポジトリと連携できる標準サーバー。無料で使えます。  
  [GitHub MCP Server](https://github.com/github/github-mcp-server)

- **Cursor AI無料プランの充実**  
  → AI補完、チャット機能、MCP連携が可能。十分実用レベルです。  
  [Cursor公式サイト](https://cursor.com/)

- **代替プラン：VS Code + AIプラグイン**  
  → Copilotの無料ティアや、他のAI拡張機能を使う方法もあります。

つまり、わざわざ高価なサブスクリプションを契約しなくても、開発支援AIはあなたの力になってくれるのです！

---

## 3. 主役はこの無料ツールたち！特徴と設定の概要
### ① GitHub公式MCPサーバー：AIとGitHubを繋ぐ無料の橋

- **役割**  
  Model Context Protocol (MCP) に準拠し、AIがGitHubリポジトリを操作できる仲介サーバー。
- **主な機能**  
  ファイルの読み書き、ブランチ操作、Issue作成・管理、Pull Request管理など。
- **設定概要**  
  - Dockerが必要です。
  - GitHubのPersonal Access Tokenを用意し、簡単なDockerコマンドで起動します。  
  ➡️ [MCP Server公式GitHub](https://github.com/github/github-mcp-server)  
  ➡️ [Personal Access Tokenの作成手順](https://docs.github.com/ja/authentication/keeping-your-account-and-data-secure/creating-a-personal-access-token)

> ✅ **ポイント：完全無料で利用可能！**

---

### ② Cursor AI 無料プラン：AI統合エディタの入り口

- **役割**  
  VS CodeベースにAI機能を組み込んだ、次世代型コードエディタ。
- **無料プランの機能**  
  - 基本的なAIコード補完  
  - AIチャット（コード説明や質問対応）  
  - MCPサーバーとの連携
- **設定方法**  
  設定画面から、MCPサーバーのアドレス（例：`http://localhost:ポート番号`）を指定します。

➡️ [Cursor公式サイト](https://cursor.com/)

---

### （補足）Dockerについて

- MCPサーバーの実行に必須。
- 個人利用なら基本無料ですが、ビジネス利用ではライセンスを要確認しましょう。

➡️ [Docker公式サイト](https://www.docker.com/)

---

## 4. 実践！無料ツールで作るAI駆動ワークフロー

### ステップバイステップ

1. Dockerをインストールして起動
2. GitHub Personal Access Tokenを作成
3. ターミナルでMCPサーバーを起動（例）  
   ```bash
   docker run -p 3000:3000 -e GITHUB_TOKEN=your_token ghcr.io/github/mcp-server:latest
   ```
4. Cursor AIを起動し、設定からMCPサーバーに接続

### 簡単な利用例

- **例1**：「MCPサーバーを使って、`my-repo/README.md`を読み込んで表示して」
- **例2**：「`main.py`の`process_data()`関数をリファクタリングし、GitHubにコミットして」

> ✅ 基本的なファイル操作や修正依頼なら、無料プランでも十分可能！

---

## 5. 無料ツールの限界と注意点
当然ながら、無料ツールには制約もあります。

- **トークン制限**  
  → CursorやCopilot無料ティアには使用量制限あり。
- **高度機能がない**  
  → Composer（プロジェクト全体操作）やAgentモード（自律作業）は有料限定。
- **設定の手間**  
  → Dockerや環境設定に慣れない人には、ややハードル高め。
- **レスポンス速度**  
  → 有料版よりも処理が若干遅いことも。

小規模プロジェクトや学習目的なら十分ですが、大規模開発を考えるなら有料版も検討する価値があります。

---

## 6. まとめ：賢くツールを選び、AI駆動開発を始めよう！ 

無料ツールを上手に組み合わせることで、コストをかけずにAI駆動開発の世界に飛び込めます。  
特にGitHub MCPサーバーは今後の標準技術になる可能性大。  

「まずは無料から試してみて、自分に合ったスタイルを見つけましょう！」  

💬 **あなたはどんな無料ツールを活用していますか？コメントでぜひ教えてください！**
【xlwings】Excel VBAからpythonコード呼び出し

# 序文

pythonが便利すぎるので、C言語の#include <Python.h>、VBAからpythonを呼び出すxlwings、近々Unityからpythonを呼び出す方法をチェック予定と、とにかくpythonを手放せない。

モジュールが便利過ぎるんですよね。

そういや、一時期Python in Excelが話題になったけど、最近は聞かないな。
個人的には、これは大歓迎。Officeを使っている理由は、VBAが7割くらいを占めているので、その縛りがなくなるなら無料ソフトに移行できるし・・・

# VBAからpythonを呼ぶ最小プログラム

## 設定前のExcelメニューバー状態確認

![WS001642867.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/6369c7db-204d-4f7c-98ea-5670e8c339ae.jpeg)


## 仮想環境準備

既存環境に影響を及ぼさせたくないので下記のコマンドをコマンドプロンプトで実行

```
python -m venv xlwings_test
cd ./xlwings_test
.\Scripts\activate
```

### 仮想環境フォルダ（コマンドで作成したxlwings_testフォルダを確認）

以下ここにpythonモジュールがダウンロードされるので、環境を汚さずにテストできます。

![WS001642867_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/c1d418cf-f0c1-417c-bd2e-5942f4c93662.jpeg)


### xlwingsをインストール

```
pip install xlwings
```

![WS001642870.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/26c5cc92-9434-42b2-b18d-67272d9f72ba.jpeg)

### xlwingsアドインのインストール

```
xlwings addin install
```

![WS001642871.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/4fc0f8b4-dab2-4d2c-a471-866210891447.jpeg)

#### Excelのメニューバーでxlwingsが追加されていることを確認

画像のようにxlwingsが追加されていればOKです。

![WS001642872_2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/64f6295c-511d-4bd2-af38-f58952becc06.jpeg)

## 動作確認プログラム

ちゃんと使えるか疎通テスト

```
xlwings quickstart test_xlwings_VBA
```

本コマンドで、VBAとpythonのセットを作ってくれるのでこれを実行します。
![WS001642873.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/e165a9fa-bb1f-4c05-a332-328884cda06f.jpeg)

![WS001642874_b.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/196fe6c4-997a-4821-bdae-4113bbd4baa6.jpeg)

## マクロを実行
### Run Mainをクリック

Run Mainをクリックし、A1セルに「Hello xlwings!」と表示されればOK！
![WS001642879.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/bab63f6b-5219-4f47-b57d-93f3e3301820.jpeg)

ちなみに、もう一回クリックすると「Bye xlwings!」に変わり、pythonコードのとおりですね。

### トラブルシューティング

下記のエラーが出た場合は、パスが通っていない可能性があるので、Interpreterでpythonのパスを貼り付け直して上げれば直ります。（VBAってエラーメッセージが不親切なんだよな・・・）

![WS001642877_.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/fa37c01f-f7ac-426a-8e9f-38b91c57b156.jpeg)

![WS001642879_path.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/530912/ea0fb19f-fa1f-48cf-90b8-d050f3225ff1.jpeg)

# 後片付け

```
xlwings addin remove
```

でアドインを削除し、Excelのメニューから消えます。
個人的備忘録：GitHubのpull_request_templateとは？レビュー効率アップ

## はじめに

GitHubでチーム開発をしていると、Pull Request（プルリクエスト）を作る機会がたくさんあります。

:::note info
そのたびに、変更内容や背景、レビューしてほしいポイントなどを毎回ゼロから書くのは大変ですよね...。
:::

そこで便利なのが **`pull_request_template`** です！この記事では、pull_request_templateとは何か、どう使うかを解説していきます。

## 書こうと思ったきっかけ

プルリクを書くとき、
- 変更内容
- 変更理由（背景）
- 動作確認方法
- レビューしてほしいポイント
- その他注意点
などを整理して書くのはとても大切ですが、毎回手打ちだと時間もかかるし、書き漏れも起きがちです。

:::note warn
***また、メンバーによって記載内容がバラバラになると、レビュワーも読むのが大変になってしまいます。***
:::

これらの課題を解決するために、あらかじめPull Requestのテンプレートを用意しておくことで、誰がプルリクを作っても、**一定のフォーマットでわかりやすい内容に整えることができる**ので、とても実用的だと感じたため、この記事を書きました！

## pull_request_templateとは？

**`pull_request_template`** は、プルリクエスト作成画面で、あらかじめ用意したテンプレートを自動で表示してくれる仕組みです。

例えば、こんなテンプレートを用意しておくと…

```markdown
## 変更内容
- なにを変更したのか？

## 背景・理由
- なぜこの変更が必要だったのか？

## 動作確認方法
- どうやって動作確認したか？

## レビューしてほしいポイント
- 特に見てほしいポイントがあれば

## その他（課題・注意点など）
- 特記事項
```

プルリクを作成するときに、この内容が自動でセットされ、
あとはそれぞれの項目を埋めるだけになります！

これにより、**情報漏れを防ぎ、レビュー効率もアップする**という効果があります。


### 配置方法

基本的な配置はシンプルです。

リポジトリ内に次のようにファイルを置きます（ファイルを非表示のディレクトリに格納する）：

```
.github/pull_request_template.md
```

この場所に置くだけで、自動的にプルリク作成時にテンプレートが反映されます！

※さらに複数テンプレートを使いたい場合など、細かい設定もできますが、最初はこれだけで十分です！

**参考文献**

https://docs.github.com/ja/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository

## まとめ

- `pull_request_template` はプルリクを書くときの"ひな形"になる
- チームで開発するなら、情報整理・レビュー効率向上のために導入がおすすめ
- `.github/pull_request_template.md` に置くだけで簡単に使える

pull_request_templateを活用して、チーム開発をもっとスムーズにしてみてください...！
ReactNative × Expoの雛形ファイルの中身 

プロジェクト雛形（テンプレート）の中身

## まず全体像：プロジェクト構成
```
app/
├── .expo/ (Expoが裏で使っている設定ファイル群。基本的に触らない)
├── app/ (画面（Screen）をまとめるフォルダ)
├── assets/ (画像、アイコン、フォントなど静的ファイルを保存)
├── components/ (アプリ内で使いまわせる小さなパーツたち)
├── constants/ (アプリ共通の定数を管理。テーマカラー、フォントサイズ、APIのエンドポイントなど)
├── hooks/ (自作のカスタムフックを置く)
├── node_modules/ (npm installやyarnで入れたライブラリたちの本体。基本的に触らない)
├── scripts/ （プロジェクト管理を助ける自動化スクリプト。リセットスクリプトが入っている）
├── .gitignore
├── app.json（Expoプロジェクトの設定ファイル。アプリ名、アイコン画像、スプラッシュ画面など）
├── expo-env.d.ts（Expo専用の型定義ファイル（TypeScript用））
├── package-lock.json（使ってるライブラリのバージョンを固定するファイル。自動生成される。基本的に触らない）
├── package.json（プロジェクトの設定ファイル。使用ライブラリ一覧など）
├── README.md
└── tsconfig.json（TypeScriptの細かい設定ファイル）
```

## 基本的に触るところ（ここを抑えていたら大丈夫）

### 📄 基本的によく触る場所
`app/`
画面（Screen）を作る場所
ルーティング（ページ遷移）もここで管理
例：トップ画面ならapp/index.tsxを編集

`components/`
再利用できるパーツを作る場所
例：共通ボタン、日記カード、カスタムモーダルなど

`constants/`
色、フォントサイズ、APIエンドポイントなどアプリ共通の設定値
デザインや値の統一感を出すために使う

`hooks/`
ロジックを切り出した自作フック
例：認証管理のuseAuth、データ取得のuseDiaryなど
複雑になりがちな処理を分けてスッキリ書ける！

`assets/`
画像やフォントなどの素材を置く場所
例：ロゴ、アイコン、カスタムフォントなどをここに保存

### ⚙️ たまに触るかも？な設定系ファイル

`app.json`
アプリの基本設定
例：アプリ名、アイコン、スプラッシュ画面など

`package.json`
使うライブラリ管理とスクリプト管理
ライブラリ追加 (npm installとか) したらここに反映される

`tsconfig.json`
TypeScriptの設定
基本はほぼ触らないけど、環境によってちょっといじることもある



## まとめ
「基本は `app/` と `components/` を触って、たまに `constants/` や `hooks/` を追加する感じです。
ここを押さえておけば、React Native × Expoアプリ開発は怖くないです
個人的備忘録：Next.jsプロジェクトにPINコード認証付きログイン画面を作ってみた

## はじめに

Next.js (TypeScript) と Tailwind CSS を使って、ログイン画面を作成しました。

:::note info
**個人の備忘録程度の走り書きとなっておりますが、温かい目で見守っていただければ幸いです。**
:::

この画面は、一般ユーザーと管理者ユーザーで振る舞いを分け、管理者ユーザーにはPINコード入力による認証を設けています。

## 書こうと思ったきっかけ

簡単なデモアプリを作る中で、管理者用のアクセス制御を簡易的に実装してみたかったためです。セキュリティを意識した設計の第一歩として、PIN認証を試しました。

**作成したコード**

https://github.com/2025SpringTeamA/frontend/blob/feature/add-login-pin-dialog/src/app/login/page.tsx

## 最初の宣言

```tsx
"use client";

import { useState } from "react";
import { useRouter } from "next/navigation";
import Link from "next/link";
```

- "use client" → Next.jsのApp Router環境で、「このコンポーネントはクライアント側で動くよ」と宣言
- useState → Reactの状態管理フック
- useRouter → ページ遷移に使用
- Link → ページ間リンクを作る

## useStateの設定とRouterの取得

```tsx
const [showPinDialog, setShowPinDialog] = useState(false);
const [pinCode, setPinCode] = useState("");
const router = useRouter();
```

- showPinDialog → PIN入力ダイアログの表示状態
- pinCode → 入力されたPINを保持
- router → ページをコード上で遷移する

## 管理者ボタンクリック時の処理

```tsx
const handleAdminClick = (e: React.MouseEvent<HTMLButtonElement>) => {
  e.preventDefault();
  setShowPinDialog(true);
};
```

- リロードを防ぐ
- PIN入力ダイアログを表示

## PIN確認ボタン押下時の処理

```tsx
const handleConfirmPin = () => {
  if (pinCode === "1234") {
    router.push("/admin-home");
  } else {
    alert("PINコードが間違っています！");
  }
};
```

- PINが"1234"と一致すれば/admin-homeへ遷移
- 違う場合はアラート出力

## メイン画面のUI構成

```tsx
<main className="flex flex-col items-center justify-center min-h-screen bg-[#0a0a0a] text-white p-8 pt-16 gap-10">
```

- 黒背景、白文字、中央よせレイアウト

## ログインタイトル

```tsx
<h1 className="text-3xl font-bold bg-gray-200 text-black px-10 py-4 rounded">
  ログイン
</h1>
```

- 大きめの文字で表示

## 入力フォーム

```tsx
<input type="text" ... />
<input type="password" ... />
```

- ユーザー名とパスワードの入力欄

## ログイン種別ボタン

```tsx
<button onClick={handleAdminClick}>管理ユーザー</button>
<Link href="/home">一般ユーザー</Link>
```

- 管理ユーザーボタン：PIN入力ダイアログを開く
- 一般ユーザーボタン：/homeへ遷移

## 戻るボタン

```tsx
<Link href="/">戻る</Link>
```

- トップページ（/）へ戻る

## PIN入力ダイアログ

```tsx
{showPinDialog && (
  <div className="fixed inset-0 flex items-center justify-center bg-black bg-opacity-50">
    ...
  </div>
)}
```

- showPinDialogがtrueのときだけ表示
- 半透明背景付きのダイアログ

## ダイアログ内部

```tsx
<input
  type="password"
  value={pinCode}
  onChange={(e) => setPinCode(e.target.value)}
  ...
/>
```

- PIN入力を受け取り、pinCodeの値を更新

```tsx
<button onClick={handleConfirmPin}>確認</button>
<button onClick={() => setShowPinDialog(false)}>キャンセル</button>
```

- 確認ボタン：PINを検証
- キャンセルボタン：ダイアログを閉じる

**実際の画面**

![Screenshot 2025-04-28 at 6.13.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/11c29ac8-3724-48a6-b7de-e31dd485fb41.png)

![Screenshot 2025-04-28 at 6.14.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662571/e231c53f-532b-4230-b3dc-eeb25e684437.png)

## まとめ

今回の実装により、一般ユーザーと管理者ユーザーを区別したログイン画面をシンプルに作成できました。

:::note warn
**管理者のみPIN認証を通過させる仕組みを取り入れることで、最小限ながらセキュリティを意識したフローを体験できました。**
:::

今後は、PINのハードコーディングをやめてサーバー連携するなど、さらに実用的なセキュリティ強化を目指していきたいです...！
アプリ開発スタートメモ（React Native × Expo）

## 🧭 目的
- 簡単なモバイルアプリ(iOS/Android)を作成したい
- 手軽に作成して、リリースしたい


## 🔧 技術スタック
| 項目             | 内容                           |
|------------------|--------------------------------|
| アプリ種別        | モバイルアプリ（iOS/Android）    |
| フレームワーク    | [React Native](https://reactnative.dev/) |
| 開発ツール        | [Expo](https://expo.dev/)        |
| 言語              | JavaScript / TypeScript（任意）   |
| 実機確認          | Expo Go アプリを使用（iOS/Android） |


## 🚀 開発スタート手順

### ① Node.js をインストール（推奨：v18 以上）

[https://nodejs.org/ja](https://nodejs.org/ja)

インストールされているかの確認方法
```
node -v
```

### ② Expo アプリ作成

```bash
npx create-expo-app my-app
cd my-app
npx expo start
```


### ③ スマホでプレビュー確認
1. スマホに Expo Go をインストール
1. npx expo start を実行して出てくる QRコードを読み取る
1. スマホ上でリアルタイムに画面が反映される！



## ✅ 参考：React Native vs Expo 比較
|項目|ReactNative単体|Expo|
|---|---|---|
|セットアップ|やや複雑（Xcodeなど必要）|簡単（すぐ動く）|
|カスタマイズ性|高い|基本的な範囲で十分|
|OTA更新|手動ビルド必要|Expoなら可能|
|初心者向き|△|◎|

→ まずは Expoで始めて、必要があればReact Nativeに移行するのがおすすめ。
grafana display name

```
solana_wallet_token_balance{token="",wallet=""} 123
```

grafana display name `${__field.labels.token}`

---

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169726/f1d8f31b-d53e-498e-99c7-7037149aab74.png)

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/169726/2edb596e-1ea1-4624-8150-dd29e7b41cf9.png)
SESって実際どうなのってことを話したい

# はじめに

SESで働いた経験からわかるいいとこ、悪いところを話したいと思います。
概ねネットにある通りではありますが、これからエンジニアを目指す方の参考になればと思います。

# そもそもSESとは？

端的に言うと派遣です。

「これが作りたい！」と、ある会社が言ったとします。
しかし、エンジニアが不足、あるいはいないので、そのままでは作れません。
そう言った時に他の企業に属しているエンジニアの技術を借りる。

そういうエンジニアを派遣して、システムの開発を手伝わせる業種を
システムエンジニアリングサービス
SESと呼んでいます。

# 実際どうなの？

エンジニアを志している方ならもう大体わかっていると思いますが、
かなり煙たがられている業界です。

+ そもそも開発経験が積めない案件に参画させられる
+ 未経験者を経験者として参画させようとする
+ 給与が低い
+ レガシー技術にしか関われない

よく言われるのはこんなとこです。


# 開発経験が積めない案件への参画

いわゆるロースキル案件ってやつです。
これはマジです。

SESは案件に参画をする際、企業と契約を結びます。
月いくらかを支払ってこの時間からこの時間までは労働してもらうという契約を結びます。

sesの場合は準委任契約といい、労働時間を満たしていればOKなので、成果物に対する責任は負いません。（あくまで法律的にはです）

極端な話、労働時間さえ満たしていればクライアントは報酬を支払う義務がありますし、クソみたいなシステムを作成したとしても、これに対して支払いを拒否することはできません。

クライアントからすればヤバいやつと契約して、月に何十万を支払った結果、使い物にならないシステムが出来上がったなんてことは避けたいわけです。

なので、当然経験豊富なエンジニアと契約したいわけです。

そうなってくると未経験あがりのエンジニアでは中々開発案件に参画するのは難しく、開発じゃない案件に参画をしてもらうと言うことが往々としてあります。

これを回避するためにチームでの案件参画をすることで、未経験者をフォローする体制を整えて参画するという方法がまず考えられるでしょう。

これに関してはそう言う体制を整えている会社さんに所属するのが一番です。
（それが中々見つからないんですよね。。）


# 経験者を経験者として参画させようとする

いわゆる経歴詐称です。
以前も問題になっていましたね。

これは事実です。

sesは必ず案件にはいる際に面談を行います。
この面談で人となりと技術力を確認することになりますが、
そもそも経験が浅いとその面談すらできないことがあります。

そこで、経験を盛るわけです。
どれくらい盛るかはわかりませんが、よく聞くのは1年半〜3年です。

やってない開発をやったことにしたり、
研修を実務扱いにしたりと

よく見かけます。

普通に犯罪です。

ただ、客からすればやることやってくれればいいので、それなりのパフォーマンスを出せば良いのでしょう。昔からあることなのにあまり話題になりません。

知り合いは一度詰められたと言っておりました。

ぶっちゃけ時間削ってちゃんと勉強すれば、なんとかなるかもしれませんが普通に誰も幸せにならないんでやめた方がいいです。

# 給与が低い

これはケースバイケースです。

ses業界では出向先と契約を結んだ際、毎月いくら支払うかを決めます。
これを単価と呼び、一人のエンジニアを一ヶ月貸し出すレンタル料だと考えてください。

この単価から会社の利益や営業のインセンティヴを差し引いた額が給与になります。

単価に対していくらもらっているかの割合を還元率と呼びます。

この還元率は会社によって異なるので、一概に給与が低い高いとは言えません。

最近では高還元率SESというものが台頭しています。

こちらは真っ当な会社であれば実際に給与は高い印象を受けますね。

ちなみに僕は単価50万円で給与が額面26万円でした。

すっくねえ。


# レガシー技術にしか関われない

これは嘘です。
全然新しい技術を使っているプロジェクトにはいることはできます。
Goを使っている案件に参画している友人がいたり、gitを使ってない案件に入った知り合いだったりと、そこは様々です。

ただ案件を選択できない、営業が希望を聞いてくれないようなses企業だとそう言った案件に入るのは運要素が強いでしょうね。

なので使ってみたい技術に関われる機会はあるかなと思います。

ただそれなら最初から自社開発とか受託開発に入った方がいいですけどね。


# sesに向いてる人

エンジニアになろうと思った時、三つ候補があるでしょう。

プロダクトを自社が持っている自社開発企業
開発をまるまる請け負う受託開発
そしてses。


一番いいとされる自社開発ですが、全てのエンジニアにとってそれが良いとは限りません。

例えば、こういう技術が使いたいと考えてるのはいいものの、肝心のサービスに興味がないとなってくると中々厳しいでしょう。

単に技術があればいいというわけではなく、ユーザー目線を意識した開発が常に求められるため、サービスについてしっかり考えることが求められるからです。

技術を追いかけたい人ならsesはあっているでしょう。

仕事は技術提供なので、関われる工程が実装のみとか詳細設計からと限られているからです。


あとは飽き性な人。

会社にいながら転職を繰り返すみたいにいろんな案件を回れるので、技術の知見は広まっていくと思います。

一つのサービスについてしっかり向き合うというのができない人はあってるかも。


# 個人的なおすすめ

新卒であればわざわざsesに行く必要もないのかなと思います。

技術にこだわりがある場合でも、自社開発企業は技術スタックが固定しているはずなんで、使いたい技術を扱う案件に参画するのを狙うより、自社開発の会社に入社すればそこは確実なはずです。

何よりsesをやっていると、社会に役立ってることをしてるのかという虚無感に追われることもあるので、このサービスは社会に役立つ意義があるものだ。だからこの企業の開発に関わりたいと思える企業に属した方が少なくとも僕は幸せなんじゃないかと思うので、自社開発を勧めます。

結局は自分の方向性なので、どうしたいかを考えましょう。


じゃ、僕も転職頑張ります。
Raycastの着地判定で発狂[Unity]

## 記事
ちょっとした手違いを気付かずに一生デバッグしているとき、あると思います。
大体は実装全体像を理解していない故に起きています。
まずは把握を優先しましょう。

## ほんへ
着地判定の実装にあたり、今回は自機が回転するので、子オブジェクトに当たり判定を導入するやり方から一新することにしました。
そこでRaycastというのを用いますが、これが大変。
レイヤーの概念など今まで意識したことがないものばかりであったため場当たり的に取り組んでいました。

## 問題+解決への道
Debug.DrawRayを用いることによって軌跡の視覚化ができていたので、rayが伸びていることは確認できていました。しかし、排他的に地面のレイヤーのみ識別するという処理がまともにできているかの検算ができなかったゆえに、なぜ判定ができないのかを解決できないでいました。

結局、対象Objのレイヤー情報を更新し忘れていただけでした...

rayerではなく段取りを怠った自分を責めました。

以下コードです。

```C#:SphereControl.cs
/*
 * Copyright (c) DeepNapEngine
 * https://github.com/TrueRyoB
 */
namespace PoseQ.Core.GamePlay.RhyRhyDaDa
{
    public class SphereControl : MonoBehaviour
    {
        private void FixedUpdate()
        {
            CheckGround();

            if (GameConfig.ShowDebugInfo)
            {
                Debug.DrawRay(
                    transform.position + groundCheckOffsetY * Vector3.up,
                    Vector3.down * _groundCheckDistance,                 
                    _onGround ? Color.green : Color.red
                );
            }
        }
    
        private void CheckGround() => 
            _onGround = Physics.SphereCast(transform.position + groundCheckOffsetY * Vector3.up, groundCheckRadius, Vector3.down, out RaycastHit hit, _groundCheckDistance, groundMask, QueryTriggerInteraction.Ignore);
    }
}

```
変数の定義や他の関係ない関数などは省略しました。

## まとめ
めげずに頑張ってください。
Blenderでテキストの画像を作成する

Blenderでは３D空間上に文字のオブジェクトを置いたりする機能はありますが
２D画像に文字を描画する機能は用意されていません

スクリプトで自動化するにあたって文字入れの操作をしたい場合もあったので
できる操作がないか探ってみました

直接的にフォントをラスタライズした画像を得る手段はないようなので
画面に文字を描画するためのblfモジュールを使ってオフスクリーンバッファ上に文字を描画させて
その画像を取得するという手順をとってみました

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151493/a1d8e800-37ec-45de-a6e8-e40279d654f8.png)

```py
import bpy
import blf
import gpu
import numpy as np

# 作成する画像のサイズ
image_width = 1920
image_height = 1080

# テキストの描画位置（左下基準）
draw_pos_x = 100
draw_pos_y = 200
draw_text = "Hello, Blender!　ハローブレンダー"


# テキスト画像を作成する関数
# Creating an image of text with python in Blender
def create_text_image(image_width, image_height, position_x, position_y, font_size, text):
    # オフスクリーンバッファを作成
    offscreen = gpu.types.GPUOffScreen(image_width, image_height)
    # フレームバッファにバインド
    with offscreen.bind():
        fb = gpu.state.active_framebuffer_get()
        # blfでテキストを描画
        font_id = 0  # デフォルトフォント
        blf.position(font_id, position_x, position_y, 0)  # スクリーン座標（X, Y, Z）
        blf.size(font_id, font_size, 72)  # フォントサイズ
        blf.color(font_id, 1.0, 1.0, 1.0, 1.0)  # 白色
        blf.draw(font_id, text)  # テキストの描画
        buffer = fb.read_color(0, 0, image_width, image_height, 4, 0, 'UBYTE')
    buffer.dimensions = image_width * image_height *4
    # オフスクリーンバッファを解放
    offscreen.free()
    return [v / 255 for v in buffer]
    
# 描画を実行
text_image = create_text_image(image_width, image_height, draw_pos_x, draw_pos_y, 80, draw_text)

# 新しい画像を作成
image_out = bpy.data.images.new("OutputImage", image_width, image_height)
image_out.pixels = text_image

# 一時画像を削除
#bpy.data.images.remove(image_out)
```

処理について海外を含め検索してみても質問はあるものの、処理例は見当たらなかったこともあって
今回コードは入力した文字列の描かれた画像オブジェクトを作成するシンプルな内容になっています
何かの参考になれば幸いです
UbuntuでCursorのデスクトップショートカットを作ってみた(備忘録)

# 前提
CursorのAppImageが実行可能な状態にしてあること

# やってみたこと（ここは失敗したので読み飛ばしてOK）

bashで以下のコマンドを実行した。

```bash:bash
printf '[Desktop Entry]\nVersion=1.0\nType=Application\nName=Cursor Editor\nComment=Cursor Code Editor\nExec=/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage\nIcon=/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage\nTerminal=false\nCategories=Development;IDE;\nKeywords=cursor;editor;\nStartupWMClass=Cursor' > ~/デスクトップ/Cursor.desktop
```

`printf` でそれ以下の内容を出力しますが、`>`と合わせることで`~/デスクトップ/Cursor.desktop`というファイルに内容を書き出しています。`echo`に似ているけど、こっちでは`\n`みたいな特殊文字を処理できるっぽい。  

:::note info
userのところや、Cursorのファイル名なんかは適宜書き換えてください。
:::

ファイルの内容は以下の通り。

```text:~/デスクトップ/Cursor.desktop
   [Desktop Entry]          # デスクトップショートカットファイルの開始
   Version=1.0             # バージョン情報
   Type=Application        # これはアプリケーションだという指定
   Name=Cursor Editor      # ショートカットの表示名
   Comment=Cursor Code Editor  # 説明文
   Exec=/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage  # 実行するファイルのパス
   Icon=/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage  # アイコンとして使用する画像
   Terminal=false          # ターミナルを開かない
   Categories=Development;IDE;  # アプリケーションの分類
   Keywords=cursor;editor;     # 検索キーワード
   StartupWMClass=Cursor      # ウィンドウマネージャーでの識別名
```

できましたか？　**次はこのファイルに実行権限を与えましょう**

```bash:bash
chmod +x ~/デスクトップ/Cursor.desktop
```

デスクトップにショートカットが追加されていますね（されていなければ再起動しましょう）
ショートカットをダブルクリックしてみると![Screenshot from 2025-04-21 01-54-54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3947598/0227f596-33ad-4ae4-befd-92d65cf37e3b.png)

**なんとこんなポップアップが出てきました。**

言われたとおりデスクトップ上のアイコンを右クリックしてみる。
![Screenshot from 2025-04-21 01-59-57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3947598/a51e1d47-7382-4342-bd2c-a10941cd8480.png)

こんな表示になるので、起動を許可してみましょう。

**このあとダブルクリックしても音沙汰なし。だめみたい**

# 成功方法
1.　AppImageを実行するシェルスクリプトを作成
2. そのシェルスクリプトへのシンボリックリンクをデスクトップに作成

まずホーム直下にShellScriptsというディレクトリを作る（任意）
```bash:bash
mkdir ~/ShellScripts
```
shellscriptの内容を書き込む。
```bash:bash
printf '#!/bin/bash\n/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage --no-sandbox' > ~/ShellScripts/start-cursor.sh
```

実行権限を付与して、動作確認してみる。
```bash:bash
chmod +x ~/ShellScripts/start-cursor.sh && ~/ShellScripts/start-cursor.sh
```
出来ていたら、デスクトップエントリファイルを作る。
```bash:bash
printf '[Desktop Entry]\nVersion=1.0\nType=Application\nName=Cursor Editor\nComment=Cursor Code Editor\nExec=/home/user/ShellScripts/start-cursor.sh\nIcon=/home/user/ダウンロード/Cursor-0.48.8-x86_64.AppImage\nTerminal=false\nCategories=Development;IDE;\nKeywords=cursor;editor;\nStartupWMClass=Cursor\nX-Ubuntu-Gettext-Domain=desktop-file\nTrusted=true' > ~/デスクトップ/Cursor.desktop
```

実行権限を付与する。
```bash:bash
chmod +x ~/デスクトップ/Cursor.desktop
```

これで作成されたショートカットをダブルクリックすれば起動できますね！

# あとがき
わざわざ別のアプローチ取ってますが、デスクトップエントリを作る段階でシェルスクリプトの実行指定なんてせずとも、`Exec=`以下でシェルスクリプトと同じ内容を書いておけばうまく行きましたよね多分（検証していませんが）。ちなみに最初のアプローチと後半の違いは `--no-sandbox`の有無です。
デスクトップエントリを勉強することでUbuntuをまた一つ使いこなせるようになる気がします。いつか勉強します。多分。
HTML Standardの文書型宣言(DOCTYPE宣言)について

## HTML Standardの文書型宣言(DOCTYPE宣言)について
　**文書型宣言**(**DOCTYPE宣言**)は、HTMLドキュメントの先頭に記述すべき要素です。レガシーとして残されている要素で、唯一の役割はブラウザが後方互換モードに切り替わることを防ぐことです。
 文書型宣言は、\<!DOCTYPE html>と記述します。なお、**文書型宣言は大文字・小文字を問いません**。そのため、\<!doctype HTML>などと記述しても動作します。
Apache Camel × Spring Bootアプリを本番同様に起動してJUnitテストする

![137D2946-F5A6-4F9A-A14E-B4EC0B074AF4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4063686/9d937ca1-8af4-490b-9d30-404499c16b1b.png)

## はじめに

Apache Camelでルートをテストする場合、単一ルートのみを対象にするのであればCamelContext単体を起動してテストすることも可能です。  
しかし、実際の業務アプリケーションでは、

- 複数のルートが連携して一連のフローを形成している
- 起動時にDI（依存性注入）されるコンポーネントや設定情報に依存している

ことが多く、**CamelContext単独起動だけでは本番環境と同じ動作を再現できない**場面に直面します。

特に、

- DIされるはずのServiceやComponentが見つからない
- application.propertiesで管理される設定値が参照できない
- 一連のフローを通した動作確認ができない

という問題が発生しやすくなります。

この課題を解決するには、  
**JUnit5からSpring Bootアプリケーションごと起動し、本番と同じDI環境でCamelルートをテストする方法**が有効です。

これにより、

- 本番同様のDI済みコンポーネントと設定値を利用できる
- 複数ルートが連携する一連の処理を実際に通してテストできる

という実用的な検証が可能になります。

なお、この方法では**Spring Bootアプリケーション全体を起動するため、テスト開始までに数秒〜十数秒の起動時間**がかかります。  
ですが、得られるテストの正確性を考えると、十分に許容できるコストです。

---

## 環境

- Java 17
- Spring Boot 3.2系
- Apache Camel Spring Boot 4.8
- Camel XML DSL

---

## アプリケーション起動クラス

```java
package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.ImportResource;

@SpringBootApplication
@ImportResource("classpath:camel-context.xml") // XML DSLを読み込む
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}
```

---

## テストクラス

```java
package com.example.demo;

import org.apache.camel.CamelContext;
import org.apache.camel.test.spring.junit5.CamelSpringBootTest;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.DirtiesContext;

@SpringBootTest(
    classes = DemoApplication.class,
    properties = {
        "spring.profiles.active=test",
        "log.file.name=test-application.log",
        "hostname=test-host",
        "aws.access.key.id=dummy-access-key",
        "aws.secret.access.key=dummy-secret-key",
        "kafka.bootstrap.servers=localhost:9092",
        "kafka.consumer.topic=test-topic",
        "kafka.consumer.group.id=test-group",
        "kafka.producer.topic=test-producer-topic"
    }
)
@CamelSpringBootTest
@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_EACH_TEST_METHOD)
class DemoRouteTest {

    @Autowired
    private CamelContext context;

    @Test
    void testRoute() {
        // ここにテストコードを記述
    }
}
```

---

## ポイントまとめ

- テスト専用プロパティを＠SpringBootTestの`properties`に直接記述
- 環境変数（AWSキーなど）は別途テスト実行時に渡す
- CamelContextだけでなく、DIされるBeanすべてを本番同様に利用可能
- 一連のフロー全体を正しく検証できる

---

## 注意点

- Spring Bootアプリ全体を起動するため、テスト開始まで多少の起動時間がかかる  
  （目安：数秒〜十数秒）
- 軽量な単体テストと使い分けが重要

---

## まとめ

Apache Camel Spring Bootアプリケーションでは、  
JUnit5から本番同様にアプリごと起動してテストを行うことで、

- 複雑な一連のフロー全体の動作確認
- 本番に近いDI環境での検証
- 外部連携を含めた実践的なテスト

が可能になります。
【備忘録】Dockerイメージレイヤーについて

# Dockerfileと完成したイメージレイヤーを図解する
```dockerfile:Dockerfile
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl

COPY . /app

CMD ["ls", "-la"]
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3348923/959417c1-6977-49be-8cb7-23fd1cf81e5e.png)

- `Dockerイメージ`は**イメージレイヤー**が重なって出来ている
    - **イメージレイヤー**は`Dockerfile`に書いた一つの命令のこと
        - **イメージレイヤー**は読み取り専用
        - **イメージレイヤー**は一つ前の**イメージレイヤー**との差分を保持する

# イメージレイヤーの数とイメージサイズの関係
- **結論**:イメージレイヤーの数が少ないほどイメージサイズも小さい
    - `Dockerfile`に書いた命令のオーバーヘッドが無いから
    
```dockerfile:①
FROM ubuntu:20.04

RUN apt update
RUN apt install -y curl
RUN apt install -y vim

CMD ["bash"]
```
- ①はイメージサイズが209MBになる

```dockerfile:②
FROM ubuntu:20.04

RUN apt update && apt install -y curl vim

CMD ["bash"]
```
- ②はイメージサイズが208MBになる

# イメージビルド時のキャッシュ戦略について
**結論**は以下の通り
- `Dockerfile`の内容が変更される可能性が高い開発初期は**イメージレイヤー**を細かく分ける
- `Dockerfile`の内容が固まったら**イメージサイズ削減**のために**イメージレイヤー**の数を減らす

**理由**は以下の通り
- `docker image build`では**イメージレイヤー単位**でビルド時にキャッシュされている
- なので、**イメージレイヤー**を細かく分けた方が再ビルド時にキャッシュが使われやすい
    - よって、`Dockerfile`の内容が固まっていない時は**イメージレイヤー**を細かく分ける
    - 最終的に、`Dockerfile`の内容が固まったらイメージサイズを削減するために**イメージレイヤー**の数を減らす
【React + TypeScript】メニューボタンの押下位置に応じたメニューの表示

# 概要

タイトルを読んだだけでは、どのような記事か想像しづらいと思うので、最初に概要を説明します。

### 条件
同じような内容の要素を繰り返し処理で複数件表示している場合

:::note info
画像では名前だけが異なる「フォルダボタン」をmapで複数件表示しています。
:::

![フォルダ一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042501/691d6a38-85cb-4bda-b8a2-2ea6db98d0dc.png)

### 対応内容
複数件表示している各要素の「メニューボタン(・が縦に3つ並んでいるボタン)」を押下した際、各要素の真横にメニューを表示する。

#### 例1：買い物メモの「メニューボタン」を押下
![買い物メモメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042501/289dbd7e-29a1-42fc-8c3a-144143e1456b.png)

#### 例2：やりたいことリストの「メニューボタン」を押下
![やりたいことリストメニュー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4042501/1c942238-d950-4449-bed9-7a3667aa284e.png)

# 手順

### １. 各「メニューボタン」押下時に、ボタンを一意に識別できる情報(ここではfolder._id)とイベント情報を引数に関数を実行する。

```diff_jsx
// 「フォルダボタン」「メニューボタン」を1つの組として表示。
{folders.map((folder) => (
    <div key={folder._id} className="folder-container">
      <button
        className="Folder-button"
        onClick={() => setSelectedFolder(folder)}
      >
        {/**省略**/}
      </button>
      {/**メニューボタン**/}
      <button
        className="folderMenu-button"
        onClick={(event) => toggleMenu(folder, event)} //実行する関数
      >
        {/**省略**/}
      </button>
    </div>
  ))}
```

### ２. 項番1の引数をそれぞれstateに保存する。

```diff_typescript
  // メニューの開閉
  const [openMenu, setOpenMenu] = useState<boolean>(false);
  // メニューボタンの位置を格納する
  const [menuPosition, setMenuPosition] = useState<{
    top: number;
    left: number;
  }>({ top: 0, left: 0 });

  // メニューボックスを開く
  const toggleMenu = (
    folder: FolderInterface,
    event: React.MouseEvent<HTMLButtonElement>
  ) => {
    // DOMRectオブジェクトからクリックされた要素の座標を受け取り、stateに保存する。
    const rect = event.currentTarget.getBoundingClientRect();
    setMenuPosition({
      top: rect.top + window.scrollY - 152,
      left: rect.right + window.scrollX,
    });
    setOpenMenu(true);
  };
```
:::note warn
DOMRectオブジェクトとは、要素の位置やサイズ情報を保持するオブジェクトのこと
:::
:::note warn
-152をしている理由については後述する。
:::

### ３. 項番2でstateに保存した値を基にメニューを表示する。

```diff_jsx
<div
  className="FolderCD-container"
  style={{
    position: 'absolute',
    top: `${menuPosition.top}px`,
    left: `${menuPosition.left}px`,
  }}
>
    {/**名前を変更ボタン・削除ボタンを以下に記述しているが、省略**/}
```

:::note warn
注1: 以上を表示する条件を、項番2のsetOpenMenuIdでstateに保存された値があることとしている。(記事では省略)
:::
:::note warn
注2: 項番2注2で-152をしている理由は、DOMRectオブジェクトから取得した座標は画面全体から見たときの位置であり、上記JSXは親要素を始点として描画されている。そのため、-152で補正していない場合ではメニューの描画に親要素から画面上端分のズレが生じていた。
:::

# 所感
stateに座標を格納するという発想し、それを基に描画するという発想は自分にはありませんでした。
記事にしたことで、今後の対応の引き出しとして蓄えられたら嬉しいです。
若手エンジニアへ：生成AI推進で挫折しそうなあなたへ送るリアルな話

## はじめに

生成AI。  
聞くだけでワクワクするし、未来が広がっていく気がしますよね。  
でも、**現場で本当に推進しようとすると、話はまったく違う**と感じたことはありませんか？

この記事は、これから生成AIプロジェクトに関わる**若手エンジニア**のみなさんに向けて。  
「うまくいかなくて当たり前」なリアルと、それでも前に進むためのコツを、  
私自身の経験も交えてまとめました。

## 生成AI推進、華やかなのは表だけ

「生成AIを導入しよう！」  
そんな言葉は未来感があってキラキラしていますが、現場で最初に直面するのはこんなリアルです。

- そもそも**何をしたらいいか**決まっていない
- **社内の理解**が追いつかず、話が進まない
- **成果を出せるかどうか**、誰にもわからない

はじめは、「これ、本当に意味あるのかな……」と不安になると思います。  
でも、**それが普通です。**

## 小さな一歩でいい

いきなりすごい成果を出す人なんて、いません。  
大事なのは、**小さな一歩を積み重ねること**です。

例えば私の場合：

- まずは「簡単な社内向けPoC（実証実験）」からスタート
- たった一人でも賛同してくれる人を探してチームを作る
- 成功も失敗も、**必ず振り返って次に活かす**

この繰り返しだけで十分。  
一歩進んで、二歩下がって、また一歩進む。  
そんな地道な歩みが、気づいたら大きな成果につながっていました。

## うまくいかないときこそ、成長している

途中でうまくいかず、孤独を感じることもあるでしょう。  
でも、それは**成長している証拠**です。

振り返ると、今バリバリ成果を出している先輩たちも、  
最初はみんな同じように悩み、立ち止まり、時には泣きながら進んでいました。

うまくいかない時間も、失敗も、すべてが**未来の自分の力**になります。

## 生成AIは、まだ誰も正解を知らない

生成AIは、まだ誰にも正解がわからない新しい世界です。  
だからこそ、**失敗も悩みも、全部が未来をつくる材料**になります。

焦らなくていい。  
落ち込んでもいい。  
大事なのは、**立ち止まらないこと**。

一緒に、未来を作っていきましょう。

## これは生成AIに限った話じゃない

こうした試行錯誤の連続は、生成AIに限ったものではありません。

- クラウド
- モバイルアプリ
- IoT
- ビッグデータ

どれも最初は「どう扱うべきか」手探りでした。  
今注目されている技術も、最初は小さな一歩から始まっています。

だから、あなたの今の挑戦も、**確実に未来へとつながっています。**

## まとめ

- 生成AI推進は、**最初からうまくいかないのが普通**
- 大事なのは、**小さな一歩を積み重ねること**
- 失敗も悩みも、**未来の力になる**
- **一緒に、未来を作ろう**
Rails × Next.jsで画像アップロードにハマった話（ActiveStorage × FormData対応）

Rails（APIモード）とNext.js（App Router）を組み合わせて開発している中で、画像アップロード処理においてActiveStorageの挙動に苦戦したため、備忘録としてまとめます。

## 使用技術
バックエンド：Ruby on Rails（APIモード） + ActiveStorage（Disk Storage）

フロントエンド：Next.js（App Router） + FormData

認証：Bearerトークンによる認証付きAPI通信

## 実装内容の概要
### フロントエンド（Next.js）
Next.js側では、以下のようなフォームを作成し、FormDataを構築してRails APIに送信しています。

```ts
const formData = new FormData();
formData.append("title", title);
formData.append("message", message);

photos.forEach((photo) => {
  if (photo) formData.append("photos[]", photo); // 配列形式で送信
});

const res = await fetch(`${process.env.NEXT_PUBLIC_API_URL}/api/v1/hosts`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
  },
  body: formData,
});
```
Rails側で params[:photos] を受け取れるよう、キー名は "photos[]" にしています。

### バックエンド（Rails）
Railsでは、以下のようにユーザーの画像を has_many_attached :photos で管理し、送信された画像を attach しています。

```ruby
def create
  user = User.find(@current_user.id)

  if user.update(user_params.except(:tags, :photos))
    user = User.find(user.id) # 明示的に再取得

    # タグの上書き
    user.tags.destroy_all
    Array(params[:tags]).each { |tag| user.tags.create(name: tag) }

    # 写真を再アタッチ
    user.photos.purge if user.photos.attached?
    Array(params[:photos]).each { |photo| user.photos.attach(photo) }

    render json: user, status: :created
  else
    render json: { errors: user.errors.full_messages }, status: :unprocessable_entity
  end
end
```
**ハマりポイント：画像が保存されない**
最初、画像を正常に attach しているつもりなのに、photos.attached? が常に false を返すという問題が発生しました。

### ログを見ると、以下のように record_id が nil や 0 になっていることが判明。

```Bash
ActiveStorage::Attachment Create ...
["record_id", nil]
```
### 原因：ActiveStorageが record_id を正しく認識できていない
user.update(...) の直後に user.photos.attach(...) を呼ぶと、Rails内部でオブジェクトのキャッシュが残っている影響か、id が正しく反映されないケースがあるようです。

この場合、ActiveStorageが record_id = nil のまま添付しようとして失敗します。

## 解決策：user を明示的に再取得する
以下の1行を追加するだけで、ActiveStorageが正しく record_id を認識し、画像の保存・URL生成が期待通りに動作するようになりました。

```ruby
user = User.find(user.id)
```
reload ではうまくいかない場合もあるので、明示的な再取得がおすすめです。

### その他のポイント
rails_blob_url(photo) を使ってAPIレスポンス内に画像URLを含めると、フロント側でもスムーズに表示可能になります。

config/environments/development.rb で以下の設定を忘れずに：

```ruby
Rails.application.routes.default_url_options[:host] = 'localhost:3000'
```
# まとめ
user.photos.attach(...) を使う前に、user.id が確実に存在していることを確認する

update 直後は find(user.id) で再取得するのが安全

photos[] 形式で画像配列を送信し、ActiveStorageで複数添付を実現

これからRails × Next.js構成で画像アップロードに挑戦される方の参考になれば幸いです。
django で DB にレコードを登録

django で DB にレコードを登録する方法のメモ。

# やりたいこと

* models.py にモデルを定義
* コマンドでDBにレコードを登録
* コマンドでDBからレコードを取得


# モデルの定義
まず、test1 アプリケーションを作成する。

```
python manage.py startapp test1
```

test1/models.py に以下の Item と AttrValue を定義する。
Item の１つのレコードに対して、AttrValue の複数のレコードが紐づく。

```python:test1/models.py
from django.db import models

class Item(models.Model):
    name = models.CharField(max_length=32)

    def __str__(self):
        return self.name


class AttrValue(models.Model):
    item_id = models.ForeignKey(Item, on_delete=models.CASCADE)
    attr = models.CharField(max_length=32)
    value = models.CharField(max_length=32)

    def __str__(self):
        return f'{self.item_id}: ({self.attr}, {self.value})'
```

# レコード登録・検索コマンドの作成

## ディレクトリ・ファイル作成

```
mkdir -p test1/management/commands

cd test1/management
touch __init__.py

cd commands
touch __init__.py
```

test1 のファイル構成

```
.
├── __init__.py
├── management
│   ├── __init__.py
│   └── commands
│       ├── create_records.py
│       └── select_records.py
├── models.py
├── tests.py
└── views.py
```

## レコード登録
Xxx.objects.create() でレコードを登録することができます。

```python:test1/management/commands/create_records.py
from django.core.management.base import BaseCommand
from test1.models import Item, AttrValue

class Command(BaseCommand):
    help = 'create records of item, attr_value'

    def handle(self, *args, **options):
        # item1
        item1 = Item.objects.create(name='item_01')
        attr_val1_1 = AttrValue.objects.create(item_id=item1, attr='length', value='10')
        attr_val1_2 = AttrValue.objects.create(item_id=item1, attr='weight', value='20')

        # item2
        item2 = Item.objects.create(name='item_02')
        attr_val2_1 = AttrValue.objects.create(item_id=item2, attr='length', value='15')
        attr_val2_2 = AttrValue.objects.create(item_id=item2, attr='weight', value='25')
```

* コマンド実行

```bash
python manage.py create_records
```


## レコード検索
Xxx.objects.all() で全レコードを検索することができます。

```python:test1/management/commands/select_records.py
from django.core.management.base import BaseCommand
from test1.models import Item, AttrValue


class Command(BaseCommand):
    help = 'create records of item, attr_value'


    def handle(self, *args, **options):
        items = Item.objects.all()
        print(items)

        attr_values = AttrValue.objects.all()
        print(attr_values)

        items_with_attrs = AttrValue.objects.select_related('item_id').all()
        print(items_with_attrs)
```

* コマンド実行

```bash
python manage.py select_records
```

* 実行結果
※わかりやすくするために改行を入れています

```text
<QuerySet [
  <Item: item_01>,
  <Item: item_02>
]>

<QuerySet [
  <AttrValue: item_01: (length, 10)>,
  <AttrValue: item_01: (weight, 20)>,
  <AttrValue: item_02: (length, 15)>,
  <AttrValue: item_02: (weight, 25)>
]>

<QuerySet [
  <AttrValue: item_01: (length, 10)>,
  <AttrValue: item_01: (weight, 20)>,
  <AttrValue: item_02: (length, 15)>,
  <AttrValue: item_02: (weight, 25)>
]>
```
tblr環境でsiunitxを用いて小数点揃えされた表組を行うときのエラーを解決する（tblr環境で小数点揃えする方法）

## 要約

tblr環境でsiunitxを用いた小数点揃えされた表組をしたとき，見出しを2段以上にするとエラーが出る．
そのときは`row{1} = {guard}`を入れるとうまくいく．

## 環境

TeX Live 2024

## 背景（tblr環境で小数点揃えする方法）

[tblr](https://ctan.org/pkg/tabularray)環境を用いて表組を行っている状態で，次のような数値が小数点で揃えられた表を作りたい．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1661993/363df806-8577-4ab8-a09e-4196aa058820.png)

そのためには，[siunitx](https://ctan.org/pkg/siunitx)を`\UseTblrLibrary{siunitx}`としてtblrに読み込ませてから，
```tex
\begin{tblr}{
  colspec = {S[table-format=3.1]S[table-format=3.2]},
}
```
などとして，S columnを用いることで小数点揃えを行うことができる[^1]．

## 課題

次のように記述するとエラーが発生する．

```TeX
\begin{table}[!htbp]
  \centering
  \begin{tblr}{
    hlines, vlines,
    colspec = {S[table-format=3.1]S[table-format=3.2]},
    rows = {halign = c},
  }
  {Header 1 \\ X [unit]} & {Header 2 \\ Y [unit]}\\
  0 & 5.12 \\
  0.3 & 600 \\
  \end{tblr}
\end{table}
```

エラーが発生する場合は，冒頭の環境において表のヘッダを2段以上にしたとき（正確には{}を見出しの各列全てにおいて用いたとき）である．たぶん．

## 解決法

>Note that you need to use one pairs of curly braces to guard non-numeric cells. But it is cumber some to enclose each cell with braces. From version 2022B a new key guard is provided for cells and rows. With guard key the previous example can be largely simplified.[^2]

とパッケージドキュメントにあるように，`guard`を見出し行に適用すればよい．

```diff_te_x
\begin{table}[!htbp]
  \centering
  \begin{tblr}{
    hlines, vlines,
    colspec = {S[table-format=3.1]S[table-format=3.2]},
    rows = {halign = c},
+   row{1} = {guard},
  }
  {Header 1 \\ X [unit]} & {Header 2 \\ Y [unit]}\\
  0 & 5.12 \\
  0.3 & 600 \\
  \end{tblr}
\end{table}
```

ちなみに，エラーの再現過程で見出しのうち1つしか2段じゃないときは`guard`抜きでエラー出なかったので，もしやバグ？とも思った．

よいtabularrayライフを．

[^1]: https://ctan.org/pkg/tabularray Package documentation p.53 5.9
[^2]: 同上
Google Apps Script のトリガーの備忘録

Google Apps Script のシンプルトリガーは、実行時にスクリプトを作成したユーザの権限が割り当てられるのではないので注意が必要
シンプルトリガーに使用されている名前を避けてスクリプトを作成した後に、スクリプトをトリガーに登録すると作成したユーザの権限が使用できる

:::note info
* 承認が必要なサービスにアクセスすることはできません。たとえば、Gmail サービスでは認証が必要になるため、単純なトリガーではメールを送信できませんが、単純なトリガーでは匿名の言語サービスを使用してフレーズを翻訳できます
https://developers.google.com/apps-script/guides/triggers?hl=ja
:::

:::note warn
シンプルトリガーに使用されている名前を付けるとシンプルトリガーとトリガー登録したスクリプトの「２回」が実行されるため、名前の付け方に注意する
:::
ChromeでHTTPバージョンを確認する方法

【免責事項】
本投稿は正確性・完全性を保証するものではありません。
万が一、本情報に基づいて被ったいかなる損害についても、一切の責任を負いかねます。
あらかじめご了承ください。


## 1. ChromeによるHTTPバージョンの確認方法
1. サイトにアクセス
2. F12キー（または右クリック→検証）で「デベロッパーツール」を開く
3. 上部タブで「Network（ネットワーク）」を選択
4. ページを再読み込み（Ctrl+R）
5. 任意のリクエストを選び、「Protocol（プロトコル）」列を見る  
※もしProtocol列が表示されていない場合、ヘッダーを右クリックして「Protocol」を追加する
👇画像はQiitaで「デベロッパーツール」を開いてみたもの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4053535/8d050b04-7865-4ef6-892b-520811ca81f1.png)


ここで表示される例：
- `h2` → HTTP/2
- `h3` → HTTP/3
- `http/1.1` → HTTP/1.1

## 2. そもそもHTTPバージョンとは
HTTPとは、Webサイトを表示するための通信ルール。  
バージョン違いは、通信のやり方・速さ・効率に影響する。  
代表的なバージョン：
- HTTP/1.0（古い）
- HTTP/1.1（標準化され普及）
- HTTP/2（現在の主流）
- HTTP/3（新世代、普及中）

## 3. 主流のHTTPバージョンについて
現在（2025年時点）の主流は**HTTP/2**。  
ただし、**HTTP/1.1**も依然多く使われ、**HTTP/3**が一部で導入進行中。  
特にGoogle、YouTube、Yahoo!など大手はh2/h3対応済み。

## 4. HTTPバージョンが違うと何がどう変わるのか
| バージョン | 特徴 | 影響 |
|:--|:--|:--|
| HTTP/1.1 | 単一接続で順番待ちが発生（重い） | ページ読み込み遅延が起こる |
| HTTP/2 | 多重化・ヘッダー圧縮で効率化 | ページ表示がかなり速くなる |
| HTTP/3 | UDPベースで接続が速い | モバイル環境で特に強い、途切れにくい |

ざっくり言うと、「ページ表示速度」「安定性」に直結する。

## 5. 情シスとして業務でどう生かせるか
- 社内システムのWebサーバー設定を確認・最適化する
- ベンダーへの仕様確認時、「HTTP/2以上対応してますか？」と聞ける
- モバイル利用の多いサービスではHTTP/3対応を検討する
- 遅い社内システム改善提案に「HTTP/2化」も選択肢に入れられる

## 6. まとめ
- Chrome開発者ツールで簡単にHTTPバージョンは見られる
- HTTPバージョンは通信の速さと安定性に直結
- 今はHTTP/2が主流、HTTP/3も広がりつつある
- 情シス・インフラ担当でも知っておくとシステム改善に役立つ

---
## 参考
・[Google ChromeのデベロッパーツールでWebサイトのSSLトラブルなどを調査する方法](https://atmarkit.itmedia.co.jp/ait/articles/1610/21/news023.html)
・[HTTPとそのバージョンについて調べてみた【HTTP/2とHTTP/3の比較】](https://qiita.com/kyrieee/items/5e77e792ddf08a5c73cc)
・[HTTPバージョンごとの違い(1.0, 1.1, 2.0)](https://www.high-level-engineer.com/posts/http)

## ✨ おわりに
この記事が役立ったら、いいねやストックいただけると嬉しいです！

## 主のコンテンツ
<a href="https://www.udemy.com/course/active-directory-p/?referralCode=1BC8474484DCD2814852">Active Directoryの基礎※ハンズオン形式</a>
<a href="https://www.udemy.com/course/active-directory-n/?referralCode=FF51293A35539D596A6A">Active Directoryの基礎 グループポリシー編※ハンズオン形式</a>
<a href="https://www.udemy.com/course/joshishelp/?referralCode=7ECEB242C114FA3736F8">情シスヘルプデスク入門※一部ハンズオン形式</a>
<a href="https://twitter.com/naoya_itbegin">X</a>
<a href="https://www.youtube.com/@%E7%A4%BE%E5%86%85%E3%83%8D%E3%83%83%E3%83%88%E3%83%8A%E3%83%93">Youtube</a>
【React】jestのテストでProviderが機能しない症状の解決方法について

# はじめに
jestのテストでログイン中にログインボタンが表示されないテストを実装するところでつまずいたので記事にします。

下記のようなエラーでログインボタンが取得されている状態でした。

:::note warn
TestingLibraryElementError: Unable to find an accessible element with the role "button" and name "ログイン"
:::

【修正前のコード】

```.tsx

beforeEach(async () => {
  render (
    <BrowserRouter>
      <Home />
    </BrowserRouter>
  );
});


//////////その他テスト/////////////////////////



it("ログアウトボタンを押すとログインボタンが表示されていること", async () => {
    const store = createStore();
    store.set(loginAtom, true);

    render(
      <Provider store={store}>
        <BrowserRouter>
          <Home />
        </BrowserRouter>
      </Provider>
    );

    const logoutButton = screen.getByRole("button", { name: "ログアウト" });
    userEvent.click(logoutButton);
    store.set(loginAtom, false);
    await waitFor(() => {
      expect(screen.getByRole("button", { name: "ログイン" })).toBeInTheDocument();
    });
  });
```


# 解決方法

beforeEach内のrender削除

# 参考
https://qiita.com/turmericN/items/4e78f242efe508b196d5


# おわりに
他のテストで使用していたbeforeEach内のrenderによって、実行させたいtest時にrender内のコンポーネントが混在しているような状態になっていました。

<br>

[<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3707255/8bfacf61-7d8d-6d27-cb07-98d1f8f27fcd.png"  width=100%>](https://projisou.jp)