OmniAICreator/Qiita-1.07M huggingface dataset:
ActiveRecordのfindはインスタンスを生成しているか確認してみた。

Railsエンジニアとして１ヶ月目の駆け出しエンジニアです。

ActiveRecordのfindに関して気になったことがあったので検証してみました。

##背景

前提としてUserクラス内にnameメソッドが定義されていることとします。

```
user = User.new
user.name
```

その場合、Userクラスのインスタンスを生成することでインスタンスメソッドのnameを呼び出すことはできますよね？

```
user = User.find(params[:id])
user.name
```
対して、ActiveRecordのfindを使用した際は

インスタンスを生成していないのに、何でインスタンスメソッドを呼び出すことができるのか？疑問に思いました・・・

##デバッグしてみると

```
user = User.find(params[:id])
binding.pry
```

気になったので``binding.pry``を挟んでみてデバック！

インスタンス化されているのか確認できるようなメソッドがないか調べていると・・・
``instance_of?``という便利メソッドを発見しました！



>instance_of?メソッドは、レシーバのオブジェクトが引数klassクラスのインスタンスであればtrue、そうでなければfalseを返します。


[Rubyリファレンス](https://ref.xaio.jp/ruby/classes/object/instance_of)を読んでみると上記のように記載されており、今の状況にピッタリなメソッドでした。

では早速``instace_of?``メソッドを使用して検証！

```
user.instance_of?(User)
=> true
```

``instance_of?``メソッドを使用することで、引数に指定したクラスのインスタンスなのか確認することができます。

trueが返ってきました！！

##結論

``instance_of?``メソッドを使用してtrueが返ってきたということは、

userはUserクラスのインスタンスということですね！

ActiveRecordのfindはインスタンスを裏で生成してくれるみたいですね！便利！



【参考記事】
https://ref.xaio.jp/ruby/classes/object/instance_of
MySQL8.xとのJDBC接続 ※注意事項※

### 注意事項①：MySQL8.x向けのJDBCドライバー
https://mvnrepository.com/artifact/mysql/mysql-connector-java/8.0.12

![企业微信截图_20190320172038.png](https://qiita-image-store.s3.amazonaws.com/0/350893/5b328c2c-9a68-e764-66e1-525984f15c3b.png)
**「jar」をクリックして、ドライバーをダウンロードできます。**

### 注意事項②：ドライバーのアドレス
8.x以前：「com.mysql.jdbc.Driver」
**8.x:「com.mysql.cj.jdbc.Driver」**

### 注意事項③：URL
8.x以前：「jdbc:mysql://localhost:3306/testdb」
**8.x:「jdbc:mysql://localhost:3306/testdb?characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B9:00&rewriteBatchedStatements=true」**
※「serverTimezone=GMT%2B9:00」とは、日本のタイムゾーン「GMT+9:00」に指定すること。
※後ろに何個のパラメータを追加する必要があります。

### **結論：新バージョンは面倒くさいなぁ:triumph::frowning2::cry:**
【未解決】Macで.htaccessを有効化する為にhttpd.confを修正したい（できない）

**【発生した問題】**
WordPressでマルチサイトを作ろうとしたが、サイトネットワーク管理者画面でマルチサイト側のダッシュボードに飛ぶと404エラーが発生した。



**【なぜなのか？（原因）】**
https://hogehoge.com/wp-admin/network/ ←ダッシュボードに飛ぶと左記にアクセスしてエラーに
https://hogehoge.com/◯◯/wp-admin/network/ ←◯◯の文字を入れるとダッシュボードが表示される
（参照：https://appcoding.net/wordpress-mulch-site/#i-6）

どうやらその原因は.htaccessが効いていない事だと分かった。
解決するにはApacheの設定ファイル（/etc/httpd/conf/httpd.conf）でAllowOverride NoneをAllowOverride Allに書き換える必要がある事が分かった。
（参照：https://www.infoscoop.org/blogjp/2014/07/10/wordpress-multisite/）

ちなみにhttpd.confファイルの場所は下記参照。
（参照：https://teratail.com/questions/130298）



**【対策の実行（未解決）】**
しかし、私はMacOS（Macbook Air）を使用しているのでhttpd.confファイルは直接上書き出来ないらしい。
そこでターミナルを起動させhttpd.confを編集する事にした。
（参照：http://shopetan.hatenablog.com/entry/2015/05/15/033928）

1.$ sudo apachectl start　で起動
2.$ sudo atom /etc/apache2/httpd.conf　でAtomでhttpd.confを開く
3.AllowOverride None → AllowOverride All　に修正、保存
4.$ sudo apachectl restart　で再起動
↓
これで動くかなと期待するも、エラー変わらず…
未だに「https://hogehoge.com/wp-admin/network/ 」に飛んでしまうので、まだ.htaccessが効いていないようだ…。
↓
下記を参照に
（参照：https://yyengine.jp/blog/mac/mac-apache-php/）
Apacheの設定ファイルを開く為に
(#)LoadModule php7_module libexec/apache2/libphp7.so の頭の#を外して
LoadModule php7_module libexec/apache2/libphp7.so に保存。
↓
状況変わらず…（イマココ）
Apacheのztsと名のつくmoduleについて

# 環境構築していて、moduleが見つからなかった
libphp5-zts.soなるものを見つけたので、libphp5.soの代用で使えるかなと思って突っ込んだら、phpinfoが表示されたので、いけたわと思い、作業続行していたら、 php-mysqlとphp-gdがどうしても読み込まれず、致し方なく、libphp5.soを探す旅に出た。見つけて作った話はこちら。
[検証環境を構築する上で知ったことパート2
](https://qiita.com/Nedward/items/84dce575785fb6505612)
で、その時に感じたこのztsって何だよお前っていう話をします。

# ZTSの正体
ZTS(Zend Thread Safe)はMPMの中でも、マルチスレッドモデルを司るmoduleに与えられている名前。

**これだけでは何のこっちゃわからん。**

## そも、MPMとは。
MPM（Multi Processing Module）の略。
Apacheは webサーバー。ならば複数のクライアントからのリクエスト処理をするためには何が必要か、それは並列処理である。そして、この並列処理には種類があり、その種類ごとに各種moduleが用意されていて、それらを総称して、MPMと人は呼ぶ・・・みたいですね。

以下に、その並列処理モデルを示す。

### マルチプロセスモデル
クライアントからのリクエストをコピーして子プロセスとして生成、その子プロセスにリクエストの処理を任せるという方式。子プロセスの生成される場所が、親プロセスのアドレス空間内なので、レスポンスが遅いということです。ただ、メモリ空間はプロセス毎にに独立して生成されるので、スクリプト言語などを組み込みやすいことや、資源の競合について考える必要がないことなどがメリットです。

### マルチスレッドモデル
クライアントからのリクエストがあるとスレッドを生成するか、リクエストを見越してスレッドを先に立てておくという２つのタイプがあるらしいです。スレッド生成のため、プロセスのようにコピー作業が発生しないので、オーバーヘッドが少ないくなるようです。メモリ空間をスレッドで共有で使うので資源の競合を防ぐように配慮する必要があります。

### イベント駆動モデル
上記２つのマルチモデルとは異なり、まずリクエストを待ち受けてレスを返すというシーケンスを持たないです。１つのプロセスで処理します。 プロセスやスレッドを使用しないので、メモリ消費されないことが利点です。マシンのコア性能がモノを言います。

## preforkとworker

```/etc/httpd/conf.d/php.conf
<IfModule prefork.c>
  LoadModule php5_module /etc/httpd/modules/libphp5.so
</IfModule>
#<IfModule worker.c>
#  LoadModule php5_module modules/libphp5-zts.so
#</IfModule>
```
 moduleを読ませるディレクティブに、マルチモデルを選ばせるようになっています。preforkがマルチプロセス、workerがマルチスレッドをそれぞれさしています。

modと名のつくmoduleを、/usr/lib/php/module/で見つけると思いますが、それらは全てマルチプロセスに対応しており、マルチスレッドでは使えません。私の場合、libphp5-zts.soモジュールをこのパス直下に入れてphpinfoが表示されて動いたと錯覚してしまった原因は、php自体は動いても、周辺のmoduleは動かない、という状況だったのではなかろうかと考えています。レゴブロックの別の色でも同じ形だから嵌め込めますが、色が気にくわないから作品としてダサくなっている状況と同じですね。

というわけで、処理方式を理解した上で、moduleを読ませましょうねというお話。
python pandas DataFrameを使用して現在のDirectoryのipynbファイルを抽出（文字列の部分一致）


```python
import os
import pandas as pd

df = pd.DataFrame(os.listdir())

df_files = df[df[0].str.endswith('.ipynb')]
df_files
```

- 公式サイト
  - https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.str.endswith.html
  - https://pandas.pydata.org/pandas-docs/stable/reference/series.html#api-series-str
python ipynbファイルをpyファイルに変換 (notebookをpython scriptに変換)

- ipynbファイルをpyファイルに変換 code

```python
import subprocess
subprocess.run(['jupyter', 'nbconvert', '--to', 'script', '*.ipynb'])
# jupyter nbconvert --to script *.ipynb
```
- ipynbファイルをpyの変換 command

```
jupyter nbconvert --to script *.ipynb
```

- 公式サイト
  - https://github.com/jupyter/nbconvert/blob/master/docs/source/usage.rst
  - https://nbconvert.readthedocs.io/en/latest/nbconvert_library.html
KotlinのMapのkey, valueでそれぞれソートする


下記のようなMapがあると仮定する。

```kotlin
val map: Map<Int, String> = mapOf<Int, String>(
    2 to "CCC",
    1 to "AAA",
    3 to "EEE",
    5 to "DDD",
    4 to "BBB"
)
```

Mapをそのまま印字する

```kotlin

println(map)

{2=CCC, 1=AAA, 3=EEE, 5=DDD, 4=BBB}
```

Mapのkeyでソートする

```kotlin
val result = map.toSortedMap()
println(result)

{1=AAA, 2=CCC, 3=EEE, 4=BBB, 5=DDD}
```

Mapのvalueでソートする

```kotlin
val result = map.toList().sortedBy { it.second }.toMap()
println(result)

{1=AAA, 4=BBB, 2=CCC, 5=DDD, 3=EEE}
```
Docker入門

社内の新人向けにDocker入門の勉強会を開催したので、備忘録も兼ねて共有

# Dockerとは
* Dockerとはコンテナ型の仮想化環境を提供するオープンソースソフトウェア(by Wikipedia)
* ホストOSのカーネルを利用し、コンテナと呼ばれる仮想区画を構築し、その区画上でアプリケーションを可動させる
* 従来の仮想化環境(VMWare、VirtualBox)と比べて、軽量・高速に動作させることが可能となっっている
* Linuxカーネルを利用するため、基本的にはLinux環境を構築するために用いられる

# 従来の仮想化環境との違い
では、なぜDockerは従来の仮想化環境と比べて軽量・高速なのか？
大きな違いはゲストOSを必要としないことがあげられる。
![Docker入門.png](https://qiita-image-store.s3.amazonaws.com/0/189121/edd3c10f-7611-234c-3d91-c5c74c00672f.png)

従来のVirtualBoxやVMWareではアプリケーションを実行するためには、まずゲストOSを起動する必要があった。
DockerではホストOSのカーネルを共有しているため、オーバーヘッドが少なく、軽量・高速に動作することが可能となっている。

# 実践
とりあえずCentOS7のDockerを作成して、Hello Worldしてみます。

```sh
# Docker HubよりDockerイメージを取得する。ここではCentOS7のイメージを取得
$ docker pull centos:7
# 取得したCentOS7のイメージを利用して、コンテナを作成・起動し、「echo 'Hello, World'」を実行する
$ docker run centos:7 /bin/echo 'Hello, World!'
Hello, World!
```

# 用語説明
### Dockerイメージ
コンテナ(実際の仮想環境)の雛形となるもの。OSやらアプリケーションやらを含んだテンプレート。
このイメージをベースにコンテナを作成する。
### Docker Hub
公式のDockerレジストリ。
公式のDockerイメージを取得したり、自分で作成したDockerイメージを公開したりすることができる。
CentOSやUbuntuはもちろん、nginxや各種DBなどはたいてい公式イメージが公開されているので、それを利用すると楽。

# Dockerfile
実際にDocker Hubに公開されているイメージだけでアプリケーションを動かすことは難しい。その場合は、Dockerfileをもとにオリジナルのイメージを作成することができる。
環境を作成するためのコマンドを列挙していくイメージ。
Docker Hubに公開されているイメージはだいたいDockerfileも公開されている。

例としてnginxのイメージを自分で作成してみる。

```Dockerfile:Dockerfile
# ベースとなるイメージを指定(docker pullと同じことをしてくれる)
FROM ubuntu:16.04

# nginxインストール
RUN apt-get update && \
	apt-get install -y nginx && \
	apt-get clean && \
    rm -rf /var/lib/apt/lists/*

# 必要なファイルをコンテナ側にコピーする
COPY ./sample/index.html /var/www/html/index.html
COPY ./config/nginx.conf /etc/nginx/conf.d/default.conf

# 80番ポートを開放
EXPOSE 80

# 起動時に実行されるコマンド
# nginxはデフォルトだとバックグラウンドで実行されるため、フォアグラウンドで実行するよう指定
CMD ["nginx", "-g", "daemon off;"]
```

# 注意点
* Dockerは基本的に1コンテナにつき1プロセスを前提としている。
* Dockerはフォアグラウンドプロセスがないと、自然終了してしまう。そのため、nginxやDBなど普段バックグラウンドで起動させるものもフォアグラウンドで起動させてあげる必要がある。
ぼくのかんがえたさいきょうのパスワード設定画面

## きっかけ
とある目的のため、Qiitaアカウントのパスワードを変えようと、設定画面で入力したところ・・・

<img width="807" alt="qiita_original.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/84205eaa-f286-03dc-02bb-3ec358420519.png">


**(# ﾟДﾟ)まずまずってなんやねん！！**

けど、ここで終わったら、ただのクレーマーになってしまうので、
プロの威信をかけて最適な画面を提案しようと思いました。


## なぜいけないのか？
今回のパスワード設定画面には大きく3つの課題があります。

**1. パスワードの強度が何を基準に評価されているか分からない**
**2. メッセージが何を意味しているのか直感的に分からない**
**3. これで続行できるのかが分からない**

全ての課題に共通する考え方として、
「システムが伝えている情報を人間が理解できない」ことが改善すべきポイントです。

エラーメッセージはとても重要な役割を果たします。システムが受け付けられない情報なので、システムとしてはユーザーに改善を求めなければいけません。

パスワード設定画面で伝えるべき情報は以下の3つです。

**1. 何を基準に評価しているか**
**2. どうすればエラーを回避できるか**
**3. 更新の操作を続行できるか**


### 伝えるべき情報１：何を基準に評価しているか
今、入力している内容が、なぜ不適切なのかを伝えてあげましょう。
Googleのパスワード入力画面を参考に持ってきました。

初回入力時には文字数を適切に提示しているので、
文字数以上は入力しなければいけないことがわかります。
<img width="666" alt="google_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/d7578125-5675-6c4b-791d-7e8ce7b4b202.png">


また、「aaaaaaaaaa」と入力した後にカーソルを離すと、
「より強力なパスワードを選択してください。」というメッセージが表示されます。
ユーザーは文字以外に数字または記号を用いる必要があると判断できます。
<img width="665" alt="google_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/5bac21c2-a35e-fd39-8534-b88e7e322b99.png">



### 伝えるべき情報２：どうすればエラーを回避できるか
今回のきっかけとなった「まずまず」。
このメッセージは2つの課題を抱えています。

 - どうすれば「まずまず」の評価以上になるのか分からない
 - 良いのか悪いのか判断できない
<img width="807" alt="qiita_original.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/e3d6e8d8-1b59-22e8-d5b6-4f928e56b282.png">


おそらくパスワードポリシーに関して「まずまず」と評価しているのだろうと推測はつきますが、
ユーザーに考えさせるシステムは良いシステムとは言えません。

入力したパスワードの安全性を判定していると思われるため、
「パスワードの安全性：やや弱い」と伝えるべきです。


[「インターフェースデザインの心理学」](https://www.amazon.co.jp/dp/4873115574)にも書いてありますが、
システム１で直感的に分かるシステムが素晴らしいシステムです。


![salesforce.png](https://qiita-image-store.s3.amazonaws.com/0/309087/889a5f3f-b2be-9a3e-d500-50e0e25ab4e2.png)

こちらはSalesforceのパスワード変更画面です。
条件を満たしているのかどうかを一眼で判断できるような工夫をしてあげれば、
ユーザーは何をすべきなのか理解できます。

### 伝えるべき情報３：入力操作を続行できるか
こちらはAmazonのパスワード変更画面です。
<img width="616" alt="amazon_01.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/6d246ae6-08a9-e295-29a9-3cc8fafcce08.png">


パスワードを入力して「変更内容を保存」ボタンをクリックすると、次の画面が表示されました。
<img width="614" alt="amazon_02.png" src="https://qiita-image-store.s3.amazonaws.com/0/309087/88654bce-a56f-d787-a6fa-5bd9d2863262.png">



「それ、早く言ってよぉ。。」


松○ 豊が頭を過ぎる瞬間です。

Bad UX、典型的なアンチパターンですね。
入力制限として6文字以上ならば、入力画面でも伝えるべきですし、
続行不可能ならばボタンを非活性にする工夫が必要です。

## ぼくのかんがえるさいきょうのパスワード設定画面

**1. 何を基準に評価しているか伝えるべき**
**2. エラーメッセージは明確に伝えるべき**
**3. 続行して良いか伝えるべき**

以上、3点を考慮した上で、ぼくのかんがえるさいきょうのパスワード設定画面を作ってみました。
![original.gif](https://qiita-image-store.s3.amazonaws.com/0/309087/9d45972a-f25e-6d27-1080-e076b10a1e0b.gif)


余談ですが、Vue.jsで30分かからず作りました。
Vueはいいぞ（ステマ）（ステマになってない）
Eclipseのインストール(Linux)

# 少し前のインストール方法
Eclipseの公式サイトからファイルをダウンロードしてmakeなどをしなくてはならなかった。
こんなことはめんどくさいので他の方法を探してみた。

# Snappyによるインストール
snapというパッケージ管理ソフトは一発でEclipseが入れられる。

```snap install eclipse```

とキーボードを叩くだけで終わる。

# Snappyについて
このサイトを参照して下さい。
https://news.mynavi.jp/article/20180227-snap_howto/
プログラミング学習記録32〜快刀乱麻〜

##今日やったこと
- Progate Rails9

今日は、

- 「投稿」と「ユーザー」を紐付ける方法
- 投稿を作成したユーザーだけが、その投稿を編集・削除できるように制限する方法

について学びました

これをしないと、どのユーザーがどの投稿をしたのかがわからなくなります。

そして、誰でも他の人の投稿を編集したり、削除したりできるので、はちゃめちゃなSNSになってしまいます。

今までのレッスンをそれなりにちゃんとやっていれば難しい内容ではないと思います。

インスタンスメソッドがこのレッスンで初めて出てきましたが、メソッドはメソッドであり、書き方が少々特殊なだけなので特に問題ないでしょう。
<br>

次のレッスンでは投稿に「いいね！」ができる機能をつけられるということで楽しみです。

明日も引き続きプログラミング学習頑張ります。

おわり
もそ、プログラミングを学ぶ【Ruby & Rails復習編】〜シンボルってなんだっけ〜

一通りのカリキュラムを終え、エラー問題にチャレンジし始めた もそ。
分かりきっていたことではありますが、もう、**笑えるぐらい解けない**。
というか半泣きで解いています（遅々として進みません...）

そんなわけで、今回からはRubyの範囲も含めた復習内容です。
図解しながら理解を深めていければと思います。

今回はシンボルについてのおさらい。

##ハッシュとは

ハッシュは、**ハッシュは複数のオブジェクトを持つことができる箱のようなもの**で、
データ自体のもつ値**バリュー**と、それに対応する**キー**と呼ばれる標識がセットになっています。
このキーとバリューのセットのことを**キーバリューストア**と呼びます。

##シンボルとは
シンボルは**ハッシュのキーのような名前を識別するラベル**のようなもので、基本的には文字列と同じように使うことができます。

ここからは図を使って説明していきます。

<img width="375" alt="無題1154.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/372174/979f1101-d1ad-0b37-141a-8bb3d135a50e.jpeg">

ここでは、瓶に入ったコーヒーを例にしてみました。

瓶の中に入っている"もそのスペシャルブレンドコーヒー"という正式名称が、ハッシュの**キー**にあたります。
そして"豆300g"、これがハッシュの**バリュー**になります。
なので今回の場合は、"もそのスペシャルブレンドコーヒー" "豆300g"が入った瓶そのものが**ハッシュ**になります。

さて、瓶には"ブレンド"という名前のラベルが貼ってあります。
このラベルこそが今回の本題、**シンボル**にあたります。

喫茶もそ（たったいま適当に命名しました）では、ブレンドコーヒーは"もそのスペシャルブレンドコーヒー"しかないとします。
ということは、瓶に"ブレンド"というラベルが貼ってあれば「ブレンドちょうだい！」と言われたとしても
「ああ、もそのスペシャルブレンドコーヒー豆300gのことか」と判断できます。

そしてもし喫茶もそにコーヒーがブレンドの一種類しかなければ、瓶に貼るラベルはもっと単純に"コーヒー"でも問題ないですよね。

シンボルは**開発者がハッシュの中身を分かりやすくしたラベル**なので、シンボルの名前が変わったからと言って**中身が変わるわけではありません。**
ただし開発環境によって、たとえばシンボルの名前をアクション名と一緒にすると分かりやすいよ〜といった場合もあります。


--
いかがでしょうか。
今は半泣きで問題を解いていますが、さらっと華麗にエラー問題を解決できるよう地道に復習していこうと思います。
映画マトリックスのネオみたいに、プログラミングスキルをインストールしてほしい...と今日もぼやきつつ、もその学習は続きます。
GKEクイックスタート

### 概要

* 以前EC2上にKubernates作ったがかなり大変だった
* GKEでどれだけ簡単になったか試してみる
* Googleのチュートリアルをそのまま実践
* マニュアルにない気がついた事などもメモ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/57350/f2bd3d38-6bb4-c612-0dff-64af926b7bf8.png)


### 事前準備

* 上記GUIコンソールは使用しない
* CloudShellを上でインスタンスを起動する

#### デフォルトのプロジェクトの設定

* gcloud config set project [PROJECT_ID]

```
$ gcloud config set project fine-scene-234606
Updated property [core/project].
```

#### デフォルトのコンピューティング ゾーンの設定
* gcloud config set compute/zone [COMPUTE_ZONE]

```
$ gcloud config set compute/zone us-central1-a
Updated property [compute/zone].
```

### クラスタの作成

* けっこう待つ。５分位？

```
$ gcloud container clusters create test-cluster-1
kubeconfig entry generated for test-cluster-1.
NAME            LOCATION       MASTER_VERSION  MASTER_IP       MACHINE_TYPE   NODE_VERSION  NUM_NODES  STATUS
test-cluster-1  us-central1-a  1.11.7-gke.4    35.222.251.218  n1-standard-1  1.11.7-gke.4  3          RUNNING
```

#### クラスタに対して認証

```
$ gcloud container clusters get-credentials test-cluster-1
Fetching cluster endpoint and auth data.
kubeconfig entry generated for test-cluster-1.
```

### アプリケーションをクラスタにデプロイ

#### Deployment作成

```
$ kubectl run hello-server --image gcr.io/google-samples/hello-app --port 8080
deployment.apps/hello-server created
```

#### Deployment公開

```
$ kubectl expose deployment hello-server --type "LoadBalancer"
service/hello-server exposed
```

### アプリケーションアクセス

* アプリケーションの状態を表示
* EXTERNAL-IPが有効になるまで数分かかる？

```
$ kubectl get service hello-server
NAME           TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
hello-server   LoadBalancer   10.43.240.xxx   35.226.222.xxx   8080:30854/TCP   2m
```

* 異なるネットワークからアクセスしてみる

```
$ curl http://35.226.222.xxx:8080
```

### 事後作業

##### アプリケーションの Service を削除

```
$ kubectl delete service hello-server
service "hello-server" deleted
```

##### クラスタを削除

```
$ gcloud container clusters delete test-cluster-1
The following clusters will be deleted.
 - [test-cluster-1] in [us-central1-a]

Do you want to continue (Y/n)?  Y

Deleting cluster test-cluster-1...done.
Deleted [https://container.googleapis.com/v1/projects/fine-scene-234xxx/zones/us-central1-a/clusters/test-cluster-1].
```

##### 所感


* 素のKubernates構築がやってられないくらい簡単
* CloudShell便利
* マニュアルわかりやすい
Asciidocで作る請求書

フリーランスの皆様こんにちは。
請求書がめんどくさい。

Wordで作るのさえも面倒。

帳票職人としてJaspersoft Studio,ActiveReportsと弄って消耗してます。
帳票ツールも使いたくない。

大門未知子のためにAsciiDocで請求書を作ります。
メロンのお供に請求書。

できたソースはGitHubにフルオープンにしておきます
[Invoice_adoc - GitHub](https://github.com/arachan/invoice_adoc)

## 環境

- Windows10 Pro 
- PowerShell v5.1
- Visual Studio Code
    - AsciiDoc extension
- Git-Bash
    - gitに付いてます

## 請求データ

- csv
- UTF8

数量と金額と合計はシェルスクリプトかPowerShellで計算させる。
Linux/Macの方はシェルスクリプトで動く。
Windowsの方はPowerShellを使えばいい。
Gitを導入されている方であればGit-Bashも使えます。

1. data.csvを作成
2. 計算済みのデータをresult.csvとして出力

データの入力は人間のやる仕事だ。
しかし、計算は人間のやる仕事ではない。

data.csvを計算させるスクリプトは下記のようになる。

```bash:calc.sh
#!/bin/sh

# ヘッダーを取得
sed -n '1p' data.csv > temp/header.csv

# ヘッダー行を抜く
# コンマ区切りで入出力
# 合計の計算
# 明細金額を計算 3行目の数量と4行目の金額を掛ける
# 合計行を追加
cat data.csv | 
sed '1d' | 
awk -F',' 'BEGIN {FS=",";OFS=","}{sum+=$3*$4;print $1,$2,$3,$4,$3*$4} END{print "","","","合計",sum}' > temp/temp.csv
# ヘッダーとデータを結合
cat temp/header.csv temp/temp.csv > result.csv

```

```posh:calc.ps1
# 明細行の計算
$data | 
Select-Object 日付,内容,数量,金額,@{name="明細額";expression={[INT]$_.数量*$_.金額}} |
Export-Csv result.csv -Encoding UTF8 -NoTypeInformation

# 合計を計算
$data=Import-Csv .\result.csv -Encoding UTF8
$sum=$data.明細額 | Measure-Object -Sum
$total=$sum.Sum

# 合計行を追加
",,,合計,$total" |Add-Content -Path .\result.csv -Encoding UTF8
```

上記のスクリプトを実行させるとdata.csvからresult.csvが出力されます。

**data.csv**

| 日付    | 内容 | 数量 | 金額     | 明細額 |
|---------|------|------|----------|--------|
| 3月13日 | 手術 | 2    | 10000000 |        |
| 3月14日 | 手術 | 1    | 13000000 |        |

**result.csv**

| 日付    | 内容 | 数量 | 金額     | 明細額   |
|---------|------|------|----------|----------|
| 3月13日 | 手術 | 2    | 10000000 | 20000000 |
| 3月14日 | 手術 | 1    | 13000000 | 13000000 |
|         |      |      | 合計     | 33000000 |


## AsciiDocで入力

下記のように入力します。

AsciiDocを編集するのにおすすめはVSCode。
AsciiDocというPluginを入れればプレビューまではやってくれます。

```asciidoc

== 請求書

=== To
帝都医科大学付属病院

〒104-0045 東京都中央区築地9-3

蛭間 重勝 様

=== From

神原名医紹介所

神原　晶

image::stamp.jpg[width=40]

〒135-0031 東京都江東区佐賀１丁目4-1

=== Contents

下記の通り請求申し上げます。
[format="csv", options="header"]
|===
include::result.csv[]
|===

=== 振込先

●●銀行 ●●支店

(普通)　000-000-000000

カンバラメイイショウカイジョ

```

### ポイント

右揃え左揃えはできない。
だから上から順番に書くデザインにする。

result.csvをincludeして表組にしている。
markdownにはない強み。

印鑑を画像で挿入している。
image::stamp.jpg[width=40]
印鑑さえ挿入されていれば何故か正式な文章として受け取ってくれる。

## PDFに出力

一番手っ取り早いのはAsciidoctorを使う方法です。

Macの方はbrewでinstallしちゃうのが早いかもしれません。

会社ではLinuxに持ち上げてLinux上のAsciidoctorに処理させています。

```bash:asciidoctor-pdf
$ asciidoctor-pdf invoice.adoc

```

WindowsにもAsciidocFXというツールがあります。
リンクを日本語にすると飛ばない。
今一つ日本語に弱いという問題があります。
最近は使ってません(´;ω;｀)

イケてるフリーランスはMacユーザー多いから大丈夫じゃないかな。

生成した請求書のPDFをメール添付で送ってあげれば請求完了！
1年のふりかえりワークショップによる効果の気付き

# 1年のふりかえりワークショップとは

[40人のビジネスパーソンが絶賛した「1年の振り返り」完全マニュアル](https://mirai.doda.jp/theme/looking-back-planning/procedure/)で紹介されている、ふりかえりの手法です。

[こちら](https://speakerdeck.com/viva_tweet_x/1nian-falsehurikaeriwakusiyotupu)でワークショップの資料も公開しています。

3/14に弊社1年目に向けて、ふりかえりのワークショップを実施してきました。
新人17名で、3人 or 4人の5グループ × 4ターン行いました。
最終ターンで2人分空きが生じたため、ファシリテーターの私もふりかえりに参加したり、新人の1名が2回目を名乗り出たり、と色々な実験ができました。

そこで実施した新人からいいフィードバックをもらえたので、ここに残しておこうと思います。

ふりかえりの手法を知りたい方はスライド等をご参照ください。

# 1年のふりかえりワークショップの効果

## 思考のタイプの違いと効果

真逆のタイプの人に対して、悩みを共有する。
真逆だからこその考え方、新たな気付きが生まれる。

同じタイプの人に対して、悩みを共有する。
思いを共感してもらい、思いを大きく広げていくことができる。
後押しをしてもらえる

## 距離による違いと効果

自分のことを知っている人に対して、悩みを共有する。
知って貰っているからこそ、「あなただったらこうできるよ」という他者から見たアドバイスができる。

自分のことを知らない人に対して、悩みを共有する。
コンテキストがあっていないからこそ、物語を説明することで自分の内省が深まったり、相手の土台に立った、自分ではイメージすらできないアドバイスがもらえる。

## 1人が複数回やることの意義

悩みを1回目で共有し、学びや気付きが生まれている状態で2回目を行います。
1回目でもらったアドバイスや学び・気付きに対しての納得感を、2回目では参加者に共有した上で進めることができます。
それにより、確実に別角度からのアドバイスや内省の深堀が行われます。
また、1回目では共有できなかった話もできます。「言えなかったこと」というのは、1回終わってみて初めて分かったり、気付いたりします。
言えなかったことを2回目で言えるようになるので、また新しい観点での気付きが得られることになります。

# おわりに

新人17人に対してファシリテーションし、弊社新人向けとしては2年連続での活動となりました。
毎年、いい学び・気付きとNext Actionをもって次の年次へと進んでいってくれていると感じています。
来年も本部の施策として、もう少し範囲を広げて行うことができれば、と考えています。
express で scss を使う方法

# やりたいこと

タイトルの通り。`express-generator` でプロジェクト作成したときにデフォルト（`css`）にしており、後から `scss` にしようとして微妙にハマったので方法をまとめておきます。

## 前提環境

実施した環境ということでご参考までに。Linux Mint は Ubuntu 互換のディストリビューションです。

| カテゴリ | ソフトウェア | バージョン |
|:---|:---|:---|
| OS  | [Linux Mint](https://linuxmint.com/)| 19 Tara Cinnamon x64 (Ubuntu 18.04 LTS ベース) |
| Node.js | [Node.js](https://nodejs.org/ja/)| 10.15.3 |
| Web Application Framework  | [Express](http://expressjs.com/)| 4.16.0 |

# やってみた

## 1. Node.js をインストール

<font color=blue>_※既にインストールされていて `node` コマンドが使える状態であればこの項目は飛ばしてください。_</font>

手順: [Linux Mint に asdf で Node.js をインストールする](https://qiita.com/takeru08ma/items/c344dd3f6117c14d0fad)

## 2. `yarn` (`npm`) で express-generator をグローバルにインストール

```bash:bash
yarn global add express-generator
# npm i -g express-generator
```

## 3. `express-generator` でプロジェクトを新規作成

```bash:bash
express express-scss-app --css=sass
cd ./express-scss-app
yarn install
# npm install
```

## 4. `style.sass` を `style.scss` へ変更

```bash:bash
cd ./public/stylesheets
mv ./style.sass ./style.scss
```

```sass:変更前（style.sass）
body
  padding: 50px
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif

a
  color: #00B7FF
```

```scss:変更後（style.scss）
body {
  padding: 50px;
  font: 14px "Lucida Grande", Helvetica, Arial, sans-serif;
}

a {
  color: #00B7FF;
}
```

## 5. `app.js` の `sassMiddleware` の設定を修正

`indentedSyntax` の設定をコメントの説明通り `true` から `false` へ変更。

```js:app.js（変更前）
app.use(sassMiddleware({
  src: path.join(__dirname, 'public'),
  dest: path.join(__dirname, 'public'),
  indentedSyntax: true, // true = .sass and false = .scss
  sourceMap: true
}));
```

```js:app.js（変更後）
app.use(sassMiddleware({
  src: path.join(__dirname, 'public'),
  dest: path.join(__dirname, 'public'),
  indentedSyntax: false, // true = .sass and false = .scss
  sourceMap: true
}));
```

## 6. 動作確認

Webサーバを起動します。

```bash:bash
yarn start
# npm start
```

ブラウザの開発者ツール（この画面は Chrome）で `style.scss` が読み込まれているか確認します。

<img src="https://docs.google.com/drawings/d/e/2PACX-1vTT-zVnpEo-09RngJU2_KApU8D57zfasSegj506slasbZrVheo4p3McvRRfipXa2LJNLVhRyETZPVkx/pub?w=1060&amp;h=380">

## 所感

- `express-generator` の `--css` オプションの選択肢に `compass` と `sass` があったので、`compass` でやるものと思ったのですが違いました。これ Ruby 用ですね。
- 分かってしまうとなんてことないですね...
python,djangoでフォームとリストを同時に出力したい。

python,djangoでフォームとリストを同時に出力したい。
えっ？そんなこと簡単なんじゃないのと思われるかもしれませんがちょっとコツが要ります。
まずなんで同時に出力できないの？ということを説明しますね。
urls.pyを見てみましょう。

```
    path('<int:pk>/', views.ListView.as_view(), name='detail'),
```

urlで使用できる関数は以下で定義されます。

```
views.ListView.as_view()
```
<br>
これって例えば

```
views.ListView.as_view(), views.FormView.as_view(),
```
<br>
とかやってフォームとコメントの一覧を1ページに出力しようとするとエラーが出ます。
これってdjango特有の不便さなんですかね？それともwebのフレームワークはおおむねそういうものなの？知っている方いたら教えてちょ！
<br>
というわけで、冒頭に話した
「えっ？そんなこと簡単なんじゃないのと思われるかもしれませんがちょっとコツが要ります。」

という話が浮上してきます。
というわけでふたつの関数をドッキングさせます。

リストビュー。

```
class ListView(generic.ListView):
    model = Post

```
<br>

フォームビュー。

```
class PostForm(forms.ModelForm):

    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'

    class Meta:
        model = Post
        fields = "__all__"       
```

<br>
<strong>フュージョン！！</strong>


```

class ListView(generic.ListView, ModelFormMixin):
    model = Post
    form_class = PostForm
    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'
    paginate_by = 15

    def get(self, request, *args, **kwargs):
        self.object = None
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        self.object_list = self.get_queryset()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)

```

詳しくは滝川成人先生のブログを見てほしいですが僕の方でも解説。
https://torina.top/detail/337/
<br>

```
class ListView(generic.ListView, ModelFormMixin):
```

ListViewをベースにしてFormをミックスします。
リストに使うモデルであるPOSTとフォーム部分に使うモデルフォームであるPostFormを定義します。

```
    model = Post
    form_class = PostForm
```

フォームとリストを使うテンプレートを定義しましょう。


```
    success_url = reverse_lazy('board:board')
    template_name = 'board/board.html'
```

<br>
上は成功時にリダイレクトするURLで下はフォームを使いたいURL。

<br>


これはページネーションのページ数。

```
paginate_by = 15
```
<br>

これはごめんなさい。分かりません！

```
    def get(self, request, *args, **kwargs):
        self.object = None
        return super().get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        self.object = None
        self.object_list = self.get_queryset()
        form = self.get_form()
        if form.is_valid():
            return self.form_valid(form)
        else:
            return self.form_invalid(form)
```

super()が継承に使うものということしかわかりません！！

<br>
これはPostのリストを新着順にする魔法。

```
    def get_queryset(self):
        return Post.objects.order_by('-date')
```
一番上から古いものが表示されます。
これで基本は終わり。でもちょっと補足します。
<br>
<br>
リストをベースにしてフォームをミックスするといいましたが
フォームビューとリストビューを別個に作り、TemplateResponseMixinと書く方法があります。

```
class FormAndListView(FormView, ListView, TemplateResponseMixin):
```
でもこの方法だとListViewがベースにならないため（だと思われる）ページネーションが出来ないです。気を付けましょうね。
ILMT (IBM License Metric Tool)の導入ポータルサイト

IBM License Metric Toolの導入ポータルサイトが新しいアドレスに変わりましたので、お知らせ致します。

https://www.ibm.com/jp-ja/partnerworld/resources/subcapacity-ilmt

ILMT導入にあたっての前提条件
各マシンのPVUの確認
ILMT V9.2.11のサーバー導入ガイド（Windows, RHEL)、運用ガイドがまとめて格納されております。ご活用ください。
WINDOWS Serverのインストールメディア作成でハマった話

#概要
WINDOWS Server 2019をISOイメージからクリーンインストールしたのですが
インストールメディアの作成がうまくいかず時間がかかってしまったので
情報整理の書き出し記事です。

#発生した問題
経緯
①WINDOWS Server 2019のOSイメージ（ISO）をボリューム ライセンス サービス センターからダウンロード

②ISOBURN.EXE(WINDOWS標準書き込みソフト)をつかってDVD-RにISOイメージを焼こうとするがサイズが足りないと怒られる（ファイルサイズ 4.8GB）
※ISOBURN.EXE参考
https://www.projectgroup.info/tips/Windows/windows10_0021.html

③IMGBURNを使ってDVD-RにISOイメージを焼こうとするがサイズが足りないと怒られる。
※IMGBURN参考
http://www.imgburn.com/

③IMGBURNを使ってDVD-RにDVDサイズに合わせた書き込みを実施する

④作成したDVDメディアを使用してOSインストールを試みるがドライバが足りないとエラーが発生して、インストールを進めることができない。


#原因
・片面１層DVDメディアの容量より大きいサイズのISOファイルを書き込もうとしていた。
・片面１層DVDメディアの場合は4GBまでしか書き込みができないらしい。
・初めからISOのサイズが大きいとエラーが発生していたのに
ISOがDVDに書き込めないはずがないという先入観から、無駄に時間を食ってしまった。
参考：
https://www.atmarkit.co.jp/ait/articles/1612/14/news048.html


#対応
USBメディアにISOイメージを書き込んでインストールメディアとしました。

作成用アプリ
ISO to USB
https://forest.watch.impress.co.jp/library/software/isotousb/

30分ぐらいかかりましたが、すんなりインストールメディアの作成が完了し
OSのセットアップも問題なく完了しました。


#最後に
DVD書き込みにこんなにハマるとは思いませんでした。
最終的には、ドライバの更新とか試したりしてました。
思い込みにはまらないように注意しないといけないと思ったケースでした。
Capistrano3でRailsアプリをデプロイしようとしたら'mysql2 is not part of the bundle. add it to your gemfile.'が出た

# 概要
Capistrano3を使ってRailsアプリをさくらvpsにデプロイしようとしたところエラーが出てはまったので、解決方法をメモとして書いておきます。

Capistrano3を使ったデプロイの手順は以下を参考にさせて頂きました。
[(初心者向け）vpsを契約して、capistrano3でRailsアプリをデプロイするまで [その1 サーバー設定編]](https://qiita.com/ryo2132/items/f62690f0b16ec11270fe)
[(初心者向け）vpsを契約して、Capistrano3でRailsアプリをデプロイするまで [その2 ローカル設定編]](https://qiita.com/ryo2132/items/03f5f52b43742f5aef10)

# エラー内容
上記のサイトを参考に以下のコマンドを実行してデプロイしようとしたところ、下記のエラーが出てデプロイに失敗しました。

```
$ bundle exec cap production deploy
```

```
・・・
01 rake aborted!
01 LoadError: Error loading the 'mysql2' Active Record adapter. Missing a gem it depends on? mysql2 is not part of the bundle. Add it to your Gemfile.
・・・
```

# 解決方法
Gemfileのproductionグループに`mysql2`を追加しインストールします。

```Gemfile
group :production, :staging do
  gem 'mysql2'
end
```

```
$ bundle install
```

ここでデプロイし直しても同じエラーが出てしまいますので、githubへ変更をpushします。

```
$ git add .
$ git commit -m 'Add mysql2 to Gemfile'
$ git push origin master
```

デプロイし直すと成功しました。
Python関数の引数と返り値の型をチェックするデコレータ

# 概要

Pythonで作った自作関数を使用する時に、意図しない利用や挙動を検出するために、引数と返り値の型をチェックするデコレータを作ってみた。
型アノテーションを利用するため、Python3が前提になります。
内容をログに出すことで、デバッグする際にも役立ちます。
※間違い等ありましたらご指摘お願いします。

# 方法

## デコレータの定義
```python:検証デコレータ
import inspect

def validate_func(func):
	def validate_func_wrapper(*args, **kwargs):
		sig = inspect.signature(func)
		args_value = sig.bind(*args, **kwargs)  # 引数名と値のdict

		# 引数の検証
		for args_name, args_value in args_value.arguments.items():
			args_type = sig.parameters[args_name].annotation
			# 型が指定されている(not empty)、かつ 型が一致していない場合エラー
			if args_type is not inspect._empty and type(args_value) != args_type:
				raise Exception('引数の型が異なります')

		results = func(*args, **kwargs)

		# 返り値の検証
		return_type = sig.return_annotation
		# 型が指定されている(not empty)、かつ型が一致していない場合エラー
		if return_type is not inspect._empty and type(results) != return_type:
			raise Exception('返り値の型が異なります')

		return results
	return validate_func_wrapper
```

## 使い方例
```python:使い方例
@validate_func
def test(a:int, b:int = 2) -> int:
    return a + b

test(1)  # 正常終了
test(1.0)  # エラー
```

# 参考
 - [Python: inspect.signature() で関数のシグネチャを調べる](https://blog.amedama.jp/entry/2016/10/31/225219)
DataBricks をgit連携する

# DataBricksのノートブックの管理方法

DataBricksを使っていてノートブックなどのバックアップをしたり履歴をトレースしたい場合は、ビルトインのVersion Controlがお手頃です。

## ビルトインのVersion Control

以下にビルトイン機能の利用方法があります。
https://docs.databricks.com/user-guide/notebooks/notebook-use.html#version-control

以下が可能です。

- コメントを追加する（随時セーブ）
- リビジョンを復旧する
- リビジョンを削除する
- リビジョン履歴を削除する

基本的にはnotebookの変更時に自動保存されるので、自分でリビジョンをコントロールするというよりは、単純にバックアップという機能に近いです。ブラウザでやっている以上、不測の事態が起こりがちなので、最低限この機能は保障されているのはうれしいところですね。

## github

githubの統合は以下の手順で可能です。
https://docs.databricks.com/user-guide/notebooks/github-version-control.html

### 1) githubアクセストークンを得る

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/cd1e68b1-937a-cecb-fc4d-f0df12badc69.png)

### 2) DataBricks側でaccess tokenを入力する

[User Setting]メニューに項目があります。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/d03ba5a7-722d-2b78-eac7-cba14d2ad745.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/ed2671a8-cb7e-9982-5d3c-0a1964826b06.png)

### 3) notebookでgitをリンク

先ほどのRevision historyタブのところにGitのリンクボタンがあるので押して、リポジトリを設定します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/dc4f753c-882e-da29-3b58-03c85cdac844.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/66706bb0-603a-73f9-d72c-885bc65c69ec.png)

### 4) マニュアルでrevision historyにセーブ

Commitしたい場合は、自動では行われないのでRevision HistoryにマニュアルでセーブするSave nowボタンを押します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/9cacd107-048d-d3d3-0512-b66a5164a2a9.png)

コメントが求められるので、その下の"Also commit to Git"チェックボックスをONにすることでGitへのcommitを同時に行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/a747f9d3-182a-2772-fc95-3b75afbb68a1.png)

## Azure DevOps (VisualStudio Online)

ADOに対するリンクは簡単です。

https://docs.azuredatabricks.net/user-guide/notebooks/azure-devops-services-version-control.html

以下のようにgitプロバイダとしてAzure DevOpsを選択するだけです。同じAzure ADを使っている場合はクリデンシャルの再登録は必要無いようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/146939/8be47b19-9456-15ca-c3ae-a23a72c33e28.png)
Spring Tool Suite が exit code = 13 で起動できない

# 現象

Windows 64bit 向け Spring Tool Suite 3.7.0 および 4.1.2 を exe クリックで起動しようとしたところ、下のメッセージを含むダイアログが表示され起動できませんでした。

```
Java was started but returned exit code = 13
```

![error.png](https://qiita-image-store.s3.amazonaws.com/0/43328/e17196a6-96cf-5395-87c8-8e7c7f37ceab.png)


# 解決

64bit 向けの STS を 32bit 向け java で実行しようとすると起こる現象のようです。

## 1. Javaの実行ファイルを確認

PowerShell で↓を実行

```
which java
```

デフォルトでどのjava.exeが実行されているかが表示されます。これが32bit向けだったため、今回の問題が起きました。

## 2. 64bit向けjavaの場所を確認

64bit向けのjava.exeは通常 `C:\Program Files\Java\jdkx.x.x_x\bin` においてあります。
もし必要があればここで64bit向けJavaをインストールしてください。

## 3. 環境変数 Path を修正

環境変数 Path から 1. で確認したパスが記述されているところを探します。

* ユーザーの環境変数とシステムの環境変数の両方に `Path` が定義されているため、両方を探してください。
* `JAVA_HOME` といった別の環境変数に切り出されているかもしれません

見つけたら、2.で見つけたパスに置き換えます。

## 4. 変更を確認

さきほど開いていた PowerShell はいったん閉じて、再度 PowerShell を開き、`which java` で 3. の変更が反映されているかを確認します。

## 5. STS を起動

これで動くはず…
HP-UX でntpq -pとしたらntpq: read: Can't assign requested addressと表示される場合

# HP-UX でntpq -pとしたらntpq: read: Can't assign requested addressと表示される場合
## 前提条件
- NTPサーバに接続できる事

## 事象
\# ntpq -p としたら以下のエラーが出てしまう
`ntpq: read: Can't assign requested address`

## 対処
1. ntpdateコマンドで時刻を合わせる
2. (あまりにもサーバの時刻が現時刻と離れていると調整できないから)
`ntpdate 111.222.333.444`

2. xntpdの再起動
`/sbin/init.d/xntpd stop`
`/sbin/init.d/xntpd start`

3. 5分後くらいにntpq -pをして*マークがつくのを確認する

```
# ntpq -p
     remote           refid      st t when poll reach   delay   offset    disp
==============================================================================
*111.222.333.444   aa.bb.cc.dd    2 u   30   64  377  134.691   -5.142  18.612
```
Linux Mint に MongoDB をインストールする

# やりたいこと

作成予定のアプリが『チャット』、言語が Node.js でフレームワークとして Express を選定、相性の良さそうなデータベースをググった結果、RDB ではなく NoSQL を選定、[mongoose](https://mongoosejs.com/) 経由で [MongoDB](https://www.mongodb.com/) を使うため、ローカルに MongoDB をインストールしました。

上述の構成は割と定番らしいのですが 私自身 MongoDB を触ったことがなかったので、MongoDB のインストールならびにサービスの設定まで実施した手順を残しておきます。

## 前提環境

実施した環境ということでご参考までに。Linux Mint は Ubuntu 互換のディストリビューションです。

| カテゴリ | ソフトウェア | バージョン |
|:---|:---|:---|
| OS  | [Linux Mint](https://linuxmint.com/)| 19 Tara Cinnamon x64 (Ubuntu 18.04 LTS ベース) |

# やってみた

## 1. MongoDB をインストール

[公式の手順](https://docs.mongodb.com/manual/tutorial/install-mongodb-on-ubuntu/)を見ながらインストールします。

```bash:bash
# OS に MongoDB をインストール
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 9DA31620334BD75D9DCB49F368818C72E52529D4
echo "deb [ arch=amd64 ] https://repo.mongodb.org/apt/ubuntu bionic/mongodb-org/4.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-4.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
```

正常にインストールされたのか確認します。

```bash:bash
mongo --version
```

```text:実行結果
MongoDB shell version v4.0.6
git version: caa42a1f75a56c7643d0b68d3880444375ec42e3
OpenSSL version: OpenSSL 1.1.0g  2 Nov 2017
allocator: tcmalloc
modules: none
build environment:
    distmod: ubuntu1804
    distarch: x86_64
    target_arch: x86_64
```

続いてサービスを起動します。

```bash:bash
sudo systemctl start mongod.service
```

ステータスコマンドで正常動作を確認します。

```bash:bash
systemctl status mongod.service
```

```text:実行結果
● mongod.service - MongoDB Database Server
   Loaded: loaded (/lib/systemd/system/mongod.service; disabled; vendor preset: enabled)
   Active: active (running) since Fri 2019-03-01 12:31:21 JST; 2h 42min ago # <== 結果はここを見る
     Docs: https://docs.mongodb.org/manual
 Main PID: 14542 (mongod)
   CGroup: /system.slice/mongod.service
           └─14542 /usr/bin/mongod --config /etc/mongod.conf
```

3行目の `Active` が `active (running)` になっていればOKです。

## 2. サービスの設定

このままだと OS の再起動後にサービスが停止してしまうので、OS が起動するとサービスも起動するように設定します。

```bash:bash
sudo systemctl enable mongod.service
```

```text:実行結果
Created symlink /etc/systemd/system/multi-user.target.wants/mongod.service → /lib/systemd/system/mongod.service.
```

## 所感

- ローカルにデータベースを構築するなら Docker で良い説... [mongo - Docker Hub](https://hub.docker.com/_/mongo)
CakePHP3: 実行されたSQLのログを取る

CakePHP3にて、実行されたSQLのログを取得する方法。

```php
$connection = \Cake\Datasource\ConnectionManager::get('default');
$connection->logQueries(true);
```

詳しくは公式ドキュメント参照: [データベースの基本 - 3.7](https://book.cakephp.org/3.0/ja/orm/database-basics.html#database-query-logging)
Xcodeのエラー（linker command failed with exit code 1）の解決策

# エラー
CocoaPodsを導入した後にビルドしようとすると以下のエラーになりました。

`clang: error: linker command failed with exit code 1 (use -v to see invocation)`

# 解決策
プロジェクトを開くときに`HogeApp.xcodeproj`で開くのではなく`HogeApp.xcworkspace`で開くと解決しました。

# 参考
https://stackoverflow.com/questions/46115708/linker-command-failed-with-exit-code-1-after-installing-cocoapods-and-firebase-p/48515378
MarkLogicのWindows版をインストール

概要
===
MarkLogicにはWindowsパソコン版が開発用としてリリースされています。今回はWindows10のパソコンにインストールしてみる手順を追ってみます。余裕があれば[こちら](https://docs.marklogic.com/guide/installation/procedures)もご参照ください。

インストーラのダウンロード
===
[公式のダウンロードサイト](https://developer.marklogic.com/products/marklogic-server)に行き、画面左側の選択欄のうちServerの欄から最新版のリンクを選択します。ダウンロードリストが出てきますので今回はMicrosoft Windowsの欄にある64-bit Windows Installerを選択します。
ここでMarkLogicコミュニティのアカウントを求める画面がでるかもしれませんが、アカウントを所持していればメールアドレスとパスワードを入力して「Download」ボタンを押下するとmsi形式のインストーラがダウンロードされます。もしアカウントを所持していなければ「Sign up」リンクを選択して作成してから再度ダウンロードリストに戻って同じ操作を行いましょう。

![Download_MarkLogic.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/9877992f-66a3-2ed5-0e8a-4808e41d8c5f.jpeg)

インストールの実行
===
ダウンロードしたmsiファイルを選択してインストールを開始します。

![Install1.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/3a14563f-2ce1-a1aa-138f-7031d27c3ba4.jpeg)

「Next」ボタンを押下します。

![Install2.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/d09efda2-9b13-a71b-d7c6-b79bfd75566d.jpeg)

３つの項目が出ましたが、とりあえず「Typical」を選択して「Next」ボタンを押下しましょう。

![Install3.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/082cdf01-2b04-bb3e-f1b1-a73a28ebf191.jpeg)

最終確認のようなので「Install」ボタンを押下します。

![Install4.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/14da37f8-1d46-3a23-f460-f75abe798351.jpeg)

インストールが進行していきます。

![Install5.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/27191976-7a6e-72f0-65ef-c6270c294007.jpeg)

インストールが無事完了されたようなので、「Finish」ボタンを押下します。

起動
===
インストールしただけではMarkLogicはソフトウェアとして起動していませんので、まずは起動させてみます。
タスクマネージャを開いて「サービス」タブを押してMarkLogicという名前のサービスを探してください。インストールしただけでは状態が停止となっていますので、右クリックで開いたところから「開始」を選択します。これで状態が実行中となればOKです。

初期設定
===
Webブラウザを開いて、ポート8001番の管理画面にアクセスします。管理画面へのURLは以下の通りです。

```
http://localhost:8001/
```

![server_install.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/d9cd25f4-5abf-fc82-5e33-e84b36e77650.jpeg)

「OK」ボタンを押下します。

![join_cluster.jpg](https://qiita-image-store.s3.amazonaws.com/0/277440/3589c594-2fdb-714e-d876-c479798809e7.jpeg)

クラスタへの参加を問う画面です。今回はクラスタを組むわけではないので「skip」ボタンを押下します。パソコンでもクラスタを組むこと自体は可能なのでご興味のある方は、クラスタを組むノードのうち２台目以降の対応の時に「Host Name」にホスト名またはIPアドレスを記述して「OK」ボタンを押下すれば、クラスタを構成することになります。

<img width="433" alt="set_up.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/277440/c3b4a524-5fe1-2b21-b8b9-e92e9ccbe9ff.jpeg">

「Security Setup」画面では管理者アカウントを決めます。データベースの全てを握るユーザとなるので、ユーザ名・パスワードは慎重に保管しましょう。なおセットアップ後に変更も可能です。Walletパスワードの設定についても入力必須となっていますが、今回は特に用いないため適当な値を設定します。
ここでOKボタンを押せば初期設定完了です。


開発者ライセンスの取得と登録
===
ライセンス費用体系は基本的にCPUのcore数課金のようですが、学習用かつデータサイズ1TB以下という条件で半年間限定の開発者ライセンスが利用できます。最新のライセンス規定については[公式サイト](https://developer.marklogic.com/free-developer)をご確認ください。
開発者ライセンスは、インターネット接続されていることを前提に管理画面から取得することが可能です。管理画面左側の「Hosts」内のホスト名を選択して、「Status」タブを選択後に出る「license key」というボタン押下すると「License Key Entry」画面が現れ、「Get Developer License」ボタンを押せば、取得画面への移行します。得られた「Licensee」と「License Key」を入れれば完了です。
ちなみにライセンスキー無しでも動くは動くのですが、日本語への構文解析機能が無い等制限があるようですので、やはりライセンスキーの取得・登録をお奨めします。

雑感
===
パッケージ製品ということもあってWindows版のインストールはそれほど大した作業もないというのが感想です。Linux版もそれほど違いはないようなのですが、必要なパッケージなどにご注意ください。
次はデータベースを構築したりクエリを書いてみたりしようと思います。


------------------------------------------------------------------------
Amazon Linux上でRails新規プロジェクトを作成すると、bundle installで落ちる

# はじめに
結論からいえば、g++のバージョンのバージョンが古い(v4.8.5)とbundle install時にtherubyracerのコンパイルに失敗するため、bundle installが完了せずRailsサーバーが起動できません。

# 再現環境
- Amazon Linux AMI release 2018.03
- rbenv 1.1.1-40
- Ruby 2.6.2p47
- Rails 5.2.2.1
- g++ version 4.8.5

# 現象
Railsプロジェクトを新規作成する際、bundle installをしようとすると下記のエラーが発生し完了しませんでした。
therubyracerでC++ソースのコンパイル時にエラーが発生しているようです。

```shell

current directory: /home/ec2-user/newprj/vendor/bundle/ruby/2.6.0/gems/therubyracer-0.12.3/ext/v8
/home/ec2-user/.rbenv/versions/2.6.2/bin/ruby -r ./siteconf20180518-15624-zeugq2.rb extconf.rb
checking for -lpthread... yes
creating Makefile

current directory: /home/ec2-user/newprj/vendor/bundle/ruby/2.6.0/gems/therubyracer-0.12.3/ext/v8
make "DESTDIR=" clean

current directory: /home/ec2-user/newprj/vendor/bundle/ruby/2.6.0/gems/therubyracer-0.12.3/ext/v8
make "DESTDIR="
compiling accessor.cc
g++: error: unrecognized command line option ‘-Wmisleading-indentation’
g++: error: unrecognized command line option ‘-Wimplicit-fallthrough=0’
g++: error: unrecognized command line option ‘-Wduplicated-cond’
g++: error: unrecognized command line option ‘-Wrestrict’
make: *** [accessor.o] Error 1

make failed, exit code 2
```

# 原因と対処法
g++のバージョン7より古い場合はtherubyracerのコンパイルが出来ません。
単純にバージョン7以降のg++をインストールすることで解決します。

```shell
$ g++ -v
gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC)
$ sudo yum remove gcc48-c++.x86_64
$ sudo yum install gcc72-c++.x86_64
$ g++ -v
gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)
```
【PL/SQL】年月データの1年後を取得する(ADD_MONTHS)

#年月データの1年後を取得する(ADD_MONTHS)
##やりたいこと
`ADD_MONTHS`関数は指定した日時に指定の月数を足して返す関数です。

```sql
SELECT 
    ADD_MONTHS(SYSDATE,1), -- 1ヶ月後の日付を取得
    ADD_MONTHS(SYSDATE,12) -- 1年後の日付を取得
FROM dual;
```
ここではこの関数を使用し、年(yyyy)や年月(yyyymm)といったデータの1年後のデータを取得します。
`ADD_MONTHS`関数は年月日揃っているデータに対し処理を行うため、年や年月のデータに対してはそのまま使用することはできません。

##コード
以下のようなデータが存在した時に下記コードを実行し、それぞれ1年後のデータを取得します。

| 年    |    年月 |
|:----------------:|:-----------------:|
| 2019            |        201904 | 

**取得したい内容**

| 年    |    年月 |
|:----------------:|:-----------------:|
| 2020            |        202004 | 

```SQL
SELECT
    TO_CHAR(ADD_MONTHS(CONCAT(test_yyyy,'0101'),12),'yyyy'),      -- yyyy形式
    TO_CHAR(ADD_MONTHS(CONCAT(test_yyyymm,'01'),12),'yyyymm')     -- yyyymm形式
FROM dual;
```
上記コードで行っているのは以下のような内容です。
・`CONCAT`関数で年のみもっていないデータに疑似的に月日のデータを付与する
・`ADD_MONTHS`関数で12ヶ月後(1年後)の日付を取得する
・`TO_CHAR`関数で取得した日付を成型しなおす
【Youtube Player API】 YouTube自動再生をコピペで完結


#1分でYouTubeのURLを埋め込んで自動再生させる（コピペ）

![alt](https://qiita-image-store.s3.amazonaws.com/0/319526/332b5870-099c-6562-2dc0-63b6fdfda3c2.png)






(一応、【要件】)   表示されたら動画を６秒間再生したあと、動画を停止。





####▼表示させたいviewに下をコピペ

```html:index.html.rb
<div id="player"></div>
```

####▼表示させたいjsに下をコピペ

```application.js

var tag = document.createElement('script');

tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);

var player;
function onYouTubeIframeAPIReady() {
player = new YT.Player('player', {
  height: '360',
  width: '640',
  videoId: 'bjmBJ1Fl0cs',
  events: {
    'onReady': onPlayerReady,
    'onStateChange': onPlayerStateChange
  }
});
}

function onPlayerReady(event) {
  event.target.playVideo();
}

var done = false;
function onPlayerStateChange(event) {
  if (event.data == YT.PlayerState.PLAYING && !done) {
    setTimeout(stopVideo, 6000);
    done = true;
  }
}
function stopVideo() {
  player.stopVideo();
}

```



######うまくできたら下の動画が自動再生される


http://www.youtube.com/watch?v=bjmBJ1Fl0cs
[![IMAGE ALT TEXT HERE](http://img.youtube.com/vi/bjmBJ1Fl0cs/0.jpg)]
(http://www.youtube.com/watch?v=bjmBJ1Fl0cs)
補足
#####youtubeURL採取方法はこれ
：https://bazubu.com/how-to-embed-youtube-to-wp-23776.html


取ってきたURLはだいたいこんな感じ

```html
<iframe width="560" height="315" 
src="https://www.youtube.com/embed/bjmBJ1Fl0cs"
frameborder="0" 
allow="accelerometer; 
autoplay; 
encrypted-media; 
gyroscope; 
picture-in-picture" 
allowfullscreen>
</iframe>
```



上のコード中の```src="https://www.youtube.com/embed/bjmBJ1Fl0cs"```の中の```bjmBJ1Fl0cs```を```videoId : 'ここ';```にコピペで色んなYouTubeを自動再生できる



参考記事：https://developers.google.com/youtube/player_parameters?hl=ja
　　　　：http://bashalog.c-brains.jp/15/02/25-100000.php

以上です！
python 年月日を計算

# 年月日を計算

- relativedelta

```python
import datetime
from dateutil.relativedelta import relativedelta

dt = datetime.datetime(2017,1,1)
print(dt, '(基準年月日)')

# 3年後
dt_plus_year = dt + relativedelta(years=3, months=6, days=23)
print(dt_plus_year, '(3年6ヶ月23日後)')

# 1ヶ月前
dt_minus_month = dt + relativedelta(months=-1)
print(dt_minus_month, '(1ヶ月前)')

# 90日前
dt_minus_day = dt + relativedelta(days=-90)
print(dt_minus_day, '(90日前)', type(dt_minus_day))
```

```
[out]

2017-01-01 00:00:00 (基準年月日)
2020-07-24 00:00:00 (3年6ヶ月23日後)
2016-12-01 00:00:00 (1ヶ月前)
2016-10-03 00:00:00 (90日前) <class 'datetime.datetime'>
```

- dateutil 公式サイト
  - https://dateutil.readthedocs.io/en/stable/
クラス内にモジュールがincludeされているか確認する方法

#モジュールの用途

・Rubyは単一継承のため、1つのクラスには1つのスーパークラスしか持てないので、複数のインスタンスメソッド、クラスメソッドを継承関係で使用したいときにモジュールを使用→Mix-in
・namespace（名前空間）の作成
・シングルトンオブジェクトのように扱って設定値などを保持する

##Mix-inする方法

・extend
→モジュール内のメソッドをそのクラスの特異メソッド（つまりクラスメソッド）にすることができる。
・include
→モジュール内のメソッドをそのクラスのインスタンスメソッドにすることができる。

##あるクラスに特定のモジュールがincludeされているか確認する方法

```
module Loggable
end

class Product
  include Loggable
end
```

上記のような、Productクラス内でLoggableモジュールをincludeしているコードがあったとします。

```
Product.include?(Loggable)
=> true
```
クラスオブジェクトに対してinclude?メソッドを呼ぶと引数で渡したモジュールがincludeされているかどうか確認することができます。

```
Product.included_modules
=>[Loggable,Kernel]
```

included_modulesメソッドを使用することで、includeされているモジュールの配列が返します。

※Kernelモジュールは、ProductのスーパークラスであるObjectクラスでincludeされているモジュールです。

（Kernelモジュールのリファレンスマニュアル）
https://docs.ruby-lang.org/ja/latest/class/Kernel.html


```
Product.ancestors
=> [Product, Loggable, Object, Kernel, BasicObject]
```

ancestorsメソッドを使用することでモジュールだけでなく、スーパークラスの情報も配列になって返すことができます。

```
product = Product.new
product.class.include?(Loggable)
=> true
product.class.included_modules
=> [Loggable, Kernel]
```

classメソッドを使用することで、クラスオブジェクトだけでなく、クラスのインスタンスからもincludeされているモジュールの情報が取得することができます。

```
Product.superclass
=> Object
```

superclassメソッドでスーパークラスを表示することもできます。



【参考記事】
プロを目指す人のためのRuby入門 言語仕様からテスト駆動開発・デバッグ技法まで（書籍）
初投稿！プログラミングスクールで2か月程学習したので振り返り

#【状況】
私は、現在codecampという完全オンラインの
プログラミングスクールで勉強をしています。
コースは４か月プランで受け放題のプランです。
スクールと併用してprogateやドットインストールなどで
足りないと思う部分を補っています。

#【学習内容】
スクールでの学習
1週間でHTML/CSSを学習
Webページ作成

1か月でjavascript,jqueryを学習
ストップウォッチとルーレット作成

1か月でPHP（途中）,MySQL,Bootstrapを学習
PHP基礎、SQL基礎、DB操作
レスポンシブ対応のwebページ作成

現在スクールで、MVC
独学でGit、Githubを勉強中。
PHPでECサイト作成予定
来月からRuby,Ruby on Railsを学習予定。

#【利用した感想】
**メリット**
・完全オンラインなので、電車に乗ってスクールに通う必要がない
・メンターがたくさんいるので、お気に入りのメンターを見つけて受講可能
・レッスンは受けられる時間帯が長く、働きながら勉強したいという方にもおすすめ
・スクールに入れば、高い料金を支払うことで、半強制的に学習しなければならないという
　環境を作ることができ、独学のように挫折してしまう可能性が少ない
・環境構築や参考書の選別などがないので、初心者にとっては学習しやすい
・現役のエンジニアに相談することができるので、何をしたいのか、どんな言語が合っている
　のかを見つけることができる。


**デメリット**
・料金的に高いと感じる（内容は満足）
・就職はプランと条件によっては、支援を受けられずにスクールを卒業することがある。
ntpの2036年

NICTのjjyグループさんに以下のページがあります。

http://jjy.nict.go.jp/tsp/PubNtp/clients.html

ntpの秒は1900年からの符号無し32bitなので、もうそんな遠くない将来にオーバーフローします。

Thu Feb  7 15:28:15 2036

最上位ビットが無くなったら、ここを始点とするというページの記載がありました。ちょっとロジックを追加してみました。

```c
#include <stdio.h>
#include <time.h>
#include <stdint.h>

main() {
uint32_t ntptime;
time_t posixtime;

printf("time_t size = %d\n", sizeof(time_t));

ntptime = 0x7fffffff;

if (ntptime < 0x80000000)
    posixtime = (time_t)ntptime + 0x100000000ULL - 2208988800UL;
else
    posixtime = (time_t)ntptime - 2208988800UL;

printf("%s¥n", ctime(&posixtime));
}
```

32Bit環境でもtime_tが8バイトであればちゃんと動くはずです。

このロジックは

Tue Feb 26 18:42:23 2104

まで有効です。

とは言え2036年を過ぎたら徐々に外していくのが良いと思われます。

lwIPのsntpのサンプルにはこのロジックは入っていないようです。

2038年問題よりも先にこの問題がある事忘れてないですか？
c++ constメンバ関数まとめ

# constメンバ関数とは
以下のように引数の後にconstが明記されたメンバ関数のことです。

メンバ関数内でメンバ変数を使用するがデータの改変を防ぎたい場合これを明示するために使います。

```hito.cpp
#include <iostream>

class Hito {
  private:
    int age = 10;
  public:
    void output_age() const { // <- constメンバ関数
      std::cout << age << std::endl; 
    }
    void grow_a_year_older() {
      age++;
    } 
}
```

# 書くとどうなるか
関数内でのメンバ変数の書き換えができなくなります。


以下のように書くことはできません。

```hito.cpp
void output_age() const {
  age++;               // <- [Err]
  age = 1;             // <- [Err]
  grow_a_year_older(); // <- [Err]
  std::cout << age << std::endl; 
}
```

# 利点
コーダーが誤ってメンバ変数を書き換える可能性を抑えられバグを減らすことができます。

デバックの際にconstメンバ関数の中身でメンバ変数が書き換えられていないか確認する必要が減ります。

つまり副作用を抑えられます。

# 注意点
### 注意点1: 関数内でメンバ変数を使わない場合
関数内でメンバ変数を使わない場合はconstメンバ関数にするよりも静的関数にした方が良いです。

以下は例です

```hito.cpp
   static output_age(const int age0) {
      std::cout << age0 << std::endl;
   }
```


### 注意点2: const メンバ変数内であってもメソッド変数が書き換えられてしまう場合がある

メンバ変数をmutableで宣言した場合です

```hito.cpp
...
  private:
    mutable int age = 10; // mutableメンバ変数
...

```

この場合constメンバ関数内で変数を直接変更することが可能になります。しかしメンバ変数を内部で変更するような関数の呼び出しはエラーになります。

```hito.cpp
void output_age() const {
  age++;               // <- Errにならない
  age = 1;             // <- Errにならない
  grow_a_year_older(); // <- [Err]
  std::cout << age << std::endl; 
}
```




# 参考
[const (C++) | Microsoft Docs](https://docs.microsoft.com/en-us/cpp/cpp/const-cpp?view=vs-2017)
Laravelで始める DBパフォーマンス入門

# 安西先生…!!　アプリケーションを速くしたいです……

---

# DBのパフォーマンスを調整してみよう

---

# まずはIndexを付与してみよう

---

# Q1. DBにおけるIndexとは？

---

# A1. データベースの性能を向上させる方法の一つ

---

## 構成要素
「探すレコードを識別するデータの項目」
「対象レコードの格納位置を示すポインタ」

## つまり
格納位置を特定し、その位置を直接アクセスする事で、検索速度をあげられる。

---

## なので
インデックスが設定されていない場合の検索では、テーブルの最初から順番に1件ずつ探すため、時間がかかります。

参考
https://www.atmarkit.co.jp/ait/articles/1703/01/news199.html

---

# 早速実践してみた。

---

# tyamahori.com で実践する

---

# インストールするもの

- https://github.com/barryvdh/laravel-debugbar
    -  色々とでバックしてくれるもの

---

# 導入直後のキャプチャ

[![Screenshot from Gyazo](https://gyazo.com/75fff9d3b8a8c5069b6a8c2d50bb81cc/raw)](https://gyazo.com/75fff9d3b8a8c5069b6a8c2d50bb81cc)


---

# ポイントはQueries
- ここを見れば発行されているクエリーが確認できる。
- それをデバッグしてクエリーを最適化する

---

# 対応前キャプチャ

[![Screenshot from Gyazo](https://gyazo.com/a534d1a93569d69da08723609a0b91b5/raw)](https://gyazo.com/a534d1a93569d69da08723609a0b91b5)

---

# 無駄にクエリが吐かれているので直す

---

# コードを修正したらがっつり減った
まずはSQLの発行は減らせた！
[![Screenshot from Gyazo](https://gyazo.com/0153b953d045a6d0d25cf3df857c9b64/raw)](https://gyazo.com/0153b953d045a6d0d25cf3df857c9b64)

--- 

# 次はSQLのデバック

---

# EXPLAINを使う
乱暴にいうと、SQLがどのように実行されるかを教えてくれるコマンド

```sample.sql
explain select * from `posts` where `published` = 1 and `posts`.`deleted_at` is null order by `created_at` 
desc
```

---

# EXPLAINを叩いた結果wwwwwww
- typeがALLになっていたらダメ
- フルスキャンがかかりパフォーマンスが悪い

[![Screenshot from Gyazo](https://gyazo.com/b9402a319cb42db61669dd2136c3b38b/raw)](https://gyazo.com/b9402a319cb42db61669dd2136c3b38b)

---

# ガバガバ実装で草が生えた

---

# とりあえずカラムにindexをつける。

---

# と思ったけど、うまくindexが効かず挫折。。。
色々と調査はしているけど。。わからず。。

---

# データが少なく、indexがつかない。。？
確固たる原因は分からず。。

---

# おしまい

---