OmniAICreator/Qiita-1.07M huggingface dataset:
速習App Router#5 ダイナミックセグメント・notFound.tsx・generateStaticParams

# はじめに
この記事は下記の講座で学んだ内容をまとめています。
理解が怪しい所があるので教えてくれるととても嬉しいです。

https://www.udemy.com/course/nextjs-supabase-app-directory

# 目次
1.[速習App Router#1](https://qiita.com/warabimochi_26/items/bb3c17f06e07c080504e)
2.[速習App Router#2](https://qiita.com/warabimochi_26/items/ad7a3876d6cd614d0837)
3.[速習App Router#3](https://qiita.com/warabimochi_26/items/163f801647a1bcfa31be) 
4.[速習App Router#4](https://qiita.com/warabimochi_26/items/41714929576c8d0cf297)
5.速習App Router#5 <- この記事
6.[速習App Router#6](https://qiita.com/warabimochi_26/items/8c0217fbd96276fb9ed8)
7.[速習App Router#7](https://qiita.com/warabimochi_26/items/85f6a05cf9cd2554e690)

## ダイナミックセグメントについて
このような`page.tsx`がネストされているファイル構造を想定します。

```
app/blogs
├── page.tsx
    layout.tsx
    [blogId]
     └─ page.tsx
        not-found.tsx
```

http\://localhost:3000/blogs -> `app/layout.tsx` + `app/blogs/layout.tsx` + `app/blogs/page.tsx` が描画される。

`app/blogs/page.tsx` が `app/blogs/layout.tsx`のchildrenの中に入ってラップされて、その`layout.tsx`を`app/layout.tsx`がラップされて描画されている。

http\://localhost:3000/blogs/[blogId] -> `app/layout.tsx` + `app/blogs/layout.tsx` + `app/blogs/[blogId]/page.tsx` が描画される。

`app/blogs/[blogId]/page.tsx` が `app/blogs/layout.tsx`のchildrenの中に入ってラップされて、その`layout.tsx`を`app/layout.tsx`がラップされて描画されている。

このように、`layout.tsx`のchildrenに渡る`page.tsx`だけをURLによって変更することで画面の一部だけ変更されるダイナミックセグメントを実装出来る。

## notFound.tsx
コンポーネントの中で `notFound()`を実行するとそのpage.tsxの代わりにnot-found.tsxが描画されます。 

```typescript:/page.tsx
export default async function BlogDetailPage({ params }: PageProps) {
    const blog = await fetchBlog(params.blogId);
    console.log(blog);
    if (!blog) return notFound()
    
    return (
      <div className="mt-16 border-2 p-8">
    　　コンポーネント内でこのように記述します。
      </div>
    )
  }

```
コンポーネント内でこのように記述します。
`変数blog`には動的なルーティングでフェッチしたデータが入っている想定です。

## generateStaticParams
ダイナミックルーティングするページをSSGする時に使います。
`Page Router` の `getStaticPaths` の App Router版です。 

```typescript:page.tsx
  export async function generateStaticParams() {
    const res = await fetch(`${process.env.url}/rest/v1/blogs?select=*`, {
      headers: new Headers({
        apikey: process.env.apikey as string,
      }),
    })
    const blogs: Blog[] = await res.json()
  
    return blogs.map((blog) => ({
      blogId: blog.id.toString(),
    }))
  }
  ```
  このように記述します。
Ruby on Railsで動的なフォーム要素を扱う方法

この記事では、Ruby on Railsで動的にフォームの表示を切り替える一例として、サービス選択に応じて特定のフォームフィールドを表示・非表示する方法を紹介します。主に`id`属性の動的な生成とJavaScriptを使用したDOMの操作に焦点を当てて解説します。

## まず結論

問題の解決策は、`id`属性をERBテンプレート内で動的に生成し、JavaScriptを用いてその`id`を持つ要素の表示を切り替えることでした。具体的には、以下のように記述しました。
※<%= service.id %>の部分が重要でした。
※コメントアウト部分はコンソールでログを出しつつ試行錯誤した履歴です。

```app/views/staffs/registrations/edit.html.erb
<div class="service-fields" id="service_fields_<%= service.id %>" style="display: none;">
  <%= text_field_tag "staff[service_fees][#{service.id}]", nil, placeholder: "Fee for #{service.name}", id: "staff_service_fees_#{service.id}" %>
  <%= text_field_tag "staff[service_durations][#{service.id}]", nil, placeholder: "Duration for #{service.name}", id: "staff_service_durations_#{service.id}" %>
</div>
```

```app/javascript/controllers/application.js
document.addEventListener('turbo:load', function() {console.log('Page loaded');
console.log(document.querySelectorAll('input[type="checkbox"]'));
  document.querySelectorAll('.service-checkbox').forEach(function(checkbox) {

    checkbox.addEventListener('change', function() {
      // console.log('Checkbox changed');
      var serviceId = this.value;
      console.log(serviceId);
      var serviceFieldsDiv = document.getElementById('service_fields_' + serviceId);
      // console.log('service_fields_' + serviceId);
      // console.log('Service fields div display before:', serviceFieldsDiv.style.display);
      console.log(serviceFieldsDiv)

      if (this.checked) {
        if (serviceFieldsDiv) serviceFieldsDiv.style.display = 'block'; // service-fieldsが存在する場合に表示
        console.log('Service fields div:', serviceFieldsDiv);
        // console.log('Service fields div display after:', serviceFieldsDiv.style.display);
      } else {
        if (serviceFieldsDiv) serviceFieldsDiv.style.display = 'none'; // service-fieldsが存在する場合に非表示
      }
    });
  });
});
```

## 試行錯誤の過程

### console.logを使ったデバッグ

実装の過程で、特にJavaScriptの挙動を理解するために`console.log`を頻繁に使用しました。特に、`checkbox.addEventListener('change', function() {...})`内でチェックボックスの状態変更を検知した際の、対応するサービスフィールドの表示・非表示の切り替えを正しく行えるよう、`console.log`を用いて変数の状態を確認しながら進めました。

### IDの付与方法の変更

初期の実装では、料金や所要時間を入力する`input`タグに直接IDを付与していましたが、複数のフィールドを一括で表示・非表示切り替えるため、外側の`div`にIDを付与する方法に変更しました。これにより、サービスが選択された際に、関連する全てのフィールドを容易に表示・非表示することが可能になりました。

### 問題の解析

ブラウザの開発者ツールを使用して、JavaScriptが`null`を返していることに気づきました。これは、指定したIDを持つDOM要素が存在しないために発生するエラーでした。この発見から、HTML要素のIDが正しく設定されておらず、JavaScriptがそれらを見つけられないことが問題の根本原因であることが明らかになりました。

### 解決策

この問題を解決するために、私はHTMLのID属性の生成方法を見直し、ERBファイル内で`id`属性を動的に生成することにしました。これにより、各サービスごとにユニークなIDが割り当てられ、JavaScriptが正確に要素を参照できるようになりました。

```erb
<div class="service-fields" id="service_fields_<%= service.id %>" style="display: none;">
```
また、`document.addEventListener('turbo:load', ...)`を使用して、ページの完全な読み込み後にJavaScriptが実行されるようにしました。これにより、動的に生成されたIDを持つ要素がDOMに存在することが保証され、JavaScriptによる表示の切り替えが正常に機能するようになりました。

```javascript
document.addEventListener('turbo:load', function() {
  // 要素の表示切り替えを行うJavaScriptコード
});
```
知らなくても開発できるけど、知っているととても便利なコマンド集① / revert

今回は、知らなくても開発できるけど、知っているととても便利なコマンドである' revert 'について紹介します。


### revertコマンドとは？
Gitの' revert 'コマンドは、リポジトリの履歴において特定の変更を取り消すために使用されます。具体的には、過去のコミットを"元に戻す"（revert）新しいコミットを作成します。これにより、過去の変更がなかったかのようにリポジトリが更新されますが、実際には過去の変更は履歴に残ります。

### なぜrevertを使用するのか？
1. **安全性**：' revert 'はリポジトリの歴史を改変せずに変更を元に戻すため、他の人が作業しているリポジトリへの影響が少ないです。
1. **追跡可能性**：' revert 'による変更は新しいコミットとして記録されるため、何がいつ変更されたのかが追跡しやすくなります。
1. **協力作業による利便性**：共有リポジトリで作業している場合、' revert 'は他の共同作業者の作業に影響を与えずに問題のある変更を取り消すことができます。

### ' revert 'の基本的な使用方法
コマンドラインでの' git revert 'の基本的な使用法は以下の通りです：
```bash
git revert ［コミットID］
```
ここで、' [コミットID] 'は元に戻したいコミットのIDです。

### ' revert 'のプロセス
1. **コミットIDの確認**：元に戻したいコミットのIDを' git log 'などで確認します。
1. **' revert 'の実行**：上記のコマンドを使用して、特定のコミットを元に戻します。
1. **コンフリクトの解決**：元に戻すコミットが最新のコミットでない場合、変更が現在のワークフローと競合する可能性があります。この場合、コンフリクトを手動で解決する必要があります。
1. **変更のコミット**：' revert 'コマンドは自動的に新しいコミットを作成し、それに変更が含まれます。必要に応じて、このコミットをリモートリポジトリに' push 'します。

:::note warn
### 注意点
- **大きな変更の' revert '**：大規模な変更や長期間にわたる変更を' revert 'する場合は、慎重に行う必要があります。コンフリクトが発生する可能性が高く、解決には注意と時間が必要です。
- **共有リポジトリでの使用**：共有リポジトリで' revert 'を使用する場合は、他のメンバーに通知し、影響を最小限に抑えるために計画的に行うことが重要です。
:::


以上のように' revert 'は非常に強力なツールであり、適切に使用すればリポジトリの整合性を保ちつつ、過去の問題を効率的に解決することができます。
初中級者向け：MacOS用IDE“CodeRunner 4”でPython仮想環境内でコードを実行する方法

# はじめに
## CodeRunner 4とは？
MacOSには“CodeRunner 4”という非常に軽い実行環境があります。VSCodeにも“CodeRunner”という拡張機能がありますが、これとは別の独立実行型のアプリケーションです。詳細は
https://coderunnerapp.com
をご覧ください。
## CodeRunner 4の注意点
Apple App Storeでも“CodeRunner 4”が購入できますが、App Storeのアプリケーションは（本来はそうあるべきだとは思いますが）サンドボックスの制約が厳しいために、思うように機能を拡張できないという不利な点があります。これはTexifier（旧名Texpad）というLaTeX用のIDEにも言えることです。
そのため、利用して課金することを決めた場合は、サイトから直接、ライセンスを購入することをお勧めします。
# Python 3.12にバージョンアップして困ったこと
## pipでインストールできないモジュールがある
Python 3.12をHomebrewでインストールした場合、Apple App Storeと同様に要求するサンドボックスの制約が強めなために、pipでモジュールをインストールできないものがあります。無論、ユーザーの操作によってシステム全体に影響を及ぼさないようにするという設計思想は重要だと思いますが、利用したいモジュールがインストールできないのでは、そもそも意味がないというのも確かです。
## 解決方法
そのような場合に最も手っ取り早いのが「仮想環境」を構築しておき、その中でpipでモジュールをインストールするという方法です。

仮想環境の作成の際は、書類内に作成するとiCloudにアップロードされて、物理ディスク内の中身がなくなってしまった場合、いちいちダウンロードするのが面倒なので、ホームディレクトリに作成するのが良いかと思います。

仮想環境の簡単な作成方法（自分のホームディレクトリに作成する場合）
```zsh:手順1（ホームディレクトリへの移動）
cd ~
```
```zsh:手順2（仮想環境の作成）
python3 -m venv myenv
```
この操作は1回のみです。
そして、通常の実行の場合はその後、ホームディレクトリの位置で
```zsh:（手順2の補足1：仮想環境の実行）
source myenv/bin/activate
```
とすることで仮想環境の中に入ることができ、
```zsh:（手順2の補足2：仮想環境の終了）
deactivate
```
で仮想環境から抜けることができます。
# CodeRunner 4で仮想環境に入りたい
## メニューバーから「Setting...」を選択
まずは下の画像のようにメニューバーの「CodeRunner」→「Setting...」で設定画面を表示させます。
![2024-02-28 1.47.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403192/d3d72e1a-e11d-e07c-71ea-8aad0bc78e56.png)

次に下の画像のように「Languages」タブの「Settings」タブを選びます。
![2024-02-28 1.33.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1403192/51fccf7d-d6b4-296d-091f-6776980a334e.png)
## Setting
Run Commandには
```zsh:手順3（“Run Command”への入力）
source $compiler ; python $filename
```
と入力しておきます。
## Language uses compile scriptに入力
次にLanguage uses compile scriptにチェックを入れて、Edit Scriptボタンを押します。
そして、末尾に
```zsh:手順4（Language uses compile scriptへの追記）
echo "/Users/[ユーザー名]/myenv/bin/activate"
```
と入力してSaveで保存します。

## ユーザー名が分からない場合
なお、[ユーザー名]部分には自分のユーザー名が入りますが、自分のユーザー名がわからない場合は、下記を入力して
```zsh:（手順4の補足1：ホームディレクトリへの移動）
cd ~
```
これでホームディレクトリに移動して、
```zsh:（手順4の補足2：現在のディレクトリの場所を出力）
pwd
```
と入力することで、自分のホームディレクトリのパスを知ることができますので、この“/Users/”の後ろに表示されているのが[ユーザー名]に該当する部分です。
例えば、上記の“pwd”を入力して
```zsh:（手順4の補足3：出力例）
/Users/hogehoge
```
と表示された場合は、Language uses compile scriptのEdit Scriptボタンで表示されたScriptの末尾には
```zsh:（手順4の補足4：入力例）
echo "/Users/hogehoge/myenv/bin/activate"
```
と入力するということになります。
# おわりに
これで仮想環境内でPythonを実行することが可能になります。
# 追記：仮想環境へのモジュールのインストール方法
モジュールをインストールしたい場合は、ターミナルでpipでこの仮想環境内に入る必要があるために
```zsh:手順5
source myenv/bin/activate
```
とすることで仮想環境の中に入ることができ、
```zsh:手順6
pip install モジュール名
```
で任意のモジュールをインストールし、
```zsh:手順7
deactivate
```
で仮想環境から抜けることができます。
データベースで残すもの

データって
自分が持つ、インフォメーションのことです。

その情報にはいろんな種類があります
プライベートなもの、一千万を超える価値があるもの。

ビックデータは特に質より量で集めます
エラーがたくさん拾えますが、全て溜めて分析する、
これで価値が見出せます。

---

…サーバはどうでしょう。
Serverは一日中働きます
私たちが眠っても、アレはずっと起きてて仕事をする
正確にはそれを管理するエンジニアが苦労をします

ですが、もっと重要なのはスペースが足りないこと。
ネットで使った住所は、いつか返却してくれないとゴミになります。
人は生まれると名前を知らせますが、死ぬ時、それは保障できません
独りでぶっ倒れるかもしれないし、明日の天気すら予測不能です。

なのに借りるのは便利で、返すのは深く考えない。
だとして、無理やり奪うと
エラーだらけの世の中、理不尽なことができる。
だから複雑なんです

---

それで、最初に考えないといけないのは
<b>紙で残すべきか、デジタルデータで残すべきか。</b>
よく変化するものなら、紙で残すよりデジタルデータがふさわしいです。
修正が容易なネットなら、バージョンの管理がやりやすくなりますから。

二つ目、<b>重要なデータなのか</b>
ビジネスで使う情報なら、金が縛られていますし別ですけど
個人でデータをセーブする場合、いつもデータベースを使う必要は
ありません。

(ここでポイント、データベースは単なるデータの集合ですが
DBMSはそれを管理できるシステムを意味します。
普通、データベースと言えばDBMSのことで
…あえていうなら間違いかも知れません。)

話を戻して、DBMSの前にはファイルシステムで
ファイルを管理していました。
それが問題がありまして、便利なDBMSを使いますが
サーバと一緒に使うと、
データベースはどこでもいつでも使えるようになります
けどその分、知識が必要とされます。

機械を扱う時は、繊細に考えるべきです。
私たちがちゃんとこれを知っているのか
確信を持って使わないと、主人ではなく、
最悪はものに支配されてしまいます。…ちょっと大袈裟でしたが、
データを無駄に蓄積すると、浪費が大きくなる
ということです

めんどくさくても、よく自分で更新して
覚えながら管理するのが一番安全です。
でないと、ごく一部だけ食べられない食物がいっぱい詰め込んでる
冷蔵庫を見るのと同じくなるかも知れません:)

三つ目、<b>敏感な情報なのか</b>
個人情報みたいに、保管に気をつけないといけないデータは
まずデジタルにセーブしないほうが賢明です。

ですが、それだと不便すぎます
ので結局機械頼りになります。
だとしたら、やることは一つ
使い慣れることです。

金が金庫にあれば、必ず泥棒ができる
弱点がバレると、必ず利用しようとする者が出る。
…いろんな人がいますから、どんなことが起きてもおかしくありません。

それをプロテクトするのもエンジニアの仕事です。
使いやすく作るとユーザーは喜ぶが、管理が難しくなり
徹底的に保護すると、ユーザーが嫌がり使わなくなります。
…とても難しいです。

---

結論。
結局ユーザーの思惑通りになる世界ですので、
エンジニアはいつも難解な解決法を探すしかありません。

3つのことに注意して、よく分別しないといけませんね。
例えば
最初の『紙で残すべきか、デジタルデータで残すべきか』は小説と辞書。
二つ目は『重要さ』でダイエット日記かアパートの相場か。
最後は『敏感さ』。検索されるとまずい情報なのかを考慮します。

それらは絶対ではなく、
ダイエット日記のように、3日で諦めてない
1年分のデータが溜まって、分析がいる場合
ただのファイルではなく、専門のDBMSで管理し
より成功的なダイエットに向けて頑張れることもあるでしょう。

そのため先ず、頑張りましょう。
私もたくさん単語覚えて、試験用のデータベース、作っちゃいます！
いつかウェブで使えるように、どうかやめませんように！
xlsxファイルが開けない原因データ特定方法

# こんなことありませんか？

プロダクトの機能の一部にデータをExcelにエクスポートする機能があったとする。
その機能を利用して、とあるユーザーのデータをExcelにエクスポートしてみた。
そのエクセルファイルを開こうとすると、このように、「ファイル名.xlsxの一部の内容に問題が見つかりました。可能な限り内容を回復しますか？」という表示が出る。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2563397/87d7ec7d-29f1-8645-f263-d32e1867e11f.png)

「はい」を選択すると
データが記載されているはずのシートが真っ白！
こんなときの原因特定方法を記しておく。


# 現象の仮説
このExcelファイルはDBにあるレコードを展開している。
このエクスポート機能自体に問題があるわけではない。
ということは、そのデータ自体が悪さをしている。
問題はそれが一体どのデータかを特定すること。
特定できればデータを修正すれば問題なく開けるようになるのではないか。


# エラー原因の情報を拾う
強引に開こうとするとこの表示が出るので、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2563397/fad2ebb5-624c-37a6-01a1-488cd3f6ab4b.png)

「表示」を選択すると
このように、エラーの原因となった部分を知ることができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2563397/6fa81ea1-ae06-2a3c-8895-39ec651afd82.png)

どうやら、/x1/worksheets/sheet2.xmlの2行目の1,103,212列目に問題がある。

# xml？
実は、「.xlsx」形式のファイルは内部情報を記録したxmlファイルの集合体である。
なので、そのxlsxを構成する、xmlを見ることができれば、問題のデータを特定できる

# xlsxを分解する
1. xlsxファイルの拡張子をzipに変更する
1. それをターミナルからunzipする
1. `unzip zipのファイルパス`

するとこのように構成ファイルが展開される。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2563397/503ec591-5f18-a64e-5e3c-7847af9715e5.png)


# 原因データ特定
あとは展開されたものの中に、
/x1/worksheets/sheet2.xmlがあるので、vscodeで開き、2行目の1,103,212列目を探す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2563397/1c27b260-cc88-e6d8-192b-4a1de941c8d3.png)

