OmniAICreator/Qiita-1.07M huggingface dataset:
MySQLで"Unknown column 'xxx' in 'where clause'"が出たときの対処法

#MysqlでSELECTを使うときの注意点

##対象者
- これからSQLを学ぶ方
- 少し触ったことのある程度の方

##今回の気づき
例えばmysqlを使用してデータを抽出したいと考えます。

```sql
SELECT * FROM users WHERE id=xxx
```


その際、このようなSQL文を組み立てるとは思うのですが、idの部分に入ってくるものは変数で管理したいですよね？？

そしたら変数で管理してみましょう！
諸事情により、環境はNodeでExpressを使用します。随時自分が学習してる言語で応用してみてください！


```node.js
const express = require('express');
const app = express();

app.listen(3000, () => console.log('Server is listening on 3000');
//このとき入ってくるindexは"a6f87ff4d4a04fa7a7a77acc1e3a6bd1"と定義します。
app.get('/users/:index', (req, res) => {
  const _id = req.params.index;
  const sql = `SELECT * FROM users WHERE id=${_id}`;
  mysql.query(sql, (err, result) => {
    if (err) throw err;
    res.send(result);
  });
});
```

一見これで完璧に見えませんか？？見えますよね？？

でも実際に動かしてみると、

```node.js
code: 'ER_BAD_FIELD_ERROR',
  errno: 1054,
  sqlMessage: "Unknown column 'a6f87ff4d4a04fa7a7a77acc1e3a6bd1' in 'where clause'",
  sqlState: '42S22',
  index: 0,
  sql: 'SELECT * FROM articles WHERE id=a6f87ff4d4a04fa7a7a77acc1e3a6bd1'
```

うわああ、エラーですねえ。。。。

##解決策
どうやらidの部分を`''`で囲む必要があるみたいです。

なので変更して実際に動かしてみると

```node.js
const express = require('express');
const app = express();

app.listen(3000, () => console.log('Server is listening on 3000');
//このとき入ってくるindexは"a6f87ff4d4a04fa7a7a77acc1e3a6bd1"と定義します。
app.get('/users/:index', (req, res) => {
  const _id = req.params.index;
  const sql = `SELECT * FROM users WHERE id='${_id}'`;
  mysql.query(sql, (err, result) => {
    if (err) throw err;
    res.send(result);
  });
});
```

こうすればしっかり動くことが確認できたと思います。

##終わり

ついさっき自分も知ったばかりなので共有したいと思います。

ではでは〜〜^^
React入門 - Part5 - jsonファイルの読み込み、表示


# 目次

# プロジェクトを作成

[Part2](https://qiita.com/yokosuka205k9/items/132fbd4129afd9b37500)を参考にプロジェクトを作成してください。

# jsonファイルを用意しよう
プロジェクトフォルダ配下に`code.json`というファイルを作成しましょう。
中身はjsonなら何でもいいのですが、今回は下記を使用します。

```json
{
    "CD001": {
        "NAME": "りんご",
        "SUPP": "赤い甘いフルーツ"
    },
    "CD002": {
        "NAME": "みかん",
        "SUPP": "オレンジ色のやつ"
    },
    "CD003": {
        "NAME": "桃",
        "SUPP": "白とかピンクのちょっと高級やつ"
    }
}
```

# jsonを読み込んでみる

pages配下に`read-json.tsx`というファイルを作成します。

```typescript
import React from 'react';
import Code from '../code.json';

export const ReadJson: React.FC = () =>{

    /** jsonデータ編集 */
    const cdList = [];
    for (var cdNo in Code) {
        for (var cd in Code[cdNo]) {
            const cdStr = <div>
                               {cdNo + '-' + cd + '-' + Code[cdNo][cd]}
                          </div>;
            cdList.push(cdStr);
        }
    }

    /** レンダー部分 */
    return (
        <>{cdList}</>
    );
};

export default ReadJson;
```

# 表示してみる

ターミナルで`yarn dev`を実行し`http://localhost:3000/read-json`にアクセスします。

以下のような表示になればOKですね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/559029/dc24d57f-8f38-6c9f-5844-b8c2f48d6bd9.png)

# ちなみに

jsonの何らかの設定をどこかにしたような気がするのだけど、忘れてしましました。
上記試して、エラーになった等の情報教えていただけましたらありがたいです。
(時間を見つけて、真っ新な環境で再度試してみます。)

以上
【MacBook/M1】Android Emulator をインストールする

#<h1>1.以下のページにアクセスする</h1>
https://github.com/google/android-emulator-m1-preview

#<h1>2.ReadmeのHow to use項目の<b>release</b>をクリック。</h1>
![スクリーンショット 2021-05-15 13.50.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/50e6803e-e66a-a6b6-d1d0-21b573eb018f.png)

#<h1>3.一番新しいリリースを選択</h1>
2021/5現在では　Initial Preview v3　でした。
![スクリーンショット 2021-05-15 13.54.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/84508567-1825-0004-7523-6d60bd5eecdd.png)

#<h1>4.Emulatorをインストール</h1>
dmgファイルをダウンロードする
![スクリーンショット 2021-05-15 13.59.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/713347ee-2d57-8cdf-c564-94da84073220.png)

ダウンロードが終わったら開きます。
![スクリーンショット 2021-05-15 14.07.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/f8b518c4-56d2-80d9-737b-c9f074cc326a.png)

[Android Emulator] を[Applications]にドラックして移動します。
![スクリーンショット 2021-05-15 14.10.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/f2cb3680-db1a-1f0e-7a96-f1c3ada3c3be.png)

こするとFinder > ApplicationsにEmulatorが表示されます。
![スクリーンショット 2021-05-15 14.15.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/fedd813d-d26c-8eb7-57c1-106c3171fd6f.png)

早速Emulatorを起動したいところですが、環境設定を変更します。

#<h1>5.システム環境設定を変更する</h1>
システム環境設定 > セキュリティとプライバシー > 一般 を開きます。
[ダウンロードしたアプリケーションの実行許可]の<b>[このまま開く]</b>をクリックします。
![スクリーンショット 2021-05-15 14.26.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/f9f81d2a-1cea-d1e5-a1d7-253bff32a9da.png)

警告画面が２つでますが [開く], [ok] とどんどん開きます。
![スクリーンショット 2021-05-15 14.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/4d88ae7b-4fe0-19e0-e071-ff0d048ae567.png)![スクリーンショット 2021-05-15 14.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/f73db800-05c7-519a-ae80-dc3125b11e58.png)

<h1>Emulator起動</h1>
![スクリーンショット 2021-05-15 14.36.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/65973592-b613-9601-5c2d-88b393d768cf.png)

あとはEmulatorを起動した状態でIDE側からEmulatorを選択し実行するだけです。
![スクリーンショット 2021-05-15 14.39.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/5106b8a7-f623-a871-933e-798c69c3c74d.png)







#<h2>参考資料</h2>
こちらを参考にしました。
英語ですが動画で確認できるので、とてもわかりやすいです。
私みたいな初心者にはオススメです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/YjUCXGGJu7E" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>

#先日はじめてMacを購入しました。

スペック
MacBook Air
CPU 8C GPU 7C
メモリ　16GB
SSD 256GB

早速、勉強中のAndroidの開発環境を整えようとしたところ悲劇が...

![スクリーンショット 2021-05-17 9.19.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/498117/2694961f-97b3-992d-f5ee-a0745a46c5b7.png)


どうやらエミュレーターが使えないようです。
開発用の実機があれば問題ないようですが、
持ってないのでエミュレーターをなんとかインストールすることにしました。
JDLA_E資格の機械学習「L1ノルム、L2ノルム」

# 初めに

機械学習で出てくるL1ノルム、L2ノルムなるものが当然の如く使われていて理解できなかったため少し調べたので整理。

# ノルムとは

ノルムとは、そもそも平面、空間におけるベクトルの長さの「大きさ」を表すための概念である。

ベクトル空間に「距離」を与えるための数学の道具である。


~~~math
\overrightarrow{x}=(x_1,x_2,\cdots, x_n) \\
~~~

ベクトル $\overrightarrow{x}$が上記のようにあるとき、**L1ノルム**とは、

~~~math
L_1 = | x_1 | + |x_2| + \cdots + |x_n|
~~~

これはマンハッタン距離といわれる。

また、**L2ノルム**は、

~~~math
L_2 = \sqrt {x_1^2 + x_2^2 + \cdots + x_n^2}
~~~

これは、ユークリッド距離である。


これらL1とL2を図示すると、

![ノルム.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/215dfe33-2608-7be5-e0d4-21275b8f9e00.png)

正則化のところで勉強したLasso推定とRidge推定のところで出てきたひし形と丸の意味がこれでつながった。

![正則化.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1436941/e7adbc45-5319-289b-268d-565da7fd4d06.png)
【Unity】SRDebuggerのセーフエリア対応

