OmniAICreator/Qiita-1.07M huggingface dataset:
SESで派遣されたのに１ヶ月で部長になった話

### はじめに

とうとうAWS SAPの有効期間が切れるので勉強を開始したのですが、正直勉強に飽きてしまい箸休め的にQiitaで過去ネタを書いています（現実逃避）

折角なので私の過去ネタが他のエンジニア（特にSES）に役立つようお伝えしたいと思います。

この派遣先で成し遂げた事を時系列で書くと以下の通り

１ヶ月目、状況を把握後に改善レポートを提出
２ヶ月目、情報システム部長に就任（なぜか）
６ヶ月目、システムの入替で、５年間で１億円のコストダウンを実現
８ヶ月目、コストダウン分の１億円を使い、新しいEC/CRM管理PJを発足し
　　　　　後任を付けてもらう。
１２月目、自らの希望で現場終了

そもそも派遣された人が部長になるのが異例であった事は否めないですが、実は上記のパターンは私の得意とするやり方です。以前の記事も書いたように私は年収２０００万円を超えた秘訣の一つになります。

### 派遣に対する考え方の違い

通常派遣された場合は、「人手」として手順書に従いルーティン作業を任されます。通常はそのタスクを黙々と行うだけで、契約は継続され契約に基づきお金が貰えます。

しかし私の考え方は違います。

:::note warn
私に対する派遣費用以上の価値を出さないと、顧客が満足しないという考えです。
:::


これをヨドバシカメラに新しいパソコンを買いに行くAさんの事例を元にお伝えします

:::note info
ヨドバシカメラにパソコンを買いに行く前に多くの人は、kakaku.comや色んなサイトを見て、「このパソコンがいいじゃないかな？」っと当たりを付けてからお店に行きます。Aさんも以前からパソコンを使っていたので事前にこれだなというパソコンは決めていました。
:::

ただし、一応買う前に、プロである店員さんにどんなPCが欲しいか要件をAさんは伝える事にしました。
そして店員さんがお勧めしてくれたのが、Aさんが当たりを付けたPCをお勧めされた時、

:::note alert
「なんだ、プロなのに俺でも分かる程度のPCしか勧めてくれないんだ」っとちょっとAさんは失望しました
プロなのにこの程度かと。。。
:::

:::note warn
顧客はITのプロではないから、プロならではの意見・提案を求めている。顧客の想像の範囲に収まるような意見・提案・行動では、顧客は満足していない。
:::

:::note alert
つまり派遣された時に、言われたことを言われた通りに”だけ”やること自体が既に顧客は不満を感じている
:::

では、顧客が満足するための行動をまたAさんの事例でお話します。

Aさんが、店員さんにどんなPCが欲しいか要件をお伝えしたとき、
なぜPCを買おうと思ったのか？
今のPCにどんな不満があったのか？
今後どのような使い方をしていきたいのか？

などをヒアリングしました。
その結果、買い換えようと思ったきっかけが最近PCの起動やアプリの起動が遅くイライラしていた。
普段使っているのはブラウザ、メール、EXCEL,powerpointぐらいとの事でした。

そのことを確認した上で、店員さんが伝えたのは、

:::note info
前早くて、今が遅いなら、一度クリーンインストールする事で早くなる可能性が高い。お金をかけず出来る旨をつたえ、２・３万円かけて、HDDをSSDに入替えメモリを増設することで新品なみの早さに出来る旨をつたえた。
そして新品を買い換えるのは、アクションゲームや動画編集など高スペックPCが必要な場合は検討してみては？とアドバイスをもらった
:::

結果Aさんは、SSDへの換装とメモリ増設を店員さんにお願いする事にしました。
なぜなら、自分では思いも付かなかった格安で問題を解決出来る手を示してもらった上に、
買い換え後のセットアップの手間が億劫だなぁっと感じていた事もクリアしたことで、
満足以上の信頼感を店員さんに寄せました。

