OmniAICreator/Qiita-1.07M huggingface dataset:
MuleSoft Composer  について知る

[MuleSoft Composerまとめに戻る](https://qiita.com/Keiji_otsubo/items/ef2fdd213551168c360b)

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

https://trailhead.salesforce.com/ja/content/learn/modules/mulesoft-composer-basics/get-to-know-mulesoft-composer?trail_id=get-started-with-mulesoft-composer

# MuleSoft Composer の機能

MuleSoft Composer を使用すると、インテグレーション作業を簡単に行えるようになります。経歴に関係なく、どのユーザーでもフローを使用して次の作業を実行できます。

+ 特定のイベントやスケジュールに基づいてデータを抽出し、あるシステムから別のシステムにデータをマップする。
+ 異なるシステムのデータを同期する。
+ 条件に基づくフローを使用して、データの絞り込みとルーティングを行う。
+ レコードのコレクションをループ処理し、各レコードで特定のアクションを実行する。
+ フローのテスト、実行、監視、管理、トラブルシューティングを行う。


https://trailhead.salesforce.com/ja/content/learn/modules/mulesoft-composer-basics/explore-mulesoft-composer?trail_id=get-started-with-mulesoft-composer

# MuleSoft Composer を起動する

MuleSoft Composer はスタンドアロンアプリケーション、または Salesforce 用 MuleSoft Composer と呼ばれる Salesforce 組織の認証済みユーザー用のアプリケーションとして提供されています。スタンドアロンバージョンをインストールする必要はありませんが、Salesforce 用 MuleSoft Composer はシステム管理者にインストールしてもらう必要があります。

:::note alert
Trailhead Playground では MuleSoft Composer は使用できません。
:::

# フロー作成タスク

次のフロー作成タスクを実行して、MuleSoft Composer を使用してフローを簡単かつ効率的に作成します。 

|タスク	|説明|
|:------------------------------|:-----------------------------------|
|1.計画||
|2.設計とテスト|次に、MuleSoft Composer を使用し、関連する接続、トリガー、If/Else ブロック、分岐、For Each ブロック、アクションを追加、設定してフローを作成します。|
|3.アクティブ化|フロー全体をテストしたら、設計したインテグレーションタスクの実行を開始できるようにアクティブ化します。|
|4.監視とトラブルシューティング|フローは有効になると、バックグラウンドで継続して実行されます。フローの実行に問題がある場合は、MuleSoft Composer の [Flow Detail Page (フローの詳細ページ)] に情報が表示されます。 |
|5.非アクティブ化|時間が経つにつれて、フローの内容が意図した目的に合わなくなった場合は、非アクティブ化します。|


+ [MuleSoft Composer のインストールと設定](https://trailhead.salesforce.com/ja/content/learn/modules/mulesoft-composer-install-and-config?trail_id=get-started-with-mulesoft-composer)

+ [MuleSoft Composer のフロー](https://trailhead.salesforce.com/ja/content/learn/modules/mulesoft-composer-flow?trail_id=get-started-with-mulesoft-composer)

https://dataweave.mulesoft.com/learn/tutorial/1.1-What_is_DataWeave%3F

https://docs.mulesoft.com/jp/general/


# APIプラットフォーム

+ [マイクロサービス開発・API連携の課題を解決する「統合APIプラットフォーム」MuleSoftを解説](https://www.dx-digital-business-sherpa.jp/blog/mulesoft)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/2995e853-118f-ed25-df60-30b6754b453d.png)
KongのRoute Transformer Advanced Pluginでアクセス先を変更する

Kong Gatewayには[Route Transformer Advanced Plugin](https://docs.konghq.com/hub/kong-inc/route-transformer-advanced)というものがある。
これの挙動を調べた時のメモ。
この記事は自分用のメモなので、説明は少なめ。　
## Route Transformer Advanced Pluginとは
Serviceの宛先を無視して、別のパスに転送してくれるプラグイン。
それだけだとあまり価値がないように見えるが、[テンプレート](https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/how-to/templates/)と組み合わせることで柔軟なパス変換が可能になる。

例えば、APIのリクエスト先が`/id/<ユーザID>`みたいになっている時、APIの仕様が変わって`/user/<ユーザID>/id`となったとする。
この場合なケースでも、Route Transformer Advancedを使うとクライアント側はアクセス先を変更せず、展開済みのServiceも変更せずにアドレスの書き換えを簡単に行う事が出来る。

## 前提
以下が利用できるようになっているものとする。

- Kong Gateway
- deck CLI

## 動作確認
ここでは先程述べたような、クライアントが`/id/<ユーザID>`にアクセスした時、実際は`/user/<ユーザID>/id`を参照するように変えてみる。

Service、Routeを作成する。
```yaml
cat <<EOF | deck gateway sync -
_format_version: "3.0"
services:
- name: example-service
  host: httpbin.org
  port: 443
  protocol: https
  routes:
  - name: example-route
    paths:
    - ~/id/(?<user_id>[0-9]+)
    protocols:
    - http
    - https
    strip_path: true
EOF
```
Serviceはhttpbin.orgを使い、アクセスした際にどのようなリクエストを投げたかが分かるようにする。
Pathに`~/id/(?<user_id>[0-9]+)`を指定しているが、これは前述の[テンプレート](https://docs.konghq.com/hub/kong-inc/request-transformer-advanced/how-to/templates/)を使うために記載している。
`?<user_id>`でuser_idというグループ名を定義し、`[0-9]+`でIDを取得している。
なお、3.0以降は正規表現を指定する場合はPathの先頭が`~`で始まる必要がある（[CHANGELOG](https://github.com/Kong/kong/blob/master/CHANGELOG.md#300)）。

次にRouteにRoute Transformer Advancedプラグインを適用する。
ここではKong Managerから設定する。
RouteからPluginを選択して以下のRoute Transformer AdvancedをEnableにする。
![20240829141309.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/547981/6e34d2cb-f6f7-5413-8357-708cc54e870a.png)

設定時、設定項目としては以下がある。
- **Host**: 転送先アドレス
- **Path**: 転送先パス
- **Port**: 転送先ポート
- **Instance Name**: Kong内での管理用の名前
- **Tags**: Kong内での管理用のタグ
- **Escape Path**: Routeのパスに`" "`などがあれば`"%20"`のようにエスケープする

ここでは以下のように設定する。
- **Path**: `/anything/user/$(uri_captures.user_id)/id`
- **Instance Name**: `httpbing-route-transfer`


Pathの`/anything`でhttpbin.orgでリクエストの内容を表示するサービス([https://httpbin.org/anything](https://httpbin.org/anything))を参照させている。
それ以下のパスはサービスには影響しないため、どのようなパスを指定しても基本的には問題ない。
`/user/$(uri_captures.user_id)/id`が変換後のパスであり、`$(uri_captures.user_id)`でRouteのPathで正規表現でグループ化したuser_idを指定するようにしている。
その他の項目はデフォルト値であればRouteの設定を引き継ぐので、特に指定する必要はない。

設定後、実際にアクセスして意図通り変換されているか確認する。
```sh
curl "localhost:8000/id/0123"
```
結果は以下となった。
```json
：（省略）
  "url": "https://localhost/anything/user/0123/id"
：（省略）
```
意図通りのパスにアクセスしたことが確認できた。
【Next.js】<> (react fragment)

reactでdomを生成する時、1つ以上タグで構成することができないため、<div>などで囲う必要がある。

```jsx
import React from "react";

const BlogCard = () => {
  return (
	  <div> // これ！
		  <h1>HOGE</h1>
		  <p>hogehoge</p>
	  </div>
  )
}

export default BlogCard;
```

ただ、こうすると無駄にdivタグでネストすることになる

こういう時はreact fragmentで対処する

※Reactをimportする「import React from "react"」が必要

```jsx
import React from "react";

const BlogCard = () => {
  return (
	  <React.Fragment> // これ！
		  <h1>HOGE</h1>
		  <p>hogehoge</p>
	  </React.Fragment>
  )
}

export default BlogCard;
```

こうすると無駄なdivがなくレンダリングされる

React.Fragmentは省略も可

```jsx
import React from "react";

const BlogCard = () => {
  return (
	  <> // これ！
		  <h1>HOGE</h1>
		  <p>hogehoge</p>
	  </>
  )
}

export default BlogCard;
```
【基本情報・Chapter7】ハードディスクとその他の補助記憶装置

<font color="DarkOrange">**今日は○○に関する知識をまとめます。
お気づきの点がございましたら、ご指摘いただけると幸甚です。ᐖ**</font>


## <font color="DarkOrange">ハードディスクの構造と記録方法</font>

#### ハードディスク
*hard disk drive、HDD*
磁性体を塗布した円盤を高速回転させ、磁気ヘッドを移動することで、情報を記録し読み出す補助記憶装置の一種である。

#### プラッタ
*platter*　盘片
プラッタはハードディスク内に収納されている磁性体を塗布した金属製やガラス製のディスクのこと。大容量ハードディスクでは1台に複数枚のプラッタが内蔵されている。
磁盘一般是由多个盘片组成的，而每个盘片都有上下2个盘面，双面都可以存储数据
#### セクタ
*sector*　扇区
磁気ディスクの記憶領域の最小単位の名称。
セクタが複数集まったものをブロック*Block*(块)と呼ぶ。
#### トラック
*track*　磁道
セクタが同心円状に集まった単位。
#### シリンダ
*cylinder*　柱面
トラックが円筒状に集まった単位。

　　　<img width="500" src="https://www.koeki-prj.org/~madoka/2012/img/hdd.png">



#### ハードディスクの記憶容量
<!--
计算方法介绍
-->
$$
総容量＝シリンダ数×トラック数×セクタ数×１セクタのバイト数
$$

#### クラスタ
*cluster*　簇
<!--
用不了的领域要浪费
-->
記憶装置の記録単位で「セクタ」がいくつか集まったもの
クラスタはファイルに割り当て可能なディスクスペースの最小論理単位である。
クラスタが大きく設定されているファイルシステムで小さなファイルを格納すると、ディスクスペースを無駄にすることになる。


#### データへのアクセスにかかる時間
アクセス時間（access）＝
シーク時間（seek,位置決め）
+サーチ時間（search,回転待ち）
+データ転送時間





## <font color="DarkOrange">フラグメンテーション</font>
#### フラグメンテーション・断片化（だんぺんか）
*fragmentation*
ハードディスクなどのストレージ（外部記憶装置）にファイルの書き込み・消去を繰り返していくと、連続した大きな空き領域が次第に少なくなり、新たに記録するファイルが小さな断片に分割されて記録されるようになってしまう。


#### デフラグメンテーション・デフラグ
*defragmentation*　碎片整理
コンピュータのファイルシステムにおけるフラグメンテーションを解消すること。



## <font color="DarkOrange">RAID</font>
#### RAID
*Redundant Arrays of Inexpensive Disks*　レイド
複数のハードディスクを組み合わせることにより　1台の仮想的なハードディスクとして認識させて冗長性を向上させる技術のこと。


#### RAIDの代表的な種類とその特徴
- **RAID 0**
*striping*　ストライピング
複数（2台以上）のハードディスクに同時に分散して読み書きを実行し、アクセスの高速化を実現できる。
- **RAID 1**
*mirroring*　ミラーリング
複数（2台以上）のハードディスクに同じデータを書き込みことでハードディスクの耐障害性を実現できる。
- **RAID 5**
データからパリティ（誤り訂正符号）を生成し、3台以上のハードディスクに分散して書き込む。1台のHDDに障害発生した場合でも、残りのHDDにより継続利用することが可能になる。

## <font color="DarkOrange">他の補助記憶装置</font>

#### 光ディスク
*Optical disc*
樹脂等で作られた厚さ数ミリ程度の円盤の表面に、微細な凹凸を形成する等の方法により、情報を記録するための記録媒体である。



- **CD**
*Compact Disc*
<!--
定义，英语
-->
直径12cm、または8cmの円盤に音や画像などのデータをデジタル化して記録したもののこと。

| CD | 特徴 |
|:-:|:-:|
| CD-ROM  | *Compact Disc Read only memory*<br>読込専用、再生専用型 |
| CD-R  |  *Compact disc-recordable*<br>一度だけ書き込める、追記型 |
|  CD-RW |  *Compact Disc-Rewritable* <br>何度でも書き換える、書き換え可能型|


- **DVD**
*Digital Versatile Disc*
<!--
定义，英语
-->
デジタル化したデータの記録媒体である光ディスクの一種。ＣＤと同じ直径一二センチで、映像・音声情報などを大量に記録できる。

| DVD | 特徴 |
|:-:|:-:|
| DVD-ROM  | *DVD Read Only Memory*<br> 再生専用型 |
|  DVD-R |  *DVD Recordable* <br>追記型|
| DVD-RW  |  *DVD ReWritable* <br>書き換え可能型|
|  DVD-RAM |  *DVD Random Access Memory* <br>書き換え可能型|






#### 光磁気ディスク
*magneto-optical disk, MO*
レーザー光と磁気を用いてデータの読み書きを行うもの

#### 磁気テープ
*Magnetic tape*
テープ状のフィルムに、磁気を使って読み書きを行う、カセット型の記憶媒体。
**テープストリーマ**とは、磁気テープに記録する方式の補助記憶装置のことである。

#### SSD
*Solid State Drive*　固态硬盘
HDDは回転する円盤に磁気でデータを読み書きしているが、SSDはUSBメモリーと同じように内蔵しているメモリーチップにデータの読み書きをしている。
- **メリット**
衝撃による故障リスクが低い
読み書きの速度が非常に速い
動作音が静か
サイズが小さく軽い
スティック型などデザインの自由度が高い
- **デメリット**
最大容量が少ない
大容量になると容量単価が高い



***
<font color="DarkOrange">**ここまで読んでくれて
お疲れ様です！
ありがとうございました！(⁎ᵕᴗᵕ⁎)**</font>
【Next.js】コンポーネントに色々渡す


propsで色々渡してボタンのコンポーネントをつくる

### コンポーネント
- コンポーネントは@/feature/ディレクトリで管理する
- tsxもスタイルもそこに格納する

```
/feature/
└ Btn
　└ index.tsx
　└ index.module.scss
```

# コンポーネント（index.tsx）
- href
- リンク内テキスト
- 付与クラス
```
import React from "react";
import styles from '@/features/Btn/index.module.scss'
import Link from 'next/link'

const Btn = (props: { href: string; addClass: string; txt: string }) => {
  return (
    <Link href={props.href} legacyBehavior>
      <a className={` ${props.addClass} ${styles.Btn}`}>{props.txt}</a>
    </Link>
  )
}

export default Btn;
```

### 親
```
import React from "react";
import PrimaryBtn from "@/features/primaryBtn/index";

const Parent = () => {
  return (
    <div className={styles.parent}>
      <h1 className={styles.parent__head}>タイトル</h1>
      <PrimaryBtn href="/hoge" txt="ボタンだよ" addClass={styles.parent__cv} />
  )
}

export default Parent;
```
大きなディスプレイは生産性を上げるらしいのでMacBook Pro Max 16インチを買ってみた



# 大きなディスプレイ

書籍「脳の外で考える」によると大きなディスプレイは生産性を上げるらしい。

逆に小さなディスプレイを使っていると知的リソースが枯渇してしまうらしい。

今までは携帯性を重視して14インチのものを使っていたが、思いきってMacBook Pro 16インチを買ってみた。

もしこれで生産性が10%でも上がれば、時間は10%程度浮くことになる。であれば安い買い物のはずだ。

# ほぼ究極のスペック

以前に Intel CPU版のMacBookからAppleシリコン CPU版に買い換えた時は、スペックアップの効果に驚いた。

どうせならこの機会に最高のスペックまで試してみたいと思い、メモリも今の倍の64GBを選択した。

MacBook Pro Max 16インチ
16コアCPU
メモリ 64GB

値段は67万4800円。

# 値段の元は取れるか？

たとえばこれで生産性が5%でも上がれば、実質的に仕事時間の30分程度は浮くことになる。

自分の時給単価によるが、これは長期的に見れば安い買い物だろう。

# そして使い始める

16インチのMacBookは14インチに比べると、何もかもがなかなかの存在感だ。

たった2インチの差が実はでかい。

# ディスプレイの体感

ディスプレイは体感、かなり広い。

数値的には2インチの違いだが、実感1.5倍ぐらい広くなったような感覚がする。

# 情報量の多さ

これだけディスプレイが広いと、いちどに多くの情報が表示されすぎて、むしろ意識が混乱するのではないか？という危惧を感じる。

だが使い始めて1日も経つ頃には目が慣れて来て「もう14インチには戻れない」という感覚になって来た。

# 文字サイズ

文字のサイズがやや小さく見えるが、たぶん絶対的なフォントサイズは変わっておらず、相対的な感じ方の違いだろうか。

# キーボードの位置

16インチを買う時はこれが最大のネックだった。

14インチよりも、キーボードの位置がが一列分ほど奥に遠いのだ。

果たして無理をせずに指が届くのだろうか。指が届きにくい問題があると、70万円が不意になってしまう。

いざ使い始めてみると、最初の数時間は「指が届きにくい」「肩が凝りそう」と思ったのだが、その日の間中に体が慣れて来たような気がする。

まるで問題なしなのでは？

# 重さ

もちろん16インチは14インチよりも重い。

だが僕は最近重いものを持ち慣れて来たので、問題ない。

PCを入れているリュックの紐をしっかりと握って歩けば問題なしだ。

# 充電器も重いのでは？

MacBook Pro 標準の充電器はなにやら重そうだが、もっと軽いタイプの充電器も楽勝で使えた。
Chromeだけネットに接続できないときの対処法

# 概要
Windows10で、ブラウザのGoogle Chromeだけネットに繋がらなくなる現象があったので、解消方法をまとめました。

# 現象
突然Google Chromeだけネットに繋がらなくなりました。他のブラウザやアプリに関しては問題無く繋がっていました。

# 解消方法
1. コマンドプロンプトを管理者権限で立ち上げます
1. コンソールに「netsh winsock reset」というコマンドを入力し、実行します
1. 実行後、コンソール画面にPCの再起動が必要という旨のメッセージがでるため、PCを再起動します
1. 再起動後、Chromeを起動すると、無事ネットに繋がりました

# コマンドの意味
- **netsh**
「Network Shell」の略で、ネットワーク構成の表示や変更を行うことができるコマンドです。ネットワーク全般を制御したい際に使用するコマンドのイメージです。

- **winsock**
「Windows socket」の略で、ネットワークに接続されたソフトウェア同士で通信を行うためにあるAPIです。

- **reset**
文字通り、リセットするコマンドです。

まとめると、winsockをresetコマンドで初期化しているイメージです。

# 参考サイト
 - [Windows10でChromeだけネットが繋がらなくなった場合の対処法](http://macruby.info/windows-10/windows10-chrome-internet-problem.html)
- [WindowsソケットAPI（Winsock）](https://fineproxy.org/ja/wiki/windows-sockets-api-winsock/)
- [「Winsock」とは？](https://support.lenovo.com/jp/ja/solutions/ht060569)
dbtの新機能および関連ツールまとめ

## はじめに

データエンジニアリングの分野は急速に進化しており、DBT（Data Build Tool）はその中心的なツールとして、多くのデータチームに採用されています。DBTはSQLベースのデータモデリングを簡素化し、データの変換プロセスを効率的に管理できるようにする一方で、さらに高度なデータ品質保証と運用性向上の機能を提供しています。

この記事では、DBTの最新機能「Contract」「Unit Test」「Exposures」「Metrics」「Elementary」に焦点を当て、それぞれの概要と参考になる記事をまとめています。

## DBT Contract

DBT Contractは、対象のモデルのデータ型や制約が定義通りであるかを保証するための機能です。具体的には、モデルの`data_types`や`constraint`を定義し、DBTの実行（`dbt run`）時にそれらの条件を満たしているかをチェックします。もし満たしていない場合、DBTはエラーを返し、テストの段階に進む前に問題を検出できる点が特徴です。これにより、DBT Testでのテスト前に不適切なデータがパイプラインに流れ込むのを防ぎます。

ただし、Snowflakeを使用する場合、`constraint`に設定できるのは`not_null`制約のみである点に注意が必要です。

https://dev.classmethod.jp/articles/dbt-try-model-contracts/


## DBT Unit Test

DBT Unit Testは、これまでのDBT Testに追加された新機能で、変換後のデータが定義された制約を満たしているかどうかをチェックします。DBT Testは一般的に変換後のデータ全体を対象にしていますが、Unit Testはより細かな粒度でデータ変換の各ステップを検証します。

この新機能はDBTバージョン1.8で導入され、テストデータはYAMLファイルとして定義するか、CSV形式で保存しておくことができます。これにより、特定のユースケースに対応した柔軟なテストが可能になります。


https://dev.classmethod.jp/articles/dbt-try-unit-tests/


## DBT Exposure

DBT Exposureは、外部で利用されているDBTモデルやデータセットを管理するための機能です。特定の利用用途を`exposure`として定義し、それがどのモデルに依存しているかを明確にすることで、exposureの管理が可能になります。


https://dev.classmethod.jp/articles/dbt-exposures/

通常、`exposure`の管理は手作業で行われますが、以下の記事ではTableauのAPIを活用することで、依存するテーブルを自動で列挙し、`exposure`を自動更新するスクリプトを作成されています。これにより、管理の負担が大幅に軽減されます。


https://www.yasuhisay.info/entry/2023/10/08/001623


## DBT Metrics

DBT Metricsは、従来のDBTメトリクス機能が廃止され、新たに`MetricFlow`として統合される予定です。これにより、TableauのSemantic Layerと連携し、コードベースでメトリクスを管理できるようになります。これにより、Tableauで計算フィールドを利用せず、コードでメトリクスを一元管理することが可能になります。

https://qiita.com/zackey2/items/a64bf79eefc789f12521

https://dev.classmethod.jp/articles/dbt-semantic-layer-ga-with-metricflow/

https://dev.classmethod.jp/articles/dbt-semantic-layer-refer-from-tableau/


## DBT Elementary

DBT Elementaryは、DBT向けのデータ監視・モニタリングツールであり、DBT Testの結果をさらに強力に補完する機能を提供します。例えば、DBT Testの結果を一覧できるダッシュボードをHTML形式で生成したり、その結果をSlackなどに通知することができます。また、異常値検出のためのテスト機能も提供しており、データの品質管理をより包括的に行うことが可能です。

https://zenn.dev/kyami/articles/f5ded861b6f56s

https://www.yasuhisay.info/entry/2023/09/14/095411

https://engineering.dena.com/blog/2024/04/dbt-test-and-elementary/


## DBT Osmosis

DBT Osmosisは、DBTプロジェクトのYAMLファイルを自動編集するツールです。このツールを利用することで、煩雑なYAMLファイルの編集作業を自動化し、プロジェクトの管理を容易にします。

https://zenn.dev/koo_0208/articles/202312_dbt_osmosis

## おわりに

DBTの新機能を活用することで、データの品質保証と運用効率を大幅に向上させることができます。それぞれの機能を理解し、適切に組み合わせることで、DBTを最大限に活用できるようになるでしょう。
Rails 7.2 (Hotwire) でDeviseのログアウトリンクを作成

最近はRailsのアプリ開発から少し離れていましたが、Rails 7あたりからHotwireやYJITなどおもしろそうな動きもあり、またRailsに興味を持ちはじめています。

Rails 7.2のアプリでDeviseのログアウトリンクを作成したとき、Hotwireに対応する方法がわからなかったのですが、以下の情報を見つけました。

https://dev.to/spaquet/rails-7-devise-log-out-d1n

https://discuss.hotwired.dev/t/simple-method-delete-with-confirm/4834

開発中のアプリには以下のように記述して、以前と同様にログアウトができるようになりました。

```erb
<%= link_to destroy_user_session_path,
      data: { turbo_method: :delete, turbo_confirm: t("views.confirm_sign_out") },
      class: "dropdown-item" do %>
  <i class="bi bi-arrow-bar-right"></i>
  <%= t("views.sign_out") %>
<% end %>
【firebase,ts,vite】ReferenceError: process is not defined

# はじめに
firebaseの初期設定でエラーが出たのでその対処法を書いていきます。

# 問題
firebaseの初期設定を終え、サーバを立ち上げると画面が真っ白になりコンソールを確認すると以下のエラーが出る。
```
Uncaught ReferenceError: process is not defined
```
以下エラー発生時の.envとfirebase.ts
```.env
REACT_APP_FIREBASE_API_KEY="XXXXX"
REACT_APP_FIREBASE_AUTH_DOMAIN="XXXXX"
REACT_APP_FIREBASE_PROJECT_ID="XXXXX"
REACT_APP_FIREBASE_STORAGE_BUCKET="XXXXX"
REACT_APP_FIREBASE_MESSAGING_SENDER_ID="XXXXX"
REACT_APP_FIREBASE_APP_ID="XXXXX"
REACT_APP_FIREBASE_MEASUREMENT_ID="XXXXX"
```
```firebase.ts
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";


const firebaseConfig = initializeApp({
  apiKey: process.env.REACT_APP_FIREBASE_API_KEY,
  authDomain: process.env.REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: process.env.REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: process.env.REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: process.env.REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: process.env.REACT_APP_FIREBASE_APP_ID,
  measurementId: process.env.REACT_APP_FIREBASE_MEASUREMENT_ID
});


export const auth = getAuth(firebaseConfig);
export const db = getFirestore(firebaseConfig);
```

# 原因と解決策
環境変数の読み込み方がviteでは少し異なるため発生していたエラーでした。今回の場合だと以下の2点を修正する必要があります。supabaseを使う場合でも同じです。
- 環境変数を読み込む際はprocess.envではなくimport.meta.envを使う
- 環境変数名の前にVITEをつける

以下修正されたコードです。
```.env
VITE_REACT_APP_FIREBASE_API_KEY="XXXXX"
VITE_REACT_APP_FIREBASE_AUTH_DOMAIN="XXXXX"
VITE_REACT_APP_FIREBASE_PROJECT_ID="XXXXX"
VITE_REACT_APP_FIREBASE_STORAGE_BUCKET="XXXXX"
VITE_REACT_APP_FIREBASE_MESSAGING_SENDER_ID="XXXXX"
VITE_REACT_APP_FIREBASE_APP_ID="XXXXX"
VITE_REACT_APP_FIREBASE_MEASUREMENT_ID="XXXXX"
```
```firebase.ts
import { initializeApp } from "firebase/app";
import { getFirestore } from "firebase/firestore";
import { getAuth } from "firebase/auth";


const firebaseConfig = initializeApp({
  apiKey: import.meta.env.VITE_REACT_APP_FIREBASE_API_KEY,
  authDomain: import.meta.env.VITE_REACT_APP_FIREBASE_AUTH_DOMAIN,
  projectId: import.meta.env.VITE_REACT_APP_FIREBASE_PROJECT_ID,
  storageBucket: import.meta.env.VITE_REACT_APP_FIREBASE_STORAGE_BUCKET,
  messagingSenderId: import.meta.env.VITE_REACT_APP_FIREBASE_MESSAGING_SENDER_ID,
  appId: import.meta.env.VITE_REACT_APP_FIREBASE_APP_ID,
  measurementId: import.meta.env.VITE_REACT_APP_FIREBASE_MEASUREMENT_ID
});


export const auth = getAuth(firebaseConfig);
export const db = getFirestore(firebaseConfig);
```
これで正常に表示されるようになりました。

:::note warn
補足
もしgithub acitonsなどでデプロイしている場合はgithubに登録している環境変数名とcicdのymlファイル内の環境変数名も修正してあげないと環境変数が読み込まれないので注意です。
:::


# おわりに
vite環境でjestを使った際はimport.metaを使えなかった記憶があったのですが、今回はなぜかテストが通ったのでこのままで行こうと思います。

https://qiita.com/bisketoriba/items/93163a95eac46802e297
# 参考
https://stackoverflow.com/questions/76090901/uncaught-referenceerror-process-is-not-defined-in-react-npm-run-dev-using-vit

https://vitejs.dev/guide/env-and-mode.html
Java Gold メソッド逆引き早見表 Optional型を返すメソッド


Optional型を返すメソッド一覧


| メソッド名 | 宣言されたクラス・インターフェイス | 戻り値の型 | メソッドの動作 | 
|------------|-----------------------------|--------------|-----------------|
| `Optional.of(T value)` | `Optional` | `Optional<T>` | 指定した非 `null` 値を持つ `Optional` を返す。`null` 値が指定されると `NullPointerException` がスローされる。 | 
| `Optional.ofNullable(T value)` | `Optional` | `Optional<T>` | 指定した値が `null` でない場合はその値を持つ `Optional` を返し、`null` の場合は空の `Optional` を返す。 | 
| `Optional.empty()` | `Optional` | `Optional<T>` | 空の `Optional` を返す。 |
| `Optional.flatMap(Function<? super T, ? extends Optional<? extends U>> mapper)` | `Optional` | `Optional<U>` | 値が存在する場合、指定された `Function` によって生成される `Optional` を返す。値がない場合は空の `Optional` を返す。 |
| `Optional.filter(Predicate<? super T> predicate)` | `Optional` | `Optional<T>` | 値が存在し、指定された述語が `true` を返す場合、その値を含む `Optional` を返す。述語が `false` の場合や値が存在しない場合は空の `Optional` を返す。 |
| `Optional.or(Supplier<? extends Optional<? extends T>> supplier)` | `Optional` | `Optional<T>` | 値が存在する場合はその値を持つ `Optional` を返し、存在しない場合は指定されたサプライヤが提供する `Optional` を返す。 |
| `Stream.findFirst()` | `Stream` | `Optional<T>` | `Stream` 内の最初の要素を返す。要素がない場合は空の `Optional` を返す。 |
| `Stream.findAny()` | `Stream` | `Optional<T>` | `Stream` 内のいずれかの要素を返す。要素がない場合は空の `Optional` を返す。 |
| `Stream.reduce(BinaryOperator<T> accumulator)` | `Stream` | `Optional<T>` | ストリームの要素を累積し、単一の結果を返す。要素がない場合は空の `Optional` を返す。 |
| `Stream.min(Comparator<? super T> comparator)` | `Stream` | `Optional<T>` | ストリーム内の最小値を持つ要素を返す。要素がない場合は空の `Optional` を返す。 |
| `Stream.max(Comparator<? super T> comparator)` | `Stream` | `Optional<T>` | ストリーム内の最大値を持つ要素を返す。要素がない場合は空の `Optional` を返す。 |
| `OptionalInt.of(int value)` | `OptionalInt` | `OptionalInt` | 指定した `int` 値を持つ `OptionalInt` を返す。 |
| `OptionalInt.empty()` | `OptionalInt` | `OptionalInt` | 空の `OptionalInt` を返す。 |
| `IntStream.max()` | `IntStream` | `OptionalInt` | IntStream の最大値を返す。要素がない場合は `NoSuchElementException` をスロー |
| `IntStream.min()` | `IntStream` | `OptionalInt` | IntStream の最小値を返す。要素がない場合は `NoSuchElementException` をスロー |
| `IntStream.findFirst()` | `IntStream` | `OptionalInt` | `IntStream` 内の最初の要素を返す。要素がない場合は空の `OptionalInt` を返す。 |
| `IntStream.findAny()` | `IntStream` | `OptionalInt` | `IntStream` 内のいずれかの要素を返す。要素がない場合は空の `OptionalInt` を返す。 |
| `IntStream.average()` | `IntStream` | `OptionalDouble` | `IntStream` の平均値を `OptionalDouble` で返す。要素がない場合は空の `OptionalDouble` を返す。 |


---

https://qiita.com/T-ngtj/private/df254aacd05be698199a
Githubのマークダウンでチェックボックスを作ったときにスペースが空く

下記のように、項目の間に空行が入ると、結果の項目間にスペースが開いてしまう。
```
- [ ] 項目1
- [ ] 項目2
- [ ] 項目3

- [ ] 項目4
```


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/1788801e-123d-456e-d780-6680949bd8af.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237839/4c2a9184-da0e-d422-800b-1000422640a9.png)


下記のように項目を詰めれば解消される
```
- [ ] 項目1
- [ ] 項目2
- [ ] 項目3
- [ ] 項目4
```
OneDrive上のファイルを編集するとファイルが複製される



ファイル名にPC名が付与される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/5e6fa1af-3456-8cfa-9ee5-310f5a9ce6a1.png)

+ [OneDrive アイコンの意味は?](https://support.microsoft.com/ja-jp/office/onedrive-%E3%82%A2%E3%82%A4%E3%82%B3%E3%83%B3%E3%81%AE%E6%84%8F%E5%91%B3%E3%81%AF-11143026-8000-44f8-aaa9-67c985aa49b3)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/1d058f33-1344-ab94-9933-4feec710509c.png)

+ [OneDriveのアイコンの意味を教えてください。](https://www.fmworld.net/cs/azbyclub/qanavi/jsp/qacontents.jsp?PID=6611-2437)

**白丸緑チェックマーク**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/04a580f6-71c7-674a-e9ec-06e9bc0986f2.png)

**青い雲**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/492ee93f-8fda-4085-283c-d0339e5d6b03.png)


白の丸に緑のチェックマークが表示されているファイルやフォルダーは、パソコン内に保存され、インターネットに接続しなくても利用可能であることを示しています。
オンラインのみのファイル（青い雲）を開くと、ファイルがパソコンにダウンロードされて、本状態（白丸緑チェックマーク）になります。

ファイルを右クリックし、表示されるメニューから「空き領域を増やす」をクリックすると、オンラインのみのファイルに戻すことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328136/ec90f27a-57a2-6f3d-d44e-23f50796c821.png)


これが関係すると思ったけど違うかな。
+ [IT 管理者 - OneDrive ポリシーを使用して同期設定を制御する](https://learn.microsoft.com/ja-jp/sharepoint/use-group-policy#coauthor-and-share-in-office-desktop-apps)
【Powershell】IP自動取得へ切替（Win11版/HP限定？）No.３

さて今回が最終になります。

（台風10号が日本縦断中です。対策準備と今現在暴風雨圏内方の安全をご祈念も仕上げます）

4月から始まったものも最終章です。
まず現在の成果物から

# 成果物１

```.bat
<# :
@echo off
openfiles >nul 2>&1
if errorlevel 1 (
  powershell start-process "'%~f0'" -verb runas
  goto :EOF
)
powershell -noprofile -command "invoke-expression (get-content '%~f0' -raw)"
goto :EOF
#>

# 以下 powershell スクリプト
$adapter = Get-NetAdapter | Where-Object {$_.InterfaceAlias -eq "Wi-Fi"}
 
# アダプターのコンフィグを取得
$conf = $adapter | Get-NetIPConfiguration
 
# IPアドレスが設定されている場合
If ($conf.IPv4Address.IPAddress) {
 
    # その設定を削除する
    $adapter | Remove-NetIPAddress -AddressFamily "IPv4" -Confirm:$false
}
 
# デフォルトゲートウェイが設定されている場合
If ($conf.Ipv4DefaultGateway) {
 
    # その設定を削除する
    $adapter | Remove-NetRoute -AddressFamily "IPv4" -Confirm:$false
}
 
$adapter | New-NetIPAddress `
 -AddressFamily "IPv4" `
 -IPAddress "172.17.2.163" `
 -PrefixLength 24 `
 -DefaultGateway "172.17.2.253"
 
 $adapter | Set-DnsClientServerAddress -ServerAddresses "211.129.12.47,211.129.14.138"
```
以下で解説しています。

https://qiita.com/takuo_maeda/items/5c87de81d8d72f599b3f

# 成果物２

```.bat
$networkAdapter = Get-PnpDevice -Class Net | Out-GridView -Title "ネットワークアダプターを選択" -PassThru
$networkAdapter |Disable-PnpDevice -Confirm:$false
#InstanceIDだけ取得
$UninstallDeviceId = ($networkAdapter).InstanceId
#アンインストール処理はPnpUtilにまかせる
pnputil.exe /remove-device $UninstallDeviceId
Restart-Computer

```

こちらはqiitaの登録者の皆様に質問しまくって完成しました（2024/08/25完成）

https://qiita.com/takuo_maeda/questions/2eda8081450aafe21b59


:::note info



**１．結局いろんなところに連絡し、質問サイトで質問させてもらい、**
**２．また会社で今起こっているトラブルを考え、**
**３．またいま自分が組んで運用可能なレベルのpowershellのコマンドレットを考え**

**以下の結論にいたりました。**

# 結論
**アダプターのドライバーを削除して、再起動して、ドライバーの再インストールを行う**

# 理由
**コマンドやPowershellで**
**サブネットマスクやデフォルトゲートウェイが消えなかった**
**DNSプライマリーセカンダリーが残った**
**IPもすべてDHCPにしようとしてがDHCPにならなかった**
**上記がうまくいくようにいろいろなサイトで**
**現状を伝え、助言やアドバイスをいただいたが、うまくいかなかった**

# 発見
<font color="blue">**qiitaに質問して最後に解決に行きついたのでqiitaの良さを再発見いたしました**</font>
:::


2つ目のpowershellはCopilotに出してもらって結局ないコマンドが混ざっていて動かずに、
（Copilotに聞くとよいというのも質問サイトからいただいた案ではあるにですが）
qiitaの皆様にお世話になり、何とか解決策として、具体案を会社の方へ提示できた次第です。

追記：今後はipの固定にしていますが、こちらを入力方式にしたいと思います。
【HTML/CSS】divで作られたボタンをdisableにしたのにクリックイベントが発火する原因と対策

## この記事は何

最近、フォームの送信ボタンをグレーアウトして、再度クリックされないようにする実装を行いました。一見ボタンがグレーアウトされて無効になっているように見えたのですが、実際にはグレーアウトした後にクリックされると、イベントが発火してしまい、思わぬバグが発生しました。
この記事では、その原因と対策について共有したいと思います。

## 発生した問題

以下のようなコードを使って、送信ボタンを無効化しようとしました。

```html
<div class="inputBtn" id="submitButton" onclick="hoge();">上記の内容で送信する</div>
```

そして、ボタンがクリックされた後に無効化するためのJavaScriptを次のように実装しました。

```javascript
function disableSendButton() {
    let sendButton = document.getElementById('submitButton');
    sendButton.removeAttribute('onclick');
    sendButton.disabled = true;
    sendButton.style.opacity = 0.5;
    sendButton.style.cursor = 'not-allowed';
}
```

しかし、見た目ではボタンがグレーアウトしているのに、クリックイベントがまだ発火してしまう現象が発生しました。

## 問題の原因

この問題の原因は、`div`要素には通常の`button`要素と異なり、`disabled`属性が存在しないため、`disabled`プロパティを設定しても機能しないことにあります。

また、`onclick`イベントを解除しても、`div`自体がクリック可能な状態のままであるため、クリックイベントが引き続き発火してしまいました。

## 解決方法

この問題を解決するためには、`div`要素のクリックを完全に無効化するために、CSSの`pointer-events`プロパティを使用します。

修正後のコードは以下の通りです。

```javascript
function disableSendButton() {
    let sendButton = document.getElementById('submitButton');
    sendButton.removeAttribute('onclick');
    sendButton.style.opacity = 0.5;
    sendButton.style.cursor = 'not-allowed';
    sendButton.style.pointerEvents = 'none'; // クリックを無効化する
}
```

`pointer-events: none;`を設定することで、その要素がクリックなどのポインターイベントを受け取らなくなり、クリックイベントが発火しなくなります。

## まとめ

`button` 要素の場合は最初のコードでいけたので使いまわせると思ったら、`div` だと使えないということを知らず、ちょっと躓きました。
何かの参考になれば幸いです。
BOTに搭載されているURL短縮コマンドの悪用による荒らしと対策

こんにちは、りょうです。
今回はshortコマンドの悪用、対策についての解説です。

## shortコマンドの悪用
DiscordBOTにはURL短縮を行う`/short`などのコマンドが実装されていることがあります。
これを悪用し、荒らしがサーバーURLを大量に投下するなどの悪用をしています。
raiderなどが搭載されたツール内にコマンド送信の機能がついているものがあったり、上向きキー+Enterでも連投ができるのでなるべく対策したほうがいいコマンドになっています。
このコマンドを悪用されている例として、**Probot、Miffy、メイドちゃん**などのBOTが挙げられます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/6f345166-986a-8976-770f-4f3032263d60.png)

## 対策方法
`サーバー設定→アプリ→連携サービス`に移動し、対策したいBOTを選択します。
下の方に移動するとコマンド一覧が表示されるのでURL短縮コマンドを選択します。
ここで`@everyone`は使えないように☓を選択して保存します。
これをすることで管理者権限があるユーザー以外にはコマンドが表示されないようになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/c1a4b297-1ec5-67b1-ddc8-f7640c46fe4e.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/9da0fa14-8034-3c7f-8c2b-7abfe82bdaf9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/fd2767ab-a9f9-4fad-0fdd-09eed7c2b936.png)

### ちなみに
今まで長い間悪用されていたTakasumiBOTは先日修正が入り、クールタイム10秒が設けられました。
BOTの開発側もクールダウンを設ける、ephemeralをかける等対策を進めると良いと思います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3818367/b64d63e1-fdc9-5996-5723-fdbd1f450cf3.png)

## まとめ
今回はDiscordBOTのURL短縮コマンドの悪用した荒らしと、その対策方法の解説でした。
Automodや対策BOTでも対処できないので、無効化以外の対策方法はほぼないです。
なので権限がある人がちゃんと行っておいたほうがいいです。

わからないことあったら書いてくれれば答えていきます。

**Discordにいる荒らしの情報や対策方法の共有をしている自鯖です**
先日500人突破しました。ぜひ参加お願いします↓↓↓↓

https://discord.gg/ESRGwGQhxc
JSにおけるオブジェクトと配列の共有渡しの解決策

### JavaScriptでは、オブジェクトと配列は共有渡しで行われます。まず、この概念について簡単に説明します。

## 共有渡し

参照型は、総称として Object 型と呼ばれます。細分すると、Object 型、Array 型、Date 型、RegExp 型、Function 型などがあります。

**参照型の値は参照によってアクセスされます**

参照オブジェクトの保存方法は、スタックに変数名を保存し（その変数の値はヒープにあるデータのポインタ、つまりオブジェクトがヒープに保存されているアドレスです）、ヒープにデータそのものを保存します。

オブジェクトは共有渡しを使用します。あるオブジェクトを新しい変数に代入すると、そのオブジェクトがヒープに保存されているアドレスが代入され、ヒープのデータそのものではありません。つまり、2つのオブジェクトは同じ記憶空間を指しており、どちらかのオブジェクトが変更されると、実際には記憶空間の内容が変更されるため、2つのオブジェクトは連動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3809422/4055734b-470e-203f-d568-f076a013a205.png)

#### コード例

```javascript
//ケース１
var a = [1, 2, 3];
var b = a;
a = [4, 5, 6];
console.log(b); // [1, 2, 3]
```

上記のコードでは、配列は基本データ型のように見えますが、実際には以下のように動作します：

```javascript
//ケース２
var a = [1, 2, 3];
var b = a;
a.pop();
console.log(b); // [1, 2]
```

これはなぜでしょうか？

```javascript
a = [4, 5, 6]; // これはa参照そのものを変更しており、配列オブジェクトを変更していません。
a.pop(); // これは配列オブジェクトを変更しており、a参照は変更されません。
b = a; // この操作により、bは配列オブジェクトを直接指すようになります。bがaを指し、aが配列を指すわけではありません。
// そのため、a参照を変更してもb参照には影響がなく、配列オブジェクトを変更すると影響があります。
```

#### 上記コードの図示

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3809422/7b552c2a-9625-e8db-8b96-e5bc5deac3af.png)

### 解決策
___
#### 1. JSON文字列に変換してからオブジェクトまたは配列に戻す

```javascript
JSON.parse(JSON.stringify(...))
```

```javascript
var a = [1, 2, 3];
var b = JSON.parse(JSON.stringify(a));
a.pop();
console.log(b); // [1, 2, 3]
```

#### 2. Lodashライブラリを使用

Lodashには、元のデータを再帰的にディープコピーする `_.cloneDeep(value)` 関数があります。詳細は[こちら](https://lodash.com/docs/4.17.15#cloneDeep)をご覧ください。

```javascript
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]); // => false
```

```javascript
const _ = require('lodash');

var a = [1, 2, 3];
var b = _.cloneDeep(a);
a.pop();
console.log(b); // [1, 2, 3]
```

---

長文をお読みいただき、ありがとうございました。
Qiita vs Zenn 書きやすさ比較


# Qiita vs Zenn 書きやすさ比較

とりあえず両者ともに初投稿してみたはいいものの  
今後も投稿していくとしたら、どっちにしようかな？という話

# 比較してみた

触ってみて気づいたポイントを雑ですがまとめました。  
優勢の判断は各サービスの特徴の違いを踏まえた個人的な主観によるもので、  
絶対的な評価ではないことをご留意ください。

| # | 比較項目           |  Qiita   |   Zenn   | 優勢 |
|:--|:---------------|:--------:|:--------:|:--:|
| 1 | 投稿形式           |    記事    | 記事, 本 ※1 | \< |
| 2 | フォーマット         | Markdown | Markdown | ≒  |
| 3 | CLI & GitHub連携 |    良     |    良     | ≒ |
| 4 | 限定公開           |    ある    |    ない    | \> |
| 5 | 記事URL          |  UUIDのみ  |    任意    | \< |

※1 スクラップも選べるが、CLIから投稿できないため除外とした

## 1. 投稿形式

Zennは本という形式でも投稿できるらしいです。  
値段をつけることで収益化も可能とのこと。

https://zenn.dev/zenn/books/how-to-create-book

複数の記事を章立てでまとめておけるらしいです。  
長い取り組みの忘備録を段階ごとに記録するのにも使えるかもしれませんが、  
普通に記事間のリンクで連続性を表現する方が良いかもしれないです。

使い所は考える必要がありますが、選択肢があるのはありがたいです。

## 2. フォーマット

どちらも Markdown記法で記述します。  
差異があるかは未確認ですが、少なくとも執筆上困ることはなさそう。

https://qiita.com/Qiita/items/c686397e4a0f4f11683d

https://zenn.dev/zenn/articles/markdown-guide

## 3. CLI & GitHub連携

両者とも、指定したリモートブランチへのコミットによる記事の公開・更新が可能でした。  

https://qiita.com/Qiita/items/32c79014509987541130

https://zenn.dev/zenn/articles/connect-to-github

QiitaはGitHub Actionsによる実装（ゆえにアクセストークンが必要）
GitHub Actionsゆえに、進行状況やエラーなどはGitHub上で確認できます。  

Zennは逆にどういう実装になっているんでしょうね。  
アクセストークンが必要ない分、管理する人は楽かもしれません。  
進行状況やエラーはダッシュボードから確認できるようです。  

個人的にはどちらも良い体験だったなと思っています。

## 4. 限定公開

Qiitaの記事のステータスは、`限定公開` or `全体に公開` となっており、  
Zennでは `下書き` → `公開` という感じでした。  

Qiitaの `限定公開` はURLさえ知っていれば誰でも見ることができました。  
Zennの `下書き` は筆者しか閲覧できませんでした。  

限定記事はクローラー対策されていました。

``` html:限定記事に含まれていたメタタグ
<meta content="noindex, nofollow" name="robots">
```

比較表の上では限定公開ができるということでQiitaを優勢にしましたが、  
人の好みによるかなという部分だと思います。

## 5. 記事URL

記事のURLがどうなるかが両者で違いました。  

検証した記事（初投稿）は下記の通りです。

https://qiita.com/HillTopTRPG/items/3fbf896a7cf8d0ee6231

https://zenn.dev/hilltop/articles/started-zenn

記事を一意に表す部分が、Qiitaでは `3fbf896a7cf8d0ee6231` なのに対し、  
Zennでは `started-zenn` なのがお分かりいただけると思います。  

この違いを説明するため、まずはCLIで執筆した生のファイルをご覧いただきたいと思います。  
※ 項目の意味を示すためのコメントを付与しています

```yml:started-qiita.md
---
title: Qiita はじめました
tags:
  - Qiita
private: false # true: 限定共有記事 / false: 公開記事
updated_at: '2024-08-29T11:23:46+09:00' # 記事を投稿した際に自動的に記事の更新日時に変わります
id: 3fbf896a7cf8d0ee6231 # 記事を投稿した際に自動的に記事のUUIDに変わります
organization_url_name: null # 関連付けるOrganizationのURL名
slide: false # true: スライドモードON / false: スライドモードOFF
ignorePublish: false # true: `publish`コマンドにおいて無視されます（Qiitaに投稿されません） / false: `publish`コマンドで処理されます（Qiitaに投稿されます）
---

記事のコンテンツ
```

```yml:started-zenn.md
---
title: "Zenn はじめました"
emoji: "🐣" # アイキャッチとして使われる絵文字（1文字だけ）
type: "idea" # tech: 技術記事 / idea: アイデア
topics: ["Zenn"]
published: true # 公開設定（falseにすると下書き）
---

記事のコンテンツ
```

どちらのファイルも `started-[サービス名].md` というファイル名です。  
Qiitaの方は `id` の項目があり、それがURLの一部となります。  
Zennではファイル名がそのままURLの一部となります。  

個人的には、Zennの仕様の方が好きです。

# まとめ

現状の判断だと、**Zennがやや優勢**という感じです。

まだ１記事ずつしか作成・公開していない状態での比較ですので、  
今後の利用で比較・検証すべきポイントが増えるかもしれません。
AWS ECS vs. EKS: 技術的な観点からの詳細比較

## はじめに
AWS ECSとEKSは、どちらもコンテナ化されたアプリケーションをデプロイするためのサービスですが、機能とアプローチにおいて明確な違いがあります。10年以上AWSを扱ってきた経験に基づき、両者のメリットとデメリットを技術的な観点から詳しく解説します。

### AWS ECS (Elastic Container Service)

**メリット**

* **容易な導入と運用:** ECSは比較的シンプルで、Dockerなどのコンテナオーケストレーションツールよりも簡単に導入できます。AWSマネージメントコンソールから直接操作できるため、複雑な設定やコマンドライン操作は不要です。
* **スケーラビリティと可用性:** ECSはAWSのインフラストラクチャ上に構築されており、高いスケーラビリティと可用性を提供します。自動スケーリングやロードバランシング機能により、トラフィックの変化に柔軟に対応できます。
* **コスト効率:**  ECSはサーバーレスなコンテナオーケストレーションサービスなので、サーバー管理やメンテナンスにかかるコストを削減できます。AWS Fargateを利用すれば、サーバー管理は完全に不要になります。
* **AWSとの統合:** ECSは他のAWSサービスとの統合性に優れています。S3、DynamoDB、IAMなど、様々なサービスとの連携がスムーズに行えます。

**デメリット**

* **柔軟性の制限:** ECSはKubernetesに比べて、コンテナのデプロイや管理における柔軟性が制限されます。カスタム構成や複雑なワークフローの実装には適していません。
* **拡張性の限界:** 大規模なクラスタや複雑なアプリケーションには、ECSの機能が不足する場合があります。大規模なスケールアップや高度なデプロイ戦略には、EKSの方が適しています。
* **コミュニティサポート:** EKSに比べて、ECSのコミュニティサポートは限定的です。トラブルシューティングや技術的な問題解決には、AWSドキュメントやフォーラムに頼らざるを得ない場合もあります。


### AWS EKS (Elastic Kubernetes Service)

**メリット**

* **高い柔軟性と拡張性:** Kubernetesはオープンソースのコンテナオーケストレーションプラットフォームであり、豊富な機能と拡張性を備えています。あらゆる規模のアプリケーションに対応でき、高度なデプロイ戦略やワークフローの実装が可能です。
* **活発なコミュニティ:** Kubernetesは世界中の開発者から支持されており、活発なコミュニティが存在します。技術的なサポートや情報収集が容易です。
* **オープンソース:** Kubernetesはオープンソースであるため、ソースコードにアクセスしてカスタマイズすることができます。独自の機能や拡張を開発することも可能です。
* **業界標準:** Kubernetesは業界標準のコンテナオーケストレーションプラットフォームであり、多くの企業が採用しています。スキルや知識を他の企業やプロジェクトに活かすことができます。

**デメリット**

* **導入と運用の複雑さ:** KubernetesはECSに比べて導入と運用が複雑です。専門知識と経験が必要になります。
* **コスト:** Kubernetesは、クラスタの管理やメンテナンスに、ECSよりもコストがかかります。
* **AWSへの依存:** EKSはAWS上で動作しますが、KubernetesはAWSに依存した機能を提供するわけではありません。他のクラウドプラットフォームに移行する場合、再構築が必要になる可能性があります。

### まとめ

ECSとEKSは、用途やニーズに応じて使い分けが必要です。

* **小規模なアプリケーション、シンプルなワークフロー:** ECSは導入が簡単で、コスト効率の高い選択肢です。
* **大規模なアプリケーション、高度なデプロイ戦略、柔軟な拡張性:** EKSは、より複雑なアプリケーションに適した選択肢です。


**どちらを選択すべきか**

最終的な選択は、アプリケーションの規模、複雑さ、技術的な要件、コスト、チームのスキル、経験などを総合的に判断して行う必要があります。

* **開発チームのスキル:** Kubernetesの経験が豊富であれば、EKSが適しています。ECSは、Kubernetesの経験がないチームでも比較的容易に導入できます。
* **アプリケーションの規模:** 小規模なアプリケーションであれば、ECSの方が適しています。大規模なアプリケーションや複雑なワークフローには、EKSの方が適しています。
* **コスト:** コストを抑えたい場合は、ECSの方が適しています。EKSは、クラスタの管理やメンテナンスにコストがかかります。

上記の情報を参考に、それぞれのサービスを比較検討し、最適な選択をしてください。
世界を動かす小さなコンピューター：MCUについて知っておくべきすべて

マイクロコントローラー（MCU）は、私たちの周りのあらゆる場所に存在しています。煙探知機から電動工具、スマートフォンや子供のおもちゃに至るまで、MCUは幅広いアプリケーションで使用されています。MCUは、単一のデバイスまたはチップ内に高度に統合された小型コンピューターと考えることができます。

典型的なコンピューターの構成を考えてみてください。中央処理装置（CPU）、短期および長期のストレージ用のメモリ、さまざまな入力と出力があり、それらは操作を実行するために必要です。MCUは、これらすべての要素を単一の小型パッケージに統合しており、異なる要素をマザーボードで接続する代わりに、すべてが一つに収まっています。このため、MCUはさまざまなアプリケーションや組み込みシステムで、単純な機能から複雑な機能までを実行することができます。

MCUの構成要素をよりよく理解するために、<a href='https://www.szcomponents.com/filter/microcontrollers/20'>MCU</a>は異なる要素に分けられます。本記事ではそれぞれの要素について概説し、後続の記事ではそれらの詳細に焦点を当てていきます。すべてのMCUがこれらの要素やサブ要素を持っているわけではありませんが、基本的な要素には以下のものがあります。

まず、MCUのコア要素です。業界では、コアは通常CPU、つまりマイクロコントローラーの「頭脳」と呼ばれる部分を指します。コアはチップ内のすべてを制御し、通常は必要な計算をすべて実行します。コアの周りには、電源システム、クロック、プログラムやデバッグ機能などのモジュールが配置されています。また、加速器によってコアに追加の計算支援が提供されることがあります。

メモリはMCUの重要な要素です。MCUには通常、揮発性メモリ（RAM）と不揮発性メモリ（フラッシュメモリまたはROM）の2種類があります。RAMはMCUの「メモ帳」のようなもので、現在の操作や計算を実行するために使用されます。一方、フラッシュメモリやROMは、プログラムやデータを保存するために使用され、コンピューターのハードドライブに似ています。

次に、入力と出力（I/O）要素です。I/OはMCUの物理ピンとその機能を制御し、MCUの内外を通過するすべての情報は最終的にこれらのピンを経由します。デジタルI/Oピンは、電圧が高いか低いかで「1」または「0」として解釈され、アナログI/Oピンは、MCUが解釈することなく電圧を通過させることができます。

最後に、MCUの「外部機能」と呼ばれる部分です。これには、タイミングと制御、データ変換器、アンプ、通信モジュールが含まれます。これらの外部機能は、特定のアプリケーションのニーズに合わせて構成されることがあり、MCUの構成や機能に大きな違いをもたらします。

MCUは、汎用的なものから特定のアプリケーションに特化したものまでさまざまな種類があり、それぞれに応じたパフォーマンスと機能が提供されます。そのため、どのようなニーズにも対応できるMCUが存在することでしょう。
Thunderbirdのメール作成ウィンドウで宛先ドメインごとにメールアドレスの色を変更する

## 自分自身にメールを送らないための工夫

ぼくのメールの運用は、以下のようになっています。

|メールアドレス|受け取る人|
|:-:|:-:|
|`個人名@example.com`|ぼくだけが受信|
|`info@example.com`|ぼくを含めて複数人が受信|

Thunderbirdでは、`個人名@example.com`に宛てられたメールに対して「全員に返信」をしても、返信メールの宛先に自分のメールアドレスは含まれませんが、`info@example.com`に宛てられたメールに対して「全員に返信」をすると、返信メールの宛先に、`info@example.com`が含まれてしまいます。**つまり、返信したメールが自分にまた送信されてしまうのです**。

## userChrome.cssで特定のドメインのメールアドレスに色を付ける

うっかり自分が受信しないように、自分のドメインには色を付けて目立たせてみることにしました。

1. Thunderbirdの`ヘルプ (H)`の`トラブルシューティング情報(T)`を開く
1. `プロファイルディレクトリー`で`ディレクトリーを開く`
1. `chrome`ディレクトリを探す。なければ作る
1. `chrome`ディレクトリの中に、`userChrome.css`があればエディタで開く。なければ作る
1. 以下、自分に合わせて加工して、cssのなかに書き込んで保存し、Thunderbirdを再起動する

```css:userChrome.css
/* example.com あてのメールはメールアドレスの枠の色を変更する */
.address-pill[emailAddress$="example.com"]
{
	background-color: rgba(255, 0, 0, 0.2) !important;
}
```

## 結果

うまくいくと、特定のドメインだけ色を変更でき、気づきやすくできます。

![thunderbird-address.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3721114/8cb971a5-e732-21a7-b1ce-2d9409a1f9c7.png "Thunderbirdのメール作成ウィンドウの宛先フィールド。一つだけアドレスピルが赤い")
【PHP】VS Codeで関数の一覧を表示させておく

## やりたいこと
関数が多くて探したい関数がすぐに見つからない！

phpの関数の一覧をVS Codeの左側に出しておいて
クリックしたらその関数に飛ぶようにしましょう。

## 拡張機能「PHP Intelephense」をインストール

[PHP Intelephense](https://marketplace.visualstudio.com/items?itemName=bmewburn.vscode-intelephense-client
) をインストール

![スクリーンショット 2024-08-29 122106.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686263/97a3c049-aa16-7005-3f18-c131d98c5cd0.png)

## VS Codeの設定を調整

VS Codeの設定画面で「outline」と検索。
以下の画像でチェックが付いているもの以外はチェックを外す。

このチェックを外さないといらないデータが一覧に混ざってきます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686263/244d4623-24ec-adbe-4a5a-8305d36f33e8.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686263/b3711c40-806c-dda3-2e0f-eaad97c1b218.png)

## アウトラインを確認
アウトラインに関数の一覧が表示されるようになりました。

![タイトルなし.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3686263/65136a24-7a91-3371-aa09-8f71dd84e001.png)


関数が何十個もあるような大きいファイルでも
これですぐに見たい関数に飛べるようになります。

デフォルトでこうなっててくれればいいですのにね。

環境設定する際は参考にしてみてください。
BedrockのナレッジベースでS3同期処理の自動化

一気に大量のデータを同期したため、2日間位同期処理が終わらずCohere Embed Modelの利用料が$30位行ってしまいました:fearful:

# 手順

下記同期の箇所です。

![detasorce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523652/2b331fe6-9e57-06bf-ef41-8f93433dba6f.png)

①Lambda用のIAMロールに`bedrock:StartIngestionJob`を追加
②Lambdaを作成

```python
import boto3

def lambda_handler(event, context):
    client = boto3.client('bedrock-agent')
    response = client.start_ingestion_job(
        knowledgeBaseId='ナレッジベースID',
        dataSourceId='データソースID'
    )
```

③EventBridgeでLambdaを定期実行

# 差分データ

同期は増分であるため、前回の同期以降に追加、変更、または削除されたドキュメントのみを処理します。

https://docs.aws.amazon.com/ja_jp/bedrock/latest/userguide/knowledge-base-ingest.html
バージョン管理の運用について

# PCとGitHubを連携させる。

- Githubにリポジトリをつくる
- PC側で、ssh-keygen -t rsaで、公開鍵をつくる
- Githubに、PC側の公開鍵を登録する

# ユーザー向け

```
git clone リポジトリのパス
```

# 開発者向け

バージョンとコメントを記入する。その後、PCからGitHubにファイルを登録する。

```
# ファイルを登録する
git add .
# タグをつける
git tag -a rev0.0 -m "初期実装"
# コミットする
git commit -m "初期実装"
# GitHubにプッシュする
git push origin rev0.0
```


# 間違ってpushした時の対応

git pushを取り消す。

```
git reset --soft HEAD^
```

# 間違ってtagを付けたときの対応

tagを取り消す。

```
git tag -d rev0.0
```

https://gist.github.com/devlights/0a53bec59d1872a5327605f67a51ce66
Windows 11 とルータ(F660A)の罠

## はじめに
Windows11のミニPCをセットアップしていた時にはまった罠です。簡単にいうと、有線LAN経由でGoogle検索はできるのに、その先の各ページに飛ぶとDNSエラーやらなんやらでページが表示されないという現象が起こりました。当時は以下のことを見直したりした結果治らなかったのですが、ようやく解決策がわかったので、それを記載します。

結論を知りたい人は一番下の[ここ](#結論)を見てね。

## 現象
Chromeブラウザでページにアクセスしたところ、エラー「ERR_ADDRESS_UNREACHABLE」が表示されます。なので、Google先生に聞いて↓の内容通りに実行するも、解決せず。

https://kinsta.com/jp/knowledgebase/err_address_unreachable/

仕方なく有線LAN接続しているにも関わらず無線LANに接続してインターネットに接続していました。

## 再戦
再戦した時に、アダプタのドライバ周りは何もしていなかったな、と思い、イーサネットアダプタのドライバ周りの設定を変更することにしてみました。

まずはアンインストールして、再度インストール。結果意味なし…

Realtek PCIe GBE Family Controllerをキーに検索した結果、↓の記事があったので、少し現象は違うけど設定できるところをやってみました。

https://eng-notebook.com/20240104/1704378503

以下のアダプタ設定を開き、設定できる項目をすべて「Disabled」に変更しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/57841b8c-d99f-229c-6576-2299101ed2d2.png)

```
ARP Offload
NS Offload
```

あと電源周りの省エネモードも関係してそうだったので、そのあたりも設定しました。
もしかしたら関係ないかもしれないが念のため。
設定手順は以下の通りです。
コントロールパネル→電源オプションを選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/00dac04b-c211-eaf4-d6f3-d46f2ce7ac3d.png)

その後、選択されているプランの「プラン設定の変更」を選択。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/732f5120-0303-0fe7-b8b9-110c3b2b6841.png)

そして、「詳細な電源設定の変更」をクリックしました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/b9b6c718-b736-c665-20ae-4e21952408eb.png)

そして↓のように設定しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/e5374782-9020-8c0e-9ff1-dabbfdbc49ce.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/abdf4cb9-c4f5-93fa-cc41-31b3ded3527f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/f3b3ea41-57cc-34b9-14a5-28a627984218.png)


これらを設定した後に、接続できるかなぁ～とあまり期待せず、メルカリページを開いたら…

無理でした…


## 原点を見直す
時系列を追ってみた。
1. 元々eo光からNURO光に変更し、ルータが変更された
1. ルータが変わっても、Windows10なら同じ設定で問題なくネットワーク接続できていた
1. ミニPCが動かなくなったので、原因調査＆復旧をした時にWindows11にアップデートした
1. 同じ設定ではネットワーク接続できなくなった（ただ、設定途中はつながっていた気もする…）

よくよく考えると、Windows11とNURO光のルータ（F660A）の相性問題か？と思った。
ただ、設定途中でネットワーク接続できていたこともありその差は何かな？と考えた結果、単なる静的IPの設定をWindows任せか、ルータで設定するかの違いだった。設定方法の違いは以下の通り。

#### ルータでのIP固定の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/1d422ddc-ba55-df05-c0f8-1b8c9eacb01d.png)

#### WindowsでのIP固定の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3846192/be3bc484-9f8c-074f-2068-8f275f60e036.png)

#### 接続確認結果
まとめると↓の通り。まさかDHCPサーバのIP割り振りに対してWindows側の設定をしていると接続できなくなるとは思わなかった。これってルータのDHCPサーバ機能のDHCP Requestがちゃんと動いていないバグなのではと思った。
||ルータでIP固定しない|ルータでIP固定する|
|-|-|-|
|Windows 10でIP固定する|接続OK|-|
|Windows 10でIP固定しない|-|不明(試していない)|
|Windows 11でIP固定する|接続NG|-|
|Windows 11でIP固定しない|-|接続OK|

## 結論
固定IPを割り振るときは、Windows側で固定IP設定するのではなく、ちゃんとDHCPサーバ側で固定IPの割当設定をしましょう
SSHの-Lオプションと-Dオプションの違いとは？

# はじめに
SSHは、リモートサーバーへのセキュアなアクセスだけでなく、トンネリングを利用してネットワーク通信を暗号化するための非常に強力なツールです。その中でも、-L（ローカルポートフォワーディング）と-D（ダイナミックポートフォワーディング）は、特に便利な機能です。しかし、これらのオプションがどのように異なり、どのように使い分けるべきかを理解しているでしょうか？この記事では、その違いをわかりやすく解説します。

# SSHのLocal Port Forwarding (-L) とは？
-Lオプションは、指定されたローカルポートからリモートサーバー上の特定のポートに通信を転送する機能です。これにより、ローカルマシン上のポートに接続するだけで、リモートサーバーの特定のポートにアクセスできるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3760374/b229d2f5-4455-8b81-2b2d-b2cfbbeb0b17.png)

### 1. コマンド例
```
ssh -L 8080:remote-server:80 user@ssh-server
```
1. 8080: ローカルマシンのポート番号
1. remote-server: リモートサーバーのホスト名またはIPアドレス
1. 80: リモートサーバーのポート番号
1. user@ssh-server: SSHサーバーに接続するためのユーザー名とホスト名

### 2. 動作の仕組み
1. ターミナルでこのコマンドを実行すると、ターミナルを閉じない限り接続状態が維持される
1. ローカルマシンの8080ポートがリッスンを開始する
1. 8080ポートに接続があると、SSHクライアントがSSHサーバーを経由して、remote-serverの80ポートにトラフィックを転送する
1. 応答も同じ経路で返される

:::note warn
ブラウザで-Lトンネリングを使用する場合、プロキシ設定を「PROXY localhost:8080」に変更してください。
:::


### 3. 典型的な利用ケース
1. **リモートデータベースへのアクセス**：社内ネットワーク内にあるデータベースに外部からセキュアにアクセスする場合
1. **ウェブサーバーの管理**：ファイアウォールで守られたリモートウェブサーバーに安全にアクセスする場合
1. **ローカル開発環境とリモートサービスの連携**: ローカルの開発環境から、リモートのAPIサーバーやデータベースにセキュアに接続する場合

# SSHのDynamic Port Forwarding (-D) とは？
-Dオプションは、SOCKSプロキシを設定し、ローカルマシンの指定したポートを通じて、任意のリモートホストへの通信を動的に転送する機能です。これにより、Webブラウジングや様々なアプリケーションのトラフィックを暗号化して、セキュアにリモートサーバー経由で通信することができます。

### 1. コマンド例
```
ssh -D 1080 user@ssh-server
```
1. 1080: ローカルマシンのポート番号（SOCKSプロキシのポート）
1. user@ssh-server: SSHサーバーに接続するためのユーザー名とホスト名

### 2. 動作の仕組み
1. ターミナルでこのコマンドを実行すると、ターミナルを閉じない限り接続状態が維持される
1. ローカルマシンの指定ポート（例：1080）にSOCKSプロキシが設定される
1. アプリケーションがこのSOCKSプロキシを使用するように設定されると、そのトラフィックはSSHサーバーを経由して転送される
1. SSHサーバーが目的のリモートホストに接続し、トラフィックを転送する

:::note warn
ブラウザで-Dトンネリングを使用したい場合、プロキシを「SOCKS5 localhost:1080」に設定してください
:::

### 3. 典型的な利用ケース
1. **セキュアなWebブラウジング**：インターネットカフェなどの安全でないネットワークから安全にブラウジングを行う場合
1. **匿名化**：トラフィックを匿名化し、リモートサーバー経由で他のネットワークにアクセスする場合
1. **地理的制限の回避**: 特定の地域からのアクセスが必要なサービスを利用する場合
1. **複数のアプリケーションのトラフィック暗号化**: 様々なアプリケーションの通信を一括してセキュアにする場合

# -L と -D の主な違い
### 1. 転送の範囲:
-L: 特定のポートと宛先のみを転送
-D: SOCKSプロキシを通じて任意のポートを動的に転送

### 2. 設定の複雑さ:
-L: 各転送に対して個別の設定が必要
-D: 1つの設定で多様な通信に対応可能

### 3. 使用場面:
-L: 特定のサービスへのアクセスに適している
-D: 多用途なトンネリングに向いている

### 4. アプリケーションの互換性:
-L: ほとんどのアプリケーションで利用可能
-D: SOCKSプロキシをサポートするアプリケーションでのみ利用可能

### 4. パフォーマンス:
-L: 特定のポートのみを転送するため、一般的に高速
-D: 多様なトラフィックを処理するため、若干のオーバーヘッドが発生する可能性がある

# どちらを使うべきか？
### 1. ローカルポートフォワーディング (-L) を使用すべき場合
1. 特定のリモートサービス（例：データベース、ウェブサーバー）にアクセスする必要がある場合
1. アプリケーションがSOCKSプロキシをサポートしていない場合
1. 転送するポートとサービスが明確に決まっている場合

### 2. ダイナミックポートフォワーディング (-D) を使用すべき場合
1. 一般的なWebブラウジングや複数のサービスをセキュアに利用したい場合
1. より汎用的なトラフィックを転送したい場合
1. クライアントアプリケーションがSOCKSプロキシをサポートしている場合

:::note warn
すべてのアプリケーションがSOCKSに対応しているわけではありません。-Dで上手くいかない場合は、-Lの使用を検討しましょう。
:::

# まとめ
SSHの-Lと-Dオプションは、それぞれ異なる用途に最適化されています。具体的なニーズに応じて、どちらを使用するかを選択することが重要です。どちらもセキュリティを強化し、ネットワークの柔軟性を高めるための強力なツールですので、ぜひその使い分けを理解して活用してください。
Excel VBAでCSVファイルを一括処理！簡単プロンプトで自動化

# これなに
chatGPTのプロンプト例です。
Excel VBAの生成においてエラーが発生することなく、ものすごく簡単に完結できました！

Excel VBAを使って、フォルダ内のCSVファイルを一括処理する方法をご紹介します。今回作成したVBAコードは、複数のCSVファイルを開き、その内容を新しいシートにコピーして、自動的に指定したプロシージャを実行するものです。

# こんな感じで依頼してみた！

今回はChatGPTに以下のプロンプトを入力してみました。

---

**プロンプト:**

```plaintext
Excel VBA のコードを生成してください。
# 生成ルール
* 標準モジュールに貼り付けて使用できる
* コメントを入れる

# 機能
* ファイル直下「csv」フォルダ内のcsvファイルをひとつずつ開き、以下の処理を行う
    1. 開いたcsvシートをコピーし新しいシートとして貼り付ける
    2. 貼り付けた新しいシートをアクティブにする
    3. MainProcessプロシージャを実行する
```

---

これだけで、以下のVBAコードが生成されました。

**生成されたVBAコード:**

```vba
Sub ProcessCSVFiles()
    ' CSVフォルダ内のすべてのCSVファイルを処理する
    Dim folderPath As String
    Dim fileName As String
    Dim ws As Worksheet
    Dim wbCSV As Workbook
    Dim wsNew As Worksheet
    
    ' フォルダのパスを設定
    folderPath = ThisWorkbook.Path & "\csv\"
    
    ' 最初のCSVファイルを取得
    fileName = Dir(folderPath & "*.csv")
    
    ' フォルダ内のCSVファイルをすべて処理するループ
    Do While fileName <> ""
        ' CSVファイルを開く
        Set wbCSV = Workbooks.Open(folderPath & fileName)
        
        ' CSVシートをコピーして新しいシートに貼り付ける
        Set ws = wbCSV.Sheets(1)
        ws.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
        
        ' 新しいシートをアクティブにする
        Set wsNew = ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
        wsNew.Activate
        
        ' MainProcessプロシージャを実行
        Call MainProcess
        
        ' CSVファイルを閉じる（保存せずに）
        wbCSV.Close SaveChanges:=False
        
        ' 次のCSVファイルを取得
        fileName = Dir
    Loop
End Sub
```

---

# まとめ

このプロンプトを使用するだけで、複数のCSVファイルを自動で処理するVBAコードが完成しました。今回のような作業を手作業で行うと大変ですが、VBAとChatGPTを組み合わせることで、簡単に自動化できました。

もし同じようなVBAコードを必要としている方がいれば、ぜひChatGPTにこのプロンプトを試してみてください！
[ rails ] ログイン後に同じページにリダイレクトする

<br>

はじめまして！オンラインスクールでRuby on Rails勉強中の初学者です。
この度卒業制作として、「甲子園NOW!」というアプリを作成いたしました。
甲子園球場の試合中の盛り上がりを可視化でき、ファン同士の交流を促進するアプリです。
そのアプリの作成中に発生した問題たちを記事にしていけたらと思います！
皆様のアプリ制作のお役に立てると幸いです＾＾

<h2>開発環境</h2>
Ruby 3.2.3<br>
Ruby on Rails 7.1<br>
gem devise


<h2>問題</h2>
LINE bot APIの実装中に、LINEのメッセージで送ったURLにリダイレクトすると、[ ログインしてください ]のバリデーションが発生しログインしなおしたら、リダイレクトしたかったページに飛べないという問題が発生しました。

<h2>原因</h2>
ログイン後のリダイレクト先をroot_pathに設定していたため。

<h2>解決方法</h2>
application_controllerに以下を記述。

```application_controller .rb
class ApplicationController < ActionController::Base
  protect_from_forgery with: :exception
  before_action :configure_permitted_parameters, if: :devise_controller?

  def authenticate_user!
    if user_signed_in?
      super
    else
      session[:user_return_to] = request.fullpath
      redirect_to new_user_session_path, :notice => 'ログインしてください。'
    end
  end

  private

  def after_sign_in_path_for(resource)
    session[:user_return_to] || root_path
  end
end
```
  ___

  上から解説していくと、
**・protect_from_forgery with: :exception**
　CSRF攻撃からアプリケーションを保護します。これは、ユーザーが認証済みのセッションを持っている場合に、そのセッションを悪用する攻撃を防ぎます。

**・before_action :configure_permitted_parameters, if: :devise_controller?**
　Deviseコントローラが使用される場合に、configure_permitted_parametersメソッドを実行します。このメソッドは、通常、ストロングパラメータの設定を行うために使用されます。

**・authenticate_user!**
　ユーザーがログインしているかどうかを確認します。ログインしていない場合、ログインページにリダイレクトし、フラッシュメッセージを表示します。また、ユーザーがログインしようとしていたページのURLをセッションに保存します。

**・after_sign_in_path_for(resource)**
　ユーザーがログインした後にリダイレクトするパスを定義します。ユーザーがログインしようとしていたページがあればそこに、なければルートパスにリダイレクトします。

___

authenticate_user!メソッド内で**session[:user_return_to] = request.fullpath**と設定しているため、ログイン前にアクセスしようとしたURL（パラメータ付きでも可）がセッションに保存されます。<br>

そして、ログイン後にafter_sign_in_path_for(resource)メソッドが呼び出され、ここでsession[:user_return_to]の値が存在すればそのURLにリダイレクトします。これにより、ログイン前にアクセスしようとしたURL（パラメータ付きでも）に正しくリダイレクトし、パラメータの値も保持されます。

<h2>結論</h2>
私の実装ではLINEのアカウントIDを取得するために、LINEbotがLINEメッセージ内で送信したURLにパラメータもつけてリダイレクトするようにしていたのですが、authenticate_user!メソッドでログイン必須になるのでこの情報が失われてしまっていました。<br>
ですが上記の記述を行ったことにより、リダイレクト先の指定とパラメータの保持が行われることで、それらの情報を保持したままログインすることに成功しました！<br>
参考になれば幸いです。<br>