Unityのデバッグ用アセットとして導入する機会の多い[SRDebugger](https://assetstore.unity.com/packages/tools/gui/srdebugger-console-tools-on-device-27688)ですが、2021年5月現在セーフエリアに対応されていないため、iPhone Xのようなディスプレイの形状が長方形ではないデバイスでのデバッグ時に少しだけ不便です。

※追記
2021年6月3日にリリースされた1.11.0でセーフエリア対応が入ったため、それ以降のバージョンを使用する場合はこの記事の対応は不要です。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32328/2d60ad78-af0b-8915-985e-74dce6271289.png" width="200">

画面上部の表示の一部がノッチの後ろに隠れますし、右上の閉じるボタンは押せなくはないのですがとても押しづらかったりします。

そこで、アセット内のスクリプトに処理を追加してなるべく簡単に解決します。

# 環境

- Unity: 2021.1.6f1
- SRDebugger: 1.10.0
- macOS: Big Sur 11.3.1 (20E241) 

# 追加するコード

DebugPanelRoot.cs内に`Awake`を追加し、プレハブのインスタンス化直後のタイミングでフレームサイズを変更します。

```csharp:Assets/StompyRobot/SRDebugger/Scripts/UI/DebugPanelRoot.cs
        protected override void Awake()
        {
            base.Awake();

            var panel = transform.GetComponentInChildren<Canvas>()?
                .transform.GetChild(0)?
                .gameObject?
                .GetComponent<RectTransform>();

            if (panel) {
                var area = Screen.safeArea;
                var anchorMin = area.position;
                var anchorMax = area.position + area.size;
                anchorMin.x /= Screen.width;
                anchorMin.y /= Screen.height;
                anchorMax.x /= Screen.width;
                anchorMax.y /= Screen.height;
                panel.anchorMin = anchorMin;
                panel.anchorMax = anchorMax;
            }
        }
```

# 対応結果

画面内に収まってスッキリしました。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32328/0bf9035c-9e32-e176-1257-0d54b2d40bbe.png" width="200">

簡単な対応なので、デバイスの向きを変更して画面が回転した時には上下左右のマージンが変化しません。`Input.deviceOrientation`を監視して向きが変わった時にフレームサイズを再計算する必要があります。

また、メインパネルのみの対応です。他にもいくつかのUIがありますが、今回の追加処理ではそこまでは影響しません。

もっとも、デバッグでしか使わないということもあるので上記2点は無視しても問題ないと思います。
herokuへのデプロイが失敗する　Precompiling assets failed.

#はじめに
railsチュートリアル第3章でherokuへのデプロイを試みました。
しかし、Precompiling assets failed.と表示されてデプロイに失敗しました。

#開発環境
MacBook Pro 
プロセッサ2 GHz クアッドコアIntel Core i5
メモリ16GB
cloud9 
rails 6.0.3

#作業

```
$ heroku create
$ git push heroku master
```

herokuへのデプロイを試みるが失敗。

```
remote:        webpack binstubs not found.
remote:        Have you run rails webpacker:install ?
remote:        Make sure the bin directory or binstubs are not included in .gitignore
remote:        Exiting!
remote: 
remote:  !
remote:  !     Precompiling assets failed.
remote:  !
remote:  !     Push rejected, failed to compile Ruby app.
remote: 
remote:  !     Push failed
```

webpack binstubsが見つかりませんでした。
rails webpacker:install を実行しましたか？との表示がある。

#解決方法

```
$ rails bundle install
$ rails webpacker:install
```

bundle installをしてから、rails webpacker:installを実行する。

```
$ git commit
$ git push heroku master
```
その後ルートURLにアクセスして、デプロイが成功したことを確認しました。
ご覧いただきありがとうございます。
DynamoDB GSIの使い方を簡潔に解説

#はじめに
個人的にDynamoDBのGSIを利用する機会かあったので簡潔にまとめてみました。
この記事ではGSI(グローバルセカンダリインデックス)の概要と基本的な作成、利用方法を解説いたします。

#DynamoDBでのクエリ
DynamoDBではパーティションキーとソートキーでしかクエリを行うことができません。
パーティションキーとソートキー以外でクエリを行いたいケースが発生した場合は主に下記の2つの対応策があります。

**1.Scan**
Scanを用いてテーブルをまるごと取得し、コードで特定のアイテムを取得するという方法です。
しかし、Scanについてはテーブルのデータ量が膨大になった場合の速度低下や1クエリで最大1MBまでしか
データを取得できないなど制約が多いためAWSドキュメントでもあまりおすすめしていないように思えます。


**2.GSI**
パーティションキーとソートキー以外でHash関数も持たせる事によって、パーティションキーやソートキーと同じようにQueryを実行することができます。

それでは今回のテーマであるGSIの作成方法と利用方法について解説していきます。


**下記のよなユーザー情報のテーブルを想定します。**
テーブル名 : Users
パーティションキー : userId
ソートキー : age

|userId|age|name|email|
|---|---|---|---|
|1|24|Olivia|olivia@example.com|
|2|32|Emma|emma@example.com|
|3|18|Isabella|isabella@example.com|


#GSIの作成(AMC)
nameをGSIでパーティションキーとして設定する方法を手順を追って解説します。

**対象のテーブル>インデックス>インデクスの作成**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237056/4a75ac0c-3037-badf-2090-bcae03c95b3a.png)

**インデックスの詳細設定**
パーティションキーはすでに存在するものでも問題ありません。
データタイプは文字列、数値、バイナリの3つしか選択でいないことが注意点です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237056/20660d70-00ec-051e-80c2-fec3a3f8b55b.png)

**インデクス作成**
作成にはテーブルの使用量にもよりますが失敗したのかなって思うぐらい時間がかかるので気長に待ちましょう...（長くて1時間ぐらい）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237056/552f2713-8fab-b674-6c65-eabac8c25a73.png)

「状態」の列が表示されなくなれば完了です。不思議なUIですね。。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237056/3e2dc349-64ce-3b0f-f259-4cd51815eaf4.png)


#GSIのパーティションキーでQuery
**まずはDynamoDBの「項目のエクスプローラー」から試してみます**
「テーブルまたはインデクス」のプルダウンに先ほど作成したGSIのインデックス名が表示されています。
パーティションキーを指定して実行すると指定したアイテムが取得できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237056/7b82b9f9-4f4a-e8a2-045d-7e8130946e6d.png)


**Python**
通常のQueryに **IndexName** を用いてGSIを指定してあげればOKです。

```python
name = 'Emma'

dynamodb = boto3.resource('dynamodb', region_name='ap-northeast-1')
table = dynamodb.Table('Users')
response = table.query(
    IndexName = 'GSIName',
    KeyConditionExpression = Key('name').eq(name)
)

pprint(response['Items'])
```

#注意事項
1. GSIのデータタイプには「文字列」「数値」「バイナリ」の3つ。
2. GSIは最大20個までしか作れない。

#終わりに
DynamoDBを利用するにあたってGSIはとても便利な機能です。
しかし、NoSQLの長所を活かしたいなどの理由以外で、設計の段階からGSIを利用する想定であればRDBMSの利用を再度検討してもいいのかもしれません。
2つの封筒問題のパラドックス

## 2つの封筒問題（金額変数版）
### 前提

- 2つの封筒があり、それぞれにお金が入っている
- 片方には`a`円、もう片方には`b`円入っている。
- `a`と`b`は異なる正の整数であり、それ以外の情報はない。

### 事実

- 1つの封筒を無作為に選んだとき、その封筒に入っている金額の期待値は、`(a + b) / 2`であり、もう一方の期待値も同じである。

### 問題

封筒を1つ無作為に選ぶ。その封筒には、`a`または`b`のお金が入っている。
さて、`a`と`b`に関する前提は同じである。したがって、`a`と`b`を交換しても前提は変わらない。

そこで、選んだ封筒の金額を`a`としてみよう。このとき、この封筒の期待値は`a`であり、もう一方の期待値は`b`である。

`a`と`b`は異なるので、2つの封筒の期待値が異なることになる。これは、事実と合わない。この理由を説明せよ。

### 解答

選んだ封筒の金額を（たとえ、値が不明でも）固定した上で、期待値を`(a + b) / 2`と計算するのが間違いである。
`(a + b) / 2`という値は、「`a`を1/2の確率で、`b`を1/2の確率で選ぶ場合」の期待値である。
たとえ、`a`が不明でも「`a`を選んだ場合」の期待値とは同じではない。

### 発展

「（値を明示しなくても）金額を仮定すると期待値は変わる」ことに注意しよう。

下記のいわゆる「2つの封筒の問題」は、上記の問題に「`a`と`b`の比は2」などの条件を追加したものである。

https://qiita.com/SaitoTsutomu/items/9784e4451d6d510dbfbb#mag-%E3%81%8A%E9%A1%8C%E3%81%9D%E3%81%AE22%E3%81%A4%E3%81%AE%E5%B0%81%E7%AD%92%E3%81%AE%E5%95%8F%E9%A1%8C

この問題は、開封時に期待値は計算できない。また、未開封でも**一方の金額を仮定すれば期待値は計算できない**。考えてみよう。

---

## 2つの封筒問題（クリンゴン版）

金額の紙の入った2つの封筒があり、片方はもう片方の2倍の金額になっている。どちらかの封筒を選んで金額の分をもらうことができる。
無作為に1つの封筒を選び、封筒の中の紙を見ると金額は**クリンゴン語**で書いてあり理解できなかった（クリンゴン語はあとで翻訳してもらえる）。