それが分かれば、DB内の、どのレコードが原因か突き止めることができると思うので、サクッとデータ修正をして再度エクスポート機能を試してみる。エクスポートしたxlsxファイルが問題なく開くことができればクリア



参考）
https://answers.microsoft.com/ja-jp/msoffice/forum/all/%EF%BD%98%EF%BD%8C%EF%BD%93%EF%BD%98%E3%81%8B/cf52d151-0440-4b2a-861c-72976f7113bf

https://www.milkmemo.com/entry/excel_watch

https://okumuralab.org/~okumura/stat/xlsx.html
ワークシートを名前順に並べ替える

 英語の教材を作っていて、ワークシートを名前順に並べ替えたいな、と思って作成。
 シート名が「〇〇大学▽△年□番」と取り扱った問題番号を示しているけれども、どの大学のどれを処理するかはそのつど目についたものにしているのであとから見るとゴチャゴチャしている。そこでソートを掛けてみた。
 ポイントは、現在選択しているシートを一番左に持ってくること。（たとえば[サマリー]なんてシートを選択しておく。）ついでにこのマクロのあるブックを裏で立ち上げておけば、別のブックでシート並べ替え作業を行えること。

```
Sub ワークシートソート()

Dim arr_wsName() As String
Dim 基準シート As String
Dim シート数 As Long

Dim ws As Worksheet
Dim ct As Long
Dim t As Long

    基準シート = ActiveSheet.Name
    シート数 = ActiveWorkbook.Worksheets.Count
    
    ReDim arr_wsName(1 To シート数)
    
    ct = 1
    For Each ws In Worksheets
        If ws.Name = 基準シート Then
            arr_wsName(1) = ws.Name
        Else
            ct = ct + 1
            arr_wsName(ct) = ws.Name
        End If
    Next
    
    Call QuickSort1(arr_wsName, 2, シート数)
    
    Worksheets(基準シート).Move before:=Sheets(1)
    For t = 1 To シート数
        Worksheets(arr_wsName(t)).Move after:=ActiveSheet
        Worksheets(arr_wsName(t)).Activate '･･･(1)
    Next t
    DoEvents
    Worksheets(基準シート).Activate

End Sub

Sub QuickSort1(ByRef argAry As Variant, ByVal lngMin As Long, ByVal lngMax As Long)
    Dim i As Long
    Dim j As Long
    Dim vBase As Variant
    Dim vSwap As Variant
    vBase = argAry(Int((lngMin + lngMax) / 2))
    i = lngMin
    j = lngMax
    Do
        Do While argAry(i) < vBase
            i = i + 1
        Loop
        Do While argAry(j) > vBase
            j = j - 1
        Loop
        If i >= j Then Exit Do
        vSwap = argAry(i)
        argAry(i) = argAry(j)
        argAry(j) = vSwap
        i = i + 1
        j = j - 1
    Loop
    If (lngMin < i - 1) Then
        Call QuickSort1(argAry, lngMin, i - 1)
    End If
    If (lngMax > j + 1) Then
        Call QuickSort1(argAry, j + 1, lngMax)
    End If
End Sub
```