:::note warn
現在顧客の抱えている悩み、状況をまず理解すること、そして理想状態を確認することに徹すること。
その上で、松竹梅(ミニマム、折衷案、ベスト）を提示しメリット・デメリットを明確化した上で、顧客に選択肢を与え自らの意識で決断出来る状態に持っていく。このことで信頼度が向上する
:::

この事例からも分かるように、

:::note info
まずは業務理解(要件）も重要だが、顧客理解がもっと重要。顧客の悩みを理解し、顧客目線で悩みを眺める事で意識も行動(発言)も変わる。
:::

私は派遣先にいくとこの顧客理解に努め、顧客の悩みを解決する提案を複数提示します。
そして顧客の悩みに共通するのが

:::note alert
やりたい事があるのに、(予算)お金がないため出来ない状態
:::

であることです。そこで私はいつも、

:::note warn 
自分の担当範囲外含めた業務理解に努め、全体予算の中にある無駄を削減するための計画を立案します
:::

もちろん立案した提案が毎回通る訳ではないですが、

:::note info
この顧客目線で問題を解決する姿勢が顧客の信頼度を上げます
:::


### 最後に

実は私は派遣先に行くときのマイルールとしては、１年以内に１億円以上の価値を出す事を目標にしています。
この時点で他の派遣さんとは圧倒的に考え方が違うため、発言・行動が違いに表れ、結果として
前述のような１ヶ月でシステム部長に派遣でありながら就任するという事になりました。

今回はスキル的要素が一切無いですのですが、年収を上げたい・正社員になりたいSESの方には是非今日から実践出来る考え方ですので、是非取り入れて欲しいなぁっと思う次第です。

ご参考程度でも心に留めて頂けたら幸いです。

２週間の勉強でSAP更新試験受ける予定で勉強始めたら、思いのほかawsの技術忘れてて現実逃避のためのこの記事書きましたが、良いリフレッシュ(過去の栄光にすがって自己肯定感が戻りました)になりました。
マージリクエストのテンプレートを考える

# 初めに
前のインターンを応募した企業でマージリクエストを利用した開発を行わせていただきました
そこでマージリクエストの重要性を教えていただきました
そのフィードバックを元に自分ならどのようにマージリクエストを作成するかを考えたので
紹介します

# マージリクエストの概要
- 実装概要
- どのように実装したか
- 開発していてわからなかった部分
- テスト項目と確認したことについて

この4項目を書くようにしています

# 実際にマージリクエストを作成してみた例

## タイトル 
ログイン画面の作成<br>

ここではマージリクエストのタイトルを決めます
できるだけわかりやすく簡潔に伝えられるようにタイトルを作成します
## 実施概要
html,cssを使ってログイン画面を実装した<br>

どのようなことをしたのか概要を伝えます
ここでもあまり長くなりすぎず簡潔に伝えられるように概要を作成します


## どのように実装したか
ヘッダー、フッターはホーム画面と同様に実装した
ログインフォームのhtmlの説明は
フォームの名前はh1タグを使用した
formタグを使用してaction属性にread.html、method属性にpostメソッドを指定した
またcssの説明は
mainタグでフォーム内の要素の真ん中寄せ、と枠線の指定を行った
formタグで要素を縦並びにするように設定した
inputタグのid属性それぞれで線、余白、位置、色の調整を行った<br>
ここでは実装の内容を具体的に書くようにします
それぞれの処理をどのように実装したのかを明確に伝えるようにします
# 開発していてわからなかった部分
フォーム自体を真ん中に寄せる方法についてmarginで調整する方法であっているか知りたい
ヘッダーとフッターの位置を固定する方法があれば知りたい<br>
ここがフィードバックを得て大事だと考えた部分の1つ目です
チーム開発で大事なこととしてリクエスト先のエンジニアの方の負担にならないように行動する
というのが挙げられると思います
私はそこを意識してリクエストを送信していました
なので評価としてよかったので絶対書くようにしています
わからないことがない方がよいと思うのですが
悩みすぎて自分の開発が進まずチームに迷惑をかけてしまうよりも
わからない部分を明確にして教えていただいた方が開発スピードが上がると考えてます
でも丸投げするのではなく日頃から自分で考えられるように訓練することも大事だと考えています


## テスト項目と確認したことについて
### ヘッダー関連
- 「todoカンリ」を押してホーム画面に飛ぶことができるか
- 「todoカンリ」ボタンの位置が仕様に合っているか
- ヘッダーの背景色がオレンジになっているか
### メイン関連
- フォームが真ん中にあるか
- メールアドレスが入力できるか
- パスワードが入力できるか
- 送信ボタンを押すと一覧画面に飛べるか
### フッター関連
- フォントの色が白になっているか
- フォントが中央揃えできているか
- 背景をオレンジになっているか<br>
ここがフィードバックを得て大事だと考えた部分の2つ目です
チーム開発で使用通りに作成するというのはタスクを行うエンジニアにとって大事なことであると考えています
デグレ、出戻りを発生させないためにもテストと確認を行ったことを示すことはマージリクエストには必要であると考えます

# 終わりに
企業ごとに決め事はあると思いますが
gitflowの意識やマージリクエストでわからないことまた仕様の確認テストを行う意識は重要であると思うので
意識して取り組んでいこうと思います
【ABC377】コンテストメモ【AtCoder】

## はじめに

この記事では、自分が参加した「AtCoder Beginner Contest」の感想や結果をまとめます。各問題の解き方や反省点も振り返りながら、今後の改善点を考えていきます。

:::note
使用言語はC++
:::

:::note
「未着手」はまだ取り組んでいない問題を指します。
「未提出」は解いたものの、提出していない問題を意味します。
:::

## 結果

* 順位: 4306th / 10194
* パフォーマンス: 621
* レーティング: 378 → 404 (+26) Highest更新！
* 完問数:3完 ABC

## 問題別評価

### A問題

* AC 3:08
* [実行結果](https://atcoder.jp/contests/abc377/submissions/59155327)

A、B、Cをすべて含むか確認すればよい。

### B問題

* AC 11:18
* [実行結果](https://atcoder.jp/contests/abc377/submissions/59164124)

全部見にいって数える。

### C問題

* AC 39:41
* [実行結果](https://atcoder.jp/contests/abc377/submissions/59175866)

全部数えるPart2。桁数が多いのでオーバーフローに注意。

### D問題

* 未提出

よくわかりませんでした。いろんな人のコードを見た感じ片方を軸にして持っていれば良いらしい。

### E問題

* 未着手

分かりません。

### F問題

* 未着手

分かりません。

### G問題

* 未着手

分かりません。

## 総評・まとめ

今回のコンテストで念願の茶色になることができました。気長にやっていたので時間がかかっていましたが、これからは一念発起して精進したいと思います。
MLflowで実験管理を自動化(サンプルコード)

## MLflowとは
以下の記事で細かく解説されています。
こちらの記事は、備忘録として最低限動作確認するためのソースコードを中心に記載します。
また、あくまでもMLFlowがメインなので、作成するモデルに関する説明は省略させていただきます。

https://qiita.com/c60evaporator/items/e0eb1a0c521d1310d95d

https://qiita.com/taka_yayoi/items/799b0320e4d8ae2e4234

## 環境 
| 項目 | 情報 |
| ---- | ---- |
| Python | 3.9.13 |
| mlflow | 2.17.1 |


## ソースコード
### 事前準備
```python
# ライブラリのインポート
import mlflow
import mlflow.sklearn
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import roc_auc_score, precision_score, recall_score
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer
from mlflow.models.signature import infer_signature

# データのロード（乳がんデータセット：二値分類用）
data = load_breast_cancer()
X = pd.DataFrame(data.data, columns=data.feature_names).astype(float)
y = data.target

# データ分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=97)

# 新しい実験名を設定
mlflow.set_experiment("qiita sample")
```

### 関数定義
```python
# 学習用関数
def fit_rfn(n_estimators, max_depth):
    # MLflowで実験を記録するためのセッション開始
    with mlflow.start_run():
        # モデルのインスタンス化とトレーニング
        model = RandomForestClassifier(n_estimators=n_estimators, max_depth=max_depth, random_state=42)
        model.fit(X_train, y_train)

        # 予測と評価
        predictions = model.predict(X_test)
        probabilities = model.predict_proba(X_test)[:, 1]

        # メトリクスの計算
        auc = roc_auc_score(y_test, probabilities)
        precision = precision_score(y_test, predictions)
        recall = recall_score(y_test, predictions)

        # ハイパーパラメータの記録
        mlflow.log_param("n_estimators", n_estimators)
        mlflow.log_param("max_depth", max_depth)

        # メトリクスの記録
        mlflow.log_metric("AUC", auc)
        mlflow.log_metric("Precision", precision)
        mlflow.log_metric("Recall", recall)

        # サンプル入力（input_example）の設定
        input_example = X_test.iloc[0:1]  # テストデータの最初の行を使用

        # スキーマの設定
        signature = infer_signature(X_test, predictions)

        # モデルの保存
        mlflow.sklearn.log_model(model, "model", signature=signature, input_example=input_example)

        print(f"Logged Model - AUC: {auc}, Precision: {precision}, Recall: {recall}")
```

### モデル作成
```python
# ハイパーパラメータを変更して複数回実行
fit_rfn(n_estimators=100, max_depth=10)
fit_rfn(n_estimators=200, max_depth=20)
fit_rfn(n_estimators=50, max_depth=5)
```

## 結果確認
以下のコマンドを入力すると、ブラウザから作成したモデルの情報を確認することができます。
```
mlflow ui
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/479797/c6f128e1-f827-9542-605a-472f42786222.png)
VB.NET勉強会資料　オブジェクト指向 抽象クラス・インターフェース


## 1. ねらい
オブジェクト指向の応用として抽象クラスとインターフェースについて学ぶことです。  
プログラムの拡張性や保守性を高める設計手法をとりいれましょう
- - -
## 2. サンプルプログラムの紹介
VB.NETを使用して、抽象クラスとインターフェースの違いや使い方を解説
日時の変換処理を行うプログラムを題材とする
- - -
### サンプルプログラムの概要
- 入力された日時を異なるフォーマットで変換
- UTC、JST、和暦などの変換に対応
- - -
## 3. ファイル構成
以下がプログラムのファイル構成です：

- `FrmMain.vb` - メインフォームのイベント処理を記述
- `UtcToJstConverter.vb` - UTCをJSTに変換するクラス
- `JstToUtcConverter.vb` - JSTをUTCに変換するクラス
- `ToGgyyConverter.vb` - 和暦変換クラス
- `IDateConverter.vb` - 日時変換用インターフェース
- `BaseDateConverter.vb` - 基本の抽象クラス
- - -
## 4. 動作を確認
プログラムでは以下の動作が確認できます：

- 各ボタンをクリックすると、入力された日時が指定の形式に変換され、結果が表示されます。
- 結果はクリップボードに自動的にコピーされます。

例：
- 「UTC to JST」をクリックすると、UTCからJSTへの変換が行われます。
- - -
## 5. 抽象クラスとは
抽象クラスは、インスタンス化できないクラスで、継承されることを前提としています。  
共通の処理やインターフェースを提供し、具象クラスが具体的な処理を実装します。
- - -
### 特徴:
- 抽象クラスは具象クラスが持つ共通の処理を提供する
- 具象クラスは抽象クラスを継承し、特定のメソッドを実装する必要がある
- `MustInherit` キーワードを使って定義
- - -
### 例:
```vb
Public MustInherit Class BaseDateConverter
    Implements IDateConverter

    Public MustOverride Function ConvertDate(inputDate As String) As String

    Protected Function InvalidDateMessage() As String
        Return "日時が不正です。"
    End Function
End Class
```
- - -
## 6. インターフェースとは
インターフェースは、クラスに対して必ず実装すべきメソッドやプロパティを定義します。  
実装そのものは提供せず、複数のクラスに共通の機能を持たせたいときに使用します。

### 特徴:
- 複数のクラスに共通の振る舞いを定義する
- クラスがインターフェースを実装する場合、定義されたすべてのメソッドを実装しなければならない
- `I` で始まる名前をつけるのが一般的
- - -
### 例:
```vb
Public Interface IDateConverter
    Function ConvertDate(inputDate As String) As String
End Interface
```
- - -
## 7. メインフォームの説明
`FrmMain.vb` では、各ボタンのクリックイベントに対して、対応する日時変換処理を呼び出しています。  
`ConvertDateWithConverter` メソッドを使って、統一的に処理を行い、結果を表示し、クリップボードにコピーします。

```vb
Private Sub ConvertDateWithConverter(converter As IDateConverter)
    txtResult.Text = converter.ConvertDate(txtInput.Text)
    Clipboard.SetText(txtResult.Text)
End Sub
```
- - -
### ボタンイベント例:
```vb
Private Sub BtnToJST_Click(sender As Object, e As EventArgs) Handles btnToJST.Click
    Dim converter As IDateConverter = New UtcToJstConverter()
    ConvertDateWithConverter(converter)
End Sub
```
- - -
## 8. インターフェースと抽象クラスの違い

### インターフェースの特徴
- 実装すべきメソッドやプロパティの仕様を定義
- 複数のクラスに共通の機能を持たせたいときに使用
- クラスに複数のインターフェースを実装可能

### 抽象クラスの特徴
- 継承されることを前提とし、共通の処理をまとめる
- 具体的な処理と抽象的な処理を組み合わせて定義可能
- 一部のメソッドは具体的に実装し、一部は継承クラスで実装
- - -
### 使い分けの基準
- **インターフェース**: 複数のクラス間で共通の振る舞いを定義する場合
- **抽象クラス**: 共通のロジックをまとめ、サブクラスで実装を補完する場合
- - -
## 9. 可視化
以下は、インターフェースと抽象クラスの関係を可視化した図です。

```mermaid
classDiagram
    IDateConverter <|.. BaseDateConverter
    BaseDateConverter <|-- UtcToJstConverter
    BaseDateConverter <|-- JstToUtcConverter

    class IDateConverter {
        <<interface>>
        + ConvertDate(inputDate As String) : String
    }

    class BaseDateConverter {
        <<abstract>>
        + ConvertDate(inputDate As String) : String
        + InvalidDateMessage() : String
    }

    class UtcToJstConverter {
        + ConvertDate(inputDate As String) : String
    }

    class JstToUtcConverter {
        + ConvertDate(inputDate As String) : String
    }
```
- - -
## 10. まとめ
- **抽象クラス**は共通の処理をまとめ、クラス間でロジックを再利用できる
- **インターフェース**は共通の仕様を定義し、異なるクラスで同様のメソッドを強制的に実装させることができる
- 適切な設計手法を選ぶことで、プログラムの拡張性と保守性が向上します
CrystalのFiberとスケジューラの仕組みを調べてみたのでメモ

## はじめに

CrystalのFiberの**リスケジューリング**がどう動いているのか気になって、軽く調べてみました。

:::note info
といってもChatGPTを使って、Crystal本体のコードを読んでもらった結果をまとめたものですが、あとから簡単に振り返られるように記録に残したいのでQiita記事にします。
:::

## Fiberのコードを見る

まず、`fiber.cr`を読んでみます。

[fiber.cr](https://github.com/crystal-lang/crystal/blob/master/src/fiber.cr)  

ここで、Fiberの実行は`Crystal::Scheduler`によって管理されていることが分かりました。そこで、次に`scheduler.cr`を確認します。

[scheduler.cr](https://github.com/crystal-lang/crystal/blob/master/src/crystal/scheduler.cr)  

調べてみると、**`Fiber.swapcontext`**で現在のFiberの実行コンテキストを保存し、別のFiberを再開する仕組みがあることがわかります。では、この`swapcontext`はどこに実装されているのでしょうか？

## Fiberのコンテキスト切り替え

`fiber/context`ディレクトリに各プラットフォーム向けの実装が用意されています。

```
fiber
├── context
│   ├── aarch64.cr
│   ├── arm.cr
│   ├── i386.cr
│   ├── interpreted.cr
│   ├── wasm32.cr
│   ├── x86_64-microsoft.cr
│   └── x86_64-sysv.cr
├── context.cr
└── stack_pool.cr
```

**`x86_64-sysv.cr`**は、Linuxで使用される**System V ABI**用の実装です。ここでは、**アセンブリ**を使って**レジスタやスタック**を直接操作しています。

### 2つの重要な関数
- **`makecontext`**：Fiberが最初に実行されるエントリーポイントを`fiber_main`に設定します。
- **`swapcontext`**：スタックポインタを切り替えて、現在のFiberから新しいFiberに実行コンテキストを移します。  

低レベルの実装は理解困難ですが、ざっくりとこのような仕組みで動いていることが分かりました。

## スタックプールの仕組み

次に、`stack_pool.cr`についても確認します。

[stack_pool.cr](https://github.com/crystal-lang/crystal/blob/master/src/fiber/stack_pool.cr)  

ここでは、各Fiberごとに**8 MiBのスタックメモリ**が割り当てられ、効率的に管理されています。スタックの再利用や解放を通じて、メモリの使用量を抑える仕組みになっています。

## スケジューラが次のFiberを選ぶ仕組み

次に、Crystalのスケジューラが**どのように次のFiberを割り当てるか**を見ていきます。以下が`reschedule`メソッドの実装です。

```crystal
protected def reschedule : Nil
  loop do
    if runnable = @lock.sync { @runnables.shift? }
      resume(runnable) unless runnable == @thread.current_fiber
      break
    else
      Crystal.trace :sched, "event_loop" do
        @event_loop.run(blocking: true)
      end
    end
  end
end
```

- **実行可能なFiber**がある場合、キュー（`@runnables`）から取得して`resume`で再開します。
- 実行可能なFiberがない場合、`@event_loop.run(blocking: true)`が呼ばれ、次のイベントが発生するまで**ブロッキング**されます。


## EventLoopとlibeventの関係

`@event_loop`は、Crystalの**EventLoop**です。

[event_loop.cr](https://github.com/crystal-lang/crystal/blob/master/src/crystal/system/event_loop.cr)

Linuxでは、**`Crystal::LibEvent::EventLoop`**が使用されており、これは**libevent**のバインディングです。

[lib_event2.cr](https://github.com/crystal-lang/crystal/blob/master/src/crystal/system/unix/lib_event2.cr)

`libevent`は**非同期IO**や**タイムアウト**を管理するC言語のライブラリで、Crystalはこの仕組みを使ってイベントを効率的に監視しています。

`libevent`は、Linuxでepollのような**システムコール**を使ってイベントを監視します。

https://qiita.com/developer-kikikaikai/items/69f889e03133441ffbe0

Crystalの[`LibEvent2.event_base_loop`](https://github.com/crystal-lang/crystal/blob/0e1018fb2369afef0bf4c4aa9a3944cff10c39ec/src/crystal/system/unix/event_libevent.cr#L64C1-L69C10)は、**イベントが発生するまで待機**します。例えば、`epoll_wait`を使うことで、ソケットやファイルディスクリプタの状態変化を監視し、イベントが発生すると対応するFiberを再開します。
git revertとは

# git revert
> 既存のコミットを元に戻す

# 説明
> 1 つ以上の既存のコミットがある場合、関連するパッチによって導入された変更を元に戻し、それを記録するいくつかの新しいコミットを記録

#### 上記の説明を分解し、図化したもの
**revert CはBと同じ状態**
![スクリーンショット 2024-09-28 132421.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3634951/b644fb8e-908b-8bec-7ad2-478a4cc24e0b.png)



# 公式サイト
https://git-scm.com/docs/git-revert

# 最後に
まだ完全に理解しきれていないので、間違っている部分があると思います。
気づいたらご指摘いただけるととてもありがたいです:bow_tone1:
Reactで学習記録アプリを作成

# はじめに
JISOUに入会して初めての課題ということで学習記録アプリを作成しました。

# 作ったもの
作ったものはこんな感じです
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2068403/11aa5a48-54e7-2b69-a906-8d78fd471d95.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2068403/0a5fad2c-1bc0-f080-5dcc-a50f1d275461.png)


機能としてはこんな感じ
* 学習内容と学習時間を入力して登録ボタンを押すと入力内容がリストに表示される
* 入力せずに登録ボタンを押すとエラーメッセージを表示する
* 登録した学習時間を足して合計時間を表示する

# 感想
作成するにあたって特にここで苦労したといったような内容はありませんでしたが、先日動画で見た基本文法を覚えていなかったりで毎回調べながらやってたので、思ったより時間がかかってしまいました。
こういうのはその内覚えるし一旦放置でいいと言いたいところですが、いつもそれで何も身につかないまま終わっていたので今回は復習しようと思います。
Dockerfileって何？

# Dockerfileとは
Dockerfileはイメージにレイヤを追加する設定ファイルです。コンテナはレイヤで構成されています。Dockerfile内の特定のコマンド(`FROM`、`ADD`、`COPY`など)を実行するたびに新しいレイヤが生成されます。

# なぜDockerfileが必要なのか
Docker Hubなどの一般に公開されているDockerイメージは汎用的に作られています。そのため、手元で使う際には追加で何かしらのモジュールのインストールや設定ファイルなどが必要になることもあると思います。Dockerfileを使えば、そのようなDockerイメージの拡張を行うことができます。

# Dockerfileで利用できる命令の一部
| 命令 | 説明 |
| --- | --- |
| FROM | ベースイメージを追加する |
| RUN | コマンドを実行してレイヤを確定する |
| ENV | イメージの環境変数を指定する |
| ARG | イメージビルド時の変数を定義する |
| COPY | ホストマシンのファイルをイメージにコピーする |
| ADD | ホストマシンやインターネットのファイルをイメージに追加する |
| ENTRYPOINT | コンテナ起動時に実行するコマンドを指定する |
| CMD | コンテナ起動時に実行するコマンドのデフォルト部を指定する |

# Dockerfileを作ってみる
## 環境変数の設定
MySQLイメージからコンテナを起動し、現在時刻がどうなっているか確認してみます。
デフォルトではタイムゾーンはUTCなので、これを日本時間に直してあげます

**Dockerfile**
```Dockerfile
FROM mysql:8.4.3

ENV TZ=Asia/Tokyo
```

ビルドしてからコンテナを起動して現在時刻を確認してみます。
**ビルド**
```zsh
% docker image build -t my-mysql:time .
```

**コンテナの起動**
```zsh
% docker container run --name db --rm --detach --env MYSQL_ROOT_PASSWORD=secret --publish 3306:3306 my-mysql:tokyo

% mysql --host=127.0.0.1 --port=3306 --user=root --password=secret

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2024-10-26 16:10:41 |
+---------------------+
1 row in set (0.00 sec)
```
select now();で現在時刻を確認してみると、日本時間になっていることが確認できます。`docker container stop db`でコンテナは停止できます。
このようにしてENVを使えば環境変数を変更することができます。

## ホストマシンのファイルをイメージにコピー
先ほど起動したMySQLコンテナは、クエリを実行しても一般クエリログが出ません。ログを有効し化して出力先を設定するためには設定ファイル(/etc/my.cnf)を作成する必要があります。

自分のPC内で設定ファイルを作成します。

**my.cnf**
```
[mysqld]
general_log = 1
general_log_file = /var/log/query.log
```

続いて、my.cnfファイルと同じディレクトリにDockerfileを作成します。COPYを使ってホストマシンのコピー元ファイルをイメージ内にコピーします。

**Dockerfile**
```Dockerfile
FROM mysql:8.2.0

ENV TZ=Asia/Tokyo

COPY ./my.cnf /etc/my.cnf
```

先ほどと区別するために異なるタグでビルドしてイメージを作成します。

**ビルド**
```zsh
% docker image build -t my-mysql:time .
```

ログを確認するために、コンテナを起動してクエリを発行します。

**コンテナの起動**
```zsh
% docker container run --name db --rm --detach --env MYSQL_ROOT_PASSWORD=secret --publish 3306:3306 my-mysql:log

% mysql --host=127.0.0.1 --port=3306 --user=root --password=secret

mysql> select now();
+---------------------+
| now()               |
+---------------------+
| 2024-10-26 16:10:41 |
+---------------------+
1 row in set (0.00 sec)

mysql> exit
```

クエリを実行したので、次は一般クエリログを確認します。my.cnfで出力先として設定した/var/log/query.logを確認してみます。
```zsh
% docker container exec db ls /var/log
mysqld.log
query.log

% docker container exec db tail -n 5 /var/log/query.log
)engine = 'performance_schema'
2024-10-27T10:33:59.890286Z	    8 Connect	root@_gateway on  using SSL/TLS
2024-10-27T10:33:59.891387Z	    8 Query	select @@version_comment limit 1
2024-10-27T10:34:14.661208Z	    8 Query	select now()
2024-10-27T10:34:16.362365Z	    8 Quit
```
my.cnfによる設定が反映されていることが確認できました。
VBAで５分以内にEdgeでアクセスしたページのHTMLを読み込む（Edge操作なし、キャッシュ使う）

## Edgeで開かれているページのHtmlを取得したい
　過去には、Shell.ApplicationのWindowを用いて開かれているIEのページを取得したり、win32api1のFindWindowを用いてIEモードのページを取得したりしていたと思います。
  しかし、同様のことをEdgeでやろうとすると、どうしても自動ログインや複雑な操作が避けられません。
  そこで、簡単なコードでキャッシュから直近のHTMLとってきちゃおうという試みです。
## Edgeを操作せず直近でアクセスしたサイトから情報を取り込む
５分以内のキャッシュをHTMLドキュメントとして取り込む例です。
　もっとも、サイトによって文字コードはUTF-8,EUC-jpなど様々です。
　取り出したいサイトの文字コードをあらかじめ調べておくとよいと思います。
```vb:vba
Sub pickup_cache()
    
    Dim fso As Object
    Set fso = CreateObject("Scripting.FileSystemObject")
    Dim CacheFolder As Object
    Set CacheFolder = fso.GetFolder("C:\Users\" & Environ("USERNAME") & "\AppData\Local\Microsoft\Edge\User Data\Default\Cache\Cache_Data")
    
    Dim adoDbStream As Object
    Set adoDbStream = CreateObject("ADODB.Stream")
    
    Dim file As Object
        For Each file In CacheFolder.Files
            If DateAdd("n", -5, Now) < file.DateLastModified And InStr(file.ShortName, "f_") > 0 Then
                Dim htmlDoc As Object
                Set htmlDoc = CreateObject("htmlfile")
                With adoDbStream
                .Open
                .Charset = "UTF-8"
                .LoadFromFile file.Path
                Dim cTxt As String
                cTxt = ""
                cTxt = .readText
                    If InStr(cTxt, "UTF-8") > 0 Then'そのサイトに必ず含まれる文章で拾う
                        htmlDoc.write .readText
                        Debug.Print htmlDoc.nameProp
                    End If
                .Close
                End With
                
            End If
        
        Next file
    End Sub
```
【備忘録】iptablesの即時有効化/記入方法

## tcp/udpの有効化
### tcpの場合
```
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
```
### udpの場合
```
-A INPUT -p udp -m state --state NEW --dport 8080 -j ACCEPT
```
### 範囲を指定しての場合
```
-A INPUT -p udp -m state --state NEW --dport 8001:8010 -j ACCEPT
```
### サンプル
```
# See the Oracle-Provided Images section in the Oracle Cloud Infrastructure
# documentation for security impact of modifying or removing these rule

*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [463:49013]
:InstanceServices - [0:0]
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p udp --sport 123 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 443 -j ACCEPT
-A INPUT -p udp -m state --state NEW --dport 8080:8088 -j ACCEPT
```
### 編集、反映する方法

```
sudo iptables-restore < /etc/iptables/rules.v4
```
【イベントレポート】【LT大会】プロジェクトを円滑に進めるPM・PdM・EMのマネジメント手法LT会！

いつも記事を読んでいただきありがとうございます！
モブエンジニア（[@mob-engineer](https://qiita.com/mob_engineer))です！

今回は10/25（金）に参加したイベントについて簡単にレポートをまとめたいと思います！
※本当は当日に記事を上げたかったorz

:::note info
本記事は「【LT大会】プロジェクトを円滑に進めるPM・PdM・EMのマネジメント手法LT会！」に関する参加レポートとなります。参加してみて、「私が感じたこと」や「新たな発見」についてまとめております。
:::

# 目次
1. 参加したきっかけ
1. イベント概要　※途中参加のため一部の方は割愛
    1. MMORPGから学ぶ採用とマネジメント（HarukiExplore氏）
    1. インターン生が活躍できる開発組織（長沼 遼氏）
    1. 開発プロセスのE2E化による学び（中川 椋太郎氏）
    1. エンジニアのためのプロジェクトマネジメント入門（市古 空氏）
1. まとめ

## 参加したきっかけ
私が参加したきっかけとして3点あります。

1. **今まで触れ合ったことがない方と交流を深めていく**
1. **PM、PdMとしてのキャリアパスを考えるきっかけづくり**
1. **プロジェクトマネジメントに関する情報収集**

## イベント概要
::: note info
Connpassイベントページより参照
:::

>組織や事業の拡大に伴い、課題となってくることのひとつとして、チームやプロジェクトのマネジメントではないでしょうか。業種やカルチャー、組織の規模が違えば、きっと最適なマネジメント手法も違うはず。今回のLT会は、そんな「マネジメント」をテーマとしています。
「世の中のプロジェクトや組織は、どのような手法で物事を円滑に進めているのか？」
LTは、1人5～10分程度を予定しています。LT枠で参加申込みをされる場合、LTのタイトルが既に決まっていれば記載をお願いいたします。

### MMORPGから学ぶ採用とマネジメント（HarukiExplore氏）

#### LT概要
「MMORPGでのギルドの作り方・クエストの進め方」は、実は「プロジェクト内での活動（採用・オンボーディング・マネジメント）と関係あるんだよ」といったお話でした。身近なテーマだったため、話す内容についてすっと腹落ちさせることができました。

#### ポイント
- どのような活動に対しても**Jibungoto（じぶんごと）**としてとらえてみる
- ミスは当たり前なので、**ミスした後のリカバリ**、**ミス防止の仕組みづくり**がポイント
- 分からないことがあっても、**分からない状態のまま放置しておかない**

### インターン生が活躍できる開発組織（長沼 遼氏）

#### LT概要
長期インターン生が社内で活躍できる環境を作っていくために、企業、そして開発チームはどのような取り組みを行っていけばいいかといったお話でした。お話を聞いてみて、インターン生だけでなく、新規プロジェクト参画者に対しても応用して使えるといった印象を持つことができました。

#### ポイント
- 言語選定・アーキテクチャ選定の段階から**分かりやすい仕様**を考える
- **卒業を前提としたオンボートディング（引継ぎ・脱属人化など）**を行っていく
- リードエンジニアは、**チームメンバーの属性にあったタスクを渡していくこと**がポイント

### 開発プロセスのE2E化による学び（中川 椋太郎氏）

#### LT概要
ウォーターフォール開発内で「小さなアジャイル開発」と取り入れたことで、どのような**良いこと***と**課題**があったかに関するお話でした。**アジャイル開発導入時、どのようなことを考えていけばよいか**のヒントを見つけることができました。

#### ポイント
- 開発スケジュールをHow（どのように？）でなくWhat（何を？）の視点で考えてみる
- アジャイル開発を行うことで、**開発メンバー間での認識そご**を抑止することができる
- 1つのプロダクトを複数の小さなプロダクトとして考えてみる（小さなケーキの集合体）

### エンジニアのためのプロジェクトマネジメント入門（市古 空氏）

#### LT概要
チームメンバーとしてプロジェクトマネジメントに貢献していくには、どのような取り組みを行っていくことが大切なのかに関するお話でした。個人的に、私の中で「なるほど」と思う場面が多くありました。

#### ポイント
- チームメンバーとして開発プロジェクト内の**情報の交通整理**を行っていくことが大切
- 情報整理として、**タスク目的の振り返り**や**何が重要なのかの質問**がある
- 情報の交通整理を正しく行うことで、**手戻りなくプロジェクトを推進することができる**

## まとめ
本イベントを通じて、プロジェクトマネジメントを通じて**私たちは何を行っていく必要があるのか**といった視点で、多く考えるきっかけを持つことができました。そのうえで、プロジェクトマネジメントだけでなく、**コミュニティ活動**などでも活用できる視点が多くあったと思いましたので、継続して**キャッチアップすること**と**アウトプット活動を行っていくこと**が大切だと思いました。

:::note info
最後まで記事を読んでいただきありがとうございます！

記事を読んでみて、「良かった」と思った方は**いいね**と**ストック**を行っていただけますと、私のアウトプット活動の励みになりますのでお願いいたします！

また、コメントなどについても遠慮なくお願いいたします！
:::

## イベントサイト
[【LT大会】プロジェクトを円滑に進めるPM・PdM・EMのマネジメント手法LT会！](https://finatext.connpass.com/event/331334/)
【C#】クラス型(Loto6)のListを作成

# 1.はじめに
list配列では、整数型、文字列型の可変配列の使用例はよく見かける。
ただ、型の違うデータを纏めて扱いたいことがある。
こんな時にはカスタムクラス型のlistを作成することになる。
忘れないために、自分用のメモとして本記事を書いている。

# 2.カスタムクラス型のListメモ
__前提__
`クラス名:loto6`
`メンバ変数:numdata,stardata`
`numdata:6つの数字の組み合わせ`
`stardata:6番目の数字分の★`
`list名:list_lt6`

__(1)カスタムクラス型(loto6)のlistを作成__
```
List<loto6> list_lt6 = new List<loto6>();
```
__(2)カスタムクラス型のlistにデータ追加__
```
loto6 lt=new loto6();
lt.numdata="1,2,6,4,5,3";
lt.stardata="★★★";
list_lt6.Add(lt);
loto6 lt2=new loto6();
lt2.numdata="11,2,16,34,25,6";
lt2.stardata="★★★★★★";
list_lt6.Add(lt2);
```
__(3)カスタムクラス型のlistの要素へのアクセス__
```
//2番目のデータのstardataを表示
Console.WriteLine(list_lt6[1].stardata)
```


# 3.ソース

__処理内容：
6数字の組み合わせと、6番目の数字数の★を
5回表示するプログラム__

```c#:Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace con_loto6_list
{
 internal class Program
 {
//ランダムにType0個の数字を生成
  static int[] make_lotodata(int Max,int Type0,Random rand)
  {
   List<int> lotoqp_list = new List<int>();
   int nn;
   for (int j = 1; j <= Max; j++)
   {
    lotoqp_list.Add(j);
   }
   int[] tmplist = new int[Type0];

   for (int j = 0; j < Type0; j++)
   {
    nn = rand.Next(Max - j);
    tmplist[j] = lotoqp_list[nn];
    lotoqp_list.RemoveAt(nn);
   }
   lotoqp_list.Clear();
   return tmplist;
  }

//n0個の★を作成
  static string printstar(int n0)
  {
   string retstr = "";
   for (int i = 0; i < n0; i++) retstr += "★";
   return retstr;
  }

  static void Main(string[] args)
  {
   int n=5;
   int Max = 43;
   int Type0 = 6;

   List<loto6_qp> list_lt6 = new List<loto6_qp>();
   int[] arr_lt = new int[6];
   Random rand = new Random();

   for (int i = 0; i < n; i++)
   {
    arr_lt = make_lotodata(Max,Type0,rand);
    loto6_qp lt =new loto6_qp();
    lt.Loto6_data = string.Join(",",arr_lt);
    lt.Loto_star = printstar(arr_lt[5]);
    list_lt6.Add(lt);
   }

   for(int i = 0; i < n; i++)
   {
    Console.WriteLine(list_lt6[i].Loto6_data + ":" + list_lt6[i].Loto_star);
   }
   Console.WriteLine("キーを押すと終了します");
   Console.ReadKey();
  }
 }
}
```

```c#:loto6_qp.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace con_loto6_list
{
 internal class loto6_qp
 {
  private string _loto6_data;
  private string _loto_star;
  public string Loto6_data
  {
   set {  _loto6_data = value; }
   get { return _loto6_data; }
  }
  public string Loto_star
  {
   set { _loto_star = value; }
   get { return _loto_star; }
  }
 }
}
```

# 4.実行結果

```
31,26,22,41,24,13:★★★★★★★★★★★★★
18,24,17,35,31,4:★★★★
37,34,27,14,9,15:★★★★★★★★★★★★★★★
19,22,13,20,36,7:★★★★★★★
10,20,33,27,2,36:★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
キーを押すと終了します
```

# 5.気づいたこと

データサイズが可変の構造体のようなものなのかもしれない。
【Next.js v14】サーバーコンポーネントでページネーションを実装する

# 概要

　サーバーコンポーネントでページネーションを実装するためのクエリ文字列 `?page=1` をどのように取得すればいいかということについて書く。クライアントコンポーネントの場合は [`useSearchParams`](https://nextjs.org/docs/app/api-reference/functions/use-search-params) というフックを使うらしい。サーバーコンポーネントでは page.tsx のオプション引数を使う。

# 実装方法

　page.tsx のオプション引数 `searchParams` によりクエリ文字列を取得できる。

```react

// 1ページ当たりのデータ数
const POSTS_PER_PAGE = 10;

export default async function Page({
  searchParams,
}: {
  searchParams: { page: string };
}) {
  // ページ番号取得
  const page = parseInt(searchParams.page ?? '1');

  // GETリクエスト
  const res = await fetch(
    `${process.env.BACKEND_URL}/api/posts?page=${page}&limit=${POSTS_PER_PAGE}`,
    {
      cache: 'no-store',
    }
  );

  // レスポンスデータ処理
  // ...

  // データ数を取得
  totalPosts = // ...

  // ナビゲーションのリンク数
  const totalPages = Math.ceil(totalPosts / POSTS_PER_PAGE);

  return (
    // 他のHTML要素
      
      {/* ページネーションナビゲーション */}
      <div className={styles.pagination}>
        {Array.from({ length: totalPages }, (_, index) => (
          <Link
            key={index}
            href={`/blog?page=${index + 1}`} // 他のページパスへ
            className={`${styles.pageLink} ${
              index + 1 === page ? styles.active : '' // 閲覧中のページ番号を目立たせる
            }`}
          >
            {index + 1}
          </Link>
        ))}
      </div>
  );
}
```

上記コードは以下の個人ブログに反映したので動作を確認できる。

https://oizumi-yuta.com/blog?page=1

以下は公式ドキュメントからの引用。
[Nest.js API Reference > File Conventions > page.js](https://nextjs.org/docs/app/api-reference/file-conventions/page)

> ```tsx
> export default function Page({
>   params,
>   searchParams,
> }: {
>   params: Promise<{ slug: string }>;
>   searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
> }) {
>   return <h1>My Page</h1>;
> }
> ```

**params**

ダイナミックルートパラメータを取得する場合に使用する。

- 例: `/posts/[id]` から id を取得する

**searchParams**

クエリ文字列からキーと値を取得する場合に使用する。

- 例: `/posts?page=1&limit=10` から `{page: '1', limit: '10'}` を取得する

# 参考

https://nextjs.org/docs/app/api-reference/file-conventions/page

https://nextjs.org/docs/app/api-reference/functions/use-search-params
PHPStan(Larastan)のLevelをローカル環境で自分用にカスタマイズする


PHP(Laravel)での開発をしていて、PHPStanが導入されているのですが、自分用にLevelなどカスタマイズして、品質をあげて最終的に全体反映できたらいいなと思ってましたのでそのときの備忘録。
※該当プロジェクトにすでにphpstanがインストール済みを前提としています。

# 1.ディレクトリを作成

```
プロジェクトディレクトリ
├ phpstan-local ← ディレクトリを作成
├ app ← アプリケーションコード
├ vendor
├ public
... etc

```

# 2.phpstan.neonを作成

```
プロジェクトディレクトリ
├ phpstan-local
　├ phpstan.neon
```

```
includes:
    - ../vendor/nunomaduro/larastan/extension.neon //phpstan.neonから見たLarastanのファイル

parameters:
    paths: //対象のディレクトリ
        - ../app
        - ../tests
        - ../database
        - ../routes
        - ../resources
    excludePaths: //除外ディレクトリ
        - ../app/config*
    level: max // phpstanのLevel

```

PHPStan Level
https://phpstan.org/user-guide/rule-levels

# 3..git/info/excludeを作成してローカル設定のみでGitの対象から除外する

```
vi .git/info/exclude
```

```
# git ls-files --others --exclude-from=.git/info/exclude
# Lines that start with '#' are comments.
# For a project mostly in C, the following would be a good set of
# exclude patterns (uncomment them if you want to use them):
# *.[oa]
# *~

laravel/local-phpstan/
```
更新メソッドについて　（assign_attributes  、update ）

# はじめに
この記事は、Ruby初心者が備忘録としてまとめたものです。間違い等ありましたらご指摘お願いします。
# assign_attributes 、updateメソッド 
- `assign_attributes`を使用することで複数の属性を一度に設定することが可能になります。また、特定の属性のみを指定することができます。既存のオブジェクトの更新等に使用することができます。
 しかし、DBには保存されないので、別途で`save`メソッドが必用になります。
 例
 ```
 def update
   @post = Post.find(params[:id])
   @post.assign_attributes(body: post_params[:body])# => 属性をbodyのみ指定。titleなど他の属性は変更されません。

   if @post.save
     flash[:notice] = '更新されました'
     redirect_to posts_path
   else
     render :edit
   end
 end

 (中略)
 private

 def post_params
   params.require(:post).permit(:title, :body, :author_id)
 end
 ```
 - `update`メソッドも似たような働きをしますが、属性の設定と保存を一度に行うことができます。
 例
 ```
def update
  @post = Post.find(params[:id])
  
  if @post.update(post_params) # => 複数の属性を設定し、保存を行う。
    flash[:notice] = '投稿が更新されました'
    redirect_to posts_path
  else
    render :edit
  end
end
 ```

 # まとめ
 
 １`assign_attributes`メソッド
 - 指定した属性をセットすることができる
 - データベースに保存するされないため、`save`メソッドが必要
 - 一部の属性だけを変更し、他の属性を保持したままにできる
 
２`update`メソッド
 - 指定した属性を設定し、即座に保存
 - post_paramsを使って複数の属性を一括で設定・保存する場合に便利
 - コードがシンプルになる

# 参考
https://morizyun.github.io/ruby/active-record-attributes-save-update.html#google_vignette
ロケールを無視して並べ替える(Unicode異体字など)


sortコマンドはロケールを考慮してくれます。そのため異体字などが含まれる場合、並べ替えた順番が必ずしも同じにならないかもしれません。複数のファイルを全て同じ基準で並べ替えて比較したい場合には、それが妨げになる場合もあります。
そういう場合にはロケール(locale)を無視して、sortするように、ちょっとだけ工夫します。
```sh
LC_ALL=C sort file.txt
```
`LC_ALL=C.utf8`ではありません。`LC_ALL=C`です。これによりutf-8などのロケール(locale)を考慮しない並べ替えになります。
以上です。
XcodeプロジェクトをzipでまとめてGigaFileで送信する

# 1. Xcodeのプロジェクトの場所を確認する
場所がわかる場合、Finderでその場所まで移動してください
「プロジェクト名」のフォルダの中に、「プロジェクト名」のフォルダと、「プロジェクト名.xcodeproj」が入っている場所が正しいです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/7be5be34-f184-2bcf-a425-f770afaece9f.png)

場所がわからない場合、Xcodeから探すことができます
プロジェクト名を右クリックして、「Show in Finder」を押すと、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/9fe3a207-6c13-7c42-a753-8fef514830d5.png)

Finderでアプリの場所まで移動できます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/7be5be34-f184-2bcf-a425-f770afaece9f.png)

# 2. プロジェクトをzipにまとめる
プロジェクトファイルを右クリックして、「"プロジェクト名"を圧縮」を押します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/597cdaec-a60b-a226-8270-bcf0f2b9cfbf.png)

`プロジェクト名.zip`が完成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/c15e2977-8adb-8435-8f5d-a6009bbaebcf.png)

# 3. GigaFileで送信する
`https://gigafile.nu`にアクセスします

https://gigafile.nu/

下にスクロールして、このような画面を見つけます

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/f5992671-9e4e-6b00-a4be-19229cadf283.png)

以下のように`プロジェクト名.zip`のファイルをドラッグ&ドロップします

![gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/17010fcc-f87d-49a6-792b-0cdf714e3f1d.gif)

画面中央のURLをコピーして、送りたい人に送りましょう！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540178/57c49e26-2638-dc4e-b0f6-bbda36a12219.png)
JavaScriptでカレンダーを出力するプログラムを作成する

## はじめに

前回、Rubyで表題と同じ内容のプログラムを作成しましたが、JavaScriptでも書いてみたのでメモ書きとして残しておくことにします。

参考：[Rubyでカレンダーを表示するプログラムを作成する](https://qiita.com/at-sacai/items/9d46b20adf89e10e7f81)

## アウトプット

ターミナルで、対象のディレクトリにて```node calender.js -m ${1-12}```と実行すると、対象月のカレンダーを表示することができました。

![スクリーンショット 2024-10-27 17.28.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2290540/2817cd0f-62fa-cefd-b7ca-4cc5541397b6.png)

なお、前回（Rubyのコード）からの変更点は以下の通りです。

- すべて日本語で表示（前回：すべて英語）
- カレンダーは日曜始まり（前回：月曜始まり）

## コード

コード作成時の考え方や詳細な説明は、[前回（Rubyのコード）の記事](https://qiita.com/at-sacai/items/9d46b20adf89e10e7f81)で解説しているため割愛します。

JavaScript特有の重要な点については、以下にまとめておきます。

``` JavaScript:calendar.js
const showCalendar = (month) => {
	let startDate = new Date(2024, month - 1, 1);
	let endDate = new Date(2024, month, 0);

	process.stdout.write(`    ${month}月 2024年    \n`);
	process.stdout.write('日 月 火 水 木 金 土\n');

	let weekdayIndex = startDate.getDay();
	let spaces = '   '.repeat(weekdayIndex);
	process.stdout.write(`${spaces}`);

	for (let day = startDate.getDate(); day <= endDate.getDate(); day++) {
		let tempDate = new Date(2024, month - 1, day);
		process.stdout.write(day.toString().padStart(2, ' ') + ' ');

		if (tempDate.getDay() === 6) {
			process.stdout.write('\n');
		}
	}
	process.stdout.write('\n');
};

let selectedMonth = new Date().getMonth() + 1;

let args = process.argv.slice(2);
let monthArgIndex = args.indexOf('-m');

if (monthArgIndex !== -1 && args[monthArgIndex + 1]) {
	selectedMonth = parseInt(args[monthArgIndex + 1], 10);
}

if (selectedMonth < 1 || selectedMonth > 12) {
	console.log(`${selectedMonth} is neither a month number (1..12) nor a name`);
} else {
	showCalendar(selectedMonth);
}

```

- ```let startDate = new Date(2024, month - 1, 1);```
    - Dateオブジェクトが月を0から11で扱うため、```-1```とする
- ```process.stdout.write```
    - 改行のタイミングを任意に調整したいため、上記メソッドを利用する


## おわりに

今回の気づきとしては、前回はRubyで本プログラムを作成しましたがJavaScriptで作成しても基本的なプログラム作成時の考え方は同じで書き方が微妙に異なるだけでした。

ただ、それぞれの書き方を正確に把握していなかったため、混乱し少々作成に時間がかかってしまいました。

引き続き学習を続けていきます。
Linuxのネットワーク設定が書き換わる問題への対処法

### 問題点

/etc/resolv.confに書くと再起動やアップデートする際にリセットされてDNS等が勝手に切り替わってしまう
これは
```
resolv.conf<- NetworkManager<- netplan
```
とデーモンが数珠つなぎになっており、互換性のために以前のソフトウェアの設定ファイルが残っているものの最終的な設定は末端のソフトウェアで行うという形式をとっているからである
なのでnetplanをつかっていれば設定が置き換わることはなく自動的に各種ネットワーク設定ができるようになっている

(ChefやAnsible、Puppetといった自動設定ツールの一部だと考えるとよい)

### 設定例
静的ipアドレスを設定したいときは以下のようにする

/etc/netplan/01-netcfg.yaml
```yaml
network:
  version: 2
  renderer: networkd
  ethernets:
    eno1np0:
      dhcp4: false
      optional: true <- wifiなどつながらない可能性のあるインターフェイスの設定
      addresses: [$my-ip/25]
      gateway4: $my-gateway
      nameservers:
        addresses: [8.8.8.8]
```

以下で反映
```sh
sudo netplan apply
```

optionalをつけなかった場合、起動時にネットワークがつながるまでまたされますので注意

[自作クラスタ計算機:固定ipアドレスの設定 [雑多な記録]](http://www2.yukawa.kyoto-u.ac.jp/~koudai.sugimoto/dokuwiki/doku.php?id=自作クラスタ計算機:固定ipアドレスの設定)

[Ubuntu の Network設定 - Qiita](https://qiita.com/Shakapon/items/0eea9f7492d0868c5cb1)

[netplanを使ったネットワーク設定](https://cosmoz.jp/usage/netconf.html)

### おまけ
どうしてもresolv.confが使いたい際は上書きしないようにできる
[第21章 /etc/resolv.conf ファイルの手動設定](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/8/html/configuring_and_managing_networking/manually-configuring-the-etc-resolv-conf-file_configuring-and-managing-networking#disabling-dns-processing-in-the-networkmanager-configuration_manually-configuring-the-etc-resolv-conf-file)
良いモデルとは

なぜソフトウェアを開発するのでしょうか？それは、**ソフトウェアによって、ある領域の特定の問題を解決するため**と言えるでしょう。そのために必要不可欠なのが、モデリングです。モデルを作成する活動を行うことで、ソフトウェアの価値を高めることができます。
## モデルとは
モデルには様々な種類があり、目的によって使い分けられます。本記事ではモデルという単語は、「ソフトウェアでアプローチする対象領域の問題を解決するためのモデル」とします。

### モデルの例
先ほどモデルを定義しましたが、イメージが湧きづらいので具体例を用いて説明します。

ソフトウェアを構築するために「履歴書」のモデルを作成するとします。実際に履歴書を書いたときのことを思い出すと、以下のような要素が抽出できるでしょうか。
* 名前
* 経歴
* 志望理由
* 顔写真

しかし、現実の履歴書には次のような要素も含まれます。
* 筆跡
* 履歴書のフォーマット
* 履歴書を書くときの気持ち

しかし、このような要素全てをソフトウェアに落とし込むことは不可能でしょう。問題を解決するために、必要な要素はモデルに取り込みたいですし、不要な要素は取り込みたくありません。

ここで、「どの要素を取り込むか」という工程が必要になります。このプロセスが抽象化であり、その成果物がモデルということになります。

## 良いモデル、良くないモデル
### 良いモデルとは
良いモデルとはどのようなモデルなのでしょうか。

このような質問をすると、分かりやすいモデル、粒度が適切なモデル、拡張性のあるモデル...といったことが挙げられることがあります。

しかし、「問題解決のために、物事の特定の側面を抽象化したもの」という定義から考えると、「**良いモデルとは、問題を解決できるモデル**」と言えるでしょう。いかに理解しやすく、美しく見えても、問題が解決できなければ、それは目的を達成できない、良くないモデルということになります。

### 良くないモデルの例
例として、人事担当者の採用管理（会社の採用選考に応募してきた人の管理）のアプリケーションを考えます。

人事担当者は採用管理業務をスプレッドシートを使用した手入力によって運用で行っていましたが、ミスの発生や作業効率の悪さが問題になっていました。そこで、アプリケーションを開発して運用をシステム化することにより、この問題を解決することを目指します。

実装行うために以下のモデルを考えました。

![myBlog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3897889/29cd65ac-6100-cba8-7bc9-2af5b9bf4265.png)
図1 採用選考モデル図

あらかじめ求人が登録されており、それに対して応募者、採用選考というのが登録されます。採用選考のステータスは「書類選考→1次面接→2次面接→最終面接→内定」というステップを辿ります。

このモデルを元に実装し、アプリケーションを現場で運用したところ、次のような問題が発生しました。
* 書類選考の前に面接があるのに、設定できない
* 面接は3次、4次もあるのに追加できない
* 求人関係のない応募も許可したいのに設定できない

これでは現場の運用に適用できません。つまり、もともと目指していた問題解決ができないということです。

もし、このアプリケーションの実装が、可読性や拡張性が高く、自動テストも完璧でバグが全くでないようなものだったとしましょう。そのアプリケーションは高い価値を生み出せるでしょうか？

いいえ、そうはなりません。**モデルが良くないと、実装がどんなに素晴らしくても良い（問題解決ができる）ソフトウェアにはならない**のです。

## 良いモデルを作るには
良いモデルを作るにはどうすれば良いのか、重要な2つのアプローチがあります。
* 問題解決の領域のエキスパートと会話する
* 運用して得られた発見をモデルに還元する

というものです。それぞれ解説していきます。

### エキスパートと会話する
採用管理アプリケーションを有用なものにするには、まず採用管理領域に詳しい人、つまり人事担当者に話を聞くことが必要でしょう。

ソフトウェアの開発によくあるのは、十分にモデリングやヒアリングを行わず、開発者の部分的な理解のみで実装を進めてしまうパターンです。そのような場合、求められているものとのすれ違いに気づくには時間がかかります。そして気づいた時点では既にコードやデータが目指したい形とは異なっており、大きな修正コストが必要になってしまいます。（多くの場合、このコストを払うことができず、徐々に理想と現実が乖離します）

このような事態を避けるためには、早い段階でモデリングをエキスパートと一緒に行い、モデルに知識を反映することが必要です。

### 運用して得られた発見をモデルに還元する
エキスパートと会話することは重要ですが、彼らはソフトウェア開発のエキスパートという訳ではありません。リリースして運用いてみたら意外な改善点があった、ということは必ず発生します。この発見をモデルに反映することが、モデルを改善するためのもう一つの重要な点です。**最初からモデルは完成せず、徐々に改善していくもの**という考えが重要です。

## 最後に
ソフトウェアを開発していく上で最初のモデルを作成することは、その後の開発や運用に大きな影響を与えます。適当にならず時間をかけてモデリングを行うことをお勧めします。

また、本記事での話はDDD（ドメイン駆動設計）に通じます。
【備忘録】vscodeでAWSやORACLE-CLOUDに接続する方法

:::note warn
作成した秘密鍵を使用してもvscodeで接続すると以下のようなエラーが出る
```
Bad permissions. Try removing permissions for user: 
NT AUTHORITY\\Authenticated Users (S-1-5-11)
on file D:/authority/user.pem.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
```
これは、秘密鍵がだれからも見える状態になってるから駄目だという事らしい
Linux/macOSの場合
もしLinuxやmacOSで同じようなエラーが発生している場合、次のコマンドでファイルのパーミッションを変更できます。
```
chmod 400 user.pem
```
とするだけ、なのだがWindowからだと、やっかいになる
:::
- ファイルのプロパティから、セキュリティタブを選択し、詳細設定を開く
![userpem01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/1b915a03-0fc0-b825-96f7-fe672eda7365.png)
---
- ユーザー権限が継承されているので敬称を無効化する
![userpem02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/fb23381d-c8b3-5578-a9dc-b7e836a23ca1.png)
![userpem03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/cc2b0600-284f-a52e-7c5e-aa9065bc966f.png)
---
- 無効化するとアクセスエントリーは無くなるのでOKをクリックすると、だれからもアクセスできない傾向が表示されますが、そのままOKをクリックする
![userpem04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/cc941d69-9345-d24b-d0ef-ccb02e3ee83a.png)![userpem05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/ba7c3a12-6b2d-7b33-7687-e3a77a21edb9.png)
---
- この状態だと、だれも権限がないので、編集から自分のアクセスだけを追加する為に、アクセス許可の編集をクリックする
![userpem06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/bb2935e0-7c3f-5e3d-d9f2-3557b2f2a232.png)
- アクセス許可の編集で追加ボタンをクリックする
![userpem07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/0b5099cf-da6d-3db0-1797-c3e5623566fa.png)
---
- 選択するオブジェクトに自分のユーザー名を入力して、名前の確認を選択
- ユーザー名だけのUSERを入力して名前の確認をクリックすることが出来る
![userpem08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/2a6d6411-f60d-15c8-6ec3-407a88a40fe2.png)
---
- 追加すると以下のように表示されます
![userpem09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3920264/932b97d0-c193-fbab-0dfa-504768abeec3.png)
---
vscodeは、以下のように/ssh/configを編集する
```
Host HostName
  HostName ********.compute.amazonaws.com
  User ubuntu
  IdentityFile "秘密鍵のパスファイル" 
  
```
Github ActionsでPlaywrightのテストを動かす

## はじめに
表題通り、GithubActionsでPlaywrightを動かしていきます。

## 成果物
Appleのサイトのタブ遷移をサンプルにしています

![apple.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/599049/34efb3d8-ec4b-4dfb-019f-4aa913f956ff.gif)

## ソースコード

```shell:ディレクトリ構成
~/develop/playwright_actions  (main)$ tree -I node_modules/
.
├── package-lock.json
├── package.json
├── playwright-report
│   └── index.html
├── playwright.config.ts
├── test-results
├── tests
│   └── apple.spec.ts
└── tsconfig.json

4 directories, 6 files
```

```ts:tests/apple.spec.ts
import { test} from "@playwright/test";

test("test", async ({ page }) => {
	await page.goto("https://www.apple.com/store");
	await page.getByLabel("Mac", { exact: true }).click();
	await page.getByLabel("iPad", { exact: true }).click();
	await page.getByLabel("Watch", { exact: true }).click();
	await page.getByLabel("Vision", { exact: true }).click();
	await page.getByLabel("AirPods", { exact: true }).click();
	await page.getByLabel("TV and Home", { exact: true }).click();
	await page.getByLabel("Entertainment", { exact: true }).click();
	await page.getByLabel("Store", { exact: true }).click();
});

```

```ts:playwright.config.ts
import { defineConfig } from "@playwright/test";

export default defineConfig({
	reporter: [
		["list"], // テストの進行状況が一つ一つコンソールに表示される
		["html", { outputFolder: "playwright-report", open: "never" }], //
	],
	use: {
		launchOptions: {
			slowMo: 1000,
		},
	},
});
```

```yml:
name: Playwright Tests

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  test:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v3

      - name: Setup Node.js
        uses: actions/setup-node@v3
        with:
          node-version: '16'

      - name: Install dependencies
        run: npm install

      - name: Install Playwright Browsers
        run: npx playwright install --with-deps

      - name: Run Playwright tests
        run: npx playwright test

      - name: Upload Playwright report
        if: always() # テストが成功・失敗に関わらず実行
        uses: actions/upload-artifact@v3
        with:
          name: playwright-report
          path: playwright-report
```
【コーセラ勉強ノート】時系列分析　MAモデルについて

# MAモデルとは
MAモデル（Moving Average Model）は、時系列データにおいて、ある時点のデータが、過去のランダムなショック（ホワイトノイズ）の影響を受けていると考える統計モデルです。ここでの「ランダムなショック」や「ホワイトノイズ」とは、予測不可能で、平均が0、一定の分散を持つランダムな変動を指します。

# MA(q)モデル
MAモデルは次数𝑞によって特定され、この次数はモデルが過去のノイズの影響をどれだけ遡って考慮するかを示します。MA(q)モデルの一般的な形式は以下の通りです：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3804860/adc9b11c-b610-132c-503f-fe3934548887.png)
# MAモデルの意味
このモデルは、現在の値が過去の一定期間のランダムな影響によって部分的に決定されることを示しています。つまり、過去の出来事が今日にどれだけ影響を与えるかを数学的に表現しています。MAモデルは特に、短期的な予測やデータのノイズの平滑化に有効です。
受信メールから探るSPF, DKIM, DMARCの対応状況(2024年10月)

# はじめに
SPF, DKIM, DMARCの可視化について以下に記載しました。

https://qiita.com/matsuhira/items/e1c5e5b068561e4c6bdb

ここでは、実際に受信したメールから、現時点の対応状況を見てみます。対象とするメールサービスは2つです。サービスその1、サービスその2とします。

# サービスその1
### 特徴
こちらのメールには、最近ではかなり多くのスパムメールが届きます。以前は、それほど多くなかったのですが、この夏くらいから増えてきている印象があり、可視化したくなった理由の一つです。調べてみた結果、こちらのサービスは、DMARCに対応していないようです。

### 問題ないケース
* dkim-adsp=pass, dkim=pass, sender-id=pass, spf=pass
この条件のメールが最も多いパタンでした。
* sender-idやdkim-adspがpassでない場合
dkim-adsp=pass, dkim=pass, <font color="maroon">sender-id=none</font>, spf=pass
dkim-adsp=pass, dkim=pass, <font color="maroon">sender-id=fail</font>, spf=pass
dkim-adsp=pass, dkim=pass, <font color="maroon">sender-id=softfail</font>, spf=pass
<font color="maroon">dkim-adsp=none</font>, dkim=pass, sender-id=pass, spf=pass
のパタンも見られました。特に多いのは、<font color="maroon">sender-id=softfail</font>のケースです。

### スパムではないが対応が必要そうなケース
メールボディのFromアドレスやメールの内容からスパムではないメールに、以下のパタンが見受けられました。
<font color="maroon">dkim=none</font>, sender-id=pass, spf=pass
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, <font color="maroon">sender-id=none</font>, <font color="maroon">spf=none</font>
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=fail</font>, sender-id=pass, spf=pass
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=neutral</font>, sender-id=pass, spf=pass
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, sender-id=pass, spf=pass

### スパムメール
メールボディのFromなどから、明らかにスパムと思われるメールで見受けられたパタンは以下です。
dkim-adsp=pass, dkim=pass, sender-id=pass, spf=pass
dkim-adsp=pass, dkim=pass, sender-id=pass, spf=pass
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, <font color="maroon">sender-id=softfail</font>, spf=pass
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, <font color="maroon">sender-id=softfail</font>, <font color="maroon">spf=none</font>
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, <font color="maroon">sender-id=softfail</font>, <font color="maroon">spf=softfail</font>
<font color="maroon">dkim-adsp=none</font>, <font color="maroon">dkim=none</font>, <font color="maroon">sender-id=none</font>, <font color="maroon">spf=none</font>
全てパスしているパタンもあります。

# サービスその2
### 特徴
こちらのメールには、もともとスパムが少なく、現在も少ないままです。

### 問題ないケース
dkim=pass, dmarc=pass, spf=pass
のみです。

### スパムではないが対応が必要そうなケース
みあたりませんでした

### スパムメール
1桁のメールなので、傾向は探れそうもありませんが、パタンは以下です
<font color="maroon">dkim=none</font>, <font color="maroon">dmarc=none</font>
<font color="maroon">dkim=none</font>, <font color="maroon">spf=none</font>, <font color="maroon">dmarc=none</font>
dkim=pass, dmarc=pass, spf=pass
spf=pass
こちらも、全てパスしているパタンもありました。ただ、Fromアドレスの詐称は無さそうでした。

# 比較
メールサービス2では、SPF, DKIM, DMARCの3つだけを処理しているようですが、メールサービス1では、DMARCが無いことと、dkim-adspとsender-idについても処理を行っているようです。この違いの良し悪しについては、断言できるほとの理解に至っていないのですが、何か歴史的経緯などがありそうに感じています。なお、dkim-adspは廃止されたとの情報もあります。

# 参考情報
https://qiita.com/matsuhira/items/5ffc39f00b200df56eaa

https://eng-blog.iij.ad.jp/archives/20946
HiltでAutoBindを使うときに気を付けたいこと

# はじめに
今回は、最近実装をしていてAutoBindアノテーションを使っていて少し詰まった部分があるので紹介していきます
### 本文
＠AutoBindを使う際に、複数個注入しようとするとエラーが出てしまいます。
その時に使えるのが、下記になります
@AutoBind(asTypes = [Hoge::class])
２個目以降をHogeのように書くことで複数個注入することができます。
ライブラリの中身を読むと書いてあるのですが、最初何も知らずに使うと「あ、複数個は何か違うやりかたしないといけないのかな？」となって少しだけ時間を食ってしまいました
### さいごに
ライブラリの中身を読めばすぐにわかることなので万人に役立つわけではないと思いますが、備忘録として記事に残しておこうと思います
該当ライブラリhttps://github.com/ansman/auto-dagger
ATM交換方式

>`遅延のない回線方式とパケット交換方式の利点のみを享受する`目的で考えられたのがATM技術です。形態としては従来のパケット交換方式を展開させたものと言えます。
 パケット交換機において生じる遅延の原因の一つとして、`パケットの多様性が挙げられます。多種多様なパケットに対応`するために、パケット交換機は複雑なソフトウェアを使って処理を行っています。ATMではこの部分に着目し、`パケット転送にかかる処理時間をできるだけ短縮`するための工夫がされています。最も特徴的なのは、`パケット（ATMではセルという）の長さを「ヘッダ部５バイト、ペイロード４８バイト」の５３バイトに統一`したことです。そのため、パケットの解析に複雑なソフトウェアは不要になり、`ハードウェアによる高速な処理を実現`します。

 https://gihyo.jp/book/2023/978-4-297-13865-3

 最大パケットが１５００バイトだったのに対しこれは53バイトになっている。
 高速みたいだ。

# ATMの階層構造の図
https://www.infraexpert.com/study/wan4.html#:~:text=ATM%E3%81%AF%E3%83%AC%E3%82%A4%E3%83%A4,over%20ATM%20%E3%80%80%E3%83%BBPPPoAl

>ATM層及びAALは、OSI基本参照モデルとしては、ともにデータリンク層に位置する。したがって、ネットワーク層に位置するIPは、イーサネットなどとの違いを意識することなくATMを利用できる。

https://gihyo.jp/book/2023/978-4-297-13865-3

# 感想
`パケットの多様性が挙げられます。多種多様なパケットに対応するため`と書いてある。データの大小で回線のスループットが落ちる可能性ある。しかし53バイトとすることでスループットが落ちず遅延が起きづらくなっている。
これも後から疑問が起こるのであろう
【Rails】furimaアプリ　商品削除機能　#1

# 実装概要
商品の情報を削除する機能を実装

### ルーティングの設定
```ruby:config/routes.rb
resources :items
```
今回で７つ目のアクションなので`only:~`以下は削除してまとめる

### destroyアクションをコントローラーに定義
```ruby:app/controllers/items_controller.rb
before_action :authenticate_user!, only: [:new, :create, :edit, :update, :destroy]
before_action :set_item, only: [:edit, :show, :update, :destroy]
before_action :correct_user, only: [:edit, :update, :destroy]

# 中略

 def destroy
    @item.destroy
    redirect_to root_path
 end
```

以上で実装完了
LGTMいただいたので次回は商品購入機能の実装に取り組んでいきます！