このとき、交換した方が得だろうか？

### 解答

交換しても変わらない。

### 解説

読めないとはいえ金額の紙を見ているので、下記の「2つの封筒問題（金額仮定版）」のように錯覚しやすい。しかし、問題の構造は「2つの封筒問題（未開封版）」と同じである。したがって、交換しても変わらないのが正解となる。

https://qiita.com/SaitoTsutomu/items/3079a88163153abf2ac2

以上
TextFieldのカーソルを末尾に設定する

```dart
@override
  Widget build(BuildContext context) {
    // TextEditingControllerのtextで初期値を設定することが出来る
    final controller = TextEditingController(text: 'テキストだよー');

    // TextEditingControllerに設定したテキストのlengthをカーソルの位置に設定する
    controller.selection = TextSelection.fromPosition(
      TextPosition(offset: controller.text.length),
    );

    return Center(
      child: TextField(
        controller: controller,
        autofocus: true,
      ),
    );
  }
```
“id”属性と”class”属性

※プログラミング学習中の私がアップロードしてます。理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

“id”属性と”class”属性
“id”と”class”の使い分けに悩む人は多いのではないでしょうか？

ざっくりとした定義は

画面の中で何回か使いまわしたい設定は”class”属性を、画面内の特定の場所（１カ所）に使用したい設定には”id”属性を使用します。

>WEB侍
>http://samurai.ataglance.jp/css_idclass/
Cloud9でインスタンスの再起動をしても繋がらない時

##はじめに
AWSのCloud9にて接続しようとしても、「This is taking longer than expected. If you think there might be an issue, contact AWS Support. It might be caused by VPC configuration issues. Please check documentation.」表示されて、接続できない状態となっていました。
エラー内容から、インスタンスの性能不足が推測できます。

この件について調べていると、インスタンスの停止→再起動で接続できるようになった方が多数いらっしゃったのですが、私はダメでした。
なので、このインスタンスの停止→再起動という手順で復旧しなかった方向けに書きます。


##ボリュームの変更
ec2のボリュームを開いて、該当するボリュームからボリュームの変更を選択します。
![スクリーンショット 2021-05-13 9.33.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340120/1fc9f36b-8ac2-623b-4ac9-27ab9c41e13b.png)
すると「ボリュームの変更」が出てきますので、ここのサイズを例えば8GB→16GBなどに変更します。
変更ボタンを押した後に、確認画面が表示されるので、そのまま進んでください。
![スクリーンショット 2021-05-13 9.34.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340120/8f06daa1-a6b0-3072-b30e-3d3d9823c3cb.png)
あとはボリュームの画面で、サイズが変更されていること、状態がin-useになっていることを確認してください。
状態に関しては数分待つ必要があります。

ボリューム不足が原因の場合、これで解決できます。


##インスタンスタイプの変更
まず該当するインスタンスを停止します。その状態で、アクション→インスタンスの設定→インスタンスタイプの変更にて設定します。

![スクリーンショット 2021-05-15 13.11.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340120/9bfbd3aa-d051-5b1b-13c4-f8efabc9ed5e.png)


そしてインスタンスタイプを変更します。
インスタンスタイプの詳細に関しては、公式サイトのリンクを貼っておきます。
https://aws.amazon.com/jp/ec2/instance-types/
![スクリーンショット 2021-05-15 13.13.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1340120/cf181698-94cd-3e67-c57f-1071eb91d737.png)
適用させた後はインスタンス画面にて、インスタンスタイプが変更されているかを確認します。


##ブラウザを変更する
Chrome、Safari、Firefoxなどブラウザを変更すると、接続できることもあるみたいです。
そして後日元々使用していたブラウザで起動できたりといったことがあるみたいです。

##ルートテーブルの確認
VPC内のインターネットゲートウェイを削除すると、ルートテーブルのステータスが「blackhole」になっており、これが原因の可能性もあるそうです。
この場合は、新しくルートテーブルを作成して、アタッチする必要があります。
手順に関しては、以下サイトが参考になります。
https://go-journey.club/archives/12101


以上、参考になれば幸いです。
画像のサイズを修正


画像を表示するためのimg要素にサイズの情報を付加していない場合なら
-

```HTML:HTML
<p class="sample">
    <img src="riverchildren.jpg" alt="写真">
</p>
```

上記では画像ファイル「riverchildren.jpg」を表示させていますが、縦横のサイズは記述していません。
この場合は、以下のようにCSSソースを記述するだけで、画像を望みのサイズで表示できます。


```CSS:CSS
p.sample img {
    width: 200px;  /* 横幅を200pxに */
}
```
上記では、class名に「sample」が指定されたp要素に含まれるimg要素に対して、横幅200pxで表示する指定を加えています。これだけで、横幅が200pxになった上で、高さは縦横比を維持して自動調整されます。


>https://www.nishishi.com/css/resize-image-keep-aspect-ratio.html
.clasList

※プログラミング学習中の私がアップロードしてます。理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

.classList
-

classListは、要素のクラス属性のリストを取得して返します。 classListは、element.className経由で空白区切りのクラス名の文字列を取得する代替手段として、 要素のクラス名のリストにアクセスするのに便利です。 これは下記のメソッドを含みます。

|add|要素のクラスのリストに、クラスを追加します|
|--|--|
|remove|要素のクラスのリストから、クラスを削除します|
|toggle|要素のクラスのリスト内のクラスの有無を切り替えます。 後述する2つ目の引数についてを参照してください|
|contains|指定したクラスが、要素のクラスのリストに含まれているかを確認します。|

文法
-

```javascript
var elementClasses = elementNodeReference.classList;
```

elementClassesには、 elementNodeReferenceのクラス属性を表すDOMTokenListが格納されます。 もしクラス属性が設定されていない、または空の場合、elementClasses.lengthは0を返します。element.classListそれ自身は読み取り専用ですが、add()とremove()メソッドを使用して、 変更することが可能です。toggle()メソッドは真偽値によって、 強制的にクラス名を追加または削除する任意の2つ目の引数を持ちます。 例えば、クラスを削除(存在するしないに関わらず)するために、 element.classList.toggle('classToBeRemoved', false);を呼び出し、 クラスを追加(存在するしないに関わらず)するためにelement.classList.toggle('classToBeAdded', true);を呼び出します。

例
-
```javascript
// divはclass="foo bar"を持つ<div>要素オブジェクトへの参照です。
div.classList.remove("foo");
div.classList.add("anotherclass");
// もしvisibleがあれば削除され、そうでなければ追加されます。
div.classList.toggle("visible");
alert(div.classList.contains("foo"));
div.classList.add("foo","bar"); //複数のクラスを追加
```

>js STUDIO
>https://js.studio-kingdom.com/javascript/element/class_list
楽天モバイルの通信回線は使い物になるのか

楽天モバイルを契約して一ヶ月がたった今日この頃にレビューを書いてみることとする。

# 楽天モバイルの契約
まずは、楽天モバイルの契約状態に関してだが、筆者所有の端末がiPhone SE 2でSIMカードスロットにはdocomoの回線のSIMカードが刺さっている。だが、このSIMカードに関しては音声通話ができないSIMカードであった。
そのため、音声通話をするためには別の端末を用意するか、eSIM契約のできる通信会社との契約が必要であった。
ここで、登場するのが、「楽天モバイル」である。


# eKYCで楽に契約
楽天モバイルとの契約開始に関してだが、基本的にはeSIM対応の端末と日本の運転免許証が必要とはなるものの、その条件さえクリアできれば、最短10分でネットのみで契約が完了する。条件をクリアできない場合には別途SIMカードが郵送で送られてくる。

# 実際どうなの？楽天モバイル
## メリット
#### eKYCでの容易な契約
条件をクリアする必要はあるものの、eKYCで楽に契約を完了することができ、審査さえ通れば、即日（約10分）で契約を完了させ、通話、インターネットを開始することができる。

### 格安SIMよりもマシ
かつて、UQmobileの500kbpsの使い放題SIMや日本通信の月額契約のSIMカードの契約などをしたことがある筆者だが、どの回線に関しても通信速度に関する不満は消えない。（格安SIMなので仕方がないが。）一方、楽天モバイルに関しては独自の通信回線の整備もある程度進んでいるので、独自の回線に関しては通信回線が良い方であると感じる。

## デメリット
### エリアが極端に狭い
楽天モバイルの通信エリアに関してだが、極端に狭い。特に楽天モバイルの場合にはAUの回線でも通信可能であるが、バンド固定で楽天モバイルだけの通信回線を拾おうとすると結構不便な面を感じる。

### 壁などの障害物に極端に弱い
割り当て周波数帯の問題ではあるが、障害物に極端に弱いというのが現状である。docomoの通信回線と併用で使っているので、docomoの回線は壁の向こうでも使えるのに、楽天モバイルに関しては使えないなどの事象も発生している。