　配列ソートのサブルーチンは、こちらから頂いています。
「エクセルの真髄」
https://excel-ubara.com/excelvba5/EXCELVBA228.html
いつもお世話になってます。コードが見やすいのです。

　(1)の部分は、Microsoft ExcelのVBAはバージョンアップの途中で
シートをコピーした後、そのシートがアクティブであると保証されない
という「仕様」になってしまったので、回避のためにつけたもの。
　シート名を配列に持っているんだから直接指定すれば済むのですが、なぜかこっちのほうがきれいだと思ったので。
git add .の使い方

# そもそもGitとは
Gitは、ソフトウェアのバージョン管理システムです。
コードの変更を追跡し、複数の開発者が同じプロジェクトで効率的に協力できるよう設計されています。

Gitには多くのコマンドがありますが、”git add .” はその中でも基本的かつ重要なコマンドの一つです。

それでは、”git add .” の基本的な理解を深めていきましょう。

# ”git add .” の基礎
#### 役割: 
git add .コマンドは、カレントディレクトリ（.で示される）とそのサブディレクトリにある変更された全てのファイルをステージングエリアに追加します。ステージングエリアとは、コミット（バージョン履歴に記録するための行為）する前の一時的な領域です。

#### 用途: 
このコマンドは、変更されたファイルを選択し、それらを次のコミットに含める準備をするために使用されます。


#### .の意味: 
.は現在のディレクトリを指します。つまり、git add .は「現在のディレクトリとその中の全てのファイルとサブディレクトリを追加する」という意味です。

# Gitの基本的なワークフロー
1. **変更の作業** : ファイルを編集し、変更を加えます。
1. **ステージング** : git addコマンドを使い、これらの変更をステージングエリアに追加します。
例: git add .は全ての変更をステージングしますが、特定のファイルだけをステージングしたい場合は "git add [ファイル名]" を使います。
1. **コミット** : ステージングされた変更をコミットし、リポジトリの履歴にこれらの変更を記録します。
例: git commit -m "変更の説明"
1. **プッシュ（オプション）**: ローカルの変更をリモートリポジトリ（例: GitHub）にアップロードします。
例: git push

:::note warn
- "git add ." は、新規作成されたファイルと変更されたファイルの両方をステージングエリアに追加しますが、削除されたファイルは追加しません。削除されたファイルを含める場合はgit add -Aを使用します。
- よく考えずに全てのファイルを追加すると、意図しないファイル（例: 一時ファイル、大きなバイナリファイル）がコミットに含まれる可能性があります。そのため、どのファイルを追加しているのかを意識することが重要です。
:::

以上が "git add ." コマンドの基本的な説明です。Gitは初めは複雑に感じられるかもしれませんが、基本的なコマンドを理解し、練習することで、効率的なバージョン管理が可能になります。
Deviseの内部挙動とActiveRecord::RecordNotFound の解消について

## はじめに

RailsアプリケーションにおいてDeviseを用いたユーザー認証機能のカスタマイズ中に`ActiveRecord::RecordNotFound - Couldn't find Staff without an ID:`というエラーメッセージが発生しました。この記事では、このエラーがなぜ発生したのか、そしてどのようにして解決に至ったのかを共有します。

## エラーの内容

ユーザー情報の更新フォームを送信した際に、以下のエラーメッセージが表示されました。

```
ActiveRecord::RecordNotFound - Couldn't find Staff without an ID:
  app/controllers/staffs/registrations_controller.rb:46:in `set_staff'
Started GET "/staffs/edit?id=2" for ::1 at 2024-02-28 00:00:38 +0900
Processing by Staffs::RegistrationsController#edit as HTML
  Parameters: {"id"=>"2"}
  Staff Load (1.8ms)  SELECT "staffs".* FROM "staffs" WHERE "staffs"."id" = $1 ORDER BY "staffs"."id" ASC LIMIT $2  [["id", 2], ["LIMIT", 1]]
  Staff Load (1.9ms)  SELECT "staffs".* FROM "staffs" WHERE "staffs"."id" = $1 LIMIT $2  [["id", 2], ["LIMIT", 1]]
  ↳ app/controllers/staffs/registrations_controller.rb:46:in `set_staff'
```

このメッセージは、一般的には、IDを指定せずにStaffオブジェクトを検索しようとしたときに発生します。
しかし、ログを確認するとidはパラメータとしてきちんと送信されています。問題はset_staffメソッド内で発生しているようですが、そのメソッドが正しくIDを使用してStaffオブジェクトを検索していることがログからも確認できます。

## 原因と経緯

エラーの根本的な原因は、`set_staff`メソッドとその`before_action`コールバックがDeviseのコントローラー内に記述されてDeviseの内部処理と競合していたことにありました。これらのコードは、`@staff`オブジェクトを設定するために意図されていましたが、編集画面で`@staff`変数が適切にセットされていない状況を引き起こしていました。

## 解決策

`set_staff`メソッドとそれを呼び出す`before_action`コールバックの削除が解決策でした。これらのコード行を削除することで、Deviseのデフォルトの挙動に任せることができ、エラーは解消されました。
  ```registrations_controller.rb
  before_action :set_staff, only: %i(edit update destroy)
  ```
  ```registrations_controller.rb
  def set_staff
    @staff = Staff.find(params[:id])
  end
  ```
なお、もし`set_staff`を使用したい場合は
  ```registrations_controller.rb
  def set_staff
    @staff = Staff.find(resource.id)
  end
  ```
  とすると使用できます。
## まとめ

この問題は、Deviseのフレームワークの内部動作に十分な理解がない状態で余計なコードを追加してしまった結果生じました。Deviseのような複雑なライブラリを使用する際には、そのデフォルトの動作を理解し、必要なカスタマイズのみを慎重に行うことが重要です。
Raspberry Pi 5でVNC時解像度変更でハマったら

デフォルトはWaylandとなっており、Waylandでは今までの方法（参考：https://qiita.com/kuchiba/items/452f2a464250cd67ca0c ）がうまくいかなかったので、X11に切り替えてからVNCを有効にする必要がある。手順は以下。

```shell_session
$ sudo raspi-config
```

