OmniAICreator/Qiita-1.07M huggingface dataset:
ターミナルに表示されるユーザー名を非表示にしたい

chatgptにコードそのまま貼り付ける時にユーザー名まで含まれるのが何か気になって、毎回ユーザー名を削除していたけどあまりにも面倒くさいのでそもそも表示させなければいいじゃん！と思って色々調べたら簡単に非表示にできそうなので記事にまとめました。


## PC環境
MacBook Pro
MacOS：Sonoma 14.3.1
プロセッサ：Intel Core i9
## zshrcファイルを編集
ルートディレクトリで`ls -a` コマンドを実行すると.zshrcファイルが見つかりました。ここを編集します。
![スクリーンショット 2024-02-29 11.19.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655001/2f08c045-e0d4-c6e1-1dda-601ad9e8f3de.png)
viコマンドで編集します。
```
vi ~/.zshrc
```
.zshrcファイルを開いたら以下を追記します。
```
export PS1="%~ $ "
```
よくわからないですがPS1というのがプロンプトの表示フォーマットの環境変数らしいです。

escクリック,`:wq`でファイルを抜けます。

## .zshrcを更新
このコマンドを実行しないと更新されないので忘れずに実行しましょう。
```
source ~/.zshrc
```

## まとめ
これで設定は完了です。簡単でしたね。
![スクリーンショット 2024-02-29 11.42.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3655001/c6aff02f-6c7f-a965-feed-ca19da518153.png)

もし設定変更したのに反映されない！って方はexportをファイルの下部に記載してみてください。
もしかしてら上手くいくかもです、、！
4年に1回バグが出る

# コード
```python
import datetime
dt = datetime.datetime.strptime('02月29日', '%m月%d日')
month = dt.month
day = dt.day
print(dt)
print(month, day)
```
⇓実行
```
ValueError: day is out of range for month
```
# 原因
年が渡されていないので、**"1900-02-29 00:00:00"** とライブラリが解釈しようとして、1900年に29日はありませんよ！と怒られる。

# 対策
**datetime.datetime.strptime**を使う際は、**年**も必ず入れよう！
添付ファイルを別の組織に移行する



+ [あるオブジェクトに紐づく添付ファイル(Attachment)をsandboxからsandboxへ移行したい](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ZBMcF)

前提条件もありそうです。

全てのファイルをエクスポートするには権限が必要みたいです。