# 結局どうなのよ？
楽天モバイルしか通信のできない端末などを持つことはおすすめしない。あくまで、二台目やバックアップ回線としての利用をおすすめする。
また、アプリ経由で通話やSMSをした場合には、基本的には通話料が無料なので、通信回線の契約のないデータ専用プランで通話のみ楽天モバイルなどという使い方もある。

# バンド固定に関して
楽天モバイルの割り当てされているバンドしかとれない端末があるにはある。なので、そのような端末を使えれば、楽天モバイルの通信回線分のデータ消費しかしなくなる。(auの通信回線でネットをした場合には5GBで制限がかかってしまうので。）
また、iPhoneに関してはバンド固定の方法もある。ただし、該当のバンドが取得できない場合には、他の使えるバンドで無理に電波を取得しようとするので、結局auのデータ量を消費してしまうと欠点もある。

# 一部改悪が発生した楽天モバイル
2021年7月よりユニバーサルサービス使用料が発生するパターンが発生した。それも無料で使い放題の回線に関しても1GB以上のデータ使用で発生するという代物だ。まあ、無料とはなんなんだろうか。まあ、改悪する可能性があることは契約時に明記してあるのがだ。別に解約金がかからないのだから、ユニバーサルサービス料を払いたくない人は楽天モバイルと契約しければいいといわれればそれまでではあるが。
ちなみにdocomoの代理店で契約しようとしたときに、020のデータ使用のみを目的とする番号を取得すれば、ユニバーサルサービス料を支払わなくても良いと聞いたことがあるが、真相は。。。。契約したことがある人がいたら、是非ともコメントを残してもらいたい。そもそもSMSとか使えるの？とかもありますし。
最近人気のKeychronK2を買ったのでいい感じにしてみた

## 概要

念願のKeychronK2を手にして、JIS配列から初めてのUS配列に乗換えすることになり色々困ったので何をしたのか書いていきたいと思います。


## とりあえず`英かな`

JIS配列ではスペースの両輪にいい感じに配置されている英字とかな文字の変換キーがあったのですが、US配列には両脇がCommandなので同じような動作をする定番の英かなをインストールしました。
インストールするとほとんど設定なしで馴染みの動作をするので定番ですが、お勧めです。

https://ei-kana.appspot.com/

## `caps lock`を`control`にリマップ

これはちょっとめんどくさくて、`Karabiner-Elements`というKeychronの説明書に記載のあるキーリマップアプリで変換をしました。
この設定自体はMacの環境設定の修飾キーで設定出来るのですが、Keychronには右側にもcontrolキーがあり、そっちもcapslockになってしまったので、左側だけ変更したい場合にはこのアプリが必要みたいです。
他にも細かく設定できるので、使わないFキーにショートカットを割り当てたり出来るんじゃないかと思っています。


https://karabiner-elements.pqrs.org/

## セミコロンとコロンを反対にする
 
これはUS過激派に怒られそうなのですが、US配列はセミコロンとコロンが同じキーに配置されていて、コロンを入力したいときはシフトを押さないといけません。
個人的にセミコロンよりコロンを使う頻度が高いので、コロンをシフトを使わずに入力できるようにしました。

### 設定方法
先ほどのアプリを開く
↓
`complex modifications`タブ
↓
左下の`Add rule`
↓
`Import more rules from the Internet(open a web browser)`
↓
ブラウザが開くので、`Exchange semicolon and colon`を探し出してインポート
↓
アプリに戻り、`Add rule`のモーダルに`Exchange semicolon and colon`が追加されているはずなので`Enable`を押す
↓
終わり

これでセミコロンをコロンに変換できます。
ちょっとめんどくさいですが、試してみてください他にもプラグインのようなものがあるので自分好みのカスタマイズができます。

文字だけだと分かりにくそうなのでスクショを追記する予定です

## 最後に

最近Macの細かい設定ばかりしているので、PC移行するときが怖いです笑
全てコード化できればいいですが...
何かいい方法がある方がいらっしゃったら教えてください。


## 自己紹介

日々Webアプリを開発している25歳です。
今後も気になったことや、技術情報などを書いていこうと思っております！
ブログは初めて書くので、お手柔らかにお願いします笑

Nuxtjs + graphQL(GitHubAPIv4)を活用した半自動ポートフォリオを開発しました！
このポートフォリオを見ていただくと今まで開発したものを全て見ることができます！

https://taiga-tech.tk/

GitHubはこちらです↓

https://github.com/taiga-tech/
スクリーンショットをとってSNSにシェアするアプリ機能を実装してみた[iOSアプリ]

今回は、スクリーンショットをとってSNSにシェアできる機能を作ってみたので、アウトプットしようと思います。

#環境
・Mac Book Pro(macOS:BigSur)
・Xcode(ver:12.5)

#実装例
![Unknown.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864623/ac41326a-a743-ee25-4f58-94c086b8e8d8.gif)

#コード例
```ruby:ViewController.swift
class ViewController: UIViewController {
    
    @IBOutlet weak var screenShotConfirm: UIImageView!
    var screenShotImage:UIImage!
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    
    @IBAction func takeScreenShot(_ sender: Any) {
        
        let width = CGFloat(UIScreen.main.bounds.width)
        let height = CGFloat(UIScreen.main.bounds.height / 1.3)
        let size = CGSize(width:width,height:height)
        
        UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
        "viewに書き出す"
        self.view.drawHierarchy(in: view.bounds, afterScreenUpdates: true)
        screenShotImage = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()
        
       showToast()
        
    }
    @IBAction func share(_ sender: Any) {
        let item = [screenShotImage!] as [Any]
        let activityVC = UIActivityViewController(activityItems: item, applicationActivities: nil)
        
        present(activityVC, animated: true, completion: nil)
    }
    
    "トースト表示を作成"
    func showToast(){
        let toastLabel = UILabel()
        toastLabel.frame = CGRect(x:40, y: UIScreen.main.bounds.height - 58, width: 300, height: 40)
        toastLabel.text = "スクリーンショットを撮りました。"
        toastLabel.layer.borderWidth = 1.0
        toastLabel.textAlignment = .center
        toastLabel.layer.borderColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
        toastLabel.layer.backgroundColor = #colorLiteral(red: 0.9254902005, green: 0.2352941185, blue: 0.1019607857, alpha: 1)
        toastLabel.layer.cornerRadius = 10
        toastLabel.textColor = .white
        self.view.addSubview(toastLabel)
        
        UIView.animate(withDuration: 2.5){
            toastLabel.alpha = 0.0
        }
        
        return
    }
}
```

スクリーンショッを撮影するボタンを押しただけでは、取れたかがわからないので撮影が終わったよの合図を
するためにトースト表示を作りました。

ネットの情報を見る限りでは、スクリーンショットのコードの書き方は、決まっているようでした。
これからのアプリ作成で使うことがあるかもしれないので、備忘録として記事を作りました。
ID名はハッシュ（ # ）に続けて記述します。

指定方法
-
要素名に続けてID名を指定する方法と、ID名だけで指定する方法があります。どちらの場合も、ID名はハッシュ（ # ）に続けて記述します。

```css
h1#example1 { color: red; }
#example2 { color: blue; }
```

example1 と example2 の部分がIDになります。
IDを付ける際には、以下の点に注意してください。

大文字と小文字の区別があります。
使用できる文字は、半角の英数字、ハイフン（ - ）、アンダーバー（ _ ）です。
アンダーバー（ _ ）をID名に含めると、一部の古いブラウザではIDが認識されなくなります。
アルファベットで始めなければなりません。（数字や記号で始めてはならない）
Gitコマンドメモ

<h1>コミット手順</h1>
```
git init
```

```
git add .
```
```
git commit -m "どういうコミットか説明する任意のメッセージ"
```

```
git remote add origin Githubに事前に作成したリポジトリのURL
```

```
git push origin HEAD
```
<hr>
<h1>最初にplease tell me who you areエラーが出た場合</h1>

```
git config --global user.email 自身のメールアドレス
```

```
git config --global user.name 自身の名前
```
<hr>
<h1>ローカルリポジトリでのソースコード編集をリセット</h1>

```
git checkout .
```
<hr>
<h1>ローカルリポジトリでのファイル追加ごとリセット</h1>

```
git clean -df .
```
<hr>
<h1>コミット履歴の確認</h1>
2週間前まで表示する例

```
git log --since=2.weeks
```

<hr>
<h1>ブランチ関連</h1>
ブランチ作成

```
git branch {ブランチ名}
```

ブランチ移動

```
git checkout {ブランチ名}
```
[Nuxt.js] nuxt generate すると input[type=text] に対するスタイルが適用されない

HTMLにおいて input の type 属性値はデフォルトで `text` なので `type="text"` の指定は意味をなさない。このような属性指定は `nuxt generate` で静的ファイルを生成するときに削除される。

しかしこの場合、 CSS の `input[type=text]` に対する指定が効かなくなってしまう。

さらに他ページから遷移してきた場合においては type 属性は生き残っているので、この問題に気づきにくい。

[対応方法1] `input` に対してスタイルを適用する

[対応方法2] この挙動を無効化する。
cf. https://github.com/nuxt/nuxt.js/issues/1760#issuecomment-333271270
配列に関数名を入れて、配列の中身を関数として呼び出す（JavaScript)