TUIが起動するので以下手順でX11に変更する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222089/b9e1c9c7-681f-9787-600a-f9b46b12e973.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222089/10a7443f-503c-8182-ecf8-14777336dcbf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222089/9458dce6-d2bb-c718-3730-f1ed05407b5f.png)

再起動を促されるので、再起動する。

その後、以下手順でVNCを有効化する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222089/df1bfd8f-a820-25ce-a848-2c082433944f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/222089/4c8ad99b-ae8e-f24a-63f9-b20df0e8cb52.png)

あとは`cvt`コマンドをインストールすればよい。

```
$ sudo apt install -y xcvt
```
【生成AI】ChatGPT にLinuxのようにふるまってもらった

よくChatGPTに`〇〇としてふるまってください`というプロンプトを見かけたのでLinuxのようにふるまってくれるのか試してみました。

↓が実際のやり取り
https://chat.openai.com/share/6a826041-73f1-4879-91a5-371052f70d87
以下抜粋

##### pwd
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/c5da5732-fd5e-bee8-351b-f8b7dbe0870d.png)

##### ファイル作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/0ade176c-2bba-57c1-09ee-243bbb1be59c.png)

##### ちゃんとできてる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/ff68bdeb-f0c3-c741-ec8c-3d6e60e36691.png)

##### ファイル名変更
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/3bf0d648-e333-b268-689e-af3430fe0da8.png)

##### これもできてる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/aa01c0b8-da89-4e6e-9e5c-8cc27b8bfe57.png)

##### ファイル編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/4ecdee3b-b68c-7024-69bd-0623e4987615.png)

##### viエディタが開かれ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/42f77f42-78aa-6c1d-f503-aeb45acc8535.png)

##### 書き込んで保存
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/f2abbc96-cda2-5052-634f-7dd13a084bbe.png)

##### ファイルの中身も更新された
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1710277/1c4f8d4d-d4ab-b752-ab1a-d5c0adc0db4d.png)

そのうちソフトウェアがなくなりすべてAIが今あるソフトウェアのようにふるまう日が来るのではないかと思いました。。。
asdfでWSL+Ubuntuにpythonをインストール

# はじめに

以前インストールしたプログラミング言語管理ツールのasdfを使って、WSL Ubuntuにpythonをインストールします。

（目的は、DockerCompose + Django環境を構築するにあたり、pythonやpipをいじるためです。）

https://qiita.com/perilla/items/69bc6f89001dbceb0cde

https://qiita.com/perilla/items/ef73cf57ade24bc94f19

# asdf更新

asdfを更新します。

```sh:Ubuntu
asdf update
```

# pythonの存在確認

```sh:Ubuntu
asdf plugin list all | grep -e python
# python                        https://github.com/danhper/asdf-python.git
```

https://github.com/danhper/asdf-python.git

# asdfにpythonを追加

```sh:Ubuntu
asdf plugin add python
```

# 依存パッケージをインストール

