OmniAICreator/Qiita-1.07M huggingface dataset:
デュアルブートで前回起動したOSを記憶する設定

windowsとubuntuをデュアルブートした際、起動時のOSの優先順位が固定されてしまい、不便に感じることがあると思います。
grubに以下の設定をすれば、前回起動したOSを記憶し、次回起動時に記憶したOSを優先してくれるため、windows updateが楽になります！

#<手順>
設定ファイルを編集する 

```
sudo gedit /etc/default/grub
```

以下の内容に修正する

```
GRUB_DEFAULT=saved　　　　　　　#"0"->"saved"に変更
GRUB_SAVEDEFAULT=true　　　　　#追記
```

grubを更新する

```
sudo update-grub
```

***
以上の設定をすることで、前回起動したOSが記憶され、次の起動時に優先順位が上がります。

#<参考サイト>
https://www.terakin.com/ja/blog/archives/129
初心者に向けるTiDBの学習 ～ストレージ編 第1回～

## 初心者に向けるTiDBの学習メニュー
[初心者に向けるTiDBの学習 ～ストレージ編 第1回～] (https://qiita.com/it2911/items/a676bb6a63b07e865558)  <- 今ここ
[初心者に向けるTiDBの学習 ～ストレージ編 第2回～](https://qiita.com/it2911/items/8050f76eba36f6dc7a25)
[初心者に向けるTiDBの学習 ～ストレージ編 第3回～](https://qiita.com/it2911/items/054e7a05764753964059)
[初心者に向けるTiDBの学習 ～コンピューティング編 第1回～](https://qiita.com/it2911/items/0dc6ef5e351b4e7379c5)
[初心者に向けるTiDBの学習 ～コンピューティング編 第2回～](
https://qiita.com/it2911/items/0819844669fe12b3d6b2)
[初心者に向けるTiDBの学習 ～スケジューリング編～](
https://qiita.com/it2911/items/0a5e9b4c4f0eee846ba7)

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197234/729797a4-f16a-25f6-f6cd-da4ca7e6553c.png" alt="drawing" width="400" align="center"/>

## はじめ
データベース、オペレーティングシステム、コンパイラは、コンピュータソフトウェアを構築するメインとなる基盤です。データベースはアプリケーション層に近くビジネスをサポートするシステムで、何十年にもわたって開発が続いており、日々進化し続けてます。

多くの人々が様々な種類のデータベースを利用してきたと思いますが、データベース(特に分散データベース)の開発経験がある方はごく少数と思います。データベースの実装から知るとスキル向上につながるだけでなく、他のシステムの構築にも役立ち、データベースを巧みに活用する事ができます。

技術理解を深めるのにベストな方法は、その分野のオープンソースプロジェクトに打ち込むことだと筆者は考えます。データベース分野にも多くの優れたオープンソースプロジェクトが存在します。このプロジェクトを通して、特に有名なMySQLとPostgreSQLのソースコードを読んだことがある人も多いはずです。分散データベース分野の中でTiDBも認められている数少ないプロジェクトで、上記製品と同様にソースコードを読むことも可能です。

ただ、分散データベースは複雑なため、多くの技術者にとってプロジェクト全体を理解するのが困難なようです。その為、筆者はTiDBの技術を分かりやすく解説する記事をまとめることにしました。オープンソースから読み取れるテクニックだけでなく、SQLインタフェースの背後に隠されている実装の際のテクニックなども多数ご紹介致します。

## データの格納

データベースの最も基本的な機能であるデータの格納について説明します。データを格納する方法は多数あります。一番簡単なのは、メモリ内にデータ構造を構築し、ユーザーから送信されるデータを格納するという方法です。たとえば、配列を使用してデータを格納し、データを受信したときにその配列に新しいエントリを追加できます。このソリューションはシンプルで、基本的なニーズを満たし、パフォーマンスにも優れています。しかし、これらの利点を上回る欠点が存在します。一番大きな問題は、すべてのデータがメモリに保存されるため、サーバーが停止または再起動するとデータが失われることです。

データの持続性を達成する手段としては、ディスクなどの不揮発性ストレージにデータを格納します。ディスク上にファイルを作成し、データを受信したらそのファイルに新しいデータを追加します。これは、持続性のあるストレージソリューションですが、これだけでは、十分とは言えません。なぜなら、格納しているディスクが壊れた場合、データが失われるからです。その為、ディスクが壊れた場合を想定しRAID (Redundant Array of Independent Disks)で冗長化し使用します。しかし、マシンがダウンしたらどうなるでしょうか？データにはアクセスできなくなります。 
RAIDは安全な格納場所にはなりません。他にも、ネットワーク経由でストレージにデータを保存する方法や、冗長ソフトウェアを利用し、ハードウェアレベルで複製する方法などがあります。このような方法の問題は、複製した際の一貫性の維持です。データの完全性(無損傷性)と正確性の保護は基本要件であり、実現するには、下記で示すような難しい問題が存在します。

- 高速な書き込み速度が必要
- 格納時のデータを一貫性をもって読み取ることが必要
- 同時修正に対処する必要
- 複数レコードをアトミックに修正する必要

これらの問題はどれも解決が困難ですが、全てを解決できてこそ、優れたデータベースストレージシステムと言えます。

このような背景を踏まえ、当社は、TiDBのデータストア部分であるTiKVを開発致しました。まずは、SQLの概念は忘れて、高パフォーマンスで高信頼の分散キーバリューストアのTiKVの実装方法をご紹介いたします。
**※ TiKVは、KVSとしてご利用いただくことも可能です。**

## キーバリュー

データストレージシステムにおける最初の最重要ステップは、データの格納モデルの決定、つまり、どのフォーマットでデータを格納すべきかという決定です。TiKVは、オリジナルバイト配列がキーと値から構成された巨大なマップと考えることができます。このマップでは、キーはバイト配列の生のバイナリビットに従って比較順に配置されます。以下の点に留意する必要があります。

1. これはキーバリューペアから成る巨大なマップです。
2. このマップでは、キーバリューペアはキーのバイナリシーケンスに従って順序付けられます。ユーザーはキーの位置をシークし、他のキーバリューペアに対してNextメソッドを使用できます。これらのキーバリューペアはすべてこれよりも大きくなります。

この記事で語られているストレージモデルとSQLのテーブルの関係はどうなっているの？と疑問を感じている方もいらっしゃることでしょう。はっきり言います。無関係です。

---
今回はストレージとキーバリューの基本知識を紹介しました。次回、[初心者に向けるTiDBの学習 ～ストレージ編 第2回～](https://qiita.com/it2911/items/8050f76eba36f6dc7a25)で分散Key-ValueのTiKVの原理を紹介させていただきます。
PayPal かんたん決済ボタンを作成する

## 概要

事前に作成されたコードをコピーし、お客さまのウェブサイトで販売する商品またはサービスの横に貼り付けるだけで、かんたんにPayPal Checkoutを設定できます。ショッピングカート機能を追加せずに決済機能を追加できます。

PayPalアカウントにログインし、[かんたん決済ボタンを作成](https://www.paypal.com/buttons/smart) します。
Powershell で Exchange Online の全ユーザーのメールボックスの言語設定を日本語に変える

Microsoft365でユーザー(Mailbox)を作成したとき、言語が日本語にならない（デフォルト設定する箇所ご存じの方は教えてください）。
PowerShellで言語がJPでないメールボックス（UserMailbox）を一気に日本語に変えるスクリプトです。

```powershell
Get-Mailbox -Filter "RecipientTypeDetails -eq 'UserMailbox' -and LanguagesRaw -notlike '*JP*'"|
foreach {Set-MailboxRegionalConfiguration -Identity $_.Identity -Language 'ja-JP' -DateFormat 'yyyy/MM/dd' -TimeFormat 'H:mm' -TimeZone 'Tokyo Standard Time' -LocalizeDefaultFolderName:$True }
```

※ スケジュールの共有設定がデフォルトではAvailabilityOnly（空き時間情報の表示）なのでこれを一括でReviewer（予定の詳細表示）に変えようとしたところ、スケジュールのフォルダ名が「予定表」だったり英語だったりして指定できないので日本語に統一するために作りました。
【Udemy】文系新卒がAWSを学ぶ話　~基礎用語を知る~

#◎受講の目的
目的は、大きく分けて2点あります。以下の通りです。

・AWSの経験を積む
・Udemyがどんなもんのか知る

#◎講座紹介
今回受けた講座は、以下の通りです。

AWS：ゼロから実践するAmazon Web Services。手を動かしながらインフラの基礎を習得
https://www.udemy.com/course/aws-and-infra/

#◎基礎的な用語について

### AWS って？
AWS （Amazon Web services）とは、Amazon社が提供している　**クラウドサービス**　のこと。

100種類以上の豊富なサービスを提供していて、出来ることの幅が広く、
従量課金であるため、必要な分だけを支払えば良いといったメリットを持っている。

### クラウド って？
クラウドとは、**インフラをネットワーク経由で使用・管理する形態**のこと。

サーバーを用意する必要がないため、初期費用が少ない・サーバーの増減がしやすいというメリットがある。（この点が　オンプレミス　との違い）

###  インフラ って？
インフラとは、技術用語として**システムやサービスの基盤となる設備**のことを指す。
＝ サーバー 、ネットワーク

### サーバー って？
サーバーとは、**クライアントに対してサービスを提供するコンピューター**のこと。

### ネットワーク って？
ネットワークとは、**複数のコンピューターを繋いで、データの送受信できるような仕組み**のこと。

##◎まとめ
今回は、AWSを学習していく中で、知っておくべき基礎用語についてまとめてみました。

当記事では文字だけで説明をしていますが、講座では図も交えて解説をされているため、
何倍も理解しやすくなっています。**是非！**
GAS 超簡単メールサーバの作成

# 概要
GASを勉強し始めてから、いろいろな可能性を見出すため、いろんなことをしています。
その中で今回は超簡単にメールサーバを作ることができたので、その紹介をしていきます。

***

# 準備
- google driveからgoogle app scriptを作成します。
- エンドポイントを公開する必要があるので旧エディタを開きます。（画面右上の方に、「以前のエディタを使用」をクリックします）

***

# doPost関数の作成
doPost関数を作成して、引数を受け取れるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/6df8955e-d245-7c2c-99a2-a7e9d3686117.png)

> **doPostとは？**
GASのエンドポイントを作成したときに、POSTで送られてきたリクエストはすべてdoPostが実行される仕様になってます。
他にもdoGetなどを用意すれば、GETのリクエストを処理することもできます。

***

# メールの処理
次に、メールを送信する処理を書いていきます。
今回は引数から、to, bodyを取得して、メールを送信します。

```js
function doPost(e) {
  const {
    to,
    body,
  } = JSON.parse(e.postData.getDataAsString());

  MailApp.sendEmail({
    to,
    subject: 'GASメールのテスト',
    body
  });
}
```

***

# APIを作る
次に、エンドポイントを作成します

上のタブにある
公開→ウェブアプリケーションとして導入
をクリックします。

***

今回はテストのため、ピンク枠でしている公開範囲を設定してください。
更新ボタンを押すと、エンドポイントが作成されます。
![DADEE46B-FAC3-4323-A420-3BE69F793C39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/44a6d5bf-09ff-a565-764c-01e3afb50431.png)

***

ピンク枠部分がエンドポイントになります。
コピーしてください。
![BD0EED4A-374F-4A11-9CE0-B01A68C775D4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/ce5f4f26-2dcb-b7f8-99e3-ede93f823324.png)

***

# curlの作成
最後にこれを実行して、送信できるか試してみましょう！

```
curl -X POST -H "Content-Type: application/json" -d '{ "to": "送信先のメールアドレス", "body": "メールの内容" }' https://script.google.comXXXXXXXXXX
```
"The server quit without updating PID file"の解決方法

`mysql.server start`でMySQLを起動しようとすると、`The server quit without updating PID file`のエラーが表示された時の対処法をご紹介いたします。

## 環境
- MacOS
- Homebrew 3.2.0
- MySQL 5.7

## よくある解決法

```file:PIDファイルを作成
$ touch /usr/local/var/mysql/****.local.pid
```
```file:権限変更
$ sudo chown -R _mysql:_mysql /usr/local/var/mysql
```
```file:PID削除
$ ps -ef | grep mysql
$ sudo kill -9 PID
$ sudo mysql.server start
```
```file:アンインストール
$ brew uninstall mysql
$ brew install mysql
```

これらの方法でも解決できなかった方は以下の方法をお試しください。

## 解決方法

__① local配下全削除__

```
sudo rm -rf /usr/local/mysql
sudo rm -rf /Library/StartupItems/MYSQL
sudo rm -rf /Library/PreferencePanes/MySQL.prefPane
sudo rm -rf /Library/Receipts/mysql-.pkg
sudo rm -rf /usr/local/Cellar/mysql*
sudo rm -rf /usr/local/bin/mysql*
sudo rm -rf /usr/local/var/mysql*
sudo rm -rf /usr/local/etc/my.cnf
sudo rm -rf /usr/local/share/mysql*
sudo rm -rf /usr/local/opt/mysql*
sudo rm -rf /usr/local/mysql*
sudo rm ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
sudo rm -rf /Library/StartupItems/MySQLCOM
sudo rm -rf /Library/PreferencePanes/My*
```
途中、`no matches found`や`No such file or directory`などが表示されても、続けて次のコマンドを実行してください。

② MySQLをインストール

```
$ brew install mysql@5.7
```
バージョンはご自身で指定してください

③ パスの設定
![スクリーンショット 2021-07-02 16.16.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/654387/2a645a7a-8ef8-3bb8-07d4-e8d7f8af8dcc.png)
インストールが成功すると上記のような画面になると思うので、画像の水色の部分を実行してください。

```
$ echo 'export PATH="/usr/local/opt/mysql@5.7/bin:$PATH"' >> ~/.zshrc
```
```
$ source ~/.zshrc
```
（`~/.zshrc`は環境によって異なる場合があります。）

③ MySQL起動

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

## 参考サイト
- https://zenn.dev/endo/articles/24cad36f73626abbde67
【Laravel】CKEditorを使ってWYSIWYGエディタで投稿する！

## はじめに
よし、ブログ投稿画面を作るぞ！
まずは form をつくって～...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/39ba4fb4-e254-3931-97d5-a37e7352f8a0.png)
よし出来た！
...けど文字装飾とか確認できないし、何より味気ないなぁ...

→CKEditor導入後
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/6a005bc8-1aa1-9507-4727-cd5fc1e68608.png)
これこれ！これをやりたかったんだ！

ちなみにWYSIWYGとは"What You See Is What You Get"の略で、
編集中のデータがそのまま画面に表示されるよといった意味合いです。

## 開発環境
Laravel 8.45.1
PHP 7.4.7

## 導入
なんの変哲も捻りもないフォームに対して、
①input textarea にクラスを付与
②ckeditorのスクリプト読み込み
この２件で再現可能です！

```html:edit.blade.php
<form method="POST" action="{{ route('posts.store') }}">
    @csrf
    <div >
        <label for="title_post">Title</label>
        <div>
            <input type="text-input" name="title">
        </div>
    </div>
    
    <div style="width:50%">
        <label for="text-input">Text</label>
        <div>
            // class="ckeditor"を付与
            <textarea class="ckeditor" name="text"></textarea>
        </div>
    </div>

    <div>
        <button type="submit">Post</button>
    </div>
</form>

// 外部スクリプトの読み込み
<script src="//cdn.ckeditor.com/4.14.1/standard/ckeditor.js"></script>
```
以上です、簡単！
パッケージをダウンロードしたい場合は公式からダウンロード可能です。
https://ckeditor.com/ckeditor-4/download/


## 使い方
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/0375f1eb-72fb-d96e-17fa-2932efe51e53.png)
このように直感的に作成が可能です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/508299/566b3910-38cc-3e9c-55a9-96f307bfc476.png)
POSTデータはHTML構造で格納されます。
公式ページでデモ操作が可能ですので、お試しあれ！
https://ckeditor.com/ckeditor-4/demo/

## 終わりに
今回はCKEditorを利用してWYSIWYGエディタを導入する方法をご紹介いたしました。
エディタ自体の装飾もできるようなので、どんなコンセプトのサイトでも気軽に導入できそうですね！
WordPressの子テーマでCSSとJavaScriptを即反映させる方法

WordPressで、CSSやJavaScriptを変更しても、既にページにアクセスしたことのあるユーザはキャッシュから読み込まれてしまうために、修正内容がすぐに反映されません。CSSやJavaScriptを読み込む際にファイル名の後ろにファイル更新日時をもとにしたバージョンを付加することで、即反映させることができます。


###サンプル
```php:functions.php

// CSS,JS読込
function my_wp_enqueue_scripts() {
  // CSS読込
  wp_enqueue_style( 'my-style', get_theme_file_uri( '/css/style.css') , array() , filemtime( get_theme_file_path( '/css/style.css') ) );

  // JS読込
  wp_enqueue_script( 'my-script', get_theme_file_uri('/js/script.js'), array( 'jquery' ), filemtime( get_theme_file_path( '/js/script.js' ) ), true );
}
add_action( 'wp_enqueue_scripts', 'my_wp_enqueue_scripts' );
```

##解説
###filetime()
第4引数はバージョンでfiletime()にすることで、該当ファイルが更新されたら即反映されるようにできる

###wp_enqueue_script
第5引数をtrueにするとフッター読込になる
tf.keras.utils の plot_model で Failed to import pydot. You must install pydot and graphviz for pydotprint to work と言われた時【TensorFlow】

# はじめに
タイトルの通り、**tensorflow.keras.utils** の **plot_model** を使った際、`ImportError: Failed to import pydot. You must install pydot and graphviz for pydotprint to work` と言われたときの解決策を書きます。

簡単なメモですが参考になれば嬉しいです。

# 環境

| 項目 | version |
| :-: | :-----: |
| OS | Ubuntu 18.04|
|Python |3.7|
|TensorFlow|2.2|

これらは **Anaconda** 上の **Jupyter Notebook** での話です。


# エラーが起きたコード

```python
from tensorflow.keras.utils import plot_model

# モデルは適当です
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10, activation='softmax')
])

plot_model(model)  # これ
```

このコードを実行すると、以下のようなエラーが出ます。

```
ImportError: Failed to import pydot. You must install pydot and graphviz for pydotprint to work
```

# 解決策
結論として、以下の3個のライブラリを順番にインストールすると解決しました。

```shell
conda install pydot
conda install pydotplus
conda install graphviz
```
anaconda環境でない場合はpipでも大丈夫だと思いますが未検証です。


# 余談集
ややこしい点や解決までにハマった点のメモです。

## 余談1: graphvizをインストールしなかった場合のエラー
graphvizのみインストールしていない場合は以下のエラーが出ました。きちんと3個インストールしましょう。

```
InvocationException: GraphViz's executables not found
```


## 余談2: plot_modelのパラメータについて

`plot_model`にはいくつかパラメータがあります。
お好みに合わせて調整してみてください。

```python
plot_model(model, show_layer_names=False, show_shapes=True, to_file="../fig/model.png")
```


## 余談3: to_fileで指定できる拡張子について

`to_file`で指定できる拡張子は限られているようで、`.pdf`や`.jpg`は以下のようなエラーが出てしまいました（自分だけ？）。

```
ValueError: Cannot embed the 'pdf' image format
```

しかし、フォルダを確認したところきちんと保存されていたので、皆さんも一度フォルダを確認してみてください。



# おわりに

短い記事でしたがご覧頂きありがとうございました。
ご意見等ございましたらコメントお願いします。
dockerでHOMEディレクトリを設定する

## 概要
dockerで、laravelで`php artisan tinker`を使ったらエラー発生した。
HOMEディレクトリに関係するエラーが発生したので、調べたことをメモしておく。

## 発生したエラーについて
コマンド実行するとHOMEディレクトリに`.config`フォルダを作成する。
そのため、パーミッションエラーとなったようです。

```bash
$ docker-compose exec php php artisan tinker

   ErrorException  : Writing to /var/www/.config/psysh is not allowed.

  at /var/www/www.example.com/vendor/psy/psysh/src/ConfigPaths.php:228
    224|             @\mkdir($dir, 0700, true);
    225|         }
    226| 
    227|         if (!\is_dir($dir) || !\is_writable($dir)) {
  > 228|             \trigger_error(\sprintf('Writing to %s is not allowed.', $dir), E_USER_NOTICE);
    229| 
    230|             return false;
    231|         }
    232| 
```
実行ユーザーを`www-dataユーザー`に変更していた。
しかし、HOMEディレクトリの所有者は、`rootユーザー`のままだったことが原因でした。
## HOMEディレクトリを定義する
Dockerfileで、HOMEディレクトリを設定する。
※ ついでなのでプロンプトの表示も変更してみた...

```Dockerfile
FROM php:7.3-fpm

ARG USER="www-data"
ARG UID="1000"
ARG GROUP="www-data"
ARG GID="1000"

...

# create user & group
RUN usermod -u $UID $USER && groupmod -g $GID $GROUP

# ↓ ここ追加！！ ( create home directory )
ARG HOME_DIR='/var/www'
RUN mkdir -p $HOME_DIR
RUN chown -R $UID:$GID $HOME_DIR

# application directory
ARG APP_DIR='/var/www/www.example.com'
RUN mkdir -p $APP_DIR
RUN chown -R $UID:$GID $APP_DIR

# change user ( root -> www-data )
USER $USER

# ↓ ここ追加！！ - 環境変数を設定する ( printenv HOME )
ENV HOME $HOME_DIR

# ↓ ここ追加！！ - プロンプト表示を変更する ( create .bashrc )
RUN { \
    echo 'export PS1="${debian_chroot:+($debian_chroot)}\u@\[\e[1;33m\]\w\[\e[m\] $"'; \
    echo ''; \
} >> $HOME_DIR/.bashrc

...
```

## 動作確認
修正して再度ビルドして再起動 & tinkerコマンドを実行してみました。

```bash
$ docker-compose exec php php artisan tinker
Psy Shell v0.9.12 (PHP 7.3.29 — cli) by Justin Hileman

>>> Hash::make('HogeFuga123456');
=> "$2y$10$6RS1EnIBSsHLMy/K02URCeB4QLsti1f53pkLb2px1lqXt34bRZvYa"  

>>> exit
Exit:  Goodbye
```

問題ないようです。

## 参考サイト
* [Github - docker-library/php](https://github.com/docker-library/php/blob/master/7.3/stretch/fpm/Dockerfile)
* [環境変数の一覧を表示するには](https://www.atmarkit.co.jp/flinux/rensai/linuxtips/107showenv.html)
* [DockerfileでPATHを通す時はRUNではなくENVを使おう](https://qiita.com/TakashiOshikawa/items/2b8974c242a7054e0be5)
* [Bashプロンプトの変更](https://qiita.com/zaburo/items/9194cd9eb841dea897a0)
* [Laravelのtinkerを使えるとちょっと幸せになれる](https://qiita.com/juve_534/items/96dc6e7e0652dced1428)

以上
javascript で自動スクロール

#javascript で自動スクロール
1秒後にディスプレイのリフレッシュレートに合わせて、ページ最下部までゆっくりとスクロールします。

```javascript
i = 0;
var start = function () {
    scrollTo(0, i);
    // この数字を変更することにより、進み具合を変えれます。
    i = i + 5;
    if (window.pageYOffset >= document.documentElement.scrollHeight - document.documentElement.clientHeight) {
    }else{
        window.requestAnimationFrame(start);        
    }
};
window.setTimeout(start, 1000);
```
Docker Desktop for WindowsでWindows10からDockerコンテナにGit Bashでアクセス

#目的
Docker Desktop for Windowsで作成したGitlabのrootパスワードを変更したい。

#対応方針
コンテナにターミナルを割り当てる事でLinuxのように操作ができます。
（Git BashからDockerで作成したGitLabコンテナにアクセス）
[Dockerのコンテナにターミナルソフトでアクセスする方法](https://teratail.com/questions/276905) を参考にさせて頂きました。

#Git Bashを起動（git bashを導入する方法は割愛）

```powershell
XXXX@DESKTOP-BMGUJA8 MINGW64 /
```

#コンテナにターミナルを割り当て
1. dockerディレクトリに移動

私の環境では以下ディレクトリとなります。

```
C:\docker
  └─my_prot01　
```

```powershell
$ cd c://docker/my_prot01

XXXX@DESKTOP-BMGUJA8 MINGW64 /c/docker/my_prot01
$ pwd
/c/docker/my_prot01
```

1. winptyコマンド（※1）を使用してgit bashからコンテナにアクセス

```powershell
XXXX@DESKTOP-BMGUJA8 MINGW64 /c/docker/my_prot01
$ winpty docker exec -it gitlab bash
root@gitlab:/#  ★切り替わる
```

※1
winptyコマンドについては、[[Git Bash] winpty コマンドについて調べてみた](https://mseeeen.msen.jp/what-does-winpty-command-do/) を参考にさせて頂きました。

#RilsConsoleを起動

```powershell
root@gitlab:/# gitlab-rails console -e production
--------------------------------------------------------------------------------
 Ruby:         ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-linux]
 GitLab:       14.0.1 (76b84b42f64) FOSS
 GitLab Shell: 13.19.0
 PostgreSQL:   12.6
--------------------------------------------------------------------------------
Loading production environment (Rails 6.1.3.2)
irb(main):001:0>  ★切り替わる
```
#GitLabのパスワードを変更
[GitLabのrootパスワード変更方法](https://qiita.com/crnls1985/items/4fb42d803b0685eff092) に詳しく書かれているため、こちらのサイトを参考にして頂ければと思います。
VSCodeでphp-cs-fixerのトラブル

# 環境構築

VSCodeでPHPのコード自動成型のExtensionが色々あるが、いつも[php cs fixer](https://marketplace.visualstudio.com/items?itemName=junstyle.php-cs-fixer)を使っている。

このExtentionには`php-cs-fixer.phar`が同梱されているが公式ではパフォーマンスが低いので別途インストールすることを推奨している。

> Install php-cs-fixer
  1. this extension has included php-cs-fixer.phar for beginner, maybe performance lower.
  2. if you want to install php-cs-fixer by yourself, see: php-cs-fixer Installation guide

なので、[Installation guide](https://github.com/FriendsOfPHP/PHP-CS-Fixer#installation)に則ってインストールした。
*Windows 10 on WSL2(Ubuntu-20.04)*なので手順通りターミナルより下記を入力。

```bash
$ mkdir --parents tools/php-cs-fixer
$ composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer
```

次に`Settings`より *Extentions > PHPCSFixer > Executable Path*を変更する。
`php-cs-fixer` → `(自分のホームディレクトリ）/tools/php-cs-fixer/vendor/bin/php-cs-fixer`
※Windowsで直接開発している場合は *Extentions > PHPCSFixer > Executable Path Windows* にパスを指定する。

これで、フォーマットができるようになるはず！

# 実行！あれっ！？

マニュアル通りにVSCode上で`F1` -> *php-cs-fixer: fix this file* をするが無反応......
OUTPUT を見てみる。

```
[2021-07-02 07:21:18.812] [exthost] [error] [junstyle.php-cs-fixer] provider FAILED
[2021-07-02 07:21:18.812] [exthost] [error] undefined
```

ん～、なんか失敗している。

調べるとこんなIssueが [junstyle.php-cs-fixer provider failed](https://github.com/junstyle/vscode-php-cs-fixer/issues/114)
ここに書かれている内容はデフォルトの`php-cs-fixer.phar`のパスを解決する(`${extensionPath}/php-cs-fixer.phar`)話なので、ちょっと今回の件とは違うが、VSCode自体に`Developer Tools`が存在することを知る。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89477/315177ee-efb3-d6ae-14ba-74c35b80d080.png)
VSCodeはElectronベースなコードエディタなので、ブラウザデバッグできるのだ。
`F1` -> *Developer: Toggle Developer Tools*を選択すると、右ペインにおなじみの画面が
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89477/d70a0a54-c2ff-6afe-8f58-51fa14659272.png)
この状態でもう一度`F1` -> *php-cs-fixer: fix this file*を実行するとエラーの詳細が表示された。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89477/da156de1-e99d-1ee2-1ccc-b0301e02d28a.png)

> Configuration file `.php_cs.dist` is outdated, rename to `.php-cs-fixer.dist.php`.

設定ファイル名の形式が古いからリネームしろとのこと。
どうやら`php-cs-fixer:3.0`でルールが変わったらしい。

どうするか迷ったが、チーム開発をしているので勝手にファイル名をリネームするとほかの人に迷惑がかかる。
今回は`php-cs-fixer`を2系に落として対応とした。

```sh
$ composer require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer:^2.0.0
```


設定ファイルリネームの件は[CHANGELOG.md](https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/3.0/CHANGELOG.md)を見ても特に言及がないように見える......
ネットで調べてみてもあまり情報が載ってなさそうだったので、記事にしてみた。

# 2021/09/13追記
[UPGRADE-v3.md](https://github.com/FriendsOfPHP/PHP-CS-Fixer/blob/v3.0.0/UPGRADE-v3.md)にしっかり載ってた。
Python ファイルを間引くスクリプト shutil, glob使用

ググるのがメンドウになって自作。
githubに載せるほどでもないのでメモ

～2021/07/07 コメントを受けて、編集しました(Numpy無しでもOKだったため)～


### 大まかな手順
1. ファイルの一覧を作成(#glob)
1. 3つおきに変更した配列を取得
1. 各ファイルを移動先にコピー(#shutil)


### 前提（ディレクトリ構造）
current
├─from
└─to

※ fromに複数のファイルが存在。それを間引いてtoにコピー。


### ソースコード（メモ）currentでの実行を前提
```python
import glob, shutil

# 移動元からファイル名一覧を取得（例として、 jpg画像とした）
files = glob.glob("from/*.jpg")
skipped_files = files[::3] # 例として「3つおきに取得」とした

# ファイルコピー
for f in skipped_files:
  shutil.copy(f, "to")  # 移動先をディレクトリ名だけにすると、ファイル名はそのままでコピーされる
```


### 参照 URL
globの使い方: https://www.tech-teacher.jp/blog/python-glob/
ファイルのコピー(shutil): https://qiita.com/myasu398/items/9d81c1d58816ae60db5b

---
メンドウだなーとか思ったけど、いざ作ったら一瞬だった
優秀なライブラリを作ってくれた先人たちに感謝。
CLI操作とLinuxコマンド

CLI操作とLinuxコマンドについて学習した内容をまとめています。

ターミナルでCLI操作をするにあたり、基本的な操作をLinuxコマンドで実行していきます。

### CLI操作とは
CLI **「Command Line Interface」コマンド ライン インターフェース**は、情報を文字によって表示し、キーボードからの入力によって操作を行う方式のこと。

**GUI(グラフィカルインターフェイス)**
コマンドラインとは対照的にグラフィックを用いて操作を行う仕組みをグラフィカルインターフェースと言います。

例えば、「マウスでファイルをダブルクリックして開く」という操作はGUIで行っている。

## Linuxコマンド

Linuxコマンドとは、**「PCへ操作を命令するためのコマンド」** です。
ターミナルでは、Linuxコマンドの入力でPCに様々な命令を与えます。

### Linux（リナックス）とは
Linux（リナックス）とはOSと呼ばれるPCの中身の種類となるものです。
深く入る前に **「PCに様々な命令を与える」** と理解しておけばOK。

```terminal:ターミナル
% 入力するLinuxコマンド
```

## pwdコマンド

pwdコマンドは **「print working directory」** の略で
カレントディレクトリのパスを表示するコマンドです。

```terminal:ターミナル
% pwd

# pwdコマンドにより現在の出力結果が確認できます。
/Users/ユーザー名/Desktop/現在のファイル名
```

## lsコマンド

lsコマンドは **「list segments」** の略で、ディレクトリやファイルの一覧を表示するコマンドです。
lsコマンドを実行することで、カレントディレクトリの直下にあるディレクトリやファイルの名前が一覧で表示されます。

また、lsの後に半角スペースを空けて、ディレクトリのパスを入力して実行すると指定したディレクトリの中身を一覧表示します。

```terminal:ターミナル
% ls

#指定したディレクトリの中身を一覧表示する
% ls [中身を表示したいディレクトリのパス]
```

## cdコマンド

cdコマンドは **「change directory」** の略でカレントディレクトリを移動するときに使います。
使い方はターミナルでcd[移動したいディレクトリのパス]と打ち込んでエンターを押す。

また、cdだけ入力して実行した場合は、ホームディレクトリに移動します。

## ターミナルの見方
```terminal:ターミナル
abcde@MacBook-Pro-abcde 〜　% 
```
1番左の「abcde」　→ ユーザー名
「@MacBook-Pro-abcde」　→ コンピューター名
「〜」　→ カレントディレクトリ
「％」　→ プロンプト

## ディレクトリ

### ルートディレクトリ
その階層構造の1番上にあるディレクトリのことです。
 **「cd/」** とターミナルで入力することでパスを指定することができます。

```terminal:ターミナル
# ルートディレクトリに移動
% cd /
```

### カレントディレクトリ
ターミナルで、現在作業中となるディレクトのことをカレンディレクトと呼びます。
カレントディレクトリは **「〜」** と表示されます。

### ホームディレクトリ
**新規にターミナルを立ち上げた場合に作業中となるディレクトリのこと**です。
Macでのデフォルトのホームディレクトリは **「/Users/ユーザー名」** となり、ターミナルでは **「〜」** で表示されます。
パスの指定方法は絶対パスと相対パスの2つがあります。

### 絶対パス
絶対パスとは**ルートディレクトリから指定するパス**のことです。
ルートディレクトリは **「/」** です。

```terminal:ターミナル
% /Users/ユーザー名/Desktop

# /Users/ユーザー名はホームディレクトリなので以下のように表示することもできます
% 〜/Desktop
```

### 相対パス
相対パスとは**カレントディレクトリから指定するパス**です。
ルートディレクトリから指定しないため、パスの始めに **「/」** をつけてはいけない。

```terminal:ターミナル
# カレントディレクトリがホームディレクトリの場合
% Desktop

# カレントディレクトリがホームディレクトリの場合にデスクトップにあるファイルの場所を指定することができる。
% Desktop/プログラミング.png
```

### パス
　パスとはディレクトリやファイルの所在を示す文字列のこと。
ディレクトリは階層ごとに **「/(スラッシュ)」** で区切ります。

## 最後に
基本的なLinuxコマンドは上記以外にもまだまだたくさん存在します。
これからもっと学習を進め、この記事を更新していきます。
[AWS] Cloud9上でTerraformを使えるようにしてみる

[Cloud9](https://aws.amazon.com/jp/cloud9/)から[Terraform](https://www.terraform.io/)で環境構築できるようにするための手順の整理です。

### Cloud9
マネジメントコンソールから作成します。
スペックは特にないですが、`t3.small`くらいにしておきましょう。

### Cloud9のお掃除
まず、Cloud9に最初から入っているDockerイメージを削除します。

デフォルトで、これだけのDockerイメージが入っています。
![docker.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427998/4a2fd176-4988-1bc7-b0db-4310d59a8b0b.png)
Terraformのインストールにもディスクが必要になってきますので、使用しないこれらのDockerイメージを削除しておきます。

```bash
docker images -aq | xargs docker rmi
```

### パスワードの設定
[Homebrew](https://brew.sh/index_ja)インストール中にパスワードを訊かれるので、事前に、`ec2-user`のパスワードを設定しておきます。

```bash
sudo passwd ec2-user
```

### Homebrewのインストール
今回は、Homebrew経由でインストールするので、事前にHomebrewをインストールします。

```bash
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

この流れの中でパスワードを訊かれるので、事前にセットしたパスワードを入力します。

### パスの設定
brewのパスをセットしておきます。

```bash
test -d ~/.linuxbrew && PATH="$HOME/.linuxbrew/bin:$HOME/.linuxbrew/sbin:$PATH"
test -d /home/linuxbrew/.linuxbrew && PATH="/home/linuxbrew/.linuxbrew/bin:/home/linuxbrew/.linuxbrew/sbin:$PATH"
test -r ~/.bash_profile && echo "export PATH='$(brew --prefix)/bin:$(brew --prefix)/sbin'":'"$PATH"' >>~/.bash_profile
echo "export PATH='$(brew --prefix)/bin:$(brew --prefix)/sbin'":'"$PATH"' >>~/.profile
```

### tfenv
まず、tfenvをインストールします。

```bash
brew install tfenv
```

### Terraformのインストール
最後にTerraformをインストールします。

```bash
tfenv install latest
```

バージョンを確認してみましょう。
![version.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427998/44fccc59-ec88-154f-be62-2fed8fa56768.png)

はい、これでCloud9上でTerraformが使えるようになりました！
Rubymine のショートカットを忘れがちなあなたに。

Rubymine と書きましたが JetBrains 製の IDE であれば共通だと思います。
# 結論
shift キーを二回押して実行したいコマンドを入力する。
## 例
コードの再フォーマット
![Screen Shot 2021-07-02 at 14.48.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/10b7ea6b-ba80-700c-20dc-ab48d090595e.png)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/6131a119-a3f3-f60d-6d5f-028f142cdd82.png" width=30%>
この時ショートカットも表示されているので2回目以降はショートカットで実行できます。

Preference (`⌘,`) -> Keymap から略語を設定しておくとさらに捗る。
![Screen Shot 2021-07-02 at 15.21.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/25171e78-f3c2-e838-81c5-dcdd8e1dbc04.png)
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/04858351-296f-81ef-21bf-75d4c2847956.png" width=70%>
![Screen Shot 2021-07-02 at 15.24.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/aedeb63a-89ef-97bf-dc49-19250b9ad647.png)


# おまけ
計算もできる
![Screen Shot 2021-07-02 at 15.12.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97431/0d1e12d8-08ee-27b1-c964-0d3070b7c3e0.png)


# 参考

https://pleiades.io/help/ruby/reformat-and-rearrange-code.html
https://pleiades.io/help/ruby/searching-everywhere.html
kintoneのテーブルのレコードを別アプリのレコードに登録する

今回は、テーブルの内容を別アプリにレコードとして登録するカスタマイズです。

# アプリの準備

2つアプリを作成します

## 登録用アプリ（テーブル設置側）

| フィールド種類 | フィールドコード | 備考 |
|:-:|:-:|:-:|
|  スペース |spBtn   |   |
| 文字列(1行)  | 英単語  | テーブル内  |
| 文字列(1行)  | 日本語  | テーブル内  |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/3d9249c4-beb0-0f74-c0cb-6c2134bc8323.png)


## レコードを登録したいアプリ

| フィールド種類 | フィールドコード | 備考 |
|:-:|:-:|:-:|
| 文字列(1行)  | 英単語  | |
| 文字列(1行)  | 日本語  | |

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/acdcf0f3-44f1-6f3e-3f5f-492995d61503.png)

# JavaScript

`kintone UI Component`と`kintone REST API Client`を使います。

**kintone UI Component**

https://kintone-ui-component.netlify.app/

**kintone REST API Client**

https://github.com/kintone/js-sdk/tree/master/packages/rest-api-client

## コード

```js
// スペースフィールド取得
const sp = kintone.app.record.getSpaceElement("spBtn");

// ボタン設置
const btn_addRecords = new Kuc.Button({
  text: "レコード作成",
  type: "submit",
});
sp.appendChild(btn_addRecords);

// ボタンクリック
btn_addRecords.addEventListener("click", async (e) => {
  const client = new KintoneRestAPIClient();
  const obj = kintone.app.record.get();
  const recs = [];
  obj.record.テーブル.value.forEach((r) => {
    recs.push({
      英単語: {
        value: r.value.英単語.value,
      },
      日本語: { value: r.value.日本語.value },
    });
  });

  const res = await client.record.addRecords({
    app: {レコードを登録したいアプリのID},
    records: recs,
  });
});
```

# まとめ

登録用アプリでレコード作成ボタンをクリックすると、テーブルの内容がもう一方のアプリにレコードとして追加されます。

![tbl.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/536148/aac9feef-db28-5166-6f4f-9c0ae54b323b.gif)

↓続きの記事あるよ↓
* [kintoneのテーブルのレコードを別アプリのレコードに登録する(今見てる記事)](https://qiita.com/juri_don/items/eded7d5d8ce9ef2a3e8a)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（１）](https://qiita.com/juri_don/items/d69e375498e96847d4d9)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（２）](https://qiita.com/juri_don/private/2ddb06c5ddaade5b7209)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（３）](https://qiita.com/juri_don/private/70fa08591ac1304df36d)
* [kintoneのテーブルでアプリのレコードの登録・更新・削除をする（４）](https://qiita.com/juri_don/items/aacd9c761ee84f7b7282)
【DynamoDB】AWSのDynamoDBでテーブルを作成した直後にデータを挿入できないときの対処法

皆さんこんにちは。

今回はAWSの人気サービスの1つでもあるDynamoDBのデータ挿入についての記事となります。

タイトルにも書いてあると思うのですが、DynamoDBでテーブルを作成して直後に初期データとしてデータを挿入するとエラーが起きて挿入ができないんですよね。。。

こりゃ困った。

遅延関数的なのを使ってもいいのですが、それだと腑に落ちないので色々調べてみました。

すると、なんと、ものすごく便利なメソッドがあることを知りました。

その名も**wait**関数です！！！

これは、テーブルが作成されるまで待ってくれる関数です。

逆にテーブルが消去されるまで待てるといった機能の実装も可能です！

めちゃめちゃ便利ですよね。

使用言語によって関数名は違うのですが、Node.jsだと``waitFor``という関数でした。

waitと入力すれば、それっぽい関数名が出てくると思います。

それでは使用方法の説明をしていきます。

# 使用方法

まずは、以下のソースコードをご覧ください。

```js
const AWS = require("aws-sdk");
AWS.config.update({
    region: "ap-northeast-1",
});
const dynamodb = new AWS.DynamoDB();
const docClient = new AWS.DynamoDB.DocumentClient({
    region: "ap-northeast-1"
});

dynamodb.waitFor("tableExists", { TableName: "TARGET_TABLE_NAME" }, () => {
        const params = {
                TableName: "TARGET_TABLE_NAME",
                Item: "ITEM"
            };

         await docClient.put(params).promise();
    });
```

waitFor関数の一つ目のパラメータに``tableExists``が指定されていますよね。

これがテーブルが作成されるまで待ってくれるパラメータです。

テーブルが削除されるまで待つには``tableNotExists``と指定すればOK！

言語によって渡す文字は違うかもしれないのですが、その場合はご自身でお調べください。

恐らくDynamoDBに限ったことでは無いですが、こういったデータベースに初期データを挿入したいときに標準でメソッドを用意してくれてるのはありがたいことですよね。

これを自作するとなると中々骨のある作業になると思います。

リージョンの指定を忘れるとエラーが出ますのでお気を付けください！

以上、「【DynamoDB】AWSのDynamoDBでテーブルを作成した直後にデータを挿入できないときの対処法」でした！

Thank you for reading
Gitで管理出来るDocker+Terraform（プロキシ対応）

## 背景
- インフラもコードで管理してGit管理に乗せたい(IaC)
- 簡単にTerraformを使いたい
- ローカル環境に影響を与えたくない

## 概要
- Terraformを利用できる仮想環境をDockerで作成する
- キー情報などはGit管理に含めない

## 必要なツール

- Docker

## 全ファイル
```
infrastructure
　├ docker-compose.yml
　├ .gitignore
　├ .env.sample
　├ .env
　└ terraform
　 　├ main.tf
　 　└ variables.tf
```

### docker-compose.yml
```yml
version: "3"
services:
  terraform:
    container_name: terraform
    image: hashicorp/terraform
    env_file:
      - .env
    volumes:
      - ./terraform:/terraform
    working_dir: /terraform
    entrypoint: ash
    tty: true
```

### .gitignore
- .env にはAWSのキーなどが含まれるのでGit管理から除外する

```
# env
.env

# Terraform
.terraform
*.tfstate
*.tfstate.backup
```

### .env.sample
- .env 記入用サンプル

```
AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=

HTTP_PROXY=
HTTPS_PROXY=
```

### .env
- .env.sample をコピーして値を記入する
- Git 管理は含まれない

### main.tf

```terraform
provider "aws" {
  region = var.region
}

resource "aws_vpc" "vpc" {
  cidr_block = var.vpc_cidr

  tags = {
    Name = var.vpc_name
  }
}
```


### variables.tf
```terraform
# Define variable in this file.

variable "region" {
  default = "ap-northeast-1"
}

variable "vpc_cidr" {
  default = "172.16.0.0/16"
}

variable "vpc_name" {
    default = "vpc-name"
}
```

## 利用手順

1. .env ファイルを作成して値を入力
1. docker フォルダに入り以下コマンド実行
  `> docker-compose up -d`
  `> docker-compose exec terraform /bin/ash`

1. terraform コマンドを利用可能


## 参考にさせていただいた記事

[DockerでTerraformを使う](https://zenn.dev/nagi125/articles/8d1488ecfc2f5717756b)
【Django】hrefのパス指定をミスすると、ページが2回読み込まれる？【Python】

djangoを使ったプロジェクトで納品されたフロントの改修を行っていたある日。
データもちゃんと渡せてるし見た目も整ったかな、と思いふとコンソールを見た私。
そこに飛び込んできたのは`NoSuchKey`のエラー。

あれ…？でもページはちゃんと表示されてるんだが…何が起こってるんだ…？

# 状況
viewsには1つ引数がある。内部の処理はあまり関係ないので省略。
以下がviews.pyの中身。

```python:views.py
def myapp(request, text="mock_data"):
    print(f"======================= {text} ==========================")
    context = {"text": text}
    return render(request, "models/regression/data.html", context)
```

当初は受け取った`text`内のデータを使って辞書からデータ取り出してたのだが、ここでエラーが出てた。
でも表示はできてる。
そこでこの簡略化したページを表示してみたところ...

```terminal:terminal
======================= test ==========================
[02/Jul/2021 14:57:30] "GET /myapp/test HTTP/1.1" 200 17524
======================= favicon.ico ==========================
[02/Jul/2021 14:57:31] "GET /myapp/favicon.ico HTTP/1.1" 200 17524
```

(　ﾟдﾟ)　ﾅﾆｺﾚ

なぜか二回目が読み込まれている。
しかもなぞのデータが渡されている。

# 原因
この渡されてるやつ。どうやらタブに表示するために指定してるアイコンらしい。
ここを納品時の状態のままにしていたせいで、起こってたエラーらしい。
そのコードがこちら

```html:base.html
    <link href="./favicon.ico" rel="shortcut icon" type="image/x-icon">
```

いろいろ試した結果、この`href`の中身が相対パス`./~~`で指定されてるのが問題らしい。
`/`から始めたところ何の問題もなかった。
これ、`/~~`と指定すると、`ドメイン/~~`となって、
`./~~`とすると、`現在URL/~~`が読み込まれるぽい。
ふつうはそんなパスないぞって404が出るんだけど、今回は一番後ろに引数を用意してたから、
これが引数に入れる値ね！(ｱﾀｲｯﾃﾊﾞｻｲｷｮｰﾈ!)とかってに理解して読み込んでエラーはいていたらしい。

今までこの404エラー、単純にアイコンファイルないってエラーだと思ってたから無視してたけど、パスの指定方法が悪かったんだなと理解した。

# 対策
アイコンとかファイルを指定したいときは`static`を使って読み込むように修正しよう。

```html:base.html
-    <link href="./favicon.ico" rel="shortcut icon" type="image/x-icon">
+    {% load staticfiles %}
+    <link href="{% static 'img/icon_normal.svg' %}" rel="shortcut icon" type="image/x-icon">
```

これで解決！
Athenaでデータストアを運用する際に知っておくと役立つかも知れないこと


# バックグラウンド

## BSCサービスについて
弊社BeeXではAWSコストのビジュアル分析ツールとして、BSCというサービスを提供しております
年あたりの月毎のコスト、月あたりの日別、プロダクトグループ別のコスト、日当たりのプロダクトグループ別コストをサービス別、Tag別の切り口でビジュアルに把握できます

下は月あたりのプロダクトグループ毎のコストをサービス別に見たスナップショットとなります
（実際の数値はモザイクしております）
![BSC-CloudCost.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6748/5decc3bf-1552-29f6-6fb5-b492d075782d.png)

# データストア構成

BSCのベースとなるデータはAWSのCUR(Cost and Usage Report)ファイルなんですが、parquet形式ファイルをS3に配置して、Athenaを使っています
（他にDynamoDB、Lambda等々を使っていたりしますがここらへんは別の機会に）

# 本題
Athenaデータストアを構築、運用していく際に事前に知っていたら助かったのになぁと思ったポイントを列挙していきます

### データの更新、削除ができない
データは物理ファイルにあるので、当然といえば当然なのですが、困るシーンも出てきました
結局、ファイルそのものを物理削除して対応しました

### 検索速度は問題を感じないレベル
parquet形式のおかげかも知れませんが、結構厳しめのGroupByクエリでも数秒で返ってきます
早さを感じるレベルではありませんが、安定したレスポンスタイムで返ってくるので運用面では安心しています

### パーティション分割
ご存じの方はご存知と思いますが、Athenaは読み取ったデータ量に対して課金されます
コストが抑えられるに越したことはないので、パーティション分割を行って余分なデータのロードを避けます
このパーティション分割をどう行うかは、充分な検討が必要です
月単位での検索が多いのかアカウント単位での検索が多いのかサービス単位での検索が多いのか
ファイルの分割サイズについても運用が始まる前に充分に検討しましょう
[Athena でのパフォーマンスチューニングークエリの最適化テクニック](https://docs.aws.amazon.com/ja_jp/athena/latest/ug/performance-tuning.html#performance-tuning-query-optimization-techniques)
なお、パーティション名はAthenaのテーブルに自動的に追加されます

### AWS Wrangler
parquet形式のファイルの取り扱いや、Athenaへのクエリ発行は、[AWS Data Wrangler](https://aws-data-wrangler.readthedocs.io/en/latest/api.html)を利用しています
このツールがなければAthenaをBSCのデータストアに使うこともなかったでしょう
Lambdaで使う際にはLayerで使うことが出来ます

### メタデータもparquetから
Athenaにテーブルを登録する際にはcolumn_typesというカラム名とデータ型のDictが必要となります
このデータはparquetファイルから取得できます
自分で作らなくても大丈夫です
[awswrangler.s3.read_parquet_metadata](https://aws-data-wrangler.readthedocs.io/en/latest/stubs/awswrangler.s3.read_parquet_metadata.html#awswrangler.s3.read_parquet_metadata)

### リトライの準備を
フルマネージドのサービスですが、Athenaが異常終了することもあります
`Query exhausted resources at this scale factor`
といったエラーメッセージとなります
必ず時間を置いてリトライできるようにしてください


以上となります
皆様に参考になる情報が提供できていれば嬉しく思います
開発環境とソースコード編集を考える

開発環境と言いましても、主にウェブアプリの開発環境のことになります。本番環境は Linux で動いていて、手元の開発機は Windows もしくは Macintosh という構成を想定しています。

## 開発機に直接開発環境を作る

手元の PC 環境に直接 Apache や MySQL や言語環境をインストールする方法です。個々にインストールする方法もありますし、XAMPP や MAMP のようにワンパッケージになっているものもありますね。

macOS は中身が UNIX ですので Linux 由来のアプリケーションが扱いやすくて重宝していましたが、最近の Windows では WSL が使えるようになりましたので随分楽になりました。

複数の案件を同時並行で進めていて、案件ごとに言語やミドルウェアのバージョンが違う場合は少々困ります。言語の場合は rbenv など複数バージョンを並行して使えるようにする仕組みもありますので、それを利用します。ミドルウェアの場合は、案件を切り替えるごとに使用するバージョンを起動したり、ポートを変えて複数動作させるなどの工夫が必要になります。

OS の違いに起因する問題が起こりえます。特に Windows はファイルシステムのパス構成が Linux とは大きく違いますから注意が必要です。

ソースコード編集に関しては、ミドルウェアも言語もローカル環境で動作していますから、見えているファイルシステムも同一です。ローカルのファイルを直接テキストエディタで編集すれば、言語やミドルウェアからも参照できます。

## 開発機に仮想環境を構築する

VMware や VirtualBox を使って仮想環境を構築し、仮想環境上に開発環境を構築する方法です。Docker を使う場合もこちらに含めます。

仮想環境に Linux をインストールすれば本番環境と全く同じにできますので、環境差異による問題に悩まされることはありません。仮想環境は複数同時に作成できますので、案件ごとの環境違いに対応することも容易です。

少し前までは本番環境も開発機も CPU は x86/x64 で統一されていましたが、最近はそれぞれに ARM が入りつつあります。ウェブアプリ開発では CPU アーキテクチャは気にしなくても基本的には大丈夫だとは思いますが。

仮想環境を動作させるには開発機にそれなりのスペックが要求されます。メモリ16GBが人権とか言われてるものですね。実際4GBとかだと、とても仮想環境は実用的には動きません。仮想環境でなくてもですけれども。

仮想環境内は独立したシステムですからファイルシステムも開発機とは別物になります。ですので、ソースコードの編集をどうするかというのが問題になります。

まず考えられるのは、仮想環境に ssh でログインして、仮想環境上のコンソールで動作する vim や emacs などのエディタを使用する方法です。エディタの選択肢が限られますので、好きなエディタを使うことができません。vim や emacs 使いの人はこれで問題ないでしょう。

ローカル環境にソースコード一式を持っておき、編集が終わったファイルは scp で仮想環境にコピーするという方法もあります。毎回 scp コマンドを手で実行してたら面倒で仕方ありませんが、rsync をデーモンで動かすなどしていれば自動化できますので、実際にはそれほど手間ではないでしょう。

VSCode などの最近のエディタではリモート編集機能が使えます。リモートからファイルを取ってきて編集し、編集し終わったらまたリモートにコピーしてくれるというのを勝手にやってくれるわけです。私は実際に使ったことはないのですが、多分かなり便利だと思います。というか、リモート編集が使えるエディタを使っているなら、これ一択でいいような気がします。

仮想環境から開発機のファイルシステムをマウントするという方法もあります。ファイルの同期を仮想環境システムに任せるわけですね。仮想環境のファイルアクセスが重くなるという問題があります。

ネットワークファイルシステムを使うという方法もあります。開発機をファイルサーバにする方法と、仮想環境をファイルサーバにする方法があります。ファイルサーバを別に立てるという方法もありますが、開発環境をスタンドアローンにできなくなりますので、スタバでドヤれなくなってしまいます(^^)。

## リモートに開発環境を持つ

クラウドサービスか、オンプレミスのデータセンターかはともかく、開発機とは別のコンピュータに開発環境を持つ方法です。何もインターネット経由とは限らず、オフィス内に開発機があって LAN で繋がっている場合も含みます。

開発機は基本的にエディタ編集と ssh ができればいいので、これまでの中でもっとも要求性能が低くなります。

開発環境が開発機からネットワーク的に遠いところに設置されると、アクセスが遅くてイライラします。

ソースコードを開発機上に置かなくていいので漏洩のリスクが低くなるというメリットがあります。電車でPC忘れて漏洩みたいなミスはある程度防げますかね。

ソースコードの編集については、仮想環境を用いる場合とほぼ同様です。論理的にはもともと同じですからね。違うといえば、開発機のファイルシステムをリモート環境にマウントさせられないことくらいです。
Callableの実装

普通、マルチスレッドの実装処理のサンプルは以下のようなコードになっていることが多い

```java
public class Callee implements Callable {
    public String call() throws Exeption {
        return "hoge"; // output "hoge". 
    }
}

public class Caller {
    private ExecutorService pool = Executors.newFixedThreadPool(5);

    public void multi() {
        for (int i = 0; i < 5; i++) {
            Callee callee = new Callee(); 
            pool.submit(callee);
        }
    }
}
```

サンプルとしてはこれで問題ないのだが、
「実業務で使っているとcall()というメソッド名ではいまいち何をする処理なのかわかりづらい。
また、Calleeクラスに複数のメソッドを追加して、条件で呼び分けたりしたくなることがあったりする。
コメントで補足したり、呼び出し別にクラスを作ったりしてもいいが、面倒だしそんな時間もないことが多い。
やはり、ソースコードはコードを見ただけで何をやっているか一目稜線なのがベスト。」
というのを勉強したので、以下の実装を推奨する。

```java
public class Callee {
    public String outputHoge() {
        return "hoge"; // output "hoge". 
    }
    public String outputPiyo() {
        return "piyo";
    }
}

public class Caller {
    private ExecutorService pool = Executors.newFixedThreadPool(5);

    public void multi() {
        for (int i = 0; i < 5; i++) {
            final Callee callee = new Callee(); 
            pool.submit(new Callable<String>() {
                public String call() {
                    return callee.outputHoge();
                }
            });
        }
    }
}
```

この実装は以下の点で最初の実装より優れている。
- 呼び出し先のメソッド名を具体的に命名可能
- 呼び出し元で呼び出し先メソッドを置換可能(callee.outputHoge()をcallee.outputPiyo()に変更するだけ)
- 呼び出し先がPOJOなので、マルチスレッドとシングルスレッドどちらでもロジックを流用可能


呼び出し元の実装は多少煩雑になるが、マルチスレッド処理として目立つ(呼び出し元ソースの中でCallableが見える)ので、かえって保守性が高いのではないか。 

(2021/07/06)
コードにスペルミスがあったので訂正
「random: 7 urandom warning(s) missed due to ratelimiting」カーネルメッセージについて

「*random: 7 urandom warning(s) missed due to ratelimiting*」カーネルメッセージは情報メッセージなので対処の必要はありません。

例：

```bash
[    0.000000] random: get_random_bytes called from start_kernel+0x36b/0x55b with crng_init=0
[    3.071416] random: systemd: uninitialized urandom read (16 bytes read)
[    3.124142] random: systemd: uninitialized urandom read (16 bytes read)
[    3.183129] random: systemd: uninitialized urandom read (16 bytes read)
[    6.716079] random: crng init done
[    6.731775] random: 7 urandom warning(s) missed due to ratelimiting 
```

RHEL8ではがレート制がが導入され、**random**モジュールによって出力されるメッセジーが制限されます。

サーバーでは起動時に十分なエントロピーがないため、このメッセージは一般的です。

**random**モジュールでは最大では10回このメッセージのみを出力されますが、レート制限があるため、出力が制限されます。

RHEL8では次のコードが導入されました:

**drivers/char/random.c**

```bash
if (urandom_warning.missed) {
  pr_notice("random: %d urandom warning(s) missed due to ratelimiting\n", urandom_warning.missed);
  urandom_warning.missed = 0;
}
```

以上です。
C++　名前空間とは

# 名前空間とは

名前空間は識別子の住所。名前の衝突を避けるために使われます。

```cpp
namespace name {
...
}
```

以下のように、スコープ解決演算子を用いて指定します。

```cpp
name::member;
```

## スコープ解決演算子を使用した書き方

```cpp
#include <iostream>

namespace hello {
	void print() {
		std::cout << "hello world\n" << std::endl;
	}
}

int main() {
	hello::print();
}
```

## usingディレクティブ

以下で、呼び出したスコープにおいて名前空間にあるすべてのものをスコープに挿入できます。

```cpp
using namespace name;
```

### usingディレクティブを使用した書き方

```cpp
#include <iostream>

namespace hello {
	using namespace std;
	void print() {
		cout << "hello world\n" << endl;
	}
}

int main() {
	hello::print();
}
```

### usingディレクティブをスコープの外で使用した書き方

以下でも動きます。スコープの外でusingされているstdをhelloは使用することができます。

```cpp
#include <iostream>

using namespace std;

namespace hello {
	void print() {
		cout << "hello world\n" << endl;
	}
}

int main() {
	hello::print();
}
```

## using宣言を使用した書き方

using宣言を使用することで、特定のメンバを取り込むことができます。

```cpp
#include <iostream>

namespace hello {
	using std::cout;
	using std::endl;
	void print() {
		cout << "hello world\n" << endl;
	}
}

int main() {
	hello::print();
}
```

## 参考

[c++ using使い方の名称まとめ - Qiita](https://qiita.com/luftfararen/items/8f9fb52d43f0c76ca932)
[名前空間 (C++) | Microsoft Docs](https://docs.microsoft.com/ja-jp/cpp/cpp/namespaces-cpp?view=msvc-160&viewFallbackFrom=vs-2019)
[C++ 関数やクラスを個別にusingする方法【using宣言、エイリアス宣言】 | MaryCore](https://marycore.jp/prog/cpp/using-std-explicitly/)
[名前空間](http://wisdom.sakura.ne.jp/programming/cpp/cpp38.html)
DESTROYやDBANが動かない場合のHDD全削除方法

# TL;DR

USBからUbuntuを起動してshredコマンドで消せばいい。

# 背景

仕事で使用しているWindows PCの引き上げのため、ストレージの全データをクリアする必要があった。
いつも通り、DBANで削除しようと思ったのだが、今回は違った。

# DBANが動かなかった

DBANのisoを取得して、RufusでUSBに焼いて、ブート順序をUSB優先にして、起動。
とやったのだが、普通にWindowsが立ち上がってしまった。

## UEFIでは起動できない

どうも、DBANはBIOS専用であり、UEFIモードのPCでは起動できないらしい。
代替策としてDESTROYも試してみたが同様だった。
(このあたりの知識がとても曖昧で、BIOSとUEFIが別物だということをこの件を調べていて初めて知った)

ブートオプションをUEFIからLegacy Modeに変えれば起動できるとのことだが、
オプションを端から端まで調べてみても設定項目が見当たらない。
このPCではLegacy Modeへの変更ができないようだった。

なんと、データクリアが不可能で、したがってこのままではPCの引き上げもできなくなってしまった。

# 対処

更に調べたところ、「USBからUbuntuを起動してshredコマンドで消す」という手法があることが分かった。
UbuntuならUEFIモードでも起動できるし、shredコマンドでDBANと同等なランダムビットによる上書きができる。

## Ubuntu インストールUSBを作る

イメージは Ubuntu 18.04 LTS 日本語 Remixを使用した。
https://www.ubuntulinux.jp/News/ubuntu1804-ja-remix

これをRufusでUSBに焼く。

## 起動

PCのブート順をUSB優先にして起動。
最初に選択肢が出るので「Try Ubuntu without installing」を選択してそのまま起動する。

## shredコマンドで全消し

以下、削除方法はこの記事を参考にしたので、合わせて参照いただきたく。

* [KaliLinux (shredコマンド)を使って HDDを消去する](https://qiita.com/kichise/items/ce744c063f6d349acc14)

### 消すディスクの確認

Winキーを押して出てくるメニューに `terminal` と入力すると「端末」が選択肢に出るので選択してターミナルを起動。

fdiskコマンドでディスク一覧を確認する。

```bash
sudo fdisk -l
```

### 消去実行

shredコマンドで消去する。

下記コマンドの場合、「ランダム上書き1回 (`-n 1`)、最後にオールゼロで上書き (`-z`)、途中の進捗状況を表示 (`-v`)」モードで実行する。

```bash
sudo shred -v -z -n 1 /dev/sdb
```

最後の `/dev/sdb` の部分は消したいディスクを指定する。
実行時、確認メッセージは出ない。最後の引数を間違えないように…

ちなみに932GiBのHDDを削除するのに7時間半(ランダム上書き1回、ゼロクリアにそれぞれ4時間弱)ほど掛かった。
QLColorCodeの見た目をEmacsのTango-dark風にする

# QLColorCode
macOSでソースコードをハイライトするQuickLookプラグイン
https://github.com/anthonygelibert/QLColorCode

# QLColorCodeのテーマシステム
以下の場所にテーマが格納されている（「パッケージの内容を表示」でプラグイン内のファイルを開くことが可能）
~/Library/QuickLook/QLColorCode.qlgenerator/Contents/Resources/themes

![Screen Shot 2021-07-02 at 14.32.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320451/18a75b05-259c-4526-7c72-f92b4a5f3d4d.png)

# カスタムテーマの作成
"solarized-dark.theme"を複製して"emacs-tango-dark.theme"を編集

[emacs/etc/themes/tango-dark-theme.el](https://github.com/NicolasPetton/emacs/blob/master/etc/themes/tango-dark-theme.el)を参考にした

```QLColorCode.qlgenerator/Contents/Resources/themes/emacs-tango-dark.theme
Description="Emacs Tango Dark"

Categories = { "dark" }

Default        = { Colour="#eeeeec" }
Canvas         = { Colour="#2e3436" }
Number         = { Colour="#eeeeec" }
Escape         = { Colour="#e9b96e" }
String         = { Colour="#e9b96e" }
StringPreProc  = { Colour="#e9b96e" }
BlockComment   = { Colour="#73d216" }
PreProcessor   = { Colour="#e090d7" }
LineNum        = { Colour="#eeeeec" }
Operator       = { Colour="#eeeeec" }
LineComment = BlockComment
Interpolation  = Escape

Keywords = {
  { Colour= "#b4fa70" },
  { Colour= "#8cc4ff" },
  { Colour= "#e9b2e3" },
  { Colour= "#fce94f" },
}
```

テーマを適用する

```
 $ defaults write org.n8gray.QLColorCode darkTheme emacs-tango-dark
```

同じような見た目になった

![Screen Shot 2021-07-02 at 14.43.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/320451/7365b1fb-cd89-99e0-38e4-9aa5aba35d6c.png)
【Google Cloud Day'21】「不確実性と不可逆性が高まる時代のクラウド ネイティブで実現するデータ ドリブン経営」を視聴して

https://cloudonair.withgoogle.com/events/google-cloud-day-digital-21/watch?talk=d2-pl-12
不確実性と不可逆性が高まる時代のクラウド ネイティブで実現するデータ ドリブン経営
"経済のグローバル化や国内市場の縮小、急速な変化を続ける経済活動や生活様式など、企業を取り巻く環境は不確実性と不可逆性が高まり続けており、収集して分析したデータに基づいて経営戦略の意思決定を行うデータ ドリブン経営の実施が必須となっています。
本セッションではクラウド ネイティブで実現するデータ ドリブン経営に求められる構成要素と、Google Cloud を活用したアーキテクチャおよびそのポイントについてご説明します。"

<table>
	<tr>
		<th>切り口</th>
		<th>内容</th>
	</tr>
	<tr>
		<th>課題</th>
		<td></td>
	</tr>
	<tr>
		<th>データドリブン経営に必要なもの</th>
		<td></td>
	</tr>
	<tr>
		<th>マルチクラウドへの対応について</th>
		<td>業務や部署単位で別々のパブリッククラウドをつかっていることもある</td>
	</tr>
	<tr>
		<th>ridgelinezとGoolgeCloudの協業</th>
		<td></td>
	</tr>
</table>
MySQLでエラーが出た話

## MySQLでエラー

```
 Loading local data is disabled; this must be enabled on both the client and server sides
```

や

```
LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.
```

が出た話。

####1. csvファイルのデータをMySQLにインポートしたい。

   ```mysql
   mysql> LOAD DATA LOCAL INFILE 'C:\\第11回_データ\\customers.csv' into table J19063_customers1 FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"';
   ```
  
上のようにLOAD DATA LOCAL INFILE～でcsvファイルのデータをインポートしようとすると、エラーコードが出ました。

色々調べた結果、クライアント側とサーバー側のアクセス権限が通ってないのが原因のようですのでその設定をする必要があります。
   

####2. クライアント側の local_infileを設定する。

   まず、コマンドプロンプト（Macはターミナル）で以下を入力し、実行します。

   ` mysql -u root -p --local_infile=1`

   パスワード入力を求められるので、MySQLのログインパスワードを入れます。

   ここで重要なのは、MySQL 8.0 Command Line Clientで実行するのではなく、
**コマンドプロンプトから実行する**ということです。

   じゃないとうまくいかないと思います。

   ```
   C:\Program Files\MySQL\MySQL Server 8.0\bin> mysql -u root -p --local_infile=1
   Enter password: ********
   Welcome to the MySQL monitor.  Commands end with ; or \g.
   Your MySQL connection id is 16
   Server version: 8.0.25 MySQL Community Server - GPL
   
   Copyright (c) 2000, 2021, Oracle and/or its affiliates.
   
   Oracle is a registered trademark of Oracle Corporation and/or its
   affiliates. Other names may be trademarks of their respective
   owners.
   
   Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
   
   ```

   実行する場所は何でもいいと思うんですが、わたしはなんとなく
   \Program Files\MySQL\MySQL Server 8.0\bin
   ここの場所にしました。

   

####3.  サーバー側のlocal_infileを設定する。

   ログインできたら以下を実行します。

   `set persist local_infile=1`

   そのあとは、データベースを選択し、改めてcsvファイルをインポートしてみます。

   ```mysql
   mysql> set persist local_infile=1;
   Query OK, 0 rows affected (0.00 sec)
   
   mysql> USE ec_site;
   Database changed
   
   mysql> LOAD DATA LOCAL INFILE 'C:\\第11回_データ\\customers.csv' into table J19063_customers1 FIELDS TERMINATED BY ',' ENCLOSED BY '"' ESCAPED BY '"';
   Query OK, 4 rows affected (0.02 sec)
   Records: 4  Deleted: 0  Skipped: 0  Warnings: 0
   ```

   成功しました！





#### 参考

local_file って何？って気になった人用

> local_fileは、ローカルオプションをつけてload dataするときに、サーバー側の機能を制御してくれるMySQLのシステム変数。local_infileの設定に応じて、サーバはクライアント側で有効にしたクライアントがローカルデータのロードを行うことを拒否または許可する。
>
> つまり、アクセス制限みたいなことをやってくれてる変数みたい。デフォルト状態では無効になっているから、明示的に無効か有効かを書かないといけない。
>
> 無効：local_infile = 0
> 有効：local_infile = 1

[こちらのサイトより引用](https://qiita.com/oden141/items/239a7ce3cfe3197a3ba7)

いろいろなサイトを渡り歩き結局参考になったのはこのサイト。
https://foxglovetree.wiki.fc2.com/wiki/Study.Mayumi.MySQL_import
【初学者】DOMについて

# 概要
Vue.jsを基礎から勉強しているのですが、DOMって聞いたことあるけど理解していない状態だったので、簡単にまとめて見ました。
**DOMってなに？って聞かれたときに答えられるぐらいの知識を書いておきます。**

# DOMとは
Document Object Model (DOM) は HTML や XML 文書のためのプログラミングインターフェイスです。
ページを表現するため、プログラムが文書構造、スタイル、内容を変更することができます。
DOM は文書をノードとオブジェクトで表現します。そうやって、プログラミング言語をページに接続することができます。

**噛み砕いて簡単に言うと、「JavascriptからHTMLを操作できる仕組みのこと」ぐらいに思っておけば良いのかと**

こう言われると簡単な気がしてきませんか？
クリックしたら文字が変わるとか、そういったことを実現する仕組みがDOMです。

# DOMの特徴
DOMには特徴が主に３点あるので見てみましょう。

- **ツリー構造と呼ばれる階層構造がある**
- **それぞれの階層のことを「ノード」と表現する**
- **WEBページとJavaScriptなどのプログラミング言語とを繋ぐ役割**

## DOMのツリー構造とは

図で見てみましょう。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/635867/85a71ed0-4446-96f7-1a6f-051d488a82a2.png" width="50%">

htmlの中にheadとbodyを書いて、headの中にはtitleタグがあって、みたいな構造になっているんですね。

ちなみにこれをHTMLで書くとこのようになっています。

```html:.html
<html>
 <head>
   <title>ページタイトル</title>
 </head>
 <body>
   <h1>メインタイトル</h1>
   <div>
     <p>テキストテキストテキスト</p>
     <img src="./img/hoge.jpg" alt="hoge">
   <div>
 </body>
</html>
```

ほとんどの人が無意識に階層構造で書いているんですね。

## ノードとは
**ノードは上の階層構造を表す1つ1つのこと**
上の図にもあるように、Elementオブジェクトのbodyやtitleなど１個ずつをノードと呼びます。

ノードには親子関係もあります。
例えば、
**【document】は【html】の【親ノード】**
**【p】は【div】の【子ノード】**
このように表現されることがあります。

## 最後に
実際にDOM操作をしている内容も追加したかったのですが、長くなりそうだったので、今回は割愛しております。
気になる方は参考サイトをご確認ください。

## 参考サイト
https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Introduction
[Ruby] private メソッドのテストするときにまだ send メソッド使ってるの？

# 結論
`__send__` メソッド使うのがいいらしいよ。
`send` だと再定義されたときに困るみたい。

# 参考
https://docs.ruby-lang.org/ja/latest/method/Object/i/send.html
https://docs.ruby-lang.org/ja/latest/method/BasicObject/i/__send__.html
https://stackoverflow.com/questions/4658269/ruby-send-vs-send