ボスは一筋縄では倒せない。
なぜなら行動が多様だからだ。
動作がワンパターンであれば、すぐに適当な対策がとられてしまう。
例えば、残り体力の如何によって行動が変化するパターンがある。

``` js:script.js
let HP = 5;//体力

function act(){
    if(HP >= 3){
        console.log("通常攻撃");
    } else {
        console.log("特殊攻撃");
    }
}

act();

```

これは体力が3以上であれば通常攻撃、3未満であれば特殊攻撃をするボスの行動パターンだ。
分かりやすくて何よりだが、できればif文を使いたくない。

そこで次のような工夫をする。

``` js:script.js
let HP = 2;
const standard = 2;

function normal(){
    console.log("通常攻撃");
}

function special(){
    console.log("特殊攻撃");
}

let actAry = [special, normal];

actAry[Math.sign(Math.floor(HP/standard))]();
```

`HP>=standard`であれば`Math.sign(Math.floor(HP/standard))`の値は1であり、そうでなければ0となる。

他にもこういうことができる。

```js:script.js
let boss = {};
boss.state = 0;

boss.act1 = function(){
    console.log("attack");
}
boss.act2 = function(){
    console.log("rest");
}
boss.act3 = function(){
    console.log("move");
}
boss.act4 = function(){
    console.log("specialAttack");
}

boss.action = [boss.act1, boss.act2, boss.act3, boss.act4];

boss.act = function(){
    boss.action[boss.state]();
    boss.state = (boss.state+1)%boss.action.length;
}

boss.act();

```

ボスが行動する度にstateの値がぐるぐると変化し、stateに応じたactionを行う。
CORS とは？

## 勉強前イメージ

s3とかcloudfrontにあるイメージ・・・？
あんましらん

## 調査

### CORS とは？

Cross-Origin Resource Sharing の略で、オリジン間リソース共有の意味です。
ブラウザで見ているページとは違うドメインからデータの取得を許可する仕組みのことです。
ブラウザには、セキュリティ上 クロスサイトスクリプティングを防止するため
オリジンドメインのサーバとしか通信できない制約があります。

### クロスサイトスクリプティングとは？

XSS と略されますが、
動的サイトに不正なスクリプトを挿入することで、サービスを利用しているエンドユーザーに攻撃行うサイバー攻撃です。

イメージとしては以下の図のような感じです。