[Github](https://github.com/asdf-community/asdf-python)のREADMEに従い[依存パッケージ](https://github.com/pyenv/pyenv/wiki#suggested-build-environment)をインストールします。（`Ubuntu/Debian/Mint:`の箇所です）

```sh:Ubuntu
sudo apt install build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev curl libncursesw5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
```

# 最新版pythonをインストール

```sh:Ubuntu
asdf install python latest
```

# 最新版pythonをグローバルに設定

```sh:Ubuntu
asdf global python latest
```

# pythonバージョン確認

```sh:Ubuntu
asdf current python
# python          3.12.2          /home/[user]/.tool-versions

python -V
# Python 3.12.2

pip -V
# pip 24.0 from /home/[user]/.asdf/installs/python/3.12.2/lib/python3.12/site-packages/pip (python 3.12)
```
[パート１：概要の設計] S3に保存する前ラムダでサムネイルに画像圧縮の前処理

前の[記事](https://qiita.com/17021084/items/e1078bacc2fbc32d3183)の次に、今回は実践のユーケースを説明させて頂きます。

以下の２つのパートに分かれています。

- パート１：概要の設計（本記事）
- パート２：[詳細な実行](https://qiita.com/17021084/items/0e077c7c85bd5fce657d)


## **概要**

1. 前提
2. 背景
3. 目的
4. 構成・経過
5. 評価
6. その他

## 1.前提

- Node Js 20.xx
- Lambda x86_64
- [sharp](https://sharp.pixelplumbing.com/install)  (os linux, cpu x86)
- AWS console 操作ため、管理権があるアカウントは必要

## 2.背景

SNS系アプリでよく見かけるサムネイルです。これらの処理には時間がかかりますが、たまにしか実行されません。メインのサーバーにサムネイル処理を置くと、他のサービスに影響を与える可能性があります。そこで、ラムダにサムネイル処理を移動することで、メインサーバーの負荷を軽減します。

## ３.目的・目標

目的：ラムダで画像を圧縮しS3にアプロードする仕組み

- 目標１：構成・処理流れを理解
- 目標２：S3とラムダの連結を理解
- 目標３：sharpライブラリで圧縮を理解

## 4.構成図・経過

![Screenshot 2024-02-27 at 23.03.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/703979/210dd015-e58d-2f35-5bf1-d3a98a02e2df.png)

| ステップ | 解説 |
| --- | --- |
| １ | クライアントから画像を一時的なバケツにアップロード |
| 2 | 一時的なバケツは画像情報を含むイベントでラムダファンクションをトリガー |
| ３ | ラムダファンクションは画像情報を通じて画像をダウンロード |
| 4 | 画像を処理 |
| 5 | 処理してから主なバケツに画像をアップロード |

S3ライフサイクルについては、元画像を保存する場合は設定が不要ですが、要らない場合は設定が必要です

？何故：バケツは二台がありますか？

Recursive invocationを避けるためです。

サークルトリガー形でラムダが繰り替えてトリガーして止まりません。したがって、利用金がすごく発生します

```mermaid
graph TD;
    画像-- PUTイベン-->バケツA;
    バケツA--処理ずみ-->画像;
```

### ５.評価

| メリット | デメリット |
| --- | --- |
| S3はサーバーレスのため、をcpuやramなどの計算力が自動的にスケールできて重い処理が対応可能 | 頻度が多い場合は料金がすごくかかる |
| 本サーバーから他所に処理を移転するため、本サーバー負荷を共有 | 若干処理時間がかかる |
| S３言語対応の限りでは実装可能 |  |

処理の頻度を考慮して決定する必要があります。

## 6.その他

上記の概要は、全体的にS3の前処理に関するものです。そのため、これはサムネイル処理に限らず、他のユースケースにも応用可能です。

例：ウィルススキャンやデータトランスフォームなど

## 最後

最後までご覧いただき、ありがとうございます。

内容にご興味があれば、コメントやハートを残していただけると嬉しいです。

次の[パート２](https://qiita.com/17021084/items/0e077c7c85bd5fce657d)もぜひご覧ください。


***参考***

https://sharp.pixelplumbing.com/install

https://aws.amazon.com/jp/s3/pricing/
Java ~関係演算子~

## :ledger:関係演算子
演算子の左側と右側を比較するものです。
条件分岐や繰り返しを行うために必要です。

一覧を見てください。
| 演算子 | 例 | 説明 |
|:-:|:-:|:-:|
|  > |  A>B |  AはBより大きい |
| <  |  A<B | AはBより小さい（未満）  |
| >=  |  A>=B | AはBより大きい(以上)または等しい  |
|  <= |  A<=B | AはBより小さい(以下)または等しい|
|  == |  A==B |  AとBは等しい |
| != |  A!=B | AとBは等しくない   |
| === | A===B | AとBが型まで等しい   |
|!== | A!==B | AとBが型まで含めて等しくない   |

関係演算子の演算結果は<b>`ture`</b>か<b>`false`</b>の真偽値です。

***
<b><<補足>></b>

・等しくないときの記号で`!`には`NOT`の意味があります。


次回は論理演算子について解説していきます！
AndroidTVでEATV-N01やEATV-N04が発生する問題

# AndroidTVで一部のアプリが動かない
先日、開発用にAndroidTVを購入しました。TVアプリは初めて触れるので、さまざまなアプリをインストールし動作の検証を行っていると、一部のアプリが機能しません。
例えば、NHK+は、EATV-N01やEATV-N04というエラーが頻発します。TVerやAbemaTVは最初のタイトル画面で固まってしまいますが、エラーを表示していないだけでおそらく同じ現象だと思います。

調べてみると、EATV-N01やEATV-N04は原因の特定できないネットワーク系のエラーだそうです。つまり原因はケースバイケースと認識してよさそうです。

ということで、「私の場合」という前提となりますが、解決した経緯を示したいと思います。


# ネットワーク構成
ネット回線は2つあり、それぞれ下記のとおりです。
1. フレッツ回線
   * 速度は100MB
   * IPv6とIPv4に対応 (IPoE)
   * 
1. 光ファイバー回線
   * 速度は1GB
   * IPv4のみ

# 原因の可能性
1. アプリの不具合
   * ネットで調べてみると、同じ現象が起きている人はそう多くない。というかむしろ少ない。つまりアプリの不具合というは可能性は非常に低い。
1. サービス障害
   * エラー発生当時、障害情報は確認できなかった。
1. テレビとルーターのつなぎ方
   * 有線でもWi-Fiでも挙動は変わらない。
1. 回線の種類や速度
   * フレッツでも光ファイバーでも挙動は変わらない。
1. IPアドレスをDHCPで取得するか、静的に割り振るか
   * DHCPでも静的でも挙動は変わらない。

上記のいずれも原因ではありませんでした。そして問題は解決しないまま2週間が経過します。そして解決の時は突如やってきました。

# 結論
光ファイバー側のルーターが、IPv6を使っていないにもかかわらず「使用する」設定になっていました。「IPv6ブリッジ」または「使用しない」ように変更したら、TVアプリがうまく動作するようになりました。

ネットワークの専門家ではないのでハッキリしたことは言えませんが、RAまわりでコンフリクトしてしまった可能性があります。

もし同じような現象でお困りの方は、IPv6まわりの設定を見直すと糸口が見つかるかもしれません。
【TypeScript】Zodを用いた型ガード関数の実装方法

## 型ガード関数

型ガード関数は以下のように実装します。

```ts
import type z from 'zod'

export function isValidData<T extends z.ZodTypeAny>(
  schema: T,
  data: unknown
): data is z.infer<T> {
  return schema.safeParse(data).success
}
```

## 関数の使い方

```ts
import 'server-only'
import { cache } from 'react'
import { z } from 'zod'
import { isValidData } from '@/utils/type-guard/is-valid-data'

const successSchema = z.object({
  user: z.object({
    id: z.string(),
    name: z.string(),
    bio: z.string(),
    avatarUrl: z.string().nullable(),
  }),
})

type Success = z.infer<typeof successSchema>

export const sampleFetch = cache(
  async (id: string): Promise<Success> => {
    const res = await fetch(`/sample/${id}`, {
      method: 'GET',
    })

    const data = await res.json()

    if (isValidData(successSchema, data)) {
      // ...
    }

    // ...
  }
)
```

## 参考

- Zodを使用した型ガード関数の実装方法について

https://github.com/colinhacks/zod/issues/2413#issuecomment-1777268773

- z.ZodTypeAnyについて

https://zod.dev/?id=writing-generic-functions

- z.inferについて

https://zod.dev/?id=type-inference

- z.safeParseについて

https://zod.dev/?id=safeparse

- Genericsについて

https://www.typescriptlang.org/docs/handbook/2/generics.html

- ユーザー定義の型ガードについて

https://www.typescriptlang.org/docs/handbook/2/narrowing.html#using-type-predicates
【AWS】EC2構築前に考慮すべきこと

## はじめに
初めて勉強しますと言う方に向けた記事になりますので、よろしくお願いいたします。
EC2をただ構築するだけではなく、その後の作業諸々、考えなければいけないことが
あります。別の案件作業や会議等もあるので余裕を持った、スケジュール感を考えないと
行けないと感じました。ハンズオンだけではわからない実務経験をお伝え出来たらと
思います。

## 考慮すべき点
・OS設定（Linux,Windows）
・監視設定（CloudWatchアラーム,使用している監視ツール）
・バックアップ設定(AWS,BackUP,その他バックアップツール)
・既存のパラメータシートの修正または新規でパラメータシート作成
・既存のライセンス（SQLServer等）を持ち込む場合
・タグ設定（EC2,EBS）
## 詳細
### OS設定
EC2の構築自体はパラメータシート（詳細設計書）を見ながら構築を行うので
実際には時間はかかりません。ですがその後の作業は実際どうしたらいい？
って方も多いのではないかと思います。（クラウドから始めた方とか）
基本的な変更点は以下になります。

■ホスト名変更
サーバー上の実際のPC名を変更
※変更後は再起動必要
■サーバー上のファイヤーウォールの設定（無効化）
AWSでは、Security GroupやNetwork ACLもセキュリティを管理するための手段として使用されます。これらが適切に設定されている場合、サーバー上のファイアウォールを無効化することもあります。
※セキュリティポリシーや特定のユースケースによっては一部の環境ではファイアウォールを有効にすることもあります
■タイムゾーン変更（時間変更）
基本的にUTCで設定されていることが多いので、日本の時間に直すことが多いです
■DNSの設定、ドメイン参加等
名前解決（IPアドレスとドメイン名の対応付け）のため設定することがあります。
ドメイン参加はActive Directory（AD）ドメインにコンピュータを組み込みます。
ドメインユーザでログインすることで、ドメイン配下のどの PC にログインしても、常に自分の環境を維持できる状態になります。
※ドメイン参加後は再起動必要
■ユーザー登録
ユーザー名、パスワードを登録になります。
administrator(管理者権限)はpwは基本的に変更はセキュリティの観点から
おススメはしません。※PWは永続化にすることが多い
■エージェントインストール（SSMエージェント,CloudWatchエージェント）
パラメータシートによってはエージェントやツールをダウンロードします。
バージョン等も確認する必要があります。
手動か自動（AWS Systems Manager）でもダウンロード出来ます。
■ディスク拡張
基本的に構築時は1つのEBSボリュームを用いますが、追加で設定する場合もあります。
構築時に2つのEBSボリュームが存在する時は追加分の方はディスク拡張する必要があります。WindowsやLinuxでやり方が変わるので、それぞれの方法でディスク拡張お願いいたします。

### 監視設定
監視設定に関しては、どのツールを用いて、監視を行うか考慮する必要があります。
基本AWSは構築後にすぐに監視アラームを作成することが出来ます。
監視ツールに関してはAWSと監視ツールをインテグレーションしてから
実際にアラートを発砲したり、費用を安く抑えることが出来ます。
※死活監視,ディスク監視,CPU使用率監視など
・CloudWatchエージェント
・監視ツール（NewRellic,Zabbix,Datadog）

### バックアップ設定
基本的にサーバーのバックアップを取得することが多いです。
今回はAWS BackUPを用いた、方法で紹介させていただきます。

基本的には用途によって、バックアッププランが変わります。
例えば、24時間稼働サーバーであると常にバックアップを取る必要が
あるのならば、「日次」検証環境であれば、「月次」など。
保管期間も設定できるので用途に合わせる必要があります。
■バックアッププラン
・日次（毎日）
・週次（毎週）
・月次(毎月)

### パラメータシートの修正または作成
既存の環境でサーバーを構築した際は、パラメータシート（詳細設計書）に追記する
必要があります。台帳管理として、構築をした際は情報を集約する必要があります。
パラメータシートは非常に修正することが多いので予めに新規で追加することがあれば
追記しやすい設計で作成することをおススメいたします。
■パラメータシート記載内容
・サーバー情報
・ネットワーク情報
・ディスク情報
・バックアップ情報
・監視設定情報等
・その他

### 既存のライセンス（SQLServer等）を持ち込む場合
EC2を構築する際はAMI(ゴールデンAMI)を用いて、構築します。
例えば、WindowsでSQLServer等をAWSで構築したい時に
既存のライセンス(SQLServer)を持ち込むことが出来ます。
しかし、規約など条件などがあるので実際にはAMIを選定する際は
慎重に選ぶ必要があります。
規約や条件などに引っかかると、実際に既存のライセンスを持ち込むことが出来ない場合も
存在します。
■AMI
・AWSが提供しているAMI
・SQLServerのライセンスが既に入っている,AWSが提供しているAMI
・AWS以外が提供しているAMIなど
・その他

### タグ設定
タグ設定は実際にはどう使っているのか、最初は自分もイメージが湧きませんでした。
どうして、タグの機能があるのだろう？ぐらいの感じで業務を進めていきましたが
想像以上にタグを設定することでAWS環境を管理する際に非常に便利だと実感しました。
タグの種類でも様々あります。
■タグ
・コストタグ
・バックアップタグ
・タグ（環境を把握するためのタグ,本番環境や検証環境など）

### さいごに。
実際にハンズオンだけでは紹介されていないことが意外と
多いのだと実感しました。AWSだけではなく、NW,OS周り（windows,linux）,
資料作成（エクセル,パワーポイント）など思っている以上に考慮すべき点が
沢山あるので、実務系の記事を記載出来たらと思っています。
記事を最後まで読んでいただき、ありがとうございます
※随時更新予定！！
教師あり学習について

※注意です。この記事は僕のアウトプットのために書いたものであるので、間違っている箇所もあるかと思う。
よって、もしここの認識間違っているよ等、ありましたら教えて頂けると嬉しい。

それでは早速、本題に入っていく。ここでは教師あり学習の線形回帰と決定木のアルゴリズムについて解説していく。

『教師あり学習について』
・教師あり学習は、取り扱うデータが連続値なのか離散値なのかによって、回帰と分類のタスクに分けられる。



【線形回帰】
・予測値＝特徴量と線形の関係　という仮定とする。
・この仮定より、学習データが少なくても過学習しづらい特性がある。
・ここで注意して欲しいのが、学習データが少なくても過学習しづらい、逆に捉えれば、学習データが多い時やモデルが複雑な時に関しては、過学習を起こしやすい。

【決定木】
・学習データの特徴量を使って、条件分岐を行う。
・決定木は、基本的に過学習を起こしやすく、線形回帰と比較すると、精度は落ちる。ただ、これに関しては、決定木を単体で使用した場合は、ということ。つまり複数を組み合わせて使用すれば線形回帰よりも精度はいい。
・要するに、この決定木を弱学習器としてアンサンブル学習すれば、複雑なモデルにも対応できる。（※アンサンブル学習については前回の記事に書いてあるので、そちらを見るように。）
・で、このアンサンブル学習には「勾配ブースティング」と「ランダムフォレスト」の二種類がある。
・この二つのアンサンブル学習については、また次の記事で触れることにする。

以上が、線形回帰と決定木のアルゴリズムである。また補足事項があれば継ぎ足していき、認識が間違っていればその部分を変更していく。
ここまで、僕の記事を読んでくれてありがとう。これからこんな感じで記事を出していくので、暇な時にでも読んでくれ。
UiPath中級者向け：実務でよく使うVB.NET集

# 1.はじめに
UiPath初心者の市民開発者がどうしても下記の内容を使わないといけない状況になったので、これを機にまとめてみました。
過去に簡単なVB.Netも作成しているので、気になる方はご覧ください。

https://qiita.com/thxUVER2012/items/72860e4a2abf29cc7fc7

どういう場面で使用のかも載せていきます。

:::note warn
注意点
・文字列とはstring型の変数です。
・変数の先頭のstはstrinng型です。
・変数の先頭のinはint32型です。
:::


# 2.If文の条件分岐でよく使用するもの
#### (1)ID番号の文字数の長さで分岐したい
・構文
　文字列.Length
・使用するタイミング
　取ってきたID番号が一定の文字数のときにある処理をしたい
 　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/8fb70cbc-03d6-73c6-88b8-d86b47aa8710.png)


# 3.代入でよく使うもの
#### (1)余計な空白や前後の改行を取りたい
・構文
　文字列.Trim
・使用するタイミング
　Webから文字抽出した文字(UVERworld)の前後に空白がある。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/e0723d63-2821-2ade-c5c0-e995bec94d61.png)

#### (2)余計な文字を切り取りたい
・構文
　文字列.Substring(切り取りたい文字の最初の文字位置数,切り出したい最後の文字位置数)
  ※Substrig=部分文字列
・使用タイミング
　一部の名前だけを取得したい。
 
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327229/0ec3df2a-ebe2-bbdb-12a0-e12f1680a104.png)

# 4,おわりに
VB.Netを使用して終わるのではなく、使用したら注釈で何をしているのかを書くことで保守運用しやすいので試してみてください！
下記に詳しくまとめているので気になった方は確認してみてください！

https://qiita.com/thxUVER2012/items/11923133a781afce35be
composer（phpdotenv）を使用せずPHPで指定した環境変数の取得

## はじめに
【対象】
- PHPでの開発がメインでない方、PHPで指定した環境変数を取得したい方
- composer(phpdotenv)をインストールせずに取得できる方法を探している方

## 環境
PHP：version 8.3.3

## 取得例
```php:config.inc
<?php
const DB_USER = 'sample-db-user';
const DB_PASS = 'sample-db-password';
const DB_NAME = 'sample-db-name';
?>
```
`config.incファイルですが、PHPで取得する場合はその形式で書くと取得できました。`
```php:echoInc.php
<?php
include( __DIR__ . '/config.inc');

echo 'DB_USER is ' . DB_USER . "\n";
echo 'DB_PASS is ' . DB_PASS . "\n";
echo 'DB_NAME is ' . DB_NAME . "\n";
?>
```
` . "\n"：改行コード。出力結果が見えやすいように書きました。`
`config.incファイルとechoInc.phpの階層は同じ階層に設定しました。`

```php:出力結果
DB_USER is sample-db-user
DB_PASS is sample-db-password
DB_NAME is sample-db-name
```

## おわりに
- 投稿初期は「config.inc」ファイルの部分を「.env」ファイルで設定していました。
- 「.env」ファイルをPHPの形式で書くことで値を取得することができましたが、他のライブラリなど使用している場合や業務で使用する場合は環境変数の取得に悪影響を与える恐れがあるためおすすめできません。
- (@YuneKichi様からコメントをいただき修正いたしました。誠にありがとうございます。)
【Rails】画像の上に文字を中央揃えで表示する方法

# 概要
この記事では、Railsアプリケーションにおいて画像の上に文字を中央揃えで表示する方法を説明します。
実装方法の参考として残しておく形なので詳しい解説はあえてつけていません。

# 環境
**Rails**: 6.1.4
**Ruby**: 3.1.2
**Bootstrap**: 4.5

:::note warn
**注意**
Bootstrapが導入されている前提で進めますので、もし導入されていない場合は、Bootstrapを導入するか、その部分を自作のclassで置き換えるかして対応してください。
:::

# 結果
最初にコード実装後の結果を貼っておきます。
実装後に下記の画像のようになっていれば表示されていれば、問題ないと思います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2524017/7c9784cd-155e-26d1-1364-31dea00348b8.png)


# 準備
`app/assets/images`配下に背景画像としたい画像を用意しておいてください。
著作権等が気になる方は生成AIのツールなどを用いて作成すると良いでしょう。
画像は縦:横が`3:4`にしておくと、レイアウトを綺麗に揃えやすいのでオススメです。

# 実装
`stylesheets/application.scss`に、`bg_img`という自作のclassを追加します。
名前は`bg-img`でなくても問題ありません。好みでつけてください。
urlの中のファイル名は自分で追加した画像のファイル名で置き換えてください。
```stylesheets/application.scss
.bg-img{
  background-image: url("v_cake.jpg");
  background-size: cover;
  background-position: center;
  border-radius: 30px;
  box-shadow: 10px 10px 15px -10px;
  height: 400px;
  width: 100%;
}
```
画像と文字をセットで表示したいViewページに実装を行います。
Bootstrapやstyleの説明は省きますので、気になったら調べてみてください。
`opacity`で少し透過させているのですが、気に入らなかったら削除してもらって構いません。
```erb:top.html.erb
<div class="bg-img d-flex justify-content-center align-items-center mb-5">
    <p class="bg-white p-3 rounded" style="opacity: 90%;">
      ようこそ、V-Cakeへ！<br>
      このサイトはケーキ販売のECサイトになります。<br>
      会員でない方も商品の閲覧は可能ですが、<br>
      購入するには会員登録が必要になりますのでお気をつけください。<br>
    </p>
</div>
```

# おわりに
画像の上に文字をおいて中央揃えする方法は、様々あると思いますが、少しでも参考になればとても嬉しいです。
最後にですが自分のブログを紹介させてください。Qiitaの記事にするまでもないような内容をまとめていたりします。下記のリンクから見ていっていただけると幸いです。

https://kt-tech.blog
CoreUIのReact Chart.jsで100%積み上げ棒グラフを描画したい！

## はじめに
[CoreUIのReact Chart.js](https://coreui.io/react/docs/components/chart/)で100%積み上げ棒グラフを描画することになりました。
調べてみるとChart.jsには[`chartjs-plugin-stacked100`](https://github.com/y-takey/chartjs-plugin-stacked100)という物があり
ふむふむこれシンプルだしCoreUIのChart.jsでもできるかなと使ってみましたが描画できなかったので、素直に`data`や`option`を設定し実装を行いました。
今回はその説明をします。
## 実装
:::note warn
以下コードには含んでいませんが色の設定を追加して描画しています。
:::
### 1. 表示したいデータ
```tsx
const chartData: ChartData<'bar'> = {
  labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
  datasets: [
    {
      label: 'My First Dataset',
      data: [65, 59, 80, 81, 56, 55, 40],
    },
    {
      label: 'My Second Dataset',
      data: [28, 48, 40, 19, 86, 27, 90],
    },
  ],
};

return (
  <CChart type="bar" data={chartData} />
)
```
<img width="400px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690936/efa64f4d-04ab-df25-dff6-1d7e9b8dce4d.png">

ただデータを入れるだけではデフォルトの表示になってしまいます。

### 2. グラフを100%表示にするために今回追加した関数
```tsx
const calculatePercentage = (data: ChartData<'bar'>): ChartData<'bar'> => {
  const totals = data.datasets.reduce((acc, dataset) => {
    dataset.data.forEach((value, index) => {
      acc[index] = (acc[index] || 0) + value;
    });
    return acc;
  }, [] as number[]);

  const datasetsWithPercentage = data.datasets.map((dataset) => ({
    ...dataset,
    data: dataset.data.map((value, index) => {
      const total = totals[index];
      const percentage = total ? (value / total) * 100 : 0;
      return percentage;
    }),
  }));

  return { ...data, datasets: datasetsWithPercentage };
};

return (
  <CChart type="bar" data={calculatePercentage(chartData)} />
)
```
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690936/ac16ebf2-611d-f4e8-dc25-f597ebbc544c.png" width="400px">

このままではまだ積み上がっていないし、カーソルを当てた時に表示される数字も違う、、、

### 3. optionsでグラフの設定を行う
ここでグラフの描画に関する具体的な設定を行います。
今回行ったのは
・横に並んで表示されてしまうグラフを縦に積み上げて表示
・tooltipに表示される内容の変更
です。
labelの部分を変更することで表示する内容を変えるができます。
```tsx
const chartOption = (data: ChartData<'bar'>) => ({
  scales: {
    x: {
      stacked: true,
    },
    y: {
      stacked: true,
    },
  },
  plugins: {
    tooltip: {
      callbacks: {
        label: (context: TooltipItem<'bar'>) => {
          const label = context.dataset.label || '';
          const valueIndex = context.dataIndex;
          const originalValue =
            data.datasets[context.datasetIndex]?.data[valueIndex];
          return `${label}: ${originalValue}`;
        },
      },
    },
  },
});

return (
  <CChart type="bar" data={calculatePercentage(chartData)} options={chartOption(chartData)} />
)
```

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3690936/b88dbacd-e462-f58a-a828-6a3924b44fbd.png" width="400px">

以上のようにすることでpluginなしで100%積み上げ棒グラフを描画することができました。

## 終わりに
今回はCoreUIのReact Chart.jsで100%積み上げ棒グラフを描画する方法を紹介しました。
違うやり方があるよーとか別のパッケージ使えるよとかあったらじゃんじゃんコメント待っています。
最後まで読んでいただきありがとうございました。
NFT取引データの分析方法: Duneを活用したSQLクエリの紹介(アドレス入力でデータ確認する)

Dune を使ったメモ

![](https://pbs.twimg.com/media/F_yCF2YboAAFJ5N?format=jpg\&name=large)

アドレス入力で、自分のそのNFTに対するトランザクション結果を見ることができるSQLコード

以下はログインして実行で1回20クレジット取られるけど無料プラン2,500Credits/月なので気にしなくて平気

- Infinity frog ＆ Infinity Flies 購入履歴(アドレス入力) 

リンク<br><https://dune.com/shogaku_toushi/infinity-frog-and-infinity-flies-gou-ru-lu-li-adoresuru-li?your_address_t15da6=0x57FD2A3eB0c26eB4cD598e16a66879912BeC9dED>

***

# NFT取引データの分析方法: Duneを活用したSQLクエリの紹介

### はじめに

NFT市場の成長に伴い、取引データの分析が投資家やコレクターにとってますます重要になっています。この記事では、Dune Analyticsを使用して特定のNFTコレクションの取引データを分析する方法を紹介します。

### Dune Analyticsとは

Dune Analyticsは、ブロックチェーンデータを簡単に分析できるプラットフォームです。ユーザーはSQLクエリを使用してデータを抽出し、ダッシュボードを作成して情報を視覚的に表示できます。

### 分析の準備: Infinity Frogの取引データ

例として、ICPにブリッジ出来たNFTコレクションであるInfinity Frogの取引データを分析します。分析の第一歩として、以下のSQLクエリを使用します。

```sql
SELECT
  block_time AS transaction_time,
  token_id,
  collection,
  amount_usd AS usd_amount,
  amount_original AS ETH,
  buyer,
  seller,
  tx_hash
FROM
  nft.trades
WHERE
  nft_contract_address = 0xa2480eb41dd1f2b0abade9f305826c544d47f696  -- Infinity Frogのコントラクトアドレス
  AND buyer = {{your_address}}  -- ユーザーが入力する購入者アドレス
ORDER BY
  block_time DESC;
```

### クエリの説明

このクエリでは、特定のNFTコントラクトアドレス（Infinity Frog）に対して行われた取引を、購入者アドレスに基づいて抽出します。各取引について、トランザクションの時間、トークンID、コレクション名、取引額（USDおよびETH）、購入者と販売者のアドレス、トランザクションハッシュが表示されます。

### 分析の実施

*   **トランザクション時間**: 取引が行われた正確な時刻を確認できます。
*   **USDおよびETHでの取引額**: 市場の動向や特定のNFTの価値を把握するのに役立ちます。
*   **購入者と販売者のアドレス**: 市場の主要プレイヤーやアクティブなウォレットを特定できます。
*   **トランザクションハッシュ**: 取引の詳細を深堀りするための出発点となります。

### まとめ

Dune Analyticsを使用することで、NFT取引データの分析がよりアクセスしやすくなります。今回紹介したSQLクエリは、個々の投資家やコレクターが自身の取引履歴を分析するための出発点となるでしょう。これを基に、より複雑なクエリを作成して、市場の深い洞察を得ることが可能です。

***

***

# Polygonチェーン

***

### PolygonチェーンにおけるNFT取引データの分析

Ethereumチェーンと同様に、PolygonチェーンでもNFT市場は急速に成長しています。Polygonは低いガス料金と高速なトランザクションが特徴で、多くのNFTプロジェクトやコレクターが利用しています。ここでは、Polygonチェーン上のNFTコレクション「Infinity Flies」の取引データを分析するためのSQLクエリを紹介します。

#### SQLクエリ: Polygonチェーンの例

```sql
SELECT
  block_time AS transaction_time,
  token_id,
  collection,
  amount_usd AS usd_amount,
  amount_original AS WETH,
  buyer,
  seller,
  tx_hash
FROM
  nft.trades
WHERE
  nft_contract_address = 0xdFcBCc1D5333c95F88CA869D56cAA308c1C30b77  -- Infinity Fliesのコントラクトアドレス
  AND buyer = {{your_address}}  -- ユーザーが入力する購入者アドレス
ORDER BY
  block_time DESC;
```

このクエリでは、Infinity Fliesコレクションに対する取引を抽出しています。Polygonチェーンでは、通常のETHではなくWETH（Wrapped ETH）が使用されることがあります。これは、ETHをERC-20互換の形式にラップすることで、より多くのデフィ（DeFi）アプリケーションやNFTマーケットプレイスとの互換性を持たせるためです。

#### 分析のポイント

*   **トランザクション時間**: Polygonチェーン上での取引タイミングを特定します。
*   **USDおよびWETHでの取引額**: Polygonチェーン上のNFTの価値と流動性を評価します。
*   **購入者と販売者のアドレス**: アクティブな参加者と市場の動向を把握します。
*   **トランザクションハッシュ**: 取引の詳細をさらに調査するためのキーとなります。

### まとめと展望

EthereumとPolygonチェーンのデータ分析を比較することで、NFT市場の多様性とエコシステム全体の健全性を理解することができます。Dune Analyticsを活用して、これらのクエリを実行することで、投資家やコレクターはより情報に基づいた意思決定を行うことが可能になります。今後も、さまざまなブロックチェーン上でのNFT取引データの分析が市場の透明性を高め、新たな機会を生み出していくでしょう。

***

って、感じ。
特定ユーザ除くコンソールログインを一括禁止するように

組織内でIAM（Identity and Access Management）ユーザーからSSO（Single Sign-On）ユーザーへの移行を計画している場合、スムーズでセキュアな過渡期を確保することは非常に重要です。この記事では、IAMユーザーを無効化し、SSOユーザーへ移行するためのプロセスを紹介します。特に、数百人のユーザーを対象とした場合の自動化スクリプトの作成と利用に焦点を当てます。
（忙しい方は直接に最後[スクリプト](#スクリプト)へ）


# IAM無効化の必要性
IAMユーザーをSSOユーザーへ切り替える過程で、IAMの無効化はセキュリティ上のリスクを最小限に抑えるための重要なステップです。一斉に削除することのリスクを避け、過渡期間を設けることで、組織内のすべてのユーザーがスムーズに移行できるようにします。

# スクリプトの準備
IAMユーザーを効率的に無効化するために、AWS Native原則ですぐ使えるCloudshell利用でbashスクリプトを作りました。このスクリプトは、指定されたIAMユーザー以外のログインパスワードを一時的に削除しました。スクリプトの使用には、適切なAWSアクセス権限が必要です。

# スクリプトの概要
目的: IAMユーザーのログイン権限を無効化し、SSO移行を促進する。
機能: 指定ユーザーのログインを無効化し、必要に応じてパスワードを設定して再有効化する。
利用シナリオ: 緊急対策、一斉無効化、個別無効化など。

# 使用方法
環境準備: AWS　Cloudshell
スクリプト設定: スクリプトに除外用IAMユーザーのリストを事前作成する。
実行: スクリプトを実行し、IAMユーザーのプロファイル削除を行う。
確認: AWSコンソールまたはCLIを使用して、変更を確認します。


# まとめ
IAMからSSOへの切り替えは、組織のセキュリティを強化する重要なステップです。このプロセスを安全かつ効率的に進めるために、IAM無効化スクリプトの作成など自動化することが役立ちます。この記事で紹介したスクリプトが、皆さんのIAMからSSOへの移行作業を支援することを願っています。

また、このスクリプトは、IAMユーザーを速やかに無効化することで、セキュリティインシデント発生時の緊急対策としても有効ですので、不正アクセスが疑われる場合に迅速に対応できるように、事前に準備しておくことをお勧めします。


# スクリプト 
```
#!/bin/bash

# user.csvから対象外のユーザ名を配列として読み込む
declare -A csvUsers
while IFS=, read -r userName targetFlag
do
    if [ "$targetFlag" == "yes" ]; then
        csvUsers["$userName"]=1
    fi
done < "user.csv"

# AWS CLIを使用して全IAMユーザーのリストを取得
allUsers=$(aws iam list-users --query 'Users[*].UserName' --output text)

# 処理カウンタの初期化
totalUsers=0
successCount=0
skipCount=0
failedCount=0


# 全IAMユーザーに対して処理を行う
for userName in $allUsers; do
    ((totalUsers++))
    if  [ "${csvUsers["$userName"]}" != "1" ]; then
        # ユーザーがcsvに存在しない、またはTargetFlagが"No"の場合
        echo "ログインプロファイルを削除中: $userName"
        if aws iam delete-login-profile --user-name "$userName"; then
            ((successCount++))
            echo "成功: ログインプロファイルが削除されました - $userName"
        else
            ((failedCount++))
            echo "エラー: ログインプロファイルの削除に失敗しました - $userName"
        fi
    else
        ((skipCount++))
        echo "ログインプロファイルの削除をスキップした: $userName"
    fi
done
# 処理結果の出力
echo "処理結果：合計ユーザ数 $totalUsers、成功数 $successCount、スキップ数 $skipCount、失敗数 $failedCount"
```
Qiitaさん曰くエンジニアではあるらしいので

# はじめに
DegeneracyCraft開発者のEpitapです！
Qiitaさん曰くエンジニアの定義として

・プログラミングの知識と経験を活用している人

とのこと。
私もエンジニアという判定らしいです。
それ故に、この場をお借りして一旦振り返ってみることにします。
(以前の記憶は朧げです…)

# 大まかな流れ
始めたのは2022年9月中旬辺りでしたね。自分のやりたいことを自ら供給するためにDegeneracyCraftを作ったことが始まりです。
XがTwitterであった時からMODのことについてまとめているのでもし暇かつ興味があれば、ぜひご参照ください。

https://twitter.com/Epitap8

### 2022年9月
ここらへんでIntelliJの開発環境を立て、始動しました。
MOD製作の解説動画を見まくり、なんとか自分で扱えるようにと励んでいました。
この時のVersionは意外なことに1.17.1でした。

### 2022年12月~2023年1月
少しずつ軌道に乗ってきた(追加アイテム、ブロック類追加可能レベル)になったくらいの時、開発環境が爆散。

:::note info
理由は今も不明。正直結構凹んだ…
:::
これを機に、最高高度と最低高度、地形の生成アルゴリズムに大きな変更が入った1.18台のバージョン変更を決意。
MOD製作の解説動画を見まくり、なんとか自分で扱えるようにと励んでいました。これは継続。

### 2023年1月~2023年6月
どんどん現実が迫ってくる。
(タスクが増加しており、使える時間が減少)
しかし、MOD製作の解説動画を見ていた + Minecraftの他MODからアイデア、着想を得ていた。

### 2023年7月~2023年9月
GitHubの本格的な利用を試みるが、自身のコードのレベルの低さに絶望してしまった。
この時はTextureの原型が完成しつつありました。
JEIの扱い方を少しづつ模索しながらも理解し始めてきた。

### 2023年10月~2023年12月
かなり忙しくなってきたが、なんとか開発を継続。
少しずつコードに慣れてきた(やっと)。
勉強は継続。

### 現在
GitHub開始とともに。Qiitaも利用開始(ただの忘備録ではあるが)。


# 大事なこと
調べながら不具合を探したり(泣き寝入りすると後々さらに悪化する)、それについて調べていくことは正直滅茶苦茶大変です。
そこで、アドバイスというか大切なことをまとめます。

・何をやりたいかという目的を常に持ちましょう
・あきらめずに調べましょう
・誰かに頼ることは恥ではありません

特に3つ目が重要です。
我々は一人ではありません。一人で考えていくといずれ壁にぶつかることがあります。容易には越えられない場合もあります。その問題を無理に抱え込むと折れてしまいますので気を付けていきましょう。

# おわりに
あくまで私の意見ではありますが、参考にしていただければ幸いです。
Rubyの基本（制御構造）

# if文による条件分岐
下記の例の「sample②」のように、実行したい処理を前に、条件を後に書くことも可能。
簡単な条件の処理であれば②の方がよりシンプルに書くことができる。
```ruby:sample_01.rb
score = gets.to_i

# sample①
if score >= 90
    puts "A"
end

# sample②
puts "A" if score >= 90
```

# case文による条件分岐
数値の条件は「>」などの記号だけでなく、「..」で指定することも可能。
```ruby:sample_02.rb
score = gets.to_i

case score
when 90..100
  puts "A"
when 70..89
  puts "B"
else
  puts "C"
end
```
# for文による条件分岐
繰り返す回数が決まっている場合はfor文が使える。
forの後に書く変数（「i」でなくても良い）はスコープ内で使用できる。
```ruby:sample_03.rb
# 「Hello」を３回表示
for i in 1..3
  puts "Hello"
end

# 九九の９の段の答えを表示
for num in 1..9
  puts 9 * num
end
```
[TypeScript]Record型

## はじめに
今回はRecord型の使い方や、どのような場面で使用できるかについて書いていきます。

## サンプルコード

以下がサンプルコードになります。

```ts
type Prefectures = "Tokyo" | "Chiba" | "Saitama" | "Shiga";

type Covid19InfectionInfo = {
  kanji_name: string;
  confirmed_cased: number;
  large: string;
};

const Covid19Japan: Record<Prefectures, Covid19InfectionInfo> = {
  Tokyo: { kanji_name: "東京", confirmed_cased: 1900, large: "260km" },
  Chiba: { kanji_name: "千葉", confirmed_cased: 200, large: "230km" },
  Saitama: { kanji_name: "埼玉", confirmed_cased: 500, large: "200km" },
  // エラー↓
  Shiga: { kanji_name: "滋賀", confirmed_cased: 70},
  //  エラー Gunma: { kanji_name: "滋賀", confirmed_cased: 70, large: "300km" },
};

console.log(Covid19Japan);
// 出力↓
// {
//     Tokyo: { kanji_name: '東京', confirmed_cased: 1900, large: '2000km' },
//     Chiba: { kanji_name: '千葉', confirmed_cased: 200, large: '2000km' },
//     Saitama: { kanji_name: '埼玉', confirmed_cased: 500, large: '2000km' }
// }
```

## Record型を使う場面
### オブジェクトのマッピング
Record型は、特定の型のキーに対して特定の型の値をマッピングする場合に便利です。例えば、文字列をキーとして特定の型のオブジェクトをマッピングする場合に使用できます。
```ts
// ユーザーの名前をIDにマッピングする例
type UserID = string;
type User = { name: string };

const users: Record<UserID, User> = {
    'user1': { name: 'Alice' },
    'user2': { name: 'Bob' },
    // 他のユーザー
};
```
### オブジェクトの形状を制限する
特定の形状を持つオブジェクトのセットを表現するために、Record型を使用することができます。
```ts
// オブジェクトの形状を制限する例
type Car = {
    make: string;
    model: string;
    year: number;
};

const cars: Record<string, Car> = {
    'car1': { make: 'Toyota', model: 'Camry', year: 2020 },
    'car2': { make: 'Honda', model: 'Accord', year: 2019 },
    // 他の車
};
```

### 動的なキーのマッピング
Record型は、実行時に動的にキーを追加または削除する必要がある場合に役立ちます。

```ts
// 動的なキーのマッピングの例
const scores: Record<string, number> = {};
scores['Alice'] = 95;
scores['Bob'] = 87;
// 他のユーザーのスコアを追加
```
# 最後に
他にも色々な記事を書いているので、よければ読んでいってください、、、

https://qiita.com/hukuryo/items/97797a91d7e2ee0bcabc

https://qiita.com/hukuryo/items/2c07c52ff3386d5d75b9

https://qiita.com/hukuryo/items/ebeb26823f944f143b11
sqlの文脈での「dumpファイル」と一般的な文脈での「dumpファイル」

### 初めに
業務中に「dump」「dumpファイル」「dumpする」などという言葉が行き交い、またそれが使われる場面にも差異があり、なんとなくsplに関するなにかのファイルという認識しかなかったため、改めて調べてみました。

### 結論
**・SQLの文脈での「dumpファイル」や「dumpする」**
→データベース内のテーブル構造とデータを特定の形式（通常はSQLのクエリ形式やCSV形式）でファイルに保存したものを指すということでした。
これはデータベースのバックアップ、データの転送、または復元の際に使用されるみたいです。

**・一般的な文脈での「dumpファイル」や「dumpする」**
→通常、メモリの状態を保存するためのバイナリファイルを指すみたいです。問題のトラブルシューティングやデバッグのために保存するようです。

### まとめ

sqlの文脈で言われたら、DBの情報をまるっとファイルに保存することまたは保存したファイルを指し、他の文脈で言われたら、なにかしらのシステムの情報を保存すること、または保存したファイルを指す。

ダンプ（Dump）とは、コンピュータの世界では、コンピュータに保存された情報を複製しディスクなど別の場所に格納する行為を意味する。


[参考サイト]
・https://e-words.jp/w/%E3%83%80%E3%83%B3%E3%83%97.html

[単語]
・バイナリファイル→テキストファイル以外のファイルのこと。
selectedUserがundefinedになる [  Reactに入門した人のためのもっとReactが楽しくなるステップアップコース完全版  ]

# はじめに
どうもこんにちは！僕は現在1ヵ月本気の技術力向上を目指している現役高校生1年生(@shunii )です！とあるUdemyの講座にしたがってReactのアプリを開発していたところ躓いたところがあったので共有します。

#### 対象読者
今回は下記の講座を受けている前提で話を進めさせていただきます。

https://www.udemy.com/course/react_stepup/?couponCode=ST22FS22724

# 問題
selectedUser(選択したユーザーの名前)が表示されない！

#### 筆者の状況
- ユーザーカードをクリックした際にidを取得することはできている
- console.logで確認するもののselectedUserはundefinedである
- usersをconsole.logで確認すると、空配列([ ])になっている
- たまにselectedUserが表示される
<br/>

```jsx:UserManagement.tsx
export const UserManagement: FC = memo(() => {
    const { getUsers, users, loading } = useAllUsers();
    const { isOpen, onClose, onOpen } = useDisclosure();
    const { onSelectUsers, selectedUser } = useSelectUsers();
    const { loginUser } = useLoginUser();
    
    console.log(selectedUser);  //ここ

    const onClickUser = useCallback((id: number) => {
        onSelectUsers({ id, users, onOpen });
    }, []);

    useEffect(() => {
        getUsers();
    }, []);

    return //...以下省略
});
```

# 解決策
結論
<font color="red">**onClickUserでuseCallbackの第2引数に *users* を追加する**</font>

原因としては、usersを設定していない(要するにgetUsersが完了する前の)段階でonClickUser関数を生成していたので、usersが空配列(初期値)となってしまっていました。それに加え、useCallbackの第2引数の配列を空にしていたため、usersが設定されても新しく関数が再生成されることはありません。

# 検証
最初に示した通り、**なぜか *selectedUser* がたまに表示される**という現象が起こったのでそれを解明しておきたいと思います。

以下のようにconsole.logを仕込んでみます。
```jsx:UserManagement.tsx
export const UserManagement: FC = memo(() => {
    const { getUsers, users, loading } = useAllUsers();
    const { isOpen, onClose, onOpen } = useDisclosure();
    const { onSelectUsers, selectedUser } = useSelectUsers();
    const { loginUser } = useLoginUser();

    console.log("============ aaaaaaa  ============");  //追加
    console.log(selectedUser);  //ここ

    const onClickUser = useCallback((id: number) => {
        onSelectUsers({ id, users, onOpen });
    }, []);

    useEffect(() => {
        getUsers();
    }, []);

    return //...以下省略
});
```

以下のように検証します
console.logの中身だけを適当に変更してみます。すると、selectedUserがしっかりととれていることがわかります。
![ChakraUIapp.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3554025/bcdc9804-73a5-3129-ba96-32b3c3b5fdd7.gif)

# なぜたまに表示されるのか
たまに表示されたのは、
> <font color="red">**親コンポーネントで再レンダリングが走った**</font>

ということが原因であるとわかりました。
さきほど[検証](#検証)でconsole.logの中身を変更するだけでselectedUserを取り出すことに成功しました。

これはUserManagementコンポーネントで変更(console.logの)が検出されたために再レンダリングが走り、それによってその配下にあるonClickUser関数が再生成されたからです。再生成時にはusersが既に設定済み(ある程度時間がたっているから)なのでうまく実行できます。

# 終わりに
今回の問題は自分だけで解決することができませんでしたが、Reactの再レンダリングの条件の復習などを兼ねることができたためよかったです！

# About Me
- X(Twitter)

https://twitter.com/shunii_hack