[データローダを使って、コンテンツのドキュメントやファイルをクエリしたり、エクスポートする](https://help.salesforce.com/s/articleView?id=000381137&type=1)

英語ですが詳細な説明があります。
https://jayakrishnasfdc.wordpress.com/2021/07/18/import-and-export-contentdocuments-and-contentversions-in-salesforce/


ここでもサードパーティーのツールが紹介されていますね。
https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007T4PdsSAF


ファイルはZipファイルとしてインポートするので、エクスポートもZipファイルにする必要があるかもしれませんね。

[Bulk APIを使って添付ファイルをアップロードする](https://qiita.com/Keiji_otsubo/items/49440d0203b75048be18)

もう１つ気になるのは２つのSandboxで添付先のレコードのidは違いますよね？
ContentDocumentLinkに指定するIdをどう指定するかが気になります。
添付先のオブジェクトに外部キーなどがあれば楽かもしれません。

もう少し調べてみると詳細な手順が説明されていました。
結構面倒そうです。サードパーティーのツールが楽そうですが有償なんですよねぇ。

https://www.stimulusconsulting.co.uk/news/salesforce-data-migration/

https://ekwis.com/migrating-salesforce-contentdocuments-files/


+ [ファイルやライブラリを送信変更セットで検証環境⇒本番環境に適用する方法](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ah9TD)


:::note
ファイルはメタデータでないので、変更セットではなくてデータローダで移行できるとは思いますが、ファイルはContentDocumentとContentDocumentLinkの２つのオブジェクトですので少々難しいと思います。

この中にはライブラリはないかな。

変更セットで使用可能なコンポーネント
https://help.salesforce.com/s/articleView?id=sf.changesets_about_components.htm&type=5
:::

# Sandbox用のツール

+ [SFDX Data Move Utility](https://qiita.com/Keiji_otsubo/items/dac4f78a78da76ced36b)
汎化と特化

継承では
・親クラスになるほど一般的で抽象的な内容（汎化）
・子クラスになるほど特殊で具体的な内容（特化）
になると好ましいとされています。

ただし、安易な継承はプログラムの可読性を下げてしまう為、クラスの内容を一部変える場合は委譲の利用が推奨されます。

https://qiita.com/joshua_kanae/items/a62608bb19eeae0db8bb

# 参考文献
https://usd.sie.dendai.ac.jp/programming/2019/object_aj/C1_3.htm
Android Glideを使用したimageダウンロードと表示（kotlin）

## この記事でわかること
- Glideを使用した画像のダウンロード
- 画像ダウンロードのデバッグ・確認方法
- ダウンロードした画像の表示

https://github.com/bumptech/glide

## Glideを使用した画像のダウンロード
引数で保存先のディレクトリとファイル名を指定できるようにしています。ディレクトリを深く作成することも可能です。
```kotlin
fun save(imageUrl: String, directoryName: String, fileName: String) {
    Glide.with(context)
        .asBitmap()
        .load(imageUrl)
        .into(object: CustomTarget<Bitmap>() {
            override fun onResourceReady(resource: Bitmap, transition: Transition<in Bitmap>?) {
                val directory = File(context.filesDir, directoryName).apply {
                    if (!exists()) mkdirs()
                }
                val file = File(directory, fileName)
                val quality = 100
                FileOutputStream(file).use { out ->
                    resource.compress(Bitmap.CompressFormat.PNG, quality, out)
                    Log.i(TAG, "image saved to internal storage path=${file.absolutePath}")
                }
            }

            override fun onLoadCleared(placeholder: Drawable?) {
            }
        })
}

```
`resource.compress(Bitmap.CompressFormat.PNG, quality, out)`ここでは、保存時のファイル形式と画質と保存先を渡しています。
ファイル形式は、JPEG, PNG, (WEBP), WEBP_LOSSY, WEBP_LOSSLESSが指定できます。
`use`関数を使用して、エラーが出た時にリソースを閉じています。今回の開発で初めて知りましたが、主にファイル書き込みやdatabase接続などのCloseableリソースを扱う際に使用されます。
`onLoadCleared`は画像表示に失敗した際に実行されます。

## 画像ダウンロードのデバッグ・確認方法
1. View > Tool Windows > Device Explorer をクリックします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513666/df323217-a539-2cdc-57b8-f8ff63864206.png)
2. Device Explorerから`data/data/[Packege Name]/files/[directory name]/`を確認するとファイルが保存される

## ダウンロードした画像の表示
```kotlin
@Composable
fun OfflineImage(
    filePath: String,
    modifier: Modifier = Modifier,
    contentScale: ContentScale = ContentScale.Fit,
    context: Context = LocalContext.current,
    ) {
    val imageBitmap: ImageBitmap? by produceState<ImageBitmap?>(initialValue = null, filePath) {
        val file = File(context.filesDir, filePath)
        value = if (file.exists()) {
            val bitmap = BitmapFactory.decodeFile(file.absolutePath)
            bitmap.asImageBitmap()
        } else {
            null
        }
    }

    imageBitmap?.let {
        Image(
            bitmap = it,
            contentDescription = null,
            contentScale = contentScale,
            modifier = modifier
        )
    }
}

```
`produceState`を使用して非同期でbitmapを取得して`imageBitmap(value)`にセットして画像を表示しています。

### 参考リンク
https://developer.android.com/jetpack/compose/side-effects#producestate
https://bumptech.github.io/glide/
データクラウドからデータをクエリする



+ [CRM Analytics でデータクラウドからデータをクエリする](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007Yw5AGSAZ)

手順が詳しく説明されている。
+ [Query data from Data Cloud in CRM Analytics](https://www.salesforceblogger.com/2023/03/31/query-data-from-data-cloud-in-crm-analytics/)
メールテンプレートを作成するときの権限



+ [Alternatives for classic email template development w/o the need for VS/CLI/Modify All Data permission](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ZBOqySAH)

VS/CLI/すべてのデータの変更権限を必要としない、従来の電子メール テンプレート開発の代替手段
当社のマーケティングチームには、Lightning メールテンプレートビルダーでは処理できないメールテンプレートの要件がいくつかあるため、最近採用した開発リソースを使用してクラシックでメールテンプレートを開発しています。彼らは VS と SF CLI を使用したいと考えていますが、これには API を有効にし、すべてのデータを変更する必要があります。「すべてのデータの変更」権限を必要とせずに開発できる代替手段はありますか? 開発サンドボックスで作業していますか?

Unless you use VS and SF CLI, the following permissions seem to be all you need.

Check for these permissions under System permissions in the profile or permission set:

+ Edit Classic HTML Email Templates
+ Manage Public Classic Email Templates
+ View Setup and Configuration

[Can we allow non admin user to edit classic email template?](https://www.reddit.com/r/salesforce/comments/9wyyoh/can_we_allow_non_admin_user_to_edit_classic_email/)

Lightning Email Templatesなら別権限で代用できそうですが、VS and SF CLIとなるとAPIとすべての変更権限が必要だと思うな。開発方法の問題のような気がする

+ [Email template access to other profiles other than system administrator](https://salesforce.stackexchange.com/questions/378444/email-template-access-to-other-profiles-other-than-system-administrator)

You can add it for users. There's a Manage Public Lightning Email Templates system permission outlined in this [help doc](https://help.salesforce.com/s/articleView?id=sf.email_templates_public_private.htm&type=5).

You'd add that permission to a permission set and then assign that to any non-admins who need to manage email templates.

>Users need the Manage Public Lightning Email Templates permission to create, edit, and delete public templates. Users with this permission, as well as users with the Modify All Data permission or the System Administration profile, can edit and delete any public templates, including ones they don’t own.


# 別件

+ [System Administrator can't access Email Templates](https://salesforce.stackexchange.com/questions/383802/system-administrator-cant-access-email-templates)

:::note
It appears that '"Enable Classic email templates and related features" is not enabled in the org. You can do to resolve by using "Match Production Licenses".

Setup--> Quick find--> Company information--> Match production license
This has been identified as a bug of recent Summer '22 patch release. Kindly review KI details [here](https://trailblazer.salesforce.com/issues_view?title=enhanced-letterhead-disabled-in-org&Id=a1p4V000002ykW1).
:::
【Git】コマンドまとめ

## 概要
いつもはネットワーク関連の記事を書いているのですが、気分転換として
今回は自分が実際に使ったりしているGitのコマンドを簡単にまとめてみました。

今回の記事とは特に関係ありませんが、ネットワークについての基礎を学びたいという方は是非下記の記事を読んでみてください。

https://qiita.com/nakamura_slj/items/5841195df35a8325427e

# Gitのコマンド一覧
## コミット
```
git commit -m "コミット名"
```

## Gitログの確認
```
git log
```
簡潔にみたい場合は下記
```
git log --oneline
```

## ブランチの一覧を表示
```
git branch
```

## 他のブランチを現在のブランチにマージ
```
git merge [ブランチ名]
```

## 他のリポジトリのデータを取得してローカルのブランチにプル
```
git pull [リポジトリ] [ブランチ名]
```

## ローカルブランチのデータをリモートブランチに送る
```
git push [リポジトリ] [ブランチ名]
```

# 最後に
これで以上となります。
今回は自分が作業をしていて使う頻度が多めのものを簡単にまとめました。
他にも色々コマンドはあるので是非調べてみてください。
CakePHP の beforeSave() で失敗した際、それを何とか検知したい

# はじめに

この前、弊社 CakePHP4 プロジェクトにて beforeSave() で失敗してしまう不具合がありましたが「見かけ上は save() で失敗しているのに Entity の errors には何のエラーも保存されていない…」という困った状態でした。

しかも beforeSave() の処理そのものは Behavior に書いており、 Table クラスには何も書いてなかったので、beforeSave() の存在に気付くのも遅れました。

なので beforeSave() での失敗を何とか検知したいなと思って調べた結果をメモ。


## cookbook を読んでみる

CakePHP4 の [cookbook](https://book.cakephp.org/4/ja/orm/table-objects.html#beforesave) によると

> ### beforeSave
> Cake\ORM\Table::beforeSave(EventInterface, EntityInterface, ArrayObject)
> Model.beforeSave イベントはエンティティーが保存する前に発行されます。 このイベントを止めることによって、保存を停止できます。イベントが停止すると、 このイベントの結果が返されます。

ちょっと分かりにくいですが、beforeSave() を止める（※falseを返す）と、save() も失敗しますよ。その場合 beforeSave() の結果を返しますよ、というお話かなと思います。

beforeSave() が false を返したので、save() もそれに従い false を返したという感じですかね？だとすると Entity の errors に何も保存されていないのは当然です。**そもそも保存処理を実行してない**ので。

ただそれだと困るので、何とかしたい。

# いくつか出た案まとめ

## 案1 - 例外を出す

シンプルに BeforeSaveException クラスでも作って失敗したら例外を出す、
BeforeSaveException を catch したら、beforeSave() で失敗したね、って判別出来ます。

```php
namespace App\Exceptions;

final class BeforeSaveException
{
    // 略
}
```

```php
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
    // 略

    throw new BeforeSaveException('beforeSave() に失敗しました');

    // 略
}
```

ただコレだと BeforeSaveException をキャッチする処理を他のクラスに書く必要があるんですよね

あと beforeSave() に複数のエラー判定ロジックがある場合、それぞれを判別できるようにまた新しく Exception を作るのか、もしくは例外メッセージで判別するのか…みたいな。


## 案2 - Entity の errors に突っ込む

普通に Entity の setError() メソッドを利用して、errors に突っ込みます。

Entity の errors にエラーが格納されるので、他のクラスに手を加えなくてもエラーを検知出来ます。

```php
public function beforeSave(EventInterface $event, EntityInterface $entity, ArrayObject $options)
{
    if (
        // 何らかの条件
    ) {
        $entity->setError('beforeSave', 'beforeSave() に失敗しました');
        return false;
    }
}
```

しかし保存処理を実行してないのに Entity にエラーを突っ込んで良いのか？
というか beforeSave() のエラーは Entity に入れるべきなの？という疑問が残ります…いいのかな

## 案3 - Entity の errors に何も入ってなかったら beforeSave() のエラーと考える

さすがにちょっと乱暴すぎる気がしますが…プロジェクトの規模によってはアリかも

# まとめ

弊社では案1と悩んだ挙げ句案2を採用しました
CSSでunsetを使っていたらバグになった話

## unsetとは？
>unset は CSS のキーワードで、プロパティをリセットし、親から自然に継承された場合は継承値、そうでなければ初期値を設定します。言い換えれば、前者の継承プロパティの場合は inherit キーワードのように動作し、後者の非継承プロパティの場合は initial キーワードのように動作します。
>参照： https://developer.mozilla.org/ja/docs/Web/CSS/unset

## 簡単な使い方
例えば、ある要素にmarginとcolorプロパティが設定されているとします。これらのプロパティをリセットしたい場合、以下のようにCSSを記述できます。
プロパティは継承可能か不可の2パターンに分かれています。例えば、下のように継承不可能なプロパティの場合は初期値が設定され、継承不可能な場合は親からの継承値が設定されます。
```css
.element {
  margin: unset; /* marginは継承不可能なので、初期値0が設定される */
  color: unset;  /* colorは継承可能なので、親からの継承値が設定される */
}
```

## バグった話
何も考えずに`position: unset;`を何となく使った際に、`postion`のプロパティは継承されないプロパティのため、初期値が設定されます。
`position`の初期値は`static`なので、実質`position: static`と同じ結果になります。

`postion: static;`が設定された要素は文書の通常のフローに従って配置されます。また、要素が特別な位置付け（relative、absolute、fixed、sticky）から解除され、通常のページレイアウトに従うことになります。

テーブル（一覧表）を描画するライブラリーを使った際に、間違ってドロップダウンの▼マークを`position: unset;`に設定したことがあります。この▼マークは自動生成されるもので、html上はテーブルヘッダーのすぐ下に生成されていました。

本来ですと、`position: fixed; top: -32000px; left: -32000px`で画面上表示されないはずでしたが、`position: unset`にしたせいでZ-indexが設定されたでテーブルヘッダーの下敷きになって見えなくなっていました。最初は気づかなかったのですが、データが増えることによって▼マークもデータの行数分増えてテーブルヘッダーを超えて画面上に現れ、その時にやっと気づきました。

### バグを再現した画像：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3726546/6a62bf64-22be-118d-37ab-e58de91c4540.png)

## 結論
要素に対して`unset`を設定する場合は、使い方をよく理解したうえで実装しましょう。
OpsRamp Logs - Windows Eventlog のサンプル

本記事では、OpsRamp LogsのWindows Eventlogの取り込みについて説明します。

# 概要
OpsRamp Logsでは、Windows Eventlogを取り込むことができます。

# 設定方法
OpsRamp Agentを対象Windowsデバイスにデプロイすると自動的にEventlogを検出し、イベントを取り込みます。(制限していなければ)

- Eventlogサンプル
![eventlog.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/991d2794-dc82-f85a-5e8a-2cd72f332da8.png)

---------------------------------------
[<img width = 250 height = 200 src = "https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2344939/111de30a-4d33-aa33-5c7d-83d9015093e6.png">](https://www.vistanet.jp/knowledge-base/)
Laravelでdatetimeにcastsした値を渡したら、値が異なっていた

## 経緯
受発注の納期を今まで受発注側にあったのを明細側に移したい、という話が出たので修正にかかる。
日付はFlatpickrで扱っているが、何故か編集画面において、表示上の日付とvalueの日付が異なっていたことが発覚。
例）
実際のデータの値：2024-02-02
表示上の値:2024-02-02
hiddenになってる実際にpostされる値:2024-01-31T15:00.000
みたいな感じ。

## 原因
受発注日とかもFlatpickr使ってるのに問題ないのになんでだろ？って思いましたが、心当たりが1つ。
明細部分はlivewireで作成してるんですよね。
で、そちらで扱いやすいように明細部分のデータを渡す際は配列化させたりjson化させたりしてます。
原因はここでした。
下記にある通り、Laravelではjson化した時や配列化した際は、serializeDateメソッドが走ってISO8601に変換されます。...なんで??????？
https://laravel.com/docs/8.x/eloquent-serialization#date-serialization

単純にモデルから
```
    protected $casts = [
        ...
        'delivery_date' => 'datetime',
        ...
    ];
```
部分を消せば解決はできるけど、アクセサとかも直す必要あるからやりたくないなあ...。

## 解決策
というわけで上記にある通りserializeDateをオーバーライド。
明細モデルに
```
    protected function serializeDate($date)
    {
        return $date->format('Y-m-d');
    }
```
を追加することで解決できました。
AWS SOA合格した


2024/02/18にAWS SOAの資格を受験して合格しました。

![スクリーンショット 2024-03-01 19.10.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3510714/d754bd93-ebfd-1628-a943-f08829c65a3b.png)

使った教材はUdemyの資格教材です。問題集を3〜4周ほどしました。

これでAWS関連の資格はSAAとSOAを取得したので次はDVAを取りたいと思います。
あとUdemyの英語教材は翻訳とか使うのが大変だったのでcloudtechさんの教材に変えようかと検討中。
LPIC201対策 - RAID

# この記事について

Linux Level 2 取得を目標としている筆者です。
先日 Level 1 を取得しましたが、短期詰め込みの暗記がしんどかったので、Level2はじっくり時間をかけていいから、ちゃんと理解してやっていきたい。

一方で、暗記も暗記で重要。

ということで、理解を深めるためにと、暗記しやすいように、両方の目的で、覚えたことを Qiita に整理してまとめながら受験対策することにしました。

# この分野で覚えること

## RAIDの基本

RAIDデバイスには /dev/md1 等を使う。

## madmコマンド

LinuxでソフトウェアRAIDを構築・管理するコマンド。
代表的なモードとして、以下のモードがある。

| モード | 説明 |
|:-|:-|
|Create|新規作成|
|Manage|構成デバイスの追加・削除|
|Misc|その他の様々な機能|
|Assemble|RAIDアレイの再編成|

### Create モード

```shell:書式
madm -C|--create 作成策 [オプション] デバイス1, デバイス2 ...
```

オプションには以下を指定する。

| オプション | 説明 |
|:-|:-|
|-l, --level=|RAIDレベルを指定|
|-n, --raid-devices=|利用するデバイス数を指定|
|-x, --spare-devices=|予備デバイス数を指定|

### Manage モード

```shell:書式
madm [--manage] RAIDデバイス [オプション] デバイス1, デバイス2 ...
```

オプションには以下を指定する。

| オプション | 説明 |
|:-|:-|
|-a, --add|構成デバイスを追加|
|-r, --remove|構成デバイスを削除|
|-f, --fail|構成デバイスに不良マークをつける|

:::note warn
障害発生時のハードディスク交換は、-f -> -r -> -a の順で行う。
:::

### Misc モード

mdadm コマンドに以下のオプションを指定すると、 Misc モードとして動作する。

| オプション | 説明 |
|:-|:-|
|-Q, --query|RAIDの状態を表示|
|-D, --detail|RAIDの詳細情報を表示|
|-S, --stop|RAIDを停止|


## /proc/mdstat

RAIDアレイの状態を確認できる仮想ファイル。

```: 構築中の場合
Personalities : [raid6] [raid5] [raid4]

# 稼働中のデバイスをあらわす。予備には(S)がつく（SpareのS）
md0 : active raid5 sdd1[4] sde1[3](S) sdc1[1] sdb1[0]
　　　　#末尾の[3/2]と[UU_]が、3台中2台だけが稼働していることを示す
      12345678 blocs super 1.2 level 5, 512k chunk, algorithm 2 [3/2] [UU_]
      [===========>.............] recovery = 66.6% (999/999) finish=0.4min speed=888K/sec

unused devices: <none>
```

```: 構築完了している場合
Personalities : [raid6] [raid5] [raid4]

# 稼働中のデバイスをあらわす。予備には(S)がつく
md0 : active raid5 sdd1[4] sde1[3](S) sdc1[1] sdb1[0]
      #末尾の[3/3]と[UUU]が、3台とも正常稼働していることを示す
      12345678 blocs super 1.2 level 5, 512k chunk, algorithm 2 [3/3] [UUU]

unused devices: <none>
```

## その他の暗記事項

| 暗記事項 | 説明 |
|:-|:-|
|0xfd|RAIDのパーティションタイプ<br>パーティションタイプの一覧：https://tldp.org/HOWTO/Partition-Mass-Storage-Definitions-Naming-HOWTO/x190.html|
|/dev/md[0-9]|RAIDデバイスの仮想ファイルパス<br>md = Multiple Device|


# 以上！

勉強が進んだら適宜追記・修正などしていきます。
VBAでマジックナンバーをエクセルの「設定」シートに集約する方法

# やり方
「設定」シートからマジックナンバーを読み取り、MainProcedureで使用する方法を以下に示します。
まず、Typeステートメントを使用してマジックナンバーの構造を定義します。

```VB
'Typeステートメント(構造体）
Type MagicNumbers
    magicNumberA As Integer
    magicNumberB As Integer
End Type
```
設定シートからマジックナンバーを読み取る関数
```VB
Function ReadMagicNumbersFromSettingsSheet() As MagicNumbers
    Dim settingsSheet As Worksheet
    Dim magicNumbers As MagicNumbers
    
    ' "設定"シートを参照
    Set settingsSheet = ThisWorkbook.Sheets("設定")
    
    ' マジックナンバーを読み取り、構造体に設定
    magicNumbers.magicNumberA = settingsSheet.Range("A1").Value
    magicNumbers.magicNumberB = settingsSheet.Range("B1").Value
    
    ' 構造体を返す
    ReadMagicNumbersFromSettingsSheet = magicNumbers
End Function
```
使う側の関数
```VB
Sub MainProcedure()
    Dim magicNumbersInstance As MagicNumbers
    
    ' 設定シートからマジックナンバーを読み取る
    magicNumbersInstance = ReadMagicNumbersFromSettingsSheet()
    
    ' マジックナンバーをデバッグウィンドウに表示
    Debug.Print "Magic Number A: " & magicNumbersInstance.magicNumberA
    Debug.Print "Magic Number B: " & magicNumbersInstance.magicNumberB
    
    ' 他の処理にマジックナンバーを渡すこともできます
End Sub
```
フロントエンドを触る上でデザイナーが知っとくと便利なjs知識

※現職を退職するにあたって、2020年に社内ナレッジ置き場で書いたものを転載していますので、クラスコンポーネント前提だったりと古い情報が含まれます。機会があれば随時修正します。

# どんな内容？

Reactコンポーネントのファイルも生成できる化け物じゃないけど、「Reactファイルにデザイン当てて」言われたときにエンジニアから見てデザイナーに知ってもらうと便利そうなことをまとめました。

エンジニアはデザイナーさんにはReact内のHTMLとCSSだけ触ってもらえれば超嬉しいんですが、それらがReactディレクトリの奥深くに埋まっているので、そのファイルにたどり着くまでの知識が書いてあります。

https://qiita.com/setsumaru1992/items/87f93f1f2e5d1bce3fa9

https://qiita.com/setsumaru1992/items/07f36ac0e3d6644bd8d6

https://qiita.com/setsumaru1992/items/26081f243af933f52b06

1が一番肝で、これがわかればそれなりに仕事で使うコードが読めるようになると思います。
ただ、ちゃんといじるとなると2,3がわからないといけなくなるので、理解度に合わせて読んでみてください。
【備忘】今更ですがTCP/IPモデルとは？

## TCP/IPモデルとは
### ざっくりお伝え
通信機能をどのような仕組みにするのかを整理した共通ルール。
⇒米国国防高等研究計画局（DARPA）が作ったデータ通信機能におけるモデルのこと

### 詳細
詳細は[OSI参照モデル](https://qiita.com/MaSi1031/items/d9465240dd60eae1c86f)と類似している部分あるが、OSI参照モデルとの違いは、**4つの階層**で構成されていること。

## TCP/IPモデルの4つの階層

| 階層       | 説明                                                         |
|------------|--------------------------------------------------------------|
| アプリケーション層 | ユーザーとのインタラクションを担当し、アプリケーション間の通信を可能にします。例: HTTP、FTP、SMTPなど |
| トランスポート層  | データの転送とエラーの制御を担当します。データをセグメントに分割し、信頼性の高いデータ転送を提供します。例: TCP、UDP |
| インターネット層  | データの送信元から送信先へのパケットの転送を担当します。IPアドレスを使用してルーティングを行います。例: IP、ICMP |
| ネットワークインターフェース層 | 物理的な接続とデータのフレーム化を担当します。ネットワーク上でデータを送受信するために必要な機能を提供します。例: Ethernet、Wi-Fi |

## OSI参照モデルとの違い
TCP/IPモデルとOSI参照モデルがあり、どちらも「**通信機能を定義したもの**」であるのですが、違いとしては大きく分けて2点ある

1)作成した団体
・OSI参照モデル：**国際標準化機構（ISO）**
・TCP/IPモデル：**米国国防高等研究計画局（DARPA）**

2)階層の違い
・OSI参照モデル
第7層：アプリケーション層
第6層：プレゼンテーション層
第5層：セッション層
第4層：トランスポート層
第3層：ネットワーク層
第2層：データリンク層
第1層：物理層

・TCP/IPモデル
第4層：アプリケーション層
第3層：トランスポート層
第2層：インターネット層
第1層：ネットワークインターフェイス層
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1303394/7ef88357-34ce-4e9b-fc77-128950ad15e1.png)


参考情報
https://wa3.i-3-i.info/diff322model.html
https://ryonotes.com/difference-between-osi-and-tcpip/

### 結局の違いは？
大きな違いは見られないが、下記と
・OSI参照モデルは全体の基準を作成するための「名目上の」標準。
・TCP/IPモデルは、多くの方で活用されている「事実上の」標準。
⇒要は**大枠での標準**か**実際に活用している標準**科の違いと思われる

参考情報
https://wa3.i-3-i.info/diff322model.html

## まとめ
・OSI参照モデル:全体の基準を作成するための大枠での標準
・TCP/IPモデル:、実際に活用している標準
ABC備忘録【AtCoder Beginner Contest 342 D - Square Pair】2

# はじめに
https://qiita.com/Yporon/private/32abbb9942441070194c

この記事を投稿したのですが、もっと簡単に書けるやり方があったのでそちらも残しておきます。

# 考え方
前回の記事では、平方数である条件を「素因数の指数が全て偶数であること」と扱い、素因数分解を用いて指数が奇数となる素因数のペアを作成することで答えを求めました。
今回は、事前に与えられた数字を先に平方数で割れるだけ割っておいて、その結果が等しいもの同士のペアを作成するやり方で答えを求めます。

参考解説

https://atcoder.jp/contests/abc342/editorial/9365

# コード
```python
import sys
from collections import defaultdict
import math


# 平方数で割り続ける
def divide_square(n):
    if n == 1:
        return 1
    for i in range(2, int(math.sqrt(n)) + 1):
        square = i * i
        while n % square == 0:
            n //= square
            if n == 1:
                return 0
    return n


N = int(sys.stdin.readline())
l = list(map(int, sys.stdin.readline().split()))

dictionary = defaultdict(int)
for number in l:
    if number != 0:
        n = divide_square(number)
        dictionary[n] += 1

zero_count = l.count(0)
pair_count = zero_count * (N - zero_count) + zero_count * (zero_count - 1) // 2
for n, count in dictionary.items():
    if n == 1:
        # 1と平方数との積は必ず平方数となる
        pair_count += count * dictionary[0]
    pair_count += count * (count - 1) // 2

print(pair_count)
```

# 終わりに
平方数で割っていった商が同じもの同志の積は平方数になるという考えは、言われてみれば当たり前ですけどまるで気付けなかったので勉強になりました。
フロントエンドを触る上でデザイナーが知っとくと便利なjs知識〜2. jsx内にに書かれそうなjsの記法〜

※現職を退職するにあたって、2020年に社内ナレッジ置き場で書いたものを転載していますので、クラスコンポーネント前提だったりと古い情報が含まれます。機会があれば随時修正します。

親記事

https://qiita.com/setsumaru1992/items/f9263eeab5c651471fca

大抵下記の記事の知識があればデザインをあてられるんですが、
エンジニアがjsxを書くところに書いてしまうエンジニアチックなコードがあり、いずれ向き合うだろうと思うので、説明しておきます。

https://qiita.com/setsumaru1992/items/87f93f1f2e5d1bce3fa9


- `{}`
- 三項演算子
- `this.~(~)`
- `true/false`
- `{ ~ && ~ }`・`{ ~ || ~ }`(ComingSoon)
- `map`(ComingSoon)
- `React.Fragment`(ComingSoon)

### `{}`
jsx、つまりjsで書けるHTMLの中でjsの記法が書けるところ
```jsx
const age = 17;
return (
  <div>年は永遠の{age}歳です！ (本当は{age + 25}歳です)</div>
)

// ↓
//  <div>年は永遠の17歳です！  (本当は42歳です)</div>
```

## 三項演算子
if文を1行でも書ける便利なやつ。
`(条件) ? (合致した場合) : (合致しなかった場合)`という書き方
```js
const message = 年収 > 1000万 ?  '結婚してください' : '去れ、ドブネズミ';
```

## `this.~(~)`
メソッド(関数)呼び出し。
`render`メソッドと並列に並んでいるものを呼ぶ。
`onClick={this.~}`ならクリックイベントを呼ぶくらいなので、デザイナーさんは気にしなくていい。
しかしjsx書いてあるところに書いてあったら、デザイナーさんも追う必要がある。そのメソッドのreturnのところで書いているjsxをその部分で描画しているから。

呼んでいるメソッドのreturnのところだけ見ればOK

```jsx
  private displayCountComponent(displayCount: number){
    const itemCount = 100;
    if(itemCount === displayCount){
      return (<strong>{displayCount}</strong>)
    } else {
      return(<a>{displayCount}</a>)
    }
  }

  public render(){
    return (
      <div>
        表示件数
        {this.displayCountComponent(25)} | {this.displayCountComponent(50)} | {this.displayCountComponent(100)} | {this.displayCountComponent(200)}
      </div>
    )
  }
// ↓
// <div>表示件数　<a>25</a><a>50</a><strong>100</strong><a>200</a></div>
```
※大体こんなことしているときは複雑なことをしているので、エンジニアにそのメソッドでどういうときにifの方呼んで、どういうときにelseの方を呼ぶのか聞く必要がありそうです。
エンジニアはそこはコードを読めばわかるということでコメントを書かないので（このレベルを書くと、全部にコメントをあてなければいけなくなるという理由から）。
（デザイナーさんには申し訳ないんですが。デザイナーさんがデザイナーさんに向けたエンジニアコードに対するコメントはメンテナンス性が上がるので歓迎です。）
wslをwindowsにインストールしてlinuxを動かす

## やりたい事
ウインドウズにunixを入れてドッカーを動かしたい。

・事前準備
ドッカーデスクトップインストール
https://docs.docker.com/desktop/install/windows-install/

## wslインストール
WSL (Windows Subsystem for Linux) 
コマンドプロンプトの拡張版がパワーシェル。
今回はパワーシェルを使います。
```powershell:powershell
wsl --install
```

ユーザー名とパスワードを聞かれるので設定する。
```powershell:powershell
Enter new UNIX username: *** 
New password: ***
Retype new password: ***
```

## よく使うコマンド
wsl シャットダウン
```powershell:powershell
wsl --shutdown
```

wsl 立ち上げ
```powershell:powershell
wsl
```

wslを立ち上げた後はlinuxのコマンドを使います。

```powershell:powershel wsl内
cd ~

git clone ***
```
Nuxt3 - SheetJs で JSON をエクセルファイルに変換してダウンロードする

# インストール

```
npm i --save https://cdn.sheetjs.com/xlsx-0.20.1/xlsx-0.20.1.tgz
```

参考:

https://docs.sheetjs.com/docs/

# コード例


```vue
<script setup>
import { ref } from 'vue'
import { utils, writeFileXLSX } from 'xlsx'

const pres = ref([
  { name: 'George Washington', birthday: '1732-02-22' },
  { name: 'John Adams', birthday: '1735-10-19' },
])

function exportFile() {
  const ws = utils.json_to_sheet(pres.value)
  const wb = utils.book_new()
  utils.book_append_sheet(wb, ws, 'Data')
  writeFileXLSX(wb, 'SheetJSVueAoO.xlsx')
}
</script>

<template>
  <button @click="exportFile">Export XLSX</button>
</template>
```

# 動作例

<img width="1112" alt="image" src="https://github.com/YumaInaura/YumaInaura/assets/13635059/aa7a06a0-60ec-41e4-b541-68bdcfbe0dbf">


# 参考

https://docs.sheetjs.com/docs/getting-started/examples/export/

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
フロントエンドを触る上でデザイナーが知っとくと便利なjs知識〜1. Reactで使うjsファイル・JSX・コンポーネントについて〜

※現職を退職するにあたって、2020年に社内ナレッジ置き場で書いたものを転載していますので、クラスコンポーネント前提だったりと古い情報が含まれます。機会があれば随時修正します。

親記事

https://qiita.com/setsumaru1992/items/f9263eeab5c651471fca

# ReactとかJavascriptに関する知識
- `js`, `jsx`,`ts`,`tsx`,などあるが、基本的に全部jsと思えばOK。
    - `jsx`はざっくりいうとReactで管理するHTMLが書けるjs
    - `ts`,`tsx`の`ts`はtypescriptというjavascriptの方言
- `index.js`はそのディレクトリ内の全ての取りまとめ役
    - 下記の例だと、`index.tsx`が`SearchButton`とかの部品の取りまとめ役になっている

```
SearchForm
├── SearchButton.tsx
└── index.tsx
```

## 前提
デザイナーさんは、Reactを最初からちゃんと理解できなくて大丈夫です！
ReactはHTMLを書く以上にボタン押したときの挙動とか色々カスタマイズできますが、
まずはHTMLが書かれる場所だったりとか、jsファイルにどう書けば実際の画面でどうHTMLが展開されるかだけ分かれば、少なくともエンジニアと分業できます。
（それ以上はエンジニアがやるので）

## HTML(jsx)を書く場所は大きく2つあります
デザイナーさんがファイルの中で見る場所はjsファイルのHTML(jsx)部分です。それが書かれる場所は「関数コンポーネント」と「クラスコンポーネント」の2つがあります。

コンポーネントとは、HTMLタグで括られたHTMLのブロックのことを言います。

これはわかった人用のまとめなので、詳しくはエンジニアに「ここに書いてあることってどういうことですか、デザイナーは何だけ知ってればいいですか」って聞けばわかると思います。
車輪の再発明するにも長すぎて書きたくないので結構割愛しました。

### 関数コンポーネント
```tsx
const SearchForm = (props: Props) => {
  ...
  return ( // ←htmlっぽい表記が書かれた関数の`return`の()の中
    <div>

    </div>
  )
}
export default SearchForm;  // ← jsの中でexportってやつをしたものは他のファイルから参照できます。
```

### クラスコンポーネント
```tsx
class SearchForm extends React.Component {
  render(
  ...
    return ( // ←React.Componentのブロックにあるhtmlっぽい表記が書かれたrender関数の`return`の()の中
      <React.Fragment>
  
      </React.Fragment>
    )
  }
}

export default SearchForm;
```

コンポーネントがreturnで返すjsxは1つのタグで囲われている必要があります。
コンポーネントごとに\<div>タグとかHTMLタグで囲うのが嫌であれば`<React.Fragment></React.Fragment>`とか`<></>`で囲えばコンポーネントを囲う用のタグがHTML描画時に表現されません。
（`<></>`は`<React.Fragment></React.Fragment>`の省略版）


## Railsで言うところの、html.erbのパーシャル的なことできます
```News.tsx
import React from 'react';
import Title from './Title.tsx' // ←入れ子にしたい部品コンポーネントのインポート

export default function News(props: Props) {
  return (
    <div>
      <Title /> // ←入れ子にしたい部品コンポーネントの使用
      <Content />
    </div>
  )
}
```
```Title.tsx
import React from 'react';

export default function Title(props: Props) {
  return (
    <div>
      タイトーーーーーーーーーーール
    </div>
  )
}
```

## 最低限の命名規則
※class属性(className属性)についてはデザイナーさんの領分なので、デザイナーフレンドリーに付けてもらって大丈夫です。
jQueryなどDOM要素を使った処理を使っていた時代はエンジニアもclass属性を使っていたんですが、今はもう使ってないので。

class属性以外の命名規則、というか大文字小文字の扱いについてメモっておきます。

### js関連のディレクトリ内(js,jsx,ts,tsx)
*   変数: camelCase
    *   let camelAge = 3
*   定数: UPPER_SNAKE_CASE
    * const JAPAN_TAX = 1.1
*   クラス名: PascalCase
*   ファイル名(CSS含む): PascalCase
    *   export する class 一つに対して一つのファイルを作成する場合に、PascalCase のクラス名をそのままファイル名に用いる。
    *   class を export しない場合は camelCase になる
        *   主に index.ts だけ覚えておけば良い。
*   jsx(html)のclass属性: BEM記法

*   ケース説明
    *   PascalCase
    *   camelCase
    *   snake_case
    *   kebab-case

### (参考)Ruby ・Rails
基本：スネークケース (ex search_form)
クラス名・コンポーネント名：パスカルケース (ex SearchForm)
定数：アッパースネークケース(ex SEARCH_FORM)
エクセルで特定セルの編集をロックする場合、シート保護は必須である

# 概要

エクセルでは
「シートの保護設定を有効にした時に、セルの書式設定でロックがオフになっているものは、特別に編集が可能」
という仕様のようだ。

つまり、シートを保護せずにセルをロックしただけでは、編集は可能なままということのようだ。

# STEP1. セルのロックを無効にしておく

特定のセル、あるいは列などを選択して「書式設定」からロックを無効にする

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/86064bbb-ff5b-4b19-875e-da10e31e45bf)

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/afaef40f-ee15-4a85-924a-2d683ff00a88)

# STEP2. シートを保護する


![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/4d0badc4-eb35-42d1-8dd3-e9f143952572)

## パスワード

パスワードは入力しなくても良い。
パスワード設定した場合は、シートの保護解除の時にパスワードが必要になる。

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/716a6bb4-33c3-487a-8373-d2aa4d0c8073)

# STEP3. 動作の確認

## ロックが有効なセルは編集できない

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/461bf551-ea02-498a-a803-588ffee70627)

## ロックが無効なセルは編集できる

![image](https://github.com/YumaInaura/YumaInaura/assets/13635059/6f1ff03e-c805-47a0-b9ae-e0207fc35b01)


# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ


# プロフィール・経歴

https://github.com/YumaInaura/YumaInaura
pyYAMLで読み込み時に動的に変わる設定ファイルを書く

# TL;DR
```yaml
- !!python/object/apply:eval ['hogehoge']
```

# なぜそんなことを

[mkDocs]()で文書を作ってて、最終更新日時を自動で埋め込みたくなった。

# pyYAMLの黒魔術

YAMLで設定ファイルを書く系のpython製ツールの多くはpyYAMLを使って設定ファイルを読んでいるが、pyYAMLにはデータ型を指定したりするためのタグによる拡張が含まれている。

[YAML tags and Python types - PyYAML Documentation](https://pyyaml.org/wiki/PyYAMLDocumentation#yaml-tags-and-python-types)

この中の `!!python/object/apply` を使うと、限定的ではあるけど、pythonの関数呼び出しが実現できる。

# 使えそうな関数

## os.getenv
```yaml
!!python/object/apply:os.getenv ['環境変数名', 'デフォルト値']]
```
環境変数を取り込める。あとは `mkdocs build` を呼び出すラッパースクリプトにでも値を入れれば好きな値を注入できる。

## operator.add, operator.concat
```yaml
!!python/object/apply:operator.add [文字列1, 文字列2]
```
他のタグで作った文字列を他の文字列と連結できる。なお、2項演算子の関数化でしかないので、リストに3つ文字列を入れると容赦なくエラーになるので、適宜入れ子にする必要がある。

## eval
```yaml
!!python/object/apply:eval ['python statement']
```
呼び出し元でimportされていないモジュールを使うとかでない限り、ほぼ何でもできる。これを知ってれば↑のは実は要らないけど、気持ち悪いのは理解できる。

# 最終的にこんな風になった
```yaml:mkdocs.yml
copyright: !!python/object/apply:operator.concat ['<a href="hogehoge">hogehoge</a><br>Last Modified: ', !!python/object/apply:eval ['datetime.date.today().isoformat()']]
```
copyrightに著作権表示以外のものを放り込んでいるのはご愛敬。
get_conf関数のエラーについて

## エラーの内容

前回の記事で書いたことが間違っていた感じがするので，投稿し直す．
 
 https://qiita.com/shunya_tadano/items/79f42a4d076de107929a

```shell: エラー内容
Traceback (most recent call last):
  File "parser.py", line 11, in <module>
    from utils.helpers import get_conf
ModuleNotFoundError: No module named 'utils'
```

## 使用環境

今回は ROS は関係ありませんが，一応載せます．

- 使用PC: Jetson AGX Orin
- JetPack: 5.1.2
- CUDA: 11.4
- cudnn: 8.6
- python: 3.8
- tensorflow: 2.12.0
- ubuntu 20.04
- ROS noetic
- 仮想環境`venv`を使用

## 解決方法： utils を使用する．

まずは`utils`をインストール

pathは`/home/usr_name/catkin_ws/venv/lib/python3.8/site-packages/utils`でした．

```shell: インポート
pip3 install utils
```

`utils`内の`helpers.py`に`get_conf`関数を勝手に挿入．（今回は`yaml`ファイルを読み込無用に作成）

```python: helper.py
import yaml

def get_conf(config_path):
    """YAML形式の設定ファイルを読み込んでその内容を返す関数

    Args:
        config_path (str): 設定ファイルのパス

    Returns:
        dict: 設定ファイルの内容を含む辞書
    """
    with open(config_path, 'r') as config_file:
        config = yaml.safe_load(config_file)
    return config

```

そうしたら，path を通してインポート．
実行したらできるはず．

```python: 実行したいスクリプト
import sys
sys.path.append('/home/usr_name/catkin_ws/venv/lib/python3.8/site-packages/utils')

from utils.dicts.helpers import get_conf
```


## おわりに

また分かり次第メモしていきます．
Datadog APMで測定するアプリケーションパフォーマンス

# 運用で困っていること

- インフラで発生するインシデント（メールが送られない、画面表示が遅いなど）が発生しても、即座の原因特定が難しい
- イベント（画面表示やデータ登録）ごとの発生頻度や利用時間帯がつかめない
- 時系列的に記録されたログでは、複数同時に来るリクエスト処理がごちゃごちゃに記録され、特定の関心のあるリクエストだけを追うのが難しい
- 処理が複数のサービスに分散されていると、関心のある処理を追いづらい

# Datadog APMとは

- Datadog社が提供する、アプリケーションのパフォーマンスをリアルタイムで監視し、分析するためのツール（SaaS）
- ユーザーのリクエストがシステムを通過するパスを追跡し、各モジュールでの処理時間を把握できる
- アプリケーションのパフォーマンスを監視し、異常が発生した場合に検知
- 詳細なレポーティング
- 分散システムのサポート

# 実際に組み込んでみた

ソースコードでライブラリを組み込む必要がある（Goの場合）

```go
// アプリケーション開始時
tracer.Start(tracer.WithServiceName(serviceName))
defer tracer.Stop()
```

```go
// データベース接続時
sqltrace.Register("mysql", &mysql.MySQLDriver{}, sqltrace.WithServiceName(serviceName))
db, err := sqltrace.Open("mysql", "datadog_sample:password@tcp(db:3306)/db_test", sqltrace.WithServiceName(serviceName))
if err != nil {
    logger.Error("failed to connect mysql", slog.Any("error", err))
    return
}
defer db.Close()
```

それ以外にも、datadog-agentの設定でAPM有効化を行う必要がある

# 適用後に見られる画面

## サマリ

![unnamed.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052/dfd9872a-c248-2a27-b9a3-7ed4d5d4370c.png)

リクエスト数、エラー数、レイテンシ、処理内訳が確認できた

## トレース

![unnamed (1).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052/77bc59b8-c498-5cdb-8a32-bacafd0c87b9.png)

適切に設定すれば、アプリケーションでかかった時間だけでなく、外部システム（DBやマイクロサービス）の呼び出し時間や処理内容もわかる。
メソッドごとの処理時間も、スパン（処理単位）を設定すればわかる。

## ログ

![unnamed (2).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2052/cdf284b9-2f55-72cb-9224-0572831f9c17.png)

適切に設定（span_idとtrace_idをログに出力しdatadogへ送信）すれば、リクエストごとに、紐づいたログを参照できる

# 今後の課題

- 本番環境への全体的な適用（ソースコード修正が必要）
　Goだとcontext.Contextというパラメータに、APM設定用の情報を設定し、リクエストを受け付ける処理からDBやAWS操作処理まで引き回す必要がある
　各サービスで修正する必要がある
- 各イベントの時間帯ごとの発生頻度を出す方法は調査中

# 終わりに

この記事は2024年2月15日行われた「第３木曜LT会#2」で発表した内容に加筆したものです。
渋谷スクランブルスクエアWeWorkで毎月第３木曜日にLT会を行なっていますので、ぜひご参加お願いします！

https://metaps.connpass.com/event/310598/
よく使うLinuxコマンド

## はじめに
よく使うLinuxコマンドをまとめました！

ターミナルの操作に慣れていない方（＝自分）を読者に想定し、初心者が最初に覚える基本的なコマンドを取り上げています。
また、chmodコマンドに付随して、パーミッションにも軽く触れました。


## ディレクトリ
ディレクトリの作成
```
# make directoryの略
mkdir ディレクトリ名
```

カレントディレクトリの確認
```
# print working directoryの略
pwd
```

ファイルやディレクトリ一覧の表示（カレントディレクトリ内）
```
# list segmentsの略
ls

# ① ファイルやディレクトリの詳細を表示する
ls -l

# ② 隠しファイルも含めて表示する
ls -a

# ①②の組み合わせ　（よく使う便利コマンド！）
ls -la
```

階層を移動する（カレントディレクトリを変える）
```
# change directory
cd

# １つ上の階層へ移動する
cd ..

# 1つ下の階層へ移動する
# 移動先は、ファイル頭文字 ＋ tabキーで補完入力できる
cd 移動先
```


## vi（テキストエディタ）
viエディタを開く（ファイル名が存在しない場合は、新規作成される）
```
vi ファイル名
```

入力モードにする（現在のカーソル位置から入力する）
```
# insertの略
i
``` 

コマンドモードにする
```
ESCキー
```

ファイルを閉じる
```
# 変更を保存し、viは終了しない
:w

# 変更を保存し、viを終了する
:wq

# 変更を保存しない
:q!キー
```

viを開かずにファイルの中身を確認する
```
cat ファイル名
```


## パーミッション（実行権限）
### パーミッション対応表
| フラグ | 数値 | 意味 |
|:-:|:-:|:-:|
| --- | 0 | すべて不可 |
| --x | 1 | 実行 |
| -w- | 2 | 書き込み |
| -wx | 3 | 書き込み、実行 |
| r-- | 4 | 読み込み |
| r-x | 5 | 読み込み、実行 |
| rw- | 6 | 読み込み、書き込み |
| rwx | 7 | 読み込み、書き込み、実行 |

### パーミッションの確認
```
ls -l
>>> rw-r--r--
```
パーミッション対象は、3種類
左側から3桁ずつ、①所有者 ②所有グループ ③それ以外


### パーミッションの変更
```
chmod 〇〇〇

# 例：管理者に書き込み権限を付与
chmod 400
```


## 参考サイト
### Linuxコマンド全般
- https://qiita.com/taji-taji/items/0b4bcccf097371bc143c
- https://qiita.com/nokonoko_1203/items/35c4078bf72cffb16171
- https://qiita.com/arene-calix/items/41d8d4ba572f1d652727

### ls
- https://eng-entrance.com/linux_command_ls
- https://linuxfan.info/ls

### vi
- https://atmarkit.itmedia.co.jp/ait/articles/1712/20/news004.html
- https://eng-entrance.com/linux-command-vi

### chmod
- https://www.sejuku.net/blog/50161
- https://atmarkit.itmedia.co.jp/ait/articles/1605/23/news020.html
4つ目のPRでようやく Next.js にコントリビュートできた話

## 短くまとめると
Next.js で Server Action の redirect のバグがあったから直したよ。

## 教訓
・テストやリントを通さないとPR は通りにくい
・PR を送る時はバッチなだけではなくて、バグの原因も書くといいかもしれない
・ある程度腕に自信があるなら、good first issue ではなくて、普通にissue からバグの調査をしよう

## 経緯
#### 普段してたこと
去年の12月からNext.js のコードを読むようになり、年初と2月の初めにパッチとしてPR を合計3つ出していました。
good first issue は他の人が取り組んでいるものばっかりだったので、issue を一から調査する形でパッチを作っていました。
ただテストやリントを通すことを、

https://oisham.hatenablog.com/entry/2021/12/03/002156

この記事を見るまでしてなかったので、あまり芳しくない結果でした。
ただ issue の調査を通して、Nextjsへの解像度を上げてはいたと思います。

#### Server Action のredirect のバグのissue を調査し始める
たまたま この issue を見つけて、

https://github.com/vercel/next.js/issues/62525

Server Action は読み飛ばしてた場所でしたが、調査することにしました。
最初はServer Action をよく理解しておらず、client の調査という違う方向に進んでしまったのですが、ちゃんとServer Action を調べると、一ヶ月前のコミットで 

https://github.com/vercel/next.js/commit/93e4bb823ccb6452ba591e29a3ec0b258b3a9b5c#diff-c809d50461027cdba7c092e564818b1172133d337abc5c513f829c94c8483dc6R186

SearchParams を考慮できてないことが原因になってました。
なので、SearchParams を追加したPRを作りました。

https://github.com/vercel/next.js/pull/62582

#### メンテナからすぐ連絡が来る
テストとリントを通して、バグの原因も調査していたので、今までのPRとは違って、メンテナからの連絡はすぐ来ました。

![IMG_0290.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92647/36414a8b-6feb-2dbb-92a2-70d3ec266657.jpeg)


テストを作って欲しい、とメンテナの方は言ってました。
自分はテストは数が多すぎてどこを修正すればいいか皆目分からなかったのですが、メンテナがちゃんとURLを送ってくれたので、テストも無事かけました。

#### 1日待つと
朝起きたら、なんとPRがアプルーブされてるではないですか！（よく見ると自分の修正も少し修正されてましたが。）

![IMG_0291.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92647/7e086c6a-339e-e966-d651-e0224e43f585.jpeg)


少し経ったら、マージされました。
こうして、初のNext.js へのコントリビュートが出来ました。

## まとめ
今回のPR はリントとテストを通して、原因も調査して書いてたのが功を奏したのだと思います。
自分のような実務一年ちょいのよわよわエンジニアでも、根気を持ってNextjsという大規模なコードを読めば、バグを修正してコントリビューターになれたので、皆さんも挑戦してみるといいと思います！
Bashプロンプトをいじくり回してみる

個人的なLinuxの復習のため色々やってみる。

```
[ec2-user@ip-10-0-2-106 ~]$ 
```
今回の環境のデフォルトがこれ。
bashのプロンプトはPS1という環境変数によって設定される。
```
[ec2-user@ip-10-0-2-106 ~]$ echo $PS1
[\u@\h \W]\$
[ec2-user@ip-10-0-2-106 ~]$ 
```

なのでこれを変えてみる。
まずはホスト名(の一部)が入る箇所を一時的に変更してみる。

```
[ec2-user@ip-10-0-2-106 ~]$ export PS1="[\u@prompt_test \W]\$ "
[ec2-user@prompt_test ~]$ 
```

即時反映され、ホスト名が表示されてた箇所に`prompt_test`という文字列が表示されるように。
ただしこれは一時的な設定なので例えばログインし直すと元に戻る。
```
[ec2-user@ip-10-0-2-106 ~]$ 
```

次は`~/.bashrc`に追記して恒久設定としてみる。
```
[ec2-user@ip-10-0-2-106 ~]$ echo 'export PS1="[\u@prompt_test2 \W]\$ "' >> ~/.bashrc
```

今回の環境では`~/.bashrc`はログイン時に読み込むようになっているので、次回以降のログインではログイン時点で反映されている。
```
[ec2-user@prompt_test2 ~]$ 
```

もちろん`source`コマンドで`~/.bashrc`を読み込ませて即時反映させることも可能

```
[ec2-user@prompt_test2 ~]$ sed -i -e '$d' ~/.bashrc
[ec2-user@prompt_test2 ~]$ echo 'export PS1="[\u@prompt_test3 \W]\$ "' >> ~/.ba
shrc
[ec2-user@prompt_test2 ~]$ source ~/.bashrc
[ec2-user@prompt_test3 ~]$ 
```
ちなみに`sed -i -e '$d' ~/.bashrc`はファイルの最終行を削除して上書きしている。

最後に超シンプルにしてみる。
```
[ec2-user@prompt_test3 ~]$ sed -i -e '$d' ~/.bashrc
[ec2-user@prompt_test3 ~]$ echo 'export PS1="$ "' >> ~/.bashrc
[ec2-user@prompt_test3 ~]$ source ~/.bashrc
$ 
```

…何かのNW機器とかでたまに見かけた気がする。
これはこれで。

---
参考文献

- [Bashプロンプトの変更](https://qiita.com/zaburo/items/9194cd9eb841dea897a0)
- [bashのプロンプトを変更するには](https://atmarkit.itmedia.co.jp/flinux/rensai/linuxtips/002cngprmpt.html)
- [sedで最後の行だけ削除する](https://bettamodoki.hatenadiary.jp/entry/20120130/1327902360)
Vim の「CTRL-O」「CTRL-I」コマンドの直感的な覚え方とジャンプ機能について


## 経緯

Vimを使っている際、ジャンプモーションを戻るためのコマンドをいつも忘れてしまう。
特に`ctrl + o`や`ctrl + i`のキーバインドが直感的でなく、なかなか記憶に残らなかった。
そこで、これらのコマンドについて詳しく調べ、しっかりと理解することにした。

## コマンドの覚え方

- `ctrl + o`: ジャンプ前の位置に戻る
- `ctrl + i`: 取り消したジャンプ操作を再実行

ChatGPTに相談したところ、以下のような覚え方を提案された。
- o は "Older Position"（以前の位置）を表し、
- i は "Incoming Position"（次の位置）を意味する。

これらのニーモニックを使えば、コマンドの機能を直感的に覚えやすくなる。

## ジャンプリストについて

調べたところ、`ctrl + o`や`ctrl + i`がジャンプリストを利用していることがわかった。ジャンプリストはVimの機能の一つで、過去のカーソルの位置を記録しておくリストである。このリストを`:jumps`コマンドで確認することができる。

## チェンジリストジャンプ

ジャンプリストの中でも、特に編集操作が行われた後の位置は、チェンジリストジャンプとして別に管理される。これは`:changes`コマンドで表示可能で、`g;`と`g,`コマンドを使って、それぞれ最後の変更箇所に戻ったり、やり直したりすることができる。

## 参考リンク

- [Vimドキュメント - ジャンプモーション](https://vim-jp.org/vimdoc-ja/motion.html#jump-motions)
- [Vimのジャンプリストとチェンジリストの使い方](https://baubaubau.hatenablog.com/entry/2020/09/19/203537)
## 参考

https://vim-jp.org/vimdoc-ja/motion.html#jump-motions

https://baubaubau.hatenablog.com/entry/2020/09/19/203537
[Google Sheets API] セルを挿入・削除して、既存のセルを移動させる

Google Sheets API v4（Java）を使用して、
スプレットシートにセルを挿入または削除して、既存のセルを移動させる方法
についてご紹介します。

挿入は、
メニュー：「挿入」 ⇨ 「セル」 ⇨　「セルを挿入して既存のセルを右・下に移動」
で実行できる内容と同じです。

削除は、
メニュー：「編集」 ⇨ 「削除」 ⇨　「セルを削除して既存のセルを上・左に移動」
で実行できる内容と同じです。

:::note info
APIを利用する環境の準備から始める場合や、コードを実行する際は、
[⧉[Google Sheets API] Google Sheets API v4をJavaで操作する](https://qiita.com/doran/items/3d43f776188b2281044c)
を参照ください。
```java
//例：
requests.add(moveDimension(sheetId)); //実行したいリクエストのMethodを指定
```
:::

:::note info
その他のGoogle Sheets APIは、下記の記事を参照ください。
[⧉[Google Sheets API] JavaでスプレットシートのメニューとAPIを関連づけてみた](https://qiita.com/doran/items/2f6f8932b994fbd1a170)
:::

|No|目次|
|---|---|
|1|[セルを挿入する](#1-セルを挿入する)|
|2|[セルを削除する](#2-セルを削除する)|

## 1. セルを挿入する
セルを挿入して既存のセルを右または下に移動させます。

挿入後の移動の指定はsetShiftDimensionメソッドで指定します。
ROWS：下に移動
COLUMNS：右に移動

**サンプル コード**
指定の位置にセルを挿入して既存のセルを右に移動させます。
```java
public Request insertRange(Integer sheetId) {
    Request request = new Request();

    GridRange range = new GridRange();
    range.setSheetId(sheetId);       //設定するシートID
    range.setStartRowIndex(1);       //開始行(0スタート)
    range.setEndRowIndex(3);         //終了行(1スタート)
    range.setStartColumnIndex(1);    //開始列(0スタート))
    range.setEndColumnIndex(3);      //終了列(1スタート)
    
    InsertRangeRequest r = new InsertRangeRequest();
    r.setRange(range);
    r.setShiftDimension("COLUMNS");  //右に移動させる
    
    request.setInsertRange(r);
    return request;
}
```
**実行結果**
画像の選択した位置にセルを挿入します。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/b3038a7e-aafe-2d79-8b5d-695f21d3ec89.png">

セルが挿入され既存のセルが右に移動しました。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/84820696-6b67-322f-f6a5-677670ff684b.png">

## 2. セルを削除する
セルを削除して既存のセルを上または左に移動させます。

削除後の移動の指定はsetShiftDimensionメソッドで指定します。
ROWS：上に移動
COLUMNS：左に移動

**サンプル コード**
指定の位置にセルを挿入して既存のセルを右に移動させます。
```java
public Request deleteRange(Integer sheetId) {
    Request request = new Request();

    GridRange range = new GridRange();
    range.setSheetId(sheetId);       //設定するシートID
    range.setStartRowIndex(1);       //開始行(0スタート)
    range.setEndRowIndex(3);         //終了行(1スタート)
    range.setStartColumnIndex(1);    //開始列(0スタート))
    range.setEndColumnIndex(3);      //終了列(1スタート)
    
    DeleteRangeRequest r = new DeleteRangeRequest();
    r.setRange(range);
    r.setShiftDimension("COLUMNS");  //左に移動させる
    
    request.setDeleteRange(r);
    return request;
}
```
**実行結果**
画像の選択した位置のセルを削除します。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/84820696-6b67-322f-f6a5-677670ff684b.png">

セルが削除され、既存のセルは左に移動しました。
<img width="320" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114621/b3038a7e-aafe-2d79-8b5d-695f21d3ec89.png">

<br>
おしまい。。
怒ってます。Androidの新リリース基準酷すぎる

:::note warn
この記事には、多分に毒成分が含まれます。
:::


最近個人開発アプリを出したんですが、Google Playの審査が厳しすぎたので、怒ってます。

https://choitore.hp.peraichi.com/

## 1. 20人 14日間テスターって、集められるか〜〜！ぼっち、なめんな〜

```
Googleは、2023年11月13日以降に
個人用デベロッパーアカウントを作成した方を対象に、
20人以上のテスターを集め、14日以上連続でオプトインしてクローズドテストを実施することを、
本番環境へのアクセス申請に進むための条件に加えました。
```

20人以上のテスターに、14日以上使ってもらうだと！！
14日も普通にダルいんですが、一番問題なのは20人の方。

だって日本のAndroidシェア率知ってますか?
3割ですよ、20人集めるためには、67人友達必要。
友達67人って、リア充ですか?
リア充以外出すなっていうんですか?

日本の成人男性の平均友達数知ってますか?
自分も知らんけど、「20人 。はい、オッケーです。チャチャっと声掛けして、集めますか！」
っていう人間はSSRってことは、認識してください。

facebookとか、twitterとかSNSで、呼びかけてもそんな集まらないよ。泣
そこまでして、僕の心折りたいんですか。

確かに、個人開発者がバンバンアプリだして、ストアにゴミアプリが並ぶとかありますよ。
ただ、その措置としては、ちょっと過激すぎませんか。
だって、最初は個人開発者って、「10人」の人に使ってもらえたらいいなって思ってアプリ
出すんじゃないんですか?

それで、実際はインストールすら全然されなくて、もしくは、インストールされてもすぐ使われなくなって、「うわ〜、自分よがりなアプリだったな〜。ニーズ考えてなかった〜」
とかいって、改善したり、次のアプリ考えたり考えなかったりするんじゃないんですか?

普通にストアのランキングとか、レビューとかでアプリは利用者がフィルターすればいいと思います。そこを詰むって勿体無いことだと思うんです。
Androidのオープン性を阻害してる気がするんです。

ただ、作ったアプリを世に出してみたいだけなんです。

## 2. テスターの招待フローが難しすぎる。
しかも、しかもですよ。
やっとの思いで、「協力するよ〜」という仏のような方が現れても、その後もやばいです。

- 手順が煩雑
- 英語
- 手順が公式ドキュメントにちゃんと書かれていない

まず手順が煩雑です。

テスター参加するためには、

1. テスターを見つける
2. テスターのGoogle Playのメールアドレス聞く
3. 開発者がメール登録する
4. 開発者がテスター専用ページ案内する。(メール登録したからって、特に自動で、招待メールとか送られるわけではない)
5. テスターがテストに参加する

となります。1~4のやり取り面倒。

しかも、4でテスターに表示される画面は英語。
なんか色々書いてるし、どれがボタンかわからんし、リンクだし、こんなの、非エンジニアの一般人の仏怖くなるわ。

<img width="250" alt="release1" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138863/da412f84-6ef2-26df-d562-8cb6b49fb965.jpeg">

<img width="250" alt="relese2" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/138863/08097882-3f3b-4bf6-55bb-bc79efd921e7.jpeg">


そして、その手順を書いてるドキュメントもない、、、、
流石にいたたまれなくなくなって、自分で書きました。

## 3. 最後に
「20人 14日間テスター」はやりすぎです。しかもフロー煩雑すぎます。
Androidってオープンが売りだったんじゃないんですか? iOSの方が100倍スムーズでした。
流石に、おこです。
というエッセーでした。

Googleさん、もうちょっとどうにかなりませんか。

(お口直しに)
Banしないでね。好きです。いつか誰か、社員食堂連れてってね。
ここまで読んでいただき、ありがとうございました！！
【Docker】コマンドの新旧

# はじめに

Dockerコマンドにはいくつか古い記法があるようです。

なお、ここで紹介する記法はすべて、今現在も使用可能です。
# 短縮系

|      古い記法       |          今の記法           | 機能                                        |
| :-------------: | :---------------------: | ----------------------------------------- |
|  `docker run`   | `docker container run`  | 0. （ない場合は）imageの取得<br>1. コンテナの作成<br>2. 起動 |
|  `docker stop`  | `docker container stop` | コンテナの停止                                   |
|   `docker rm`   |  `docker container rm`  | コンテナの削除                                   |
|  `docker pull`  |   `docker image pull`   | イメージのプル                                   |
| `docker images` |    `docker image ls`    | イメージのリスト表示                                |
|   `docker ps`   |  `docker container ls`  | コンテナのリスト表示                                |
|  `docker logs`  | `docker container logs` | コンテナのログ表示                                 |

## Composeとの競合：`docker run / stop / rm`

問題点：`run / stop / rm`は`container` / `compose` の2つに共通するコマンドです。
短縮形では`container`に対して
## イメージのプル：`docker pull`

今の記法：`docker image pull`

問題点：特になし
`pull`は`image`にのみ使われるコマンドであり、`docker pull`という記法に大きな問題はありません。
統一感の問題で、`docker image pull`と書くと見た目が良く、わかりやすい程度のものです。

## リスト・ログ：`docker images / ps / logs`

今の記法：`docker image ls` / `docker container ls` / `docker container logs`

問題点：特になし
「`image`や`container`といった<font color="Orange">サブコマンド下</font>に`ls`などの<font color="Orange">操作を書く</font>」の方が、わかりやすくはあります。

ちなみに`ps`コマンドはLinux / UNIX系に存在するコマンドで、"**p**rocess **s**tatus"の略のようです。
コンテナ内で実行中のプロセスの状態を確認するということです。

# docker compose系

こちらの記事にも書いています。

https://qiita.com/kohki_takatama/items/83739ce5424069863047

昔の記法：`docker-compose`

今の記法：`docker compose`

問題点：`docker-compose`というのは、dockerとdocker-composeが別のソフトウェアだったころの書き方です。
現在はdockerとして統合されており、`docker compose`の方が適切だと言えるでしょう。

# おわりに

まとめます。
- 短縮された（主要な）コマンドは`pull`と`images`を除いて`container`に関するものです
- `pull`は`image`の`pull`です
- `docker-compose`と`docker compose`には機能上の違いはありません

記事で触れた以外にも短縮されたコマンドはあるかと思うので、
「短縮された（主要な）コマンド」と逃げ道を用意しました。

このほかにも、古い記法、古くないが短縮された記法などありましたら
コメント💬いただけると嬉しいです。

ではまた
Javascript(React) 引数のアンダーバー( _ )の意味

[参考記事：アンダーバーのみの変数の意味
](https://ja.stackoverflow.com/questions/65430/%E3%82%A2%E3%83%B3%E3%83%80%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E3%81%BF%E3%81%AE%E5%A4%89%E6%95%B0%E3%81%AE%E6%84%8F%E5%91%B3)

```javascript
const rotate = a => a[0].map((_, c) => a.map(r => r[c])).reverse();
```

**参考記事より**
>まさにmap関数のindexだけを使いたい場合や、関数から返ってくるエラー情報を使わない時に無理やり変数を使わないと実行できません。
それを回避する方法として、変数名を_とすることで「この戻り値は使いません」と明示すればコンパイル可能になります。

アンダーバーを使う事でmapの引数を使用する際にあえてkeyをつける必要もない時でも、エラーは出てしまう為（keyを設定しなさいと怒られる）、この方法で回避出来る
[2024年版] Gather.town に入室中の人数をSlackに定期的に通知する

リモートワークが当たり前になり、バーチャルオフィスを導入するところも増えていますが、課題となるのがバーチャルオフィスに入っても「**誰もいなくて抜けてしまう**」こと。

それなら誰かが入室したタイミングでSlackに通知すれば、他のメンバーも自ずと入るのではないかと思っていたときに、以下の記事にたどり着きました。

https://qiita.com/sogemaro/items/9ca6b321063f1acc4eb1

しかし、プログラムを拝借してもうまく動かなかったので、仕様が変わった部分を備忘録として残しておこうと思います。

# GatherAPI と Slack と GAS の用意

詳しくは下記を参考にしてください。
記事通りGatherAPIとSlack、GASを用意していただければOKです（sogemaroさんありがとうございます）。

https://qiita.com/sogemaro/items/9ca6b321063f1acc4eb1

# APIの仕様が変わった部分

ここからが本題です。
うまく動かなかった部分と修正方法をピックアップします。

## Gather Space ID

以前はGatherスペースのURLの `app/` 以下をコピペして / (スラッシュ) を \ (バックスラッシュ)に置き換えるだけで良かったのですが、以下の方法でうまくデータを取得できました。

URL例 : https://app.gather.town/app/xxxxx/yyyyy

### Before

```javascript:@sogemaroさん記事より
// GatherのSpace IDを設定
const GATHER_SPACE_ID = 'xxxxx\yyyyy'; //スラッシュ(/)→バックスラッシュ(\)に変更
```

### After

```javascript:修正版
// GatherのSpace IDを設定
const GATHER_SPACE_ID = 'xxxxx\\yyyyy'; //スラッシュ(/)→バックスラッシュ(\)×2に変更
```

## numActive

numActive (現在アクティブなユーザー)を取得する際、エラーが出て取得できませんでしたが、以下の方法でうまくデータを取得できました。

### Before

```javascript:@sogemaroさん記事より
// スペースの人数を取得
const workSpace = data[spaceId]
const activeUserCount = workSpace['numActive']; //ここでエラーが出る
return activeUserCount;
```

### After

```javascript:修正版
const workSpace = data[spaceId]
const activeUserCount = workSpace["numActive"]; //シングルクォーテーション(')をダブルクオーテーション(")に変更
return activeUserCount;
```

# 最後に

サクッとこれだけになりますが、私と同じところで躓いている人の手助けになれば嬉しいです。

それでもうまくいかないときは、 `console.log()` で値が保持されているか都度確認するのがオススメです。
Rails7でログアウト機能を実装する際のエラーと解決法

Rails7でログアウト機能を実装しようとして以下のようなコードを使用した際、エラーが発生しました。

```ruby
<li><%= link_to 'ログアウト', destroy_user_session_path, method: :delete %></li>
```

```
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with 'id'=sign_out
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3116202/4677c69e-d199-7d05-2fd4-09ea65d96eda.png)


### 解決法
このエラーは、Rails6までは正しかったログアウトリンクの書き方がRails7で記述法に変更があったために発生したようです。

正しいログアウトリンクのコードは以下の通りです。

```ruby
<li><%= link_to 'ログアウト', destroy_user_session_path, data: { turbo_method: :delete } %></li>
```

これにより、ログアウトリンクが正しく動作し、ログアウト時にエラーが発生しなくなりました。
RailsでsasscのLoadErrorが発生した際の解決方法



## はじめに

Railsアプリケーションで、scssファイルにCSSを記述しようとしたところ、以下のエラーメッセージが発生しました：

```
LoadError in HomeController#home
cannot load such file -- sassc
```

この記事では、このエラーが発生した際の解決方法について説明します。

## 問題の原因

scssファイルにCSSを記述する際、それまで全くCSSを記述していなかったため、scssコンパイル時にsasscが必要とされたが、インストールされていなかったためにエラーが発生しました。

## 解決方法

以下の手順で問題を解決しました：

1. Gemfileにsassc-railsを追加する。
2. `bundle install` を実行してGemをインストールする。
3. Railsサーバーを再起動する。

これで問題が解消され、scssファイルにCSSを記述することができるようになりました。

## まとめ

scssファイルにCSSを記述する際には、sassc gemが必要となります。エラーが発生した際には、Gemfileにgemを追加し、bundle installを行ってGemをインストールし、Railsサーバーを再起動することで問題を解決できます。