![1# CORS とは？ - diagrams.net - Google Chrome 2021-05-.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/129517/6d3c2a9a-dd06-2c5a-9f8d-8201943ad121.png)

1. 攻撃者がwebサイトにスクリプトを仕掛けます。
2. エンドユーザーがwebページを表示すると
3. 偽サイトに飛び
4. エンドユーザーは偽サイトのwebページを表示します。
5. エンドユーザーはマルウェア感染済みなので
6. 攻撃者に情報漏洩してしまったりします。

なので、基本的にはブラウザではオリジンドメインのサーバとしか通信ができないようになっています。
それを許可するのがCORSです。

元々Ajaxは異なるオリジンと通信ができなかったので、JSONPが使われるようになったが、
JSONPは脆弱性を作り込みやすかったので、CORSが生まれました。
元々別のサーバと通信は出来ていたが、安全じゃなかったので安全に通信できるようにした経緯があります。

## 勉強後イメージ

なるほどー全然知らなかった。。
ブラウザから通信するサーバはオリジンサーバだけなのねー


## 参考

- [クロスサイトスクリプティングとは？仕組みと事例から考える対策](https://cybersecurity-jp.com/security-measures/18427)
- [CORS(Cross-Origin Resource Sharing)によるクロスドメイン通信の傾向と対策](https://dev.classmethod.jp/articles/cors-cross-origin-resource-sharing-cross-domain/)
- [Webアプリ開発者のためのHTML5セキュリティ入門](https://www.slideshare.net/muneakinishimura/webhtml5-31749532)
DockerでCentOS環境作ってOutlookのPSTファイルをtextファイルに書き出した話

　世の中には、往々にして様々な形式のファイルが存在し、また往々にして「テキスト形式で変換してやらないと別のシステムに入れ込めない」。なんて場面がエンジニアやってるとチラホラと散見されます。
（別に定常的に発生するわけではないけれど、4～5年エンジニアをしていると誰もが1～2回は出くわしてるみたいな）

　ご多分に漏れず先日知人からそんな相談をいただき、全然触ったこと無い形式のファイルでしたけれどもアレコレ調べてどうにかなったので備忘的にメモとして残しておきます。いつかどこかで誰かの助けになるといいな。

# お題：Outlookのpstファイルをtextファイルにしたい

そんなわけで本日のお題はこちら。
「pstファイルをtextファイルにしてシステムに取り込むことはできませんか！」
という相談。（っていい加減繰り返し過ぎか）

## pstファイルってなんや

「なんやpstファイルって…」というところから当然（？）始まったわけですけれども、どうやら調べてみたところメールソフトOutlook内のデータを保持しているバックアップ的なファイルらしい。
なんでも、メールアカウントごとに送受信したメール情報とか連絡先の情報とか、諸々の情報が含まれているとか。

> Microsoft Outlook で .pst ファイルを管理する方法
> https://docs.microsoft.com/ja-jp/outlook/troubleshoot/data-files/how-to-manage-pst-files

で、まあとりあえずテキストエディタで開いてみますよね。
「ワンちゃんテキストデータで開けたらラッキー」は誰でも思うはず。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/8c95942a-e83f-8b1a-0af7-f393a8dcbb92.png)
諸行無常。

## CentOSコマンドがあるらしい

とりあえずぐぐってみたら、やはり世の中似たようなことで試行錯誤している人はいたようで、参考にさせていただきました。
ありがてえありがてえ。エンジニアはこの同じWEBの世界で時間も場所も超えてつながってますよね。と思います。

> Outlookのデータ（.pstファイル）をテキストに変換する（readpstコマンド利用）

http://min117.hatenablog.com/entry/2019/04/13/090304

よし、この「`readpst`」コマンドを使おう。ってこれlinuxコマンドか。今のWindowsPC仮想環境入れてないんだよな。
どうしようか。

→　せっかくだしWindowsPCでやるならDockerで環境作ってみっか

と収まりました。

# やってみた

思い立ったら即実行。なんのかんの、実はDocker Desktop for Windowsはインストール済みな上、Udemyで2時間予習済、これはちょっとおもしろい題材かもしれない。

## Dockerにlinux環境構築

とはいえまだ自前でDocker環境構築するのは不慣れなところが多々あり、こちらの記事で勉強させていただきました。
docker run hello-world当たりまではショートカットしてやってます。

https://qiita.com/gahoh/items/7b21377b5c9e3ffddf4a

### 叩いたコマンドの羅列

それぞれの中身の紹介とは上の記事内におまかせするとして、ちょっとずつググりながら補ったコマンドを述べていきます。

#### CentOS7のイメージを取得
```
# イメージを取得
docker pull centos:centos7
docker run -it --name="centos7" centos:centos7 /bin/bash
```

コンテナ内のコマンド

```
# パッケージのインストール
yum update

# sudoのインストール
yum -y install sudo

# readpstのインストール
yum install libpst

```

※ちなみに、参考サイトの環境がUbuntuだったので、記載されてたコマンドが以下だったんですが、翌々考えてみたらCentOSでapt-get無いわってなったので、readpstは以下のサイトで調べました。こんなサイトあるんですね。これも良き。

* コマンド

```
apt-get install pst-utils
```

* 参考サイト

https://command-not-found.com/readpst

####

## Dockerコンテナ内に読みたいファイルをコピー

あとはまあ、当然なんですが問題のPSTファイルがコンテナの中になかったので、それをコピー。（実はこれも初めてやった、お恥ずかしい）
使ったコマンドと参考サイトがこちら。

* コマンド

```
# コンテナ内のtmpディレクトリにコピー
docker cp xxxxxxxxx.pst （コンテナID）:/tmp
```

* 参考サイト

https://blog.amedama.jp/entry/2018/01/30/221546

## コマンド実行

ではいよいよお待ちかねの実食です。待望の「readpst」コマンドをドン。

```
readpst -M xxxxxxxxx.pst
```

そんでできたファイルをdocker cpコマンドで元のホストの場所に戻す。

```
docker cp （コンテナID）:/tmp/xxxxxxxxxxx /任意のホストディレクトリ
```

## 結果
できた！！！！バンザイ！！！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215128/aaec91e8-ed04-8303-9530-42c20688ee6f.png)

# 感想（と続き）

チョロチョロ調べながら、そんなに手間をかけずに成功に一通りこなすことができてよかった。
やはり先人の知恵をこんなにも手軽に漁ることができるインターネットとは偉大です。
大事なことなのでもう一度言っておくと

> 「エンジニアの悩みや努力は、時代も場所も飛び越えて、このWEBの世界でつながっているんだ」
（左利きのエレン風）

ということです。今回の記事も、冒頭で述べたようにいつかどこかで誰かの役に立つといいな。
いやはや、お腹いっぱいだ。

などと油断してたら、「メールのヘッダ情報は、取り込み可能な形式に変換しなければならない」というお題が発生し、この記事が続くことになります。次回、ご期待ください。

いったん、おわり。
JavaScript の remove メソッド

※プログラミング学習中の私がアップロードしてます。理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

使い方
-

直接削除したい要素にメソッドを指定します。

```javascript:JavaScript
document.getElementById("test").remove();
```

これで #test 要素を削除することが出来ます。メソッド名も完全に同じです。

デモ
-

JavaScriptでremoveに対応しているブラウザで下にある赤い四角をクリックすると赤い四角が消えます。要素の削除をしています。
![20210515-120800.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/a28298c0-7021-5aee-3615-cb46da3c5df5.png)

remove()
以下のコードで判定しています。赤い四角の id は test です。

```javascript:JavaScript
document.getElementById("test").addEventListener("click", function() {
    this.remove();
},false)
```

ブラウザ対応
-

removeメソッドが実際使えるか使えないかで問題になるのはブラウザの対応です。

|ブラウザ|最新版での対応状況|
|--|--|
|GoogleChrome|○|
|Firefox|○|
|Opera|○|
|Safari|○|
|InternetExplorer|×|
|MicrosoftEdge|○|


まとめ
-

いつも通りと言ってはあれですが IEがダメだからという理由で当分は使えないですし、removeChildを使ったところでそれほど大変ではないので結局使われなさそうなメソッドです。ただ jQueryの良いところをネイティブの JavaScriptが吸収している前例が結構あるので、これもその1つなのかもしれません。

>q-Az
>https://q-az.net/remove-native-javascript/
データテーブルに、別データテーブル行を追記する(UiPath)

#方法1：「Invoke Method」を使う
例えば下図のような、
「データ1」の中から、「名前：佐藤」行だけを「データ2」と結合させ、これをoutputしたい場合…
![ui7.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/874ae7c1-6bc3-fcc4-b1d9-0ff2c50072ef.jpeg)
下記のように設定すればOKです。
![ui8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/4c09e718-1ef5-d05e-9513-bd675c2620c9.png)

※ちなみに、「Invoke Method」の代わりに「Add Data Row」を使うとエラーになります。
これは、「AddDataRowできるRowは、無属性のRowだけである」という性質から生じるエラーであり、
今AddしようとしているRowは、"既にデータ1に属したRowである"ため、AddDataRowが使えない…という事らしいです。
![ui9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1401870/16f77e31-75c7-a917-975e-0ec0ae656a2a.png)

#方法2：DataRow→Object[]に変換させる
「Invoke Methodを使うのはちょっと…」という人は、
別の方がInvoke Methodを使わずに行追加させる方法をまとめていますので、こちら↓の記事を参照してください。
https://qiita.com/mh_ti_fu/items/f09c01ab54e04756ddf0
.querySelector()


※プログラミング学習中の私がアップロードしてます。私の理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

指定したセレクタのグループにマッチしたdocument内(documentノードのdepth-first(深さ優先)、 pre-order traversal(前順走査)を使用して)の最初の要素を返します。

文法
-

```javascript
element = document.querySelector(selectors);
```

|引数|説明|
|--|--|
|selectors|型：string--selectorsは1つまたはカンマで区切られた複数のCSSセレクタを含む文字列です。|
|戻り値|説明|
|element|elementは、elementオブジェクトです。|

例
-

この例では、document内のmyclassクラス付きの最初の要素を返します。

```javascript
var el = document.querySelector(".myclass");
```

|訳注)上記のように単純にクラス名で探す場合はgetElementsByClassName()を、IDで探す場合はgetElementById()メソッドを使用するべきです。|
|--|

注意事項
-
もし、マッチするものが見つからなければnullを返します。 そうでなければ、最初にマッチした要素を返します。セレクタがIDとマッチし、またそのIDがドキュメント内で複数回使用する誤った扱いをされている場合、最初にマッチした要素を返します。もし指定したセレクタのグループが不正なものであれば、SYNTAX_ERR例外をスローします。
querySelector()はWebApps APIで導入されました。querySelectorへ渡される文字列引数は、CSS文法に従ったものでなければいけません。Selectors APIで指定されたCSS擬似クラスは、要素を返しません。CSS文法に従っていない(例えば、コロンまたは不適切な空白を使用したもの)IDまたはセレクタにマッチさせるには、バックスラッシュを使用して文字をエスケープしなければいけません。バックスラッシュはJavaScript内のエスケープ文字であり、もしリテラル文字として扱うのであれば、2重エスケープを行う必要があります。

>js STUDIO
>https://js.studio-kingdom.com/javascript/document/query_selector
【個人的備忘】SwiftUI, AVFoundationを使って音を付ける

###1．Assets.xcassetsに音源を登録する

###2．サンプルコード
```
import AVFoundation

struct MySes {
    private let bgm = try! AVAudioPlayer(data: NSDataAsset(name: "bgm")!.data)
    private let se1 = try! AVAudioPlayer(data: NSDataAsset(name: "se1")!.data)
    
    init() {
        bgm.numberOfLoops = -1 //-1: 無限ループ, 0: ループなし(初期値)
        bgm.volume = 0.05
        se1.volume = 0.08
    }

    func playBgm() {
        bgm.play()
    }
    func pauseBgm() {
        bgm.pause()
    }
    func stopBgm() {
        bgm.stop()
    }

    func playSe1() {
        se1.currentTime = 0 //連続再生(連打など)に対応
                            //頭に空白があるときや途中から再生するときにも使える
        se1.play()
    }
}
```
mysqlが起動できない

## 事象
mysqlを使用していてmysqlで操作確認をしよう起動すると下記のようなエラーが出る

```
$ mysql.server start
ERROR! The server quit without updating PID file
```

## 解決策
権限周りやホスト名なども弄りましたが、最終的にはmysqlを入れ直しました。
下記を実行すると...

```
# /usr/local/var/mysqlを削除する
$ sudo rm -rf /usr/local/var/mysql

# /usr/local/bin/mysqlを削除する
$ brew uninstall mysql

# 再インストール
$ brew install mysql

$ mysql.server start
Starting MySQL
 SUCCESS!
```

スタートできました！
setAttribute( )

※プログラミング学習中の私がアップロードしてます。理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

文法
-

**指定した要素上に新しい属性を追加、または既存の属性の値を変更します。**

```javascript
element.setAttribute(name, value);
```

|引数|説明|
|--|--|
|name|属性の名前を文字列で指定します。|
|value|属性に設定したい値を指定します。|

例
-
```javascript
var d = document.getElementById("d1");
d.setAttribute("align", "center");
```

注意事項
-

HTMLドキュメント内のHTML要素上で呼び出された際に、 setAttributeは引数の属性の名前を小文字にします。指定された属性が既に存在する場合、 その属性の値は引数として渡された値に変更されます。 存在しない場合は、その属性が作成されます。getAttribute()は存在しない属性に対してnullを返しますが、 属性を削除する際にelt.setAttribute(attr, null)ではなく、 removeAttribute()を使用すべきです。
 特定の値の編集にsetAttribute()を使用すること、特にXUL内の値において、 属性がデフォルト値を指定するものであると、この動作は一貫性の無いものになります。 現在の値にアクセス、または編集を行うには、プロパティを使用すべきです。 例えば、elt.setAttribute('value', val)の代わりに、 elt.valueを使用します。

>js STUDIO
>https://js.studio-kingdom.com/javascript/element/set_attribute
「Gateway of last resort is not set」の意味

Ciscoのルーティングテーブルをチェックする際に、デフォルトルートが設定されていなければ、

```
Gateway of last resort is not set
```

が表示されます。

「**last resort**」というワードが気になるので調べてみました:mag:

■気になる点
「last」については、みなさんがご存じの「(時間・順序が)最後の」という意味ですが、
問題は「**resort**」であって、一般的に「リゾート地、行楽地」として使われるため、あれって意味不明になってしまいます。

■調べた結果
https://eow.alc.co.jp/search?q=resort
しかし、上記ネット辞書で調べたら、「**頻繁に［大勢が］訪れること**」、「**足しげく通う［皆がよく訪れる］場所**」という意味が含まれており、そう考えたらまさにゲートウェイってその通りだなって理解できました:thumbsup_tone2:
createObjectURL( )

※プログラミング学習中の私がアップロードしてます。理解が浅いです。
この記事は厳密な仕様に関するものではなく、考え方理解のまとめとして受け取ってください。

オブジェクトURLとは
- 

オブジェクトURLとは、オブジェクトに便宜的でユニークなIDを付け、そのIDとURLの種類を組み合わせた文字列です。
この文字列はブラウザがURLとして解釈でき、ブラウザがオブジェクトURLを管理する仕組みに渡すことで、対応するデータを取得できます。

オブジェクトURL
-

オブジェクトURLの作成
File APIなどで取得したFileオブジェクトを、次のようにURL.createObjectURL()の引数に渡すと、オブジェクトURLを取得できます。
![20210515-111703.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/960935/f075b5ad-ff26-1e53-38b2-197c4f78a075.png)

 

```javascript:オブジェクトURLの取得
const objectUrl = URL.createObjectURL( obj );
```
 
※ObjはBlobオブジェクトを指定します。FileオブジェクトはBlobから派生しているので指定可能です。

取得したオブジェクトURLは、次のような"blob:"で始まる文字列です。

```html
"blob:null/f79b06de-2072-4fe4-bb2b-a89383231a79"
```

後ろに続く文字列は、createObjectURL()が呼び出された時に他と重複しないように作成されます。
このときオブジェクトの同一確認をしていないので、同じオブジェクトでも呼び出すたびに異なるオブジェクトURLが作成されます。

オブジェクトURLの仕組み
-

Blobから作成したオブジェクトURLは、Blob URLストアにBlobオブジェクトへの参照とペアで格納されています。

Blob URLストア:{
    Blob URL1:{ オブジェクトURL , Blobオブジェクトへの参照 }
    Blob URL2:{ オブジェクトURL , Blobオブジェクトへの参照 }
   ・・・・
}

URLの参照行為、例えばimgタグのsrcにオブジェクトURLがセットされると、Blob URLストアから一致するものを検索してBlobオブジェクトから、データを取得します。


>https://note.affi-sapo-sv.com/js-create-revoke-objecturl.php
【株式会社divのサービスを終えて】テックキャンプ &UNCOMMON卒業


##目次
・ストーリー
・カリキュラム
・転職活動
・まとめ（感想・反省）

##ストーリー
1.　マコなり社長に惹かれ、テックキャンプ夜間転職コースを2020/7〜2021/1で受講（完全オンライン）
2.　転職サポートを受ける前に一度、UNCOMMONを2021/2〜2021/3月で受講
3.　オリジナルアプリ（ポートフォリオ）のテコ入れをしつつ3月から転職活動スタート
4.　4月末に内定を頂けた。
5.　5月に内定承諾

##カリキュラム
###基礎カリキュラム
事前にProgateをやってたので、すらすら進んだ。
なので、カリキュラムは軽く流し見が多かったです。
####【やったこと】
PC環境構築、HTML・CSS、Rubyについて、WEBとは？、Ruby on Railsで簡易アプリ作成

###応用カリキュラム
少し、難しくなりメンター質問するようになった。
特に、チャットアプリは複雑でもっと質問するべきだったと反省。
####【やったこと】
画像投稿アプリ作成、アプリ開発手順、GitHubの使い方、RSpec（テストコード）、チャットアプリ作成

###発展カリキュラム
Java Scriptは殆ど理解できず、半分程度の理解で進めた。
アウトプットしようにも、インプットが難しかった。質問しようにも、何を質問すればいいのか迷ってしまった。
####【やったこと】
JavaScript、Herokuでアプリ公開、GitHubの使い方、RSpec（テストコード）、チャットアプリ作成

###最終課題カリキュラム
最後の課題として、メルカリのクローンアプリを作成します。
ここの要件定義がクリアできないと卒業できません。また、この課題をポートフォリオとして使うのは止めた方がいいです。
受講最終日にZOOMで作成物のプレゼンがありました。ここでは、このフリマアプリかオリジナルアプリを発表するかは任意です。
早めにフリマアプリを作り終えて、オリジナルアプリを作成されている方はここでオリジナルアプリを発表していました。
####【やったこと】
Formオブジェクトパターン、ActiveHash、PAY.JP（クレカ決済）、フリマアプリの作成

###追加実装カリキュラム
最終課題フリマアプリに追加の実装を考える時に、参考になるカリキュラムがあります。
ここのカリキュラムは完全任意ですが、学習の為、全て受講してウィザード形式以外は実装しました。
しかし、ここで追加実装はポートフォリオとして使うより、オリジナルアプリの為の学習教材と捉えた方が適切です。
####【やったこと】
AWS、Action Cable、ウィザード形式、エラーメッセージの日本語化、画像のプレビュー機能（画像投稿時の選択画像表示）

##転職活動
受講完了後にUNCOMMN2期へ応募していたので先にそっちへ参加しました。
当時は周知されていませんでしたが、転職サポート中でもNCOMMONとテックキャンプの並行活動は禁止です。
申込後に、突然言われたので困惑しました。
なので、転職サポートは一時停止してもらいUNCOMMONを受講しました。（転職保証は外れました）

3月から転職活動をスタートさせましたが、ポートフォリオとして提出するにはしょぼすぎたと感じたので、試行錯誤してブラッシュアップに専念しました。
ポートフォリオは一切の質問が出来ないので、非常に大変でした。
一度だけ、MENTAというサービス(https://menta.work/) を使って現役エンジニアに質問しました。

4月から、実際に転職サイトへの登録や応募など本格的にスタートしました。
キャリアアドバイザーの方は、履歴書の記入内容や面接で話す内容が分からない時は、時間を気にせず大変親身になって相談に乗って下さりました。
転職エージェントでよく聞くような、できるだけ早く適当な企業に入れようとしてくるなんて事は一切ありませんでした。

##まとめ（感想・反省）
完全オンラインで学習して、早めにカリキュラムを終わらせる事をしていました。
広告であったような仲間と共にみたいな体験は全く無かったです。
一応グループ会とかあったようだったが、他の受講生に興味が無かった、マイペースにやりたい、グループの人たちと年代が合わない、
といった理由で全く関わろうとしませんでした。テックキャンプは強制力のようなものが働き、その辺もライフコーチがケアしてくれると思っていました。
しかし、面倒で価値を感じないならグループ会には出なくていいと言われたので、広告にあるようなやり方でも認められていたことを知りました。

トータルで考えて下記の点でモヤモヤしています。
・正直、テックキャンプで高い金額を払った価値があったのか？　テックアカデミーとかでも良かったのでは？
・テックキャンプを最大限利用出来なかった？　
・アウトプットは足りていないのでは？
・もっとカリキュラムの質問を細かくするべきだったのでは？
Firestoreから取得したTimestampをDateTimeに変換する

## Firestoreの初期設定

```pubspec.yaml
dependencies:
  flutter:
    sdk: flutter

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2

  # 追加
  firebase_core: ^1.1.1
  cloud_firestore: ^2.1.0
```

```main.dart
import 'package:flutter/material.dart';
import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
```

## TimestampからDateTimeへの変換

### Firestoreの構成

collection -> document -> createdAt[Timestamp]

### Flutterの実装
```dart
import 'package:cloud_firestore/cloud_firestore.dart';

class ApiDataSource {
  final FirebaseFirestore _firestore = FirebaseFirestore.instance;

  Future fetch() async {
    final document = await _firestore
        .collection('collectionId')
        .doc('documentId')
        .get()
        .catchError((e) => print(e));

    var timestamp = document['createdAt'];
    DateTime createdAt;
    if (timestamp is Timestamp) {
      // toDate()でDateTimeに変換
      createdAt = timestamp.toDate();
    } else {
      createdAt = DateTime.now();
    }
    
    ...
  }
}
```
appendChild()の使い方

appendChild()は、特定の親ノードの子ノードリストの末尾にノードを追加します。
親要素.appendChild(追加したい要素)という形で使われます。
親要素の末尾に要素が追加されなす。
例えばulタグにliタグを追加する場合、下記のようにulタグの末尾に追加されます。


コード例
-
まず次のようなli要素が２つあるul要素を用意します。ul要素の id="list" です。

```html
<ul id="list">
    <li>リスト1</li>
    <li>リスト2</li>
</ul>
```

上のリストのli要素を１つ増やして、下のようなリストを作ります。

```html
<ul id="list">
    <li>リスト1</li>
    <li>リスト2</li>
    <li>リスト3</li>
</ul>
```

JavaScriptコード

```javascript
// 親要素
var list = document.getElementById('list');

// 追加する要素を作成
var li = document.createElement('li');
li.innerHTML = 'リスト3';

// 末尾に追加
list.appendChild(li);
```

まず、親要素（この場合は ul 要素）を取得し、 次に追加する li 要素を作成します。最後に appendChild() メソッドで追加します。

>https://step-learn.com/article/javascript/098-appendchild.html
【Laravel】初めてのAWSデプロイ ~asset関数がhttpsリンクを生成してくれない編~

Laravel + vue.jsで作成したポートフォリオをデプロイするために初めてAWSを利用したところ様々な問題にぶつかり、解決に時間を要しました。

- **発生した問題**
 - JSファイルやCSSファイルが正しく読み込まれない問題 (★ 本記事)
 - [ブラウザを問わず、**数分毎にHTTPとHTTPSが切り替わってしまう**問題](https://qiita.com/namo_berry/items/b985a8515399dc592b2b)

備忘録も兼ねて、前後編という形でここに記していきます。

※ Laravel 6.20.26

## 【前提】AWSの構成
初めてAWSを利用してインフラ構築を行ったので、十分な理解ができているとは言えないと思います。
ハンズオン形式で学習しつつ手探りで作った部分がありますので、「もっとここはこうしたら良いよ」といったことがあればご指摘いただけると幸いです。

簡単な構成図です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/25033d24-97bc-8bd6-0e41-dba5e9311bd7.png)

LaravelプロジェクトはWEBサーバに設置。
ユーザーからの通信はHTTPS通信のみ受け付け、そのリクエストの内容によりALBがWEBサーバかメールサーバかに分岐します。
ALBから先はHTTP通信でやりとりを行う、という構成です。

# JSファイルやCSSファイルが正しく読み込まれない問題
まず、最初にデプロイしてみた結果がこちらです。
![UdemyloadQiita01.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/0b1a5045-723d-94e9-2d76-9bf1348b5ea1.jpeg)

JSファイルもCSSファイルも読み込まれず、テキストだけの寂しい画面が現れました。一体どういうことなのでしょう。
早速確認してみます。すると...

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/477c1f2f-f60a-5248-ec53-8303b248188d.png)

JSファイルとCSSファイルを読み込む際に、パスが`https://~~`ではなく`http://~~`になってしまっています。 
パスが間違っているのですから当然読み込まれません。

該当箇所のHTMLは以下の通り。

```resourses/views/blade.php
    <!-- Scripts -->
    <script src="{{ asset('js/app.js') }}" defer></script>

    <!-- Styles -->
    <link href="{{ asset('css/app.css') }}" rel="stylesheet">
```
どうやらヘルパー関数`asset()`がリンクをhttpで生成してしまっていることが原因のようです。

## asser()がhttpsリンクを生成しない理由

[Laravelのドキュメントによると...](https://readouble.com/laravel/6.x/ja/requests.html#configuring-trusted-proxies)

https://readouble.com/laravel/6.x/ja/requests.html#configuring-trusted-proxies

***TLS／SSL証明を行うロードバランサの裏でアプリケーションが実行されている場合、アプリケーションがときどきHTTPSリンクを生成しないことに、気づくでしょう。典型的な理由は、トラフィックがロードバランサにより８０番ポートへフォワーディングされるため、セキュアなリンクを生成すべきだと判断できないからです。***


とのこと。

LaravelプロジェクトはALBの先にあるWebサーバに設置しているので、ユーザーがhttpsでアクセスしてきてもプロジェクト側から見ればhttpでアクセスされてきた扱いになります。
Laravelのヘルパー関数`asset()`や`url()`などは、httpアクセスされてきたことを受けて、

**「じゃあ生成するリンクもhttpにしよう！」**

と判断してしまうわけですね。

一応`asset()`ではなく`secure_asset()`を使えばhttpsに変換してくれるので一応は解決しますが、ローカル環境ではhttpですし、いちいち置き換えていくのは面倒です。

## TrustProxiesの編集

そこで、`app/Http/Middleware/TrustProxies.php`を編集していきましょう。
ALBに紐付けたサブネットのIPアドレスを記述していきます。

```app/Http/Middleware/TrustProxies.php
<?php

namespace App\Http\Middleware;

use Fideloper\Proxy\TrustProxies as Middleware;
use Illuminate\Http\Request;

class TrustProxies extends Middleware
{
    /**
     * The trusted proxies for this application.
     *
     * @var array|string
     */

    // 以下に追記！
    protected $proxies = [
        // ここにALBに紐づけたIPアドレスを記述します
        '192.168.1.0/24',
        '192.168.2.0/24',
    ];

    // 以下略
}
```

さて、追記した結果どうなったでしょうか？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/2d1c4f3a-3770-3b3a-f396-b7e75dc08cdd.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079033/cc198be2-7bc3-9939-3da3-b1eefa5039fd.png)

CSSが無事に読み込まれ、JSファイルも無事に動いているようです！
ちゃんとhttpsでリンク生成されていますね！

これで問題は無事に解決...するほど甘くはありませんでした。

[3~5分ごとにヘルパー関数が生成するリンクがHTTPとHTTPSで切り替わってしまう問題](https://qiita.com/namo_berry/items/b985a8515399dc592b2b) に続きます。
【jQuery】jQueryでハローワールド

jQueryを公式サイトからダウンロード。
参照: http://jquery.com/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/b1e2a1f2-07cd-a95b-845f-c51c48eade80.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/28eb3157-b616-cc39-ab76-a7e7612d4831.png)



そのまま、Ctrl + s で保存。※ダウンロードフォルダとかはない。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/ead16b22-8f73-e6da-1b14-bc63a0531ee1.png)





```JavaScript

<!DOCTYPE html>
<html lang="ja">
<head>
   <meta charset="UTF-8">
   <title>HelloWorld!</title>
   <script src="jquery-3.6.0.min.js"></script>
   <script>
    $(function(){
      $('body').html('HelloWorld');
    });
    </script>
<body>
</body>
</html>

```

実行結果


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954863/32c6a4f9-7709-3ffa-093f-f268c9227397.png)
PHPでメモリ不足のエラーが表示されてしまう

## 事象
環境構築などで下記のようなエラーと遭遇しましたのでその対処法を記載します。

```
Allowed memory size of *** bytes exhausted
```

## php.iniを探して編集する
まずphp.iniを確認するためパスを探します。（/etc下にいることが多いです）

```
$ ls /etc | grep php.ini
php.ini.default
php.ini.default-previous
```

上記のようにphp.iniがない場合php.ini.defaultをコピーして編集します。

```
$ sudo cp /etc/php.ini.default /etc/php.ini

# 作成されているか確認する
$ php -i | grep php.ini
Configuration File (php.ini) Path => /etc
Loaded Configuration File => /etc/php.ini

$ sudo chmod 644 /etc/php.ini
$ sudo vi /etc/php.ini
```

ファイル内に下記のような記述があるので-1に修正します。

```
; 修正前
memory_limit = 128M

; 修正後
memory_limit = -1  ; -1に変更(メモリ割当を無制限にできる)
```

修正後ターミナルを再起動すると反映されるので解決です。

参考：https://getcomposer.org/doc/articles/troubleshooting.md#memory-limit-errors
【Vue × Realtime Database】特定のkeyを参照して、削除機能実装する


#特定のkeyを参照して、削除機能実装

```html
<transition-group name="chat" tag="div" class="list content">
      <!--chatの中の{ key, name, image, message ,userid }をそれぞれ取得-->
      <section
        v-for="{ key, name, image, message, userid, time } in chat"
        :key="key"
      >
        <div v-if="userid === user.uid" class="myitem flex">
          <!-- 自身 -->
          <!--「画像」の指定-->

          <!--「名前」と「メッセージ」の指定-->
          <div class="mydetail">
            <div class="mytime">{{ $dayjs(time).format("hh:mm") }}</div>
            <div @click.right.prevent="deleteMessage(key)" class="mymessage">
              <nl2br tag="div" :text="message" />
            </div>
          </div>
          <div class="myimage flex">
            <img :src="image" width="40" height="40" />
            <div class="myname">{{ name }}</div>
          </div>
        </div>
        <div v-else class="otheritem flex">
          <!-- 自身ではない -->
          <!--「画像」の指定-->
          <div class="otherimage flex">
            <img :src="image" width="40" height="40" />
            <div class="othername">name</div>
          </div>
          <!--「名前」と「メッセージ」の指定-->
          <div class="otherdetail">
            <div class="othermessage">
              <nl2br tag="div" :text="message" />
            </div>
            <div class="othertime">{{ $dayjs(time).format("hh:mm") }}</div>
          </div>
        </div>
      </section>
    </transition-group>
```

```js
methods: {
   
    childAdded(snap) {
      const message = snap.val();
      this.chat.push({
        key: snap.key,
        name: message.name,
        image: message.image,
        message: message.message,
        userid: message.userid,
        time: message.time,
      });
      this.scrollBottom();
      //スクロールの一番下に追加。
    },

  ~ 省略 ~
 
    },
    deleteMessage(key) {
      firebase
        .database()
        .ref(this.$route.params.id + "/" + key)
        .remove();
      this.$swal({
        title: "内容確認",
        text: "メッセージを削除しますか？",
        icon: "warning",
        buttons: true,
        dangerMode: true,
      }).then((willDelete) => {
        if (willDelete) {
          this.$swal("メッセージを削除しました", {
            icon: "success",
          });
          this.$router.go({
            path: `/chat/${this.$route.params.id}`,
            force: true,
          });
        } else {
          this.$swal("キャンセルしました。");
        }
      });
    },
```

```js
{
    path: "/chat/:id",
    name: "Chat",
    component: Chat,
    meta: { requiresAuth: true },
  },
```

#チャットにて自身のメッセージのみ削除できるようにする

```html
<section v-for="{ key, name, image, message, userid, time } in chat" :key="key">
```

v-forを使ってループを回してそれぞれのメッセージに特定の値[key]を渡しているので
このkeyを使用してメッセージを特定して削除する。

```js
    deleteMessage(key) {
      firebase
        .database()
        .ref(this.$route.params.id + "/" + key)
        .remove();
```
```js
{
    path: "/chat/:id",
    name: "Chat",
    component: Chat,
    meta: { requiresAuth: true },
  },
```

deleteMessage()に引数としてkeyを渡して、firestoreのdatabaseを参照し、
.ref(this.$route.params.id + "/" + key)として

親要素 + "/" + key（それぞれのメッセージの値）

上記で特定の[key]まで参照でき値を取得できます。

これでメッセージが削除出来ます。