OmniAICreator/Qiita-1.07M huggingface dataset:
SQLプライマリーキー、外部キー、ユニークキーどう使い分ける？

##はじめに
どうも、未経験からエンジニア転職を目指しているもきおです。

自作ポートフォリオ(自分はRalisで作ってます)を作成していてデータベース設計をしている時、プライマリーキーやら外部キーやらユニークキーやら色んなキー制約があり何使えばいいんや？と感じてました。

今回SQLを改めて学習したのでそれぞれの役割、制約について書き記したいと思います。
SQL削除命令文は以下記事にまとめました。良ければご覧ください。

https://qiita.com/mokio/items/6aa443de4758a774f356

## 主キー  (PRIMARY KEY)制約
テーブルのレコードを一意に特定するためのKEY

特徴
・一意である
・基本一つのテーブルに一つだけ
・設定するだけでNULLと重複を禁止してくれる

```bash:SQL設定例
CREATE TABLE users
(
    id INT AUTO_INCREMENT PRIMARY KEY,
    name VARCHAR(255),
    age INT(3)
);
```
###一意ってなんだ？
一意とは「重複させないよ」、もっとカッコつけて言うと「オンリーワンだよ」ってこと
例：
1,2,3,4,5はそれぞれ重複しないので一意
1,1,1,2,3は1が重複しているので全体としては一意ではない

以下より抜粋

https://wa3.i-3-i.info/word12715.html
###PRIMARY KEY 使用例
基本的にはidに設定すると思います。
![スクリーンショット 2021-09-29 6.34.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/c7d64c90-1502-c898-4360-8cb097890386.png)
idを主キー(PRIMARY KEY)にすることで名前が重複していてもid,1のもっさんとid,2のもっさんに区別することができます。

## 外部キー  (FOREIGN KEY)制約
テーブル間の関係性を設定
関連するテーブル間の整合性を保証するためのKEY

```bash:SQL設定例
CREATE TABLE orders
(
id INT(10),
user_id INT,
amount INT(20),
price INT(20),
PRIMARY KEY (id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
```
先程作成したUsersテーブルとの関連図はこんな感じ
![スクリーンショット 2021-09-29 7.18.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1089852/7f9d87bc-6c6d-384d-bed7-e2c02edac798.png)

外部キーを付与するとこのようにテーブル間の関連性を持たせることができます。
ここではUsersが親テーブル、Ordersが子テーブルとなります。

そしてこのキー設定の後の**ON DELETE CASCADE**とは親テーブルのデータが削除された際にデータの整合性を保つ為、子テーブルも一緒に削除するためのオプションです。

このように外部キーを設定することでテーブル間で関連付けられた設定を行うことができます。

## ユニークキー  (UNIQUE KEY)制約
プライマリーキー以外のデータの重複を禁止

特徴
・重複を禁止
・複数設定可能

```bash:SQL設定例
CREATE TABLE users
(
id INT(3) AUTO_INCREMENT,
name VARCHAR(255),
email VARCHAR(255),
PRIMARY KEY (id),
UNIQUE KEY (email)
);
```
###UNIQUE KEY 使用例
emailとかパスワードとかの重複を防ぎたいものに対し設定することが多いかと思います。

##あとがき
今まで見様見真似で使用してしまってましたが整理することができました。

アプリケーション作成時にはデータベース設計が必ずと言っていいほど絡んでくるので引き続きSQLの理解に努めていきたいと思います。

この記事が少しでも良いと感じていただけましたらLGTMポチッとしていただけますと幸いです。
STSでCould not initialize class org.codehaus.groovy.vmplugin.v7.Java7

STS　Version: 4.10.0.RELEASE


```:エラー内容
 :: Spring Boot ::        (v2.1.2.RELEASE)
java.lang.NoClassDefFoundError: Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7
	at org.codehaus.groovy.vmplugin.VMPluginFactory.<clinit>(VMPluginFactory.java:43)
```

JREにJDK11を設定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/b66b5d0b-637b-2c81-b167-c7a1ca461982.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/e8b5da47-b324-390e-cb0e-258848fb8203.png)
ちゃんと変わってる確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33237/259acf02-3442-160c-f040-f204b3a9ba1b.png)

WARNINGはでるけど、実行できる
[Launch] NocoDB : オープンソースAirtable-あらゆるデータベースを共同スプレッドシートに変換します

今日はQiitaコミュニティにNocoDBを紹介できることに興奮しています。

# [NocoDBは、無料でオープンソースのAirtableの代替手段です。](https://github.com/nocodb/nocodb)
NocoDBは、任意のリレーショナルデータベースに接続し、それらをスマートスプレッドシートインターフェイスに変換することで機能します。これにより、チームと協力してノーコードアプリケーションを構築できます。 NocoDBは現在、MySQL、PostgreSQL、Microsoft SQL Server、SQLite、Amazon Aurora、MariaDBデータベースで動作します。

また、NocoDBのアプリストアでは、Slack、Microsoft Teams、Discord、Twilio、Whatsapp、Email、およびサードパーティのAPIを組み合わせて、ビュー上でビジネスワークフローを構築できます。さらに、NocoDBはAPIへのプログラムによるアクセスを提供するため、Zapier / Integromatおよびカスタムアプリケーションとの統合も構築できます。

![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100222/adff333f-b4d5-b995-b338-290d9de40cf6.png)

(すでに推測できると思いますが、私は日本人ではなく、英国に住んでいます。ですので、翻訳に間違いがあった場合はご容赦ください。)

# はじめに：シンプルでミニマル

### Dockerを使う

```
docker run -d --name nocodb -p 8080:8080 nocodb/nocodb:latest
```


### NPMを使用して
```
npx create-nocodb-app
```

### gitを使う
```
git clone https://github.com/nocodb/nocodb-seed
cd nocodb-seed
npm install
npm start
```
GUI
アクセスダッシュボードを使用して : http://localhost:8080/dashboard

# スクリーンショット
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100222/c7b76bbb-66c6-4b71-86fd-4d9508919f1c.png)

![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100222/3e04fbc5-76ae-c3fd-fde9-60b8db997c24.png)

![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100222/ee47a98f-d0b3-51e2-6bd0-cf8a105701c9.png)

![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2100222/f326daa8-0563-72a4-b071-60f6c61b39ae.png)


# リッチスプレッドシートインターフェース
### 検索、並べ替え、フィルタリング、列を隠す

⚡ ビューを作成する：グリッド、ギャラリー、カンバン、ガント、フォーム
⚡ シェアビュー：Public＆Password Protected.
⚡ パーソナル＆ロックビュー
⚡ 画像を細胞にアップロードする（S3、Minio、GCP、Azure、Digitalocean、Linode、Ovh、Backblazeで動作します）。
⚡ ロール：所有者、作成者、エディタ、コメンタ、ビューア、コメンタ、カスタムロール。
⚡ アクセス制御：データベース、テーブル＆カラムレベルでも微細に粒度のアクセス制御。
### ワークフロー自動化のためのApp Store：
⚡ チャット：マイクロソフトチーム、たるみ、不和、マッピー
⚡ メール：SMTP、SE、MailChimp
⚡ SMS：Twilio.
⚡ whatsapp.
⚡ 第三者APIS
### プログラムによるAPIアクセスによるアクセス
⚡ REST APIS（Swagger）
⚡ GraphQLAPI。
⚡ JWT認証とソーシャルAUTHを含む
⚡ ZAPIER、Integomatと統合するAPIトークン。


### また、次のコミュニティに参加してください。
- Github : https://github.com/nocodb/nocodb
- Discord : https://discord.gg/5RgZmkW
- Twitter : https://twitter.com/nocodb

あなたのフィードバックや提案を聞きたいです
「エンジニアはどこまで」学びとキャリアの目次

「エンジニアはどこまで」シリーズの目次です。

## 学び

https://qiita.com/e99h2121/items/a41339815d9aea87bdb4

https://qiita.com/e99h2121/items/c6afa788d87dbcb09175

https://qiita.com/e99h2121/items/fb8f04637cc420c7e1f6

https://qiita.com/e99h2121/items/c42048a0f1ac48cff9d1

https://qiita.com/e99h2121/items/f417a80983786d9a9869


## キャリア

https://qiita.com/e99h2121/items/89ec37a049adda24db2a

https://qiita.com/e99h2121/items/a25f0485f8281d793d3c

https://qiita.com/e99h2121/items/a279f8fb1fbe722aa31f


## 謝辞 :bow: 

https://blog.qiita.com/engineer-festa-presents-winners-2021/

[エンジニアはどこまで本を読めばよいのか - 良質なインプットと勉強のススメ - Qiita](https://qiita.com/e99h2121/items/c42048a0f1ac48cff9d1) にまつわり、2021年総合賞を頂きました。
【Rails】to_jsonを使わずに1クエリでいい感じにデータを返したい

## include

to_jsonには便利なオプションが沢山ある．特にinclude.多対多のデータをモデルの要素に配列として返してくれて便利．

https://qiita.com/eggc/items/29a3c9a41d77227fb10a

例えば，fooとbarそれぞれのモデルが多対多の関係にあるとして

```rb
JSON.parse(Foo.queries.to_json(include: :bars))
```

とすれば，

```rb
[{id: 1, bars: [{id: 1}, {id: 2}]}]
```

ただ，一対多なら+1, 多対多のテーブルなら中間テーブルを足して+2多くクエリーが発行される．まとめて取得したいテーブルが増えると線形に増えていってしまう．

## 1クエリーで同じ様に返すには?

なんか他にいいメソッドないかな...と思ったがない．ので書いてみる．モデルは上と同じ．DBはMYSQL．

```foo.rb
require 'hashie'
require "securerandom"

# 色々

scope hoge, -> () do
separator = SecureRandom.hex(12)

left_outer_joins(:bars)
# .queries
.select("
  foo.ids,
  foo.names,
  GROUP_CONCAT(bars.id separator '#{separator}') AS bar_identifications,
  GROUP_CONCAT(bars.name separator '#{separator}') AS bar_names
")
.group(:id)
.map {|f|
  Hashie::Mash.new({
    **f.attributes,
    bars: [
      f.bar_identifications&.split(separator) || [],
      f.bar_names&.split(separator) || []
    ].transpose.map {|row| [:id, :name].zip(row).to_h}
  })
}
end
```

### ポイント

- 左外部結合する．
- GROUP_BY(`group(:id)`)とGROUP_CONCATで関連モデルのカラムの値を文字列に連結して返す．
- separatorは値とかぶらなければよいのでランダムな文字列．
- `.<関連モデル>_ids`はRailsのメソッドして定義済みなのでidentificationsに変えている．
- [Hashie::Mash.new](https://github.com/hashie/hashie)を使うことでコントローラーやビューでモデルと同じ様にドット記法が使える．
- **f.attributesで要素を展開
- `&.`と`|| []`は値がnilだった場合用
- `bars: [{id: 1}, {id: 2}]`のようにするために`[[id1, id2], [name1, name2]]`のような二次元配列を転置させて，それぞれの要素にカラム名を加えてhashにする．

### デ/メリット

メリット
・どんなデータが返ってくるか一目でわかる
・加工しやすい

デメリット
・コードがやや長い

他に何かよい方法があったら教えて下さい．
Docker composeのコンテナ間通信でハマったとこ

# MacでコンテナごとにIPを割り当てられない

> docker (Linux) ブリッジ・ネットワークは macOS ホストから到達できません。
https://docs.docker.jp/docker-for-mac/networking.html#ip

`host.docker.internal`をホスト名に指定するといい


```
version: "3"
services:
  api:
    build: .
    ports:
      - 8080:8080
  web:
    build: .
    environment:
      - API_HOST_NAME=host.docker.internal:8080
```

# 順番通りに起動してくれない

このように`depends_on`で起動順は制御できますが**接続可能になるまでは待ってくれません**

```
version: "3"
services:
  api:
    build: .
  web:
    build: .
    depends_on:
      - api
```

[wait-for-it](https://github.com/vishnubob/wait-for-it)などを使って、以下のようにコマンドを指定するといいです

```
version: "3"
services:
  api:
    build: .
  web:
    build: .
    depends_on:
      - api
    command: ["./wait-for-it.sh", "<コンテナ名>:<ポート番号>", "--", "<接続時に実行するコマンド>"]
```

https://docs.docker.jp/compose/startup-order.html
【React】ねばねばした Loading コンポーネントを実装する

<!-- =========================================================== -->
# 概要
<!-- =========================================================== -->
**ねばねば結合するLoadingコンポーネント**を実装します。

![output(video-cutter-js.com).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358498/506f9de5-51e2-a17d-eabe-ff236c783dc8.gif)

:::note info
本記事は、以下の動画を<strong>React</strong>で実装したものです。
:::

https://www.youtube.com/watch?v=8ipFyy7HpqQ

:::note info
スタイリングには、<strong>emotion/css</strong>（CSS in JS）を使用しています。
:::

https://emotion.sh/docs/@emotion/css

https://qiita.com/nemutas/items/dac73aa645f27cde92cd

<!-- =========================================================== -->
# 実装
<!-- =========================================================== -->
```.tsx
import React, { VFC } from 'react';
import { css, cx, keyframes } from '@emotion/css';

export const LiquidLoaderAnimation: VFC = () => {
	const dots = 8
	const rotateDots = 5

	return (
		<div className={styles.container}>
			<svg className={styles.svg}>
				<filter id="gooey">
					<feGaussianBlur in="SourceGraphic" stdDeviation="10" />
					<feColorMatrix
						values="
							1 0 0 0 0
							0 1 0 0 0
							0 0 1 0 0
							0 0 0 20 -10
						"
					/>
				</filter>
			</svg>
			<div className={styles.loader}>
				{[...Array(dots)].map((_, i) => (
					<span key={i} className={styles.dot(45 * i)}></span>
				))}
				{[...Array(rotateDots)].map((_, i) => (
					<span key={i} className={cx(styles.dot(0), styles.rotate(-0.2 * i))}></span>
				))}
			</div>
		</div>
	)
}

const animations = {
	animate: keyframes`
    0% {
      transform: rotate(0deg);
    }
    100% {
      transform: rotate(360deg);
    }
  `
}

const styles = {
	container: css`
		position: relative;
		width: 100vw;
		height: 100vh;
		display: flex;
		justify-content: center;
		align-items: center;
		background-color: #0c1c21;
	`,
	loader: css`
		position: relative;
		width: 250px;
		height: 250px;
		filter: url(#gooey);
		animation: ${animations.animate} 16s linear infinite;
	`,
	dot: (rotate: number) => css`
		position: absolute;
		top: 0;
		left: 0;
		width: 100%;
		height: 100%;
		display: block;
		transform: rotate(${rotate}deg);

		&::before {
			content: '';
			position: absolute;
			top: 0;
			left: calc(50% - 20px);
			width: 40px;
			height: 40px;
			background: linear-gradient(45deg, #c7eeff, #03a9f4);
			border-radius: 50%;
			box-shadow: 0 0 30px #00bcd4;
		}
	`,
	rotate: (delay: number) => css`
		animation: ${animations.animate} 4s ease-in-out infinite;
		animation-delay: calc(${delay}s);
	`,
	svg: css`
		width: 0;
		height: 0;
	`
}
```
ねばねばしたエフェクト（gooey effect）は、svgの原子フィルター **feGaussianBlur**・**feColorMatrix** を使うことで表現しています。

**feGaussianBlur**でblurをかけて、**feColorMatrix**で透過部分（blurでぼやけた部分）のコントラストをあげることで、引っ付くような表現をしているようです。

もう少し詳しく知りたい方は、以下の記事が参考になると思います。

https://qiita.com/duka/items/3ab7be7b52c88e574273
Google Play Consoleで署名したアプリをダウンロードする方法

aab対応したアプリで且つ、Google Play Consoleでの署名管理に変更したため、
リリース前の検証用にGoogle Play Consoleで署名したアプリをダウンロードする方法を記載する。
(play store版からの上書きインストール検証に使用してます)

## 手順
1. aabファイルをアップする
　App Bundle エクスプローラ　＞ 新しいバージョンをアップロード
![スクリーンショット 2021-09-29 0.41.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/00c2662e-8cf4-6183-16aa-703ea95cfee2.png)

2. アップロードが完了したら、画面右上のaabファイル名をタップし、ダウンロードしたいバージョンに切り替える。
　ダウンロード　＞　署名済みのユニバーサルAPK ＞　右側のダウンロードアイコンタップ
![スクリーンショット 2021-09-29 0.43.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/130708/47eb6cf2-7f87-0084-ae64-c6f41a7118e4.png)

これで署名済みのapkをダウンロードすることができます。
ubuntu デスクトップ上基本設定１（仕事用ソフト）

# 目的
最近使い始めたubuntuデスクトップ上に、仕事で必要なソフトをインストールする

#環境
ubuntu 20.04

# インストールするソフト
* Chrome
* FileZilla
* Slack

# 各種インストール方法

### 0.まずはキーボード設定
ubuntuデスクトップ上では、既存の日本語レイアウトキーボードが認識されたり、
認識されてもすぐにまた欧米キーボードに戻ってしまうことがあります。
（実際にキーボード設定に関する記事が多く、最初のうちはトライアンドエラーの連続でした・・・）

#### 前提
設定画面内で、入力言語設定がJapanese(Mozc)が選択されていること。
![Screenshot from 2021-09-29 00-02-04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/9c6493c1-587b-27ff-b01d-9f63dc4b1cdf.png)

#### 設定方法
Japanese(Mozc)の入力設定ファイルを編集するだけ！以上！

1.ターミナルを開き、Japanese(Mozc)の入力設定ファイル開く

```
sudo nano /usr/share/ibus/component/mozc.xml
```
⇓
![Screenshot from 2021-09-28 23-13-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/6b7648a2-5dd2-fa33-98b1-5e54ce4e73ca.png)

2.キーボードレイアウト設定箇所を探し出し、日本語キーボードレイアウトへ設定

```
<layout>default</layout>
⇓
<layout>jp</layout>
```
3.ubuntu再起動

```
sudo reboot
```

### 1.Chrome
基本、デスクトップ上のみで使うソフトはUbuntu Softwereで見つかるはずと認識しているが、
Chormeに限っては見つからなかったので、既存のFireFoxでぐぐってみた結果ターミナル上インストールを行うことにしました。
（他の方法または、見つからなかった詳しい理由がわかる方はご教授いただけると幸いです！）

1.wgetを使ってChormeインストールパッケージをダウンロード

```
wget https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb
```
2.ダウンロードしたインストールパッケージにしたがって、Google Chromeをインストール 
(ステップ１よりディレクトリ移動をしていないテイ)

```
sudo apt install google-chrome-stable_current_amd64.deb
```

3.ソフト一覧よりGoogle Chrome発見
![Screenshot from 2021-09-29 00-33-32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/9206144b-2c49-e0e4-a5fc-f0b3ee3c00fc.png)

### 2.File Zilla, Slack
ターミナル経由がいい人もいるが、わからないうちはUbuntu Software で検索するだけ！以上！
![Screenshot from 2021-09-29 00-35-40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/ff23dba0-becc-e024-0745-cf53553c0970.png)

![Screenshot from 2021-09-29 00-36-03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/972154/99eabe6c-1df0-0200-d52a-734c4458245f.png)

:::note warn
場合によっては、slackはスクロールしないと出てこないので注意！
:::

# まとめ
基本設定だけれど、以外と悩まされてしまったため、同じような境遇の方の参考になれば幸いです！

### 参考
* https://qiita.com/arai-wa/items/3123ecb350097f79c6ef
* https://ubunlog.com/en/chrome-algunas-formas-de-instalarlo-en-ubuntu-21-04/#Con_apt
CSS 備忘録

## 使い方
* css別ファイルを作る
* HTMLファイル\<head\>\</head\>の間に記述する
* HTMLに直接記述する場合は<style></style>で挟む

## id・クラスの指定方法
```
#id-name{
}

.class-name{
}
```

## 文字の大きさを変更する例
```
.font20px {
    font-size: 20px;
}
```


## 背景の色を変える例
```css
body {
  background-color: #FFFFED;
}
```
色の参考

https://www.colordic.org/

## テーブルの２列目を非表示にする例
```css
   th:nth-child(2){ display:none; }
   td:nth-child(2){ display:none; }
```
|ポイント|解説||
|----|----|----|
|「th:」<br>「td:」|「th」タグに対して<br>「td」タグに関して|
|「nth-child(n)」|「n」番目(numberと番目を表すth)の要素<br>https://developer.mozilla.org/ja/docs/Web/CSS/:nth-child||
|display:none;|非表示||

## input type="text"の幅をテーブルの幅いっぱいにする例
```css
    input[type="text"] {
      width:100%;
      box-sizing: border-box;
    }
```
|ポイント|解説|
|----|----|
|box-sizing: border-box;|これを記述しないと線を含めないので、はみ出る。||

## 列のテーブル比率を変更する
```css
th.width15{
  width: 15%;
}
th.width10{
  width: 10%;
}
th.width5{
  width: 5%;
}
```
|ポイント|解説|
|----|----|
|th.width〇|thタグのid=width〇に対して幅のテーブル比率を〇％にする||

## レスポンシブ対応
```
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
```
## メディアクエリ
```
@media screen and (max-width: 600px) {
 処理
}
```
|ポイント|説明|備考|
|----|----|----|
|viewport|表示領域|何も設定しなかった場合、スマホで表示した際にデスクトップサイトの横幅にあわせた表示になる。<br>https://seolaboratory.jp/48581/|
|@media max-width: 600px|メディアクエリ|0～600px|

## URLの折り返し
```
  /*URLの途中で折り返す*/
  word-break: break-all;
```
|ポイント|説明|備考|
|----|----|----|
|URL|何も設定しないと途中で折り返さないためデザインが崩れる||
figma + SwiftUIでポモドーロタイマー作ってみた part1

## モチベーション
とにかく簡単にタイマーを作りたい。
せっかくバージョンアップしたxcodeを使ってあげたい。

### 使うものと作るもの
使うもの：sigma, SwiftUI(xcode)
作るもの：ポモドーロタイマー

figmaとSwiftUIとポモドーロタイマーの紹介。

figma

https://www.figma.com/

SwiftUI

https://developer.apple.com/tutorials/swiftui

ポモドーロタイマー

https://ja.wikipedia.org/wiki/ポモドーロ・テクニック

## figmaでデザイン

figmaにはiPhone用のデザインフレームがデフォルトで用意されているので、ここでは愛用のiPhoneSEを選択します。

![スクリーンショット 2021-09-28 21.24.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/adfccd6e-0f61-41d3-3d22-ac4d2757da55.png)

ざっくりイメージでテキストやボックスを置いていきます。

![スクリーンショット 2021-09-28 21.38.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/780c8ffa-ad28-2dae-0879-6f44632a0a82.png)

ボタンは文字よりマテリアルデザインのアイコンの方が目に入る情報量が少ない上に使いやすそうなので、ググったところGoogleが提供しているアイコンがすぐ出てきたので使うことにしました。

マテリアルデザインアイコン

https://fonts.google.com/icons

アイコンを配置して、素晴らしくシンプルになりました。

![スクリーンショット 2021-09-28 21.46.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/527e10ae-b2d2-d644-e999-1684cb4e18e1.png)

Googoleマテリアルデザインのアイコンは、 それぞれの開発環境から呼び出して使用できるので、ここで作ったモックと同じアイコンを使うことができます。

例として、Startアイコンを検索して、xcodeで使う場合のコードを確認しています。

![スクリーンショット 2021-09-28 21.48.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/d8c29901-1dc8-c3d3-cdf8-dcd9fc6990b9.png)

15分くらいでデザインは終わりにして、コードを書き始めます。

## SwiftUI
Flutterのおかげでxcodeの出番がめっきり減っていると思いますが、急に思い出したかのように使っていきます。

xcodeのプロジェクトを作り、タイマー機能を実装していきます。
xcodeの開発イメージはこんな感じです。

![スクリーンショット 2021-09-28 21.59.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/4f1cdfb7-87f5-0019-8a5a-2ee96182a406.png)

cocoapodsを使おうと思ったら、pod installでエラーが出る問題が発生。
M1 Macの問題だったので以下を参照してひとまず解決。

https://zenn.dev/akeome/articles/2433d792db022835c7e7

https://github.com/CocoaPods/CocoaPods/issues/10239

iconをxcodeに入れるよりappleのアイコンを使った方が早いので、方針を変えてsystemimageを使っていきます。

https://developer.apple.com/design/human-interface-guidelines/sf-symbols/overview/

以下のディベロッパーページからダウンロードすると、アプリとして実行できるアイコン一覧が手に入ります。このアプリ上のアイコン名をアプリの実装のために使用します。

![スクリーンショット 2021-09-29 0.31.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/1c586fdf-9c6c-fb8c-4482-03466762c278.png)


https://developer.apple.com/sf-symbols/

タイマーはTimeが上手いことやってくれそうなのでそのまま実装します。


```swift
//定義
class Timer : NSObject

//実装例
let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
```

https://developer.apple.com/documentation/foundation/timer/

https://www.hackingwithswift.com/quick-start/swiftui/how-to-use-a-timer-with-swiftui

タイマー動作はフラグ変数を使いながら制御しつつ、ボタンで再生や停止などの設定していきます。

```swift
//定義
struct Button<Label> where Label : View

Button(action: {
    // 実行したい処理
}){
    // ボタンの情報
}

//実装例
Button(action: {
    activeState = true
}) {
    Image(systemName: "play") //
   .imageScale(.large)
}
```

https://developer.apple.com/documentation/swiftui/button/


最終的なUI配置は以下の様になりました（超シンプル）。

![スクリーンショット 2021-09-29 0.26.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1707407/73ffd54d-ce20-83db-1f97-e174ccf01477.png)


調べながら1時間くらいでポモドーロの動作部分を作れました。
通知や音の実装は後回しにしたので、次回の課題にしておきます。

ソースは近日公開する予定です。
Dockerメモ

##### 注意：初心者のメモなので間違っていたり、理解が浅いものが多数あると思われます。

#Dockerとは

超簡単にいうと仮想化の技術。ただし、仮想マシンのような完全な仮想化できはなく、ホストOSの一つのOSを共有して利用しているので、完全仮想化より高速で軽い。コンテナは実行環境を他のプロセスから隔離して、その中でアプリケーション等を動作させる技術で、異なる計算機間で同じ構成の環境を簡単に構築できる。仮想マシンのように複数のOSを使うことはできないが、Linuxのカーネルを含まないことで軽量化され、可搬性が高い。Dockerfileとしてコード化することができるのでGitのレポジトリにソースコードと一緒に管理することができ、cloneやpullしたときにDockerfileからコンテナを作ることで開発環境まで構築できるようになる。

色々あったけど、結局は

- Dockerイメージを作れば、開発環境を構築する手間を省ける
- 開発環境と本番環境で全く同じ構成にできる

というのが便利らしい。



<参考文献>
https://udemy.benesse.co.jp/development/system/docker.html
https://tech-lab.sios.jp/archives/21675
<いい感じにまとめてくれてる記事>
https://qiita.com/gold-kou/items/44860fbda1a34a001fc1

# Docker Desktopのインストールのメモ

環境：Windows10 Pro

- WSLを有効化してUbuntu20.04を入れる。
- Windows Updateで詳細オプションにある「Windowsの更新時に他のMicrosoft製品の更新プログラムを受け取る」をオンにして更新を調べるとWSLのLinux Kernelが更新される。
-  `wsl --set-version Ubuntu-20.04 2`を実行するとwsl2を利用できる。上の更新ができていないとLinux Kernelの更新をしてくださいと出て怒られる。バージョンは`wsl -l -v`で確認できる。
- Windows proならHyper-Vを有効化、homeならCPU仮想化なんちゃらを有効化する。昔はhyper-Vは必須だったが、今はhomeでもDocker Desktopが使えるらしい。homeの方はうまくいくか未確認。
- Docker Desktopをインストール
- エラーなく起動できたらインストール完了

# Docker用語メモ（超雑）
- Docker レポジトリ:Dockerイメージを管理するところ。一つのレポジトリにはtagで管理されたイメージが保管されている。公式のレポジトリサーバーであるDocker Hubではレポジトリの保存ができる。
- Docker Image:コンテナを作るもの。必要な設定やコマンドがまとまっている。
- tag:イメージのバージョンを管理するもの
- コンテナ：イメージをもとに作られる仮想環境。ホストOSのカーネルを利用する。

# Dockerの使い方メモ
libraryにあるhello-worldイメージを持ってきて実行する。Ubuntuのイメージからコンテナを作り作業してレポジトリを更新する。

- Ubuntuを起動して`docker login`でログインする
- `docker pull hello-world`でDockerイメージを持ってくる
- `docker images`でイメージを見る
- `docker ps`で動いているコンテナの状況を見れる。止まっているコンテナも全部見たいときは`docker ps -a`で見れる。
- `docker run hello-world`でコンテナを作る。このコンテナは"Hello from Docker!"と出力してexitする。つまりrunコマンドはコンテナの作成＋実行を行っている。ちなみに作成と実行を別々に行うには`docker create <image>`と`docker start`を使う。ただし、ここで実行されるのはデフォルトのコマンド、Hello-worldでは/helloコマンドが勝手に実行される。
- `docker run -it ubuntu bash `でubuntuのイメージからubuntuのコンテナを作り、対話するためにbashを起動する。`docker run <image> <command>`とすることでデフォルトのコマンドを上書きして別のコマンドを実行できる。つまりubuntuイメージのデフォルトコマンドをbashに上書きして実行する。ただし、実はubuntuのデフォルトコマンドは/bin/bashだったりするので上書きする必要はない。ちなみに-itは-iはインプット可能、-tは表示をきれいにするオプションである。-iがあることでSTDINというチャネルをホストからコンテナに繋げることができる。よくわからなくてもおまじないだと思ってつけるといいっぽい。
- 作業を終えたら`exit`でコンテナから抜ける
- exitしたコンテナにもう一度入るときは`docker restart <container-id>`でexitの状態からup状態にできる。`docker ps -a`で状態を見れる。
- `docker exec -it <container-id> bash`で再度作ったコンテナからbashを起動する
- コンテナからイメージを作るときは`docker commit <container-id> <image-name>`でコミットできる。イメージの名前の後ろに:をつけると後ろはタグになる。
- Docker Hubで新しいレポジトリを作る。レポジトリ名は<username>/<repo-name>となる。
- イメージをレポジトリに上げるためにはレポジトリの名前とイメージの名前が一致している必要がある。`docker tag <source> <target>`で新しいイメージ名のイメージができる。古い名前のイメージもそのまま残っている。`docker images`でIMAGE IDを見ると同じIDになっている。
- `docker push <image>`でレポジトリにプッシュする。
- `docker rmi <image>`でローカルのイメージを削除できる。

# 最後に

DockerFileの詳細とかbuildとかまではまだ手をつけられていないので、そのうち勉強したらメモ書きとして残すかもしれない。機械学習の環境構築が大変だったり、Githubにあげられてるサンプルコードの実行環境用意するのが面倒だったりするので、自分でなにか作ったときはDockerfileから一発で呼び出せるようにしてドヤりたい。
要素を順番に切り替える

```jquery:jquery
var items = $('.items');
items.hide()
var num = -1;
function fadeinout() {
    num++;
    items.eq(num % items.length).fadeIn(500).delay(500).fadeOut(500, fadeinout);
 }

```

ーーーーーーーーーーーーーーーーーーーーーーーーーー


参考にしました

https://js.studio-kingdom.com/jquery/traversing/eq


https://www.jquerystudy.info/reference/effects/fadeOut.html
「未経験必見」Vimを使うことができるメリットまとめ（デメリットは書きません）

#最初に
Vimとは何なのか。エディターのことです。さくらエディタやらメモ帳などもエディタですが、Vimも、その中の一つです。そんなVimについてのメリットを簡単に紹介していこうかと思います。

#メリット

###キーボードのみで全て完結する
Macでいうところのターミナルを開く。Linuxコマンドを使い、編集したいファイルをVimで開く。ここまではキーボードのみで完結しますよね。Vimも同じで、Vimコマンドを駆使すればマウス移動なんてせずにファイル編集を終えることができるのです。マウス移動の、あの微妙な調整とかって個人的にですが意外とストレス溜まりやすいので超楽です。

そんなVimコマンドの解説はこちらのリンクがお勧めですね。
https://qiita.com/fasahina/items/2767891134028648f288?utm_source=Qiita%E3%83%8B%E3%83%A5%E3%83%BC%E3%82%B9&utm_campaign=e0351f3a19-Qiita_newsletter_369_07_10_2019&utm_medium=email&utm_term=0_e44feaa081-e0351f3a19-34949601


###サーバー内にssh接続しても今まで通りファイルを編集できる
先程の通り、キーボードで完結できるのでサーバー内でも同じことができます。Linuxコマンドで編集したいファイルをVimで開きVimコマンドを駆使してファイル編集完了。VimはcentosもAmazonLinux2も既存で入ってるので大抵のサーバーで最初からファイルを編集をできます。Vimって何だか凄いでしょ。

###ターミナルで基本生きていくのでプログラマー感はめっちゃ強い
Macでも開発できますし、Linuxパソコン買ったって開発できます。何ならラズパイだって無問題。コマンドさえ打てればね。黒い画面にひたすら何か打ち込むってちょっとかっこよくないですか。見た目って大事ですよ。まずは、見た目からお試しあれ。

###「未経験必見」Vimを使ってるだけで何だか未経験じゃなくなる
開発者でメインにVimを据えてる人は多くはないので、希少性が高く、何だか凄そう、Vimができるのであれば開発もできるよねってことで未経験の殻を破れます。少なくとも、僕が未経験エンジニアと一緒に開発することになって、その方がVimmerだったら期待しちゃいます。面接でVimを推していくってのもありなのではないでしょうか。

###噛めば噛むほど美味しくなる
Vimは正直言って最初はめんどくさいです。プログラミング以外でPCを触ってきてる方はよりめんどくさいと思います。ただ、慣れてくるとQiitaの記事書いてる時でもVimコマンドを押しちゃうぐらい中毒になってしまいます。僕もかれこれ2年ぐらい触ってますが、何でVimコマンド使えないんだよーっていう場面に遭遇することがあるのでVimはやっぱり便利なんだと思います。

#まとめ
Vimmerになってみませんか。
ABC175 C - Walking Takahashi に挑戦した

https://atcoder.jp/contests/abc175/tasks/abc175_c

![abc175_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1a405a32-4914-44ce-8672-6292fe8dd5a8.png)
![abc175_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/4db997b8-f447-31f0-0cf3-e1575a5771fb.png)
![abc175_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/2238b59d-f9e6-2ca2-e239-e2cf2844c162.png)

なんかコレ↓の類題じゃね？

https://qiita.com/AKpirion/items/85de771b6132535dde1a

有識者は最適解を求められるのだろうが、
私は一個一個場合分けしないと edge case を
網羅できる自信が無かった。

```WalkingTakahashi.py
x,k,d = map(int,input().split())
cnt = abs(x // d)
if x == 0:
    if k%2 == 0:
        print(0)
    else:
        print(d)
elif x > 0:
    if abs(k-cnt)%2 == 0:
        if k < cnt:
            print(abs(x-k*d))
        else:
            print(abs(x-cnt*d))
    else:
        if k < cnt:
            print(abs(x-k*d))
        else:
            print(min(abs(x-(cnt+1)*d),abs(x-(cnt-1)*d))) # <= ココ
else:
    if abs(k-cnt)%2 == 0:
        if k < cnt:
            print(abs(x+k*d))
        else:
            print(abs(x+cnt*d))
    else:
        if k < cnt:
            print(abs(x+k*d))
        else:
            print(min(abs(x+(cnt+1)*d),abs(x+(cnt-1)*d)))# <= ココ
``` 

手探り感、バリバリ(笑)
コメントにある **ココ** 、記述にあるように cnt+1 or cnt-1 は、その時の状況に合わせて
最小値を選択する必要がある。ここに気付くまでに WA を 2 回引いた。

もっとスマートに、サクッと出来るようになりたい。
まずは自力で辿り着けてホッとした。
[Docker]COPYとADDについて

# はじめに
本記事では、Dockerfileの`COPY`と`ADD`について記述します。

# COPY
`build context`にあるDockerfile以外のファイルをDocker imageやコンテナに持っていくことができる。

単純にファイルフォルダをコピーする場合。

```
COPY <ホストにあるコピーしたいファイル名> <コンテナ内にコピーしたものを入れるためのディレクトリ>
```

# ADD
tarファイルなど圧縮ファイルをコピーして使う場合。

## COPYの流れ
`build context`をもとに`Dockerdeamon`が`Dockerfile`から`Dockerimage`を作ります。

[ビルドコンテキストの理解](https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/dockerfile_best-practices/#%E3%83%93%E3%83%AB%E3%83%89%E3%82%B3%E3%83%B3%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88%E3%81%AE%E7%90%86%E8%A7%A3)より
> docker buildコマンドを実行したときの、カレントなワーキングディレクトリのことを ビルドコンテキスト（build context）と呼びます。

Dockerimageを構築するには、`Dockerfile`と`build context`を渡します。

そこからDockerimageを`docker run -it ~~`をすることで、
コンテナにてDockerfileを記述することができます。

今回は、`another`というファイルを一緒に起動します。
コンテナ内にもanotherを入れるために、`COPY`を記述します。

```
FROM ubuntu:latest
↑私は、ubuntuをよく使うのでこうします。

RUN mkdir /another_dir
↑コンテナ上で、another_dirというanotherファイルを入れるためのディレクトリを作ります。

COPY another /another_dir/
↑「build context」内にあるanotherをCOPYして、コンテナ内の「another_dir」にanotherを入れます。
```

```
% docker build .

% docker run -it image名 bash
```

このような流れになります。

## ADDの流れ
Dockerimageに移した時に、圧縮ファイルを解凍して、コンテナに渡します。

```
FROM ubuntu:latest
↑私は、ubuntuをよく使うのでこうします。

ADD compressed.tar /
↑tarファイルをDockerimageに移したときに解答して、コンテナに渡す。
```

```
% mkdir another_dir
ホストに「another_dir」というディレクトリを作ります。

% echo 'aaa' > aaa
「aaa」というファイルを作った上、「aaa」というテキストを入力しておきます。

% tar -cvf compressed.tar another_dir
「another_dir」を圧縮ファイルにする。ホスト上に「compressed.tar」が出来上がる

% docker build .
ここで、Dockerfileには、「ADD」の記載があるので、圧縮ファイルもimageへ。

% docker run -it image名 bash
コンテナにて解凍されたファイル「aaa」が存在でき、「another_dir」というディレクトリの中に入っている状態になる。
```

このような流れになります。

以上です。

# 終わりに
少しずつですが、インプットとアウトプットを交互にやり理解ができるようになってきました。
これも最高の講座に出会えたおかげや。。。

私の学習している動画はこちらです。(有料)
最高に分かりやすいのでオススメです。
米国AI開発者がゼロから教えるDocker講座

明日もDockerやってくぞー！
tmuxのバージョンを確認するコマンド

## 前説
以前にtmuxをインストールした記憶があったのですが、わけがわからずインストールしただけで終わってしまったのですが今回もう1回チャレンジしようと思いました。

そこでまずバージョンを確認しようと```tmux -v```と打つと

```bokunoMacBookAir.local:[0]      1:zsh*     [2021-09-28(火) 23:58]```

と表示されてビビりました。。tmuxが立ち上がったみたいで```tmux kill-server```で事なきを得ました。

## 本題
結論から申し上げると```tmux -V```です。pythonのバージョン確認も`python -V`と大文字Vを使いますが、この辺ってなんか思想があったりするんですかね...?

また参考文献にも書かれていますがサーバーが立ち上がった時点でカレントディレクトリにlogファイルが生成され、細かいログが残されていってますね。

参考文献：https://www.te-nu.com/entry/2017/07/19/210344
AWSでのLaravelプロジェクト作成時のエラー

composer コマンドでLaravelのプロジェクト作成時に何かしらの理由で、正常に作成されていなくてエラーが出てしまった時。

```$ cd ~/environment
$ rm -rf (プロジェクト名)
$ sudo yum -y install php73 php73-mbstring php73-pdo php73-mysqlnd
$ sudo alternatives --set php /usr/bin/php-7.3
$ curl -sS https://getcomposer.org/installer | php
$ sudo mv composer.phar /usr/bin/composer
```

上記コマンドで1回プロジェクトを消す。
再度プロジェクト作成する。
Databricks ReposにてAdd Git remote laterの設定で作成したレポジトリーをAzure DevOpsにおけるAzure Reposにコミットする方法

## 概要
Databricks Reposにて`Add Git remote later`の設定後のコミット先として初期状態のレポジトリーを指定する必要があるのですが、Azure Reposのデフォルト設定である`Add a README`がチェックされていることでエラーとなるため、その注意事項を共有します。

## 課題
Databricks ReposにてAdd Git remote laterの設定で作成したレポジトリーを、Azure DevOpsにおけるAzure Reposにコミットしようとすると下記のエラーが発生しました。

> Could not add repo. Make sure the repo doesn't have any previous commits.

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/77c989a3-d961-eae5-97c4-6863cae97d2e.png)


## 対応方法
### 1. Azure Reposにて、`Add a README`のチェックを外して、レポジトリーを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/6b8e2e8a-2c6b-25ef-31c9-8c07b45abcc9.png)

### 2. Databricks にて、レポジトリーを設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/52089daf-6284-ec0e-7202-1a1868c77277.png)

### 3. Databricksにて、変更内容をコミット
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/c107fc6f-352c-f913-467f-80a8a33b097d.png)

### 4. ファイルがコミットされたことを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/24031/036932fd-3fa7-33b2-23f4-299b7f2a78fe.png)
NestJSでシンプルなBasic認証

# 1. パッケージをインストール

認証ライブラリのPassport.jsと、Basic認証を使うのに必要なpassport-httpを入れます。

```shell
yarn add passport passport-http @nestjs/passport
yarn add -D @types/passport @types/passport-http
```

http://www.passportjs.org/

# 2. Basic認証のストラテジーを作成

```typescript:basic.strategy.ts
import {BasicStrategy as Strategy} from 'passport-http';
import {PassportStrategy} from '@nestjs/passport';
import {Injectable, UnauthorizedException} from '@nestjs/common';

@Injectable()
export class BasicStrategy extends PassportStrategy(Strategy) {
  constructor() {
    super();
  }

  validate(username: string, password: string): boolean {
    if (username === 'admin' && password === 'changeme') return true;
    else throw new UnauthorizedException();
  }
}
```

（ハードコーディングなので、`username`、`password`はconfigにするなりしたほうがよいでしょう）

# 3. Basic認証のGuardを作成

`AuthGuard('basic')`で直接利用できますが、`'basic'`がMagicStringになるため、Guardにします。

```typescript:basic-auth.guard.ts
import {Injectable} from '@nestjs/common';
import {AuthGuard} from '@nestjs/passport';

@Injectable()
export class BasicAuthGuard extends AuthGuard('basic') {}
```

# 4. Basic認証利用したいモジュールでimportする
Basic認証を利用したいモジュールに、以下のimportsとprovidersを追記してください。

```typescript:your.module.ts
import {Module} from '@nestjs/common';
import {PassportModule} from '@nestjs/passport';
import {BasicStrategy} from '@strategies/basic.strategy'; // 2で作成したファイル

@Module({
  imports: [PassportModule],
  providers: [BasicStrategy],
})
export class YourModule {}
```

# 5. ControllerでBasic認証を利用する

`@UseGuards(BasicAuthGuard)`のデコレータをつければ完了です。

```typescript:your.module.ts
import {Controller, Post, UseGuards} from '@nestjs/common';
import {BasicAuthGuard} from '@guards/basic-auth.guard'; // ３で作成したファイル

@Controller('sample')
export class YourController {
  @Post('/test')
  @UseGuards(BasicAuthGuard)　// ←これ
  restrictedRoute() {
    return true;
  }
}
```
【Jest入門】Errorの評価しよう~toThrow関数~

# JestでErrorを確認しよう
JestでErrorを評価する際は、```toThrow関数```を使用します。


## ```toThrow関数```
* [公式ドキュメント](https://jestjs.io/ja/docs/expect#tothrowerror)
* 正規表現: エラーメッセージがパターンに マッチする か検証します
* 文字列:エラーメッセージが文字列を含む か検証します
* error オブジェクト: エラーメッセージがオブジェクトのmessageプロパティと等しいかを検証します
* errorクラス： errorオブジェクトがそのクラスのインスタンスであるかを検証します
* 例外処理をテストする際は**無名関数でラップする**必要があります
    * その理由は、テスト対象の関数でエラーが発生すると、マッチャーのtoThrow関数が呼ばれる前に関数の実行が停止してしまい、ジェストがエラーを検証できなくなるためです

```javascript:
test("引数がないときにエラーを投げる", () => {
  class Foo {
    constructor({ message }) {
      this.message = message;
    }
  }

  expect(() => new Foo()).toThrow(); // ErrorがThrowされたかチェック
  expect(() => new Foo()).toThrow(TypeError); //型のチェック
  expect(() => new Foo()).toThrow(
    "Cannot destructure property 'message' of 'undefined' as it is undefined."
  ); //エラーメッセージのチェック
});
```

```sh:実行結果
npm test /Users/jest-basic/src/assertion.test.js

> jest-basic@1.0.0 test /Users/jest-basic
> jest "/Users/yoshihiro/jest-basic/src/assertion.test.js"

 PASS  src/assertion.test.js
  ✓ 引数がないときにエラーを投げる (9 ms)

Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        0.711 s, estimated 1 s
Ran all test suites matching
```
【Rails】ancestryを用いてエリアの登録(多階層、親-子)を行う

#はじめに

ancestryを用いてエリアの登録(親、子)を行ったので、まとめておきます。

#手順

1. Gemfileに記述する

```ruby:Gemfile
gem 'ancestry'
```
```ruby:ターミナル
$ bundle install
```

2.モデルの作成

```ruby:ターミナル
rails g model Region name:string ancestry:string
```

作成したマイグレーションファイルを開き、nameにnull: falseを指定する

```ruby:ターミナル
rails db:migrate
```

3.モデルの記述

```ruby:region.rb
has_ancestry
```

4.seedの作成

```ruby:db/seeds.rb
#親のレコードを作成
hokkaido, tohoku, kanto, chubu, kinki, chugoku, shikoku, kyushu  = Region.create(
  [
    { name: '北海道地方' },
    { name: '東北地方' },
    { name: '関東地方' },
    { name: '中部地方' },
    { name: '近畿地方' },
    { name: '中国地方' },
    { name: '四国地方' },
    { name: '九州地方' }
  ]
)
#子のレコードを作成
['北海道'].each do |name|
  hokkaido.children.create(name: name)
end

['青森県', '岩手県', '宮城県', '秋田県', '山形県', '福島県'].each do |name|
  tohoku.children.create(name: name)
end

['東京都', '茨城県', '栃木県', '群馬県', '埼玉県', '千葉県', '神奈川県'].each do |name|
  kanto.children.create(name: name)
end

['新潟県', '富山県', '石川県', '福井県', '山梨県', '長野県', '岐阜県', '静岡県', '愛知県'].each do |name|
  chubu.children.create(name: name)
end

['京都府', '大阪府', '三重県', '滋賀県', '兵庫県', '奈良県', '和歌山県'].each do |name|
  kinki.children.create(name: name)
end

['鳥取県', '島根県', '岡山県', '広島県', '山口県'].each do |name|
  chugoku.children.create(name: name)
end

['徳島県', '香川県', '愛媛県', '高知県'].each do |name|
  shikoku.children.create(name: name)
end

['福岡県', '佐賀県', '長崎県', '大分県', '熊本県', '宮崎県', '鹿児島県', '沖縄県'].each do |name|
  kyushu.children.create(name: name)
end
```

5.seedを読み込みなおし、コンソールでデータが入っていることを確認

```ruby:ターミナル
$rails db:migrate:reset
$rails db:seed
```

```ruby:ターミナル
$rails c
 > Region.all #全レコードを確認（数が多く、最後に[...]と表記があればOK）
 > Region.count #全レコード数を確認
 > Region.last #レコードの最後がseedの最後のデータであれば問題なく登録できている
```

他にも確認方法はあると思いますが、私はこれらで確認をしました。

#終わりに

ancestryを用いてデータの登録までできました。
ここからコントローラーやビューの定義をし、機能を実装していきます。
出来次第まとめます。

#参考

https://pikawaka.com/rails/ancestry
mapメソッドのまとめ

#はじめに
今日はmapメソッドについて学習したので内容をアウトプットしていきたいと思います。
最近、転職活動中で勉強時間に十分な時間を充てらなくもっと生産性を持って学習していきたいと思っている次第であります。

#mapメソッドとは
配列のArrayオブジェクトが持つメソッド。配列の全てのデータに対して指定した処理をおこない、新しい配列を作ることが可能。

>[MDNリファレンス](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/map)

#mapメソッドの使用例

__数字の配列に対して一つずつ２倍にして新しい配列を作りたいと思います。__

```javascript:エディター
var numbers = [1,2,3];
// ２倍した数字を置ける配列を作る
var doubledNumbers = [];

for(var i = 0; i < numbers.length; i++) {
    // 対象となる配列を２倍して配列に入れる
    doubledNumbers.push(numbers[i] * 2);
}

doubledNumbers;
```

```javascript:結果
[2,4,6]
```

__メモ書き__


```javascript:エディター
var numbers = [1,2,3];
// ２倍した数字を置ける配列を作る
var doubledNumbers = [];

```

なぜ新しい配列を作るのか？それに対してはすでにあるデータを変えるない方が良いとされている（ミューテート）。
numbersに元々入っていたものを変えてしまい[2,4,6]にして状態となっています。
大きな規模になるとnumbers = [1,2,3]が入っているもととしてプログラムを組んでしまった・・・。
しかし中身が変更されていたケースがあったりする。結果、意図しない動作になることもある。
つまり、元のデータを変えないようにすることが思考が必要である！

```
for(var i = 0; i < numbers.length; i++) {
 numbers[i] = numbers[i] * 2
}
numbers;
```

__では、mapメソッドで書いてみよう！！！__

```javascript:エディター
var doubled = numbers.map(function(number) {
    return number * 2;
})

doubled;

```
イメージとしてnumbers配列を２倍して新しい配列に渡される
![IMG_6831.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1572216/21fbd444-be57-27b9-b9a2-9a7e68f7d0a0.jpeg)

ポイントはreturnを忘れないこと！新しい配列に何を入れたら良いかわからなくなりnullが返ってくる。

```
return number * 2;
```
FastAPIのチュートリアルの環境構築

こちら
https://fastapi.tiangolo.com/ja/

1番最初のinstallをしようとしたところpipが入ってないと怒られたので、まずはpipをインストールした

```
$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py
$ python get-pip.py
$ pip -V
pip 21.2.4 from /usr/local/lib/python3.9/site-packages/pip (python 3.9)
```

これで完了した。


次の方をインストールしようとしたらまた怒られたので必要なものインストールする。

```
$ pip install uvicorn[standard]
zsh: no matches found: uvicorn[standard]

$ pip install uvicorn
```

これで問題なく進められるようになった。

ひとまず最低限の動作確認ができた
Expoで作成したiOSアプリでgoogle mapsを使う

# ライブラリを用意

react-native-mapsを利用します。

`expo install react-native-maps`でインストール（expoなのでlinkは行いません）

https://github.com/react-native-maps/react-native-maps

# GoogleMapsを有効化する(※Expoシミュレータのみで有効)

Expoシミュレータで利用する場合、MapViewのproviderをgoogleにするだけでOKです。
`<MapView provider="google" />`

[カスタムマップスタイルを利用したい場合](https://github.com/react-native-maps/react-native-maps#customizing-the-map-style)は、PROVIDER_GOOGLEを指定する必要があります。

```javascript
import MapView, { PROVIDER_GOOGLE } from 'react-native-maps'

// ...

<MapView
  provider={PROVIDER_GOOGLE}
  customMapStyle={MapStyle}
>
```

これでGoogleMapsが使えますが、このままStandaloneで動かそうとするとクラッシュします。

# Standalone版でGoogleMapsを動かす

AppleMapsでは不要ですが、iOSでGoogleMapsを利用する場合は、APIキーの設定が必要です。

https://docs.expo.io/versions/latest/sdk/map-view/#deploying-google-maps-to-a-standalone-app

## 1. Google Cloud APIプロジェクトの登録とMaps SDK for iOSの有効化

- ブラウザでGoogle API Managerを開き、プロジェクトを作成します。
- プロジェクトが作成されたら、そのプロジェクトでMaps SDK for iOSを有効にします。

## 2. APIキーを作成し、本番アプリ向けにキーを制限します

- Google Cloud Credential manager（APIとサービス）にアクセスし、[認証情報]、[APIキー]の順にクリックします。
- モーダルで [キーの制限] をクリックします。
- [アプリケーションの制限] で [iOS アプリ] ラジオ ボタンを選択します。
- [リクエストを受け入れる iOS アプリのバンドル ID] で [項目を追加] ボタンをクリックします。
- `app.json`の`ios.bundleIdentifier`（例：`com.company.myapp`）をバンドルIDフィールドに追加します。
- 「完了」をクリックした後、「保存」をクリックします。

## 3. プロジェクトにAPIキーを追加する

- `ios.config.googleMapsApiKey`フィールドの下の`app.json`にAPIキーをコピーします。
- コードの中で、`react-native-maps`から`{ PROVIDER_GOOGLE }`をインポートして、`provider=PROVIDER_GOOGLE`というプロパティを`<MapView>`に追加します。このプロパティは、iOSとAndroidの両方で動作します。
- アプリのバイナリを再構築します。設定がうまくいったかどうかをテストする簡単な方法は、シミュレータビルドを行うことです。

www.DeepL.com/Translator（無料版）で翻訳しました。
rbenvを利用してのrubyのインストールに失敗したときの対処　m1 mac macOS 11.6

#書いた理由
3日間くらいずっと詰まっていたのが解決したので、
同じ事象が起きている人に届けばと思い、以下に記載します。

#起こったこと

`rbenv install 3.0.2`

を実行したら以下のエラーメッセージでコケた


```
BUILD FAILED (macOS 11.6 using ruby-build 20210925)

In spect or clean up the working tree at/var/folders/62/ptdcgtz16zz093mpzzwmj_8w0000gn/T/ruby-build.20210928220009.63146.rhDrPV
Results logged to /var/folders/62/ptdcgtz16zz093mpzzwmj_8w0000gn/T/ruby-build.20210928220009.63146.log
```

#解決したこと
homebrewの再インストール

#参考にしたところ
Installation issues with Arm Mac (M1 Chip)
https://github.com/rbenv/ruby-build/issues/1691#issuecomment-751695485
ABC198 C - Compass Walking から学んだ

https://atcoder.jp/contests/abc198/tasks/abc198_c

![abc198_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/0615bfeb-f068-5f8d-45fb-52d96a4fb06f.png)
![abc198_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/76439b49-8a47-7efe-b475-2ca06de6c02f.png)
![abc198_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/3a59d3a8-b857-2cea-509a-1f574f7ca9d7.png)
![abc198_4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/737344/1fdfc8e8-4f88-4073-ea69-9f27bf95e854.png)

diff 茶色の洗礼か。
全く意味が分からない。

実は過去にも挑戦しており、当時解説を見ているはずだが、全く頭に入らなかった事を覚えている。
さて、今はどうだろう。

https://www.youtube.com/watch?v=wHgVlM0UVO4

かろうじて意味が分かった。
イメージしながら書いてみて、一応通った。

```CompassWalking.py
r,x,y= map(int,input().split())

#【重要】
# 二乗のまま使うことで、小数点の誤差を気にせず話を勧められる。
target = x**2 + y**2
ans = 1

#(ans**2)*(r**2) == target のとき、r を ans 歩で丁度ぴったりケースなら break
#(ans**2)*(r**2) >  target のとき、r を ans 歩で丁度超えたばかりのケースなら break
# ==> 丁度超えたばかりのケースを回答として使える理由は入力例 2 , 3 を見てほしい。
#     target を超えた 1 歩と、そのひとつ前の 1 歩を直線ではなく、組み合わせて迂回させることで
#     丁度 target につくことが出来る(問題文で小数点を許したのは、そういう意図か。。気付かなかった)。
while True:
    if (ans**2)*(r**2) >= target:
        break
    else:
        ans += 1

#解説にもある edge case に気を付けたい。最初の一歩が target とピッタリイコールなら問題ない。
#しかし、target を超える歩幅の場合はどうだろうか？その場合は ans = 1 ではなく、ans = 2 となる。
if ans == 1:
    if r**2 > target:
        ans = 2

print(ans)#87ms
```

解説を聞いた後に、自力でイメージを作りながら書いたが、
それでも悩みながら進めた。
大変勉強をさせてもらった 1 題であった。感謝。

***

あれからサッパリ忘れて再チャレンジ。
以下で通った。

```abc198c.py
R,X,Y = map(int,input().split())
dis = (X**2 + Y**2)**0.5
if dis%R == 0:#数歩でピッタリな場合
    print(int(dis//R))
elif dis < R:#一歩未満にgoalがある場合
    print(2)
else:#上記以外
    print(int(dis//R+1))#27ms
```

一歩未満にゴールがある場合を思いつくまで WA を引いてしまった。
一発で AC となりたいところだ。
DMM WEBCAMPで行ってきたことを振り返る

## 目次
- 概要
- 在学中の過ごし方について
- 実施したこと
- 就職後の在り方
- あとがき

※学習については一切記載していません。ただのポエムです。

## 概要
私は2021年の6月よりDMM WEBCAMPというスクールに通い、プログラミングの勉強をしています。（以下同期は6月生と記載）
4カ月のコースに通っていて、残すところあと3日。
来月から本格的に就職活動を行っていくという状況です。
現在32歳ですので、これからエンジニアのキャリアを踏む人間としては相当高齢な部類だと思います。
ここではスクールのご紹介をしたいわけではなく、ただひたすら私が何を考えていたのかということを記載しています。
自己分析してたんだな、とさっくりご笑覧ください。

### DMM WEBCAMPへ決めた理由
ざっと下記のようなことが理由です。
後述するshuffleというコミュニティに入ってからは、**生涯、切磋琢磨できる仲間を求めていた**ということに気づきました。

- 教育訓練給付金制度の対象であること（最大70%支給）
- 大手であること**（人が集まる）**
- 入校前の選考で落ちている人がいるらしい（=やる気ない人はいない？）
- チーム開発があること
- 親会社のDMM.comが[42Tokyo](https://42tokyo.jp/)のfounding sponcerでもありノウハウの共有に期待していた（学生だったら42Tokyoの選考にチャレンジしてたと思います。）



## 在学中の過ごし方について
私の場合、振り返るとこのようなフェーズで推移していました。

- 仲間づくり
- ポートフォリオ制作
- 就活

### 仲間づくり
大きく1～2カ月目は仲間づくりに終始していたように思います。
スクールが用意してくれた、毎日進捗を確認し合うデイリースクラム、チーム開発という場。この2つに全力で取り組むことで仲間の仲間……という形で輪が広がりました。
私は前職で率いることも、先輩になるという経験すらほとんどなかったので、どのタイミングでも手を挙げて、リーダーとしての役割をやらせてもらいました。
仲間づくりの一番の契機はshuffleという、DMM WEBCAMP在校生の有志（今は現役の方も所属）で構成しているコミュニティに入ったことです。Twitterで勉強記録etcを呟いていたところ、声をかけてもらい参加。
連絡を取り合っていた仲間にも参加してもらって、6月生が11人、全体では33人在籍しています。
ここでも運営かつ6月生のリーダーとしているので、仲間に何か出来ることがないか日々考えています。（行ったことは後述）

### ポートフォリオ制作
3カ月目にはポートフォリオ制作を行いました。
就職活動を行う際の技術証明というより、作りたいものを表現する機会、日々感じている課題に提案するんだという気持ちで臨んでいました。
詳細は・・・長くなりそうなので別記事とさせてください。

オーケストラの出欠入力サイト、Otoderu。ご意見頂戴できれば幸いです。
URLは[コチラ](https://otoderu.com/)
GitHubは[コチラ](https://github.com/sagittarius3008/Otoderu)

### 就活
4カ月目は新しい言語を学びつつも、就活への準備期間の位置づけです。
まだ本格的に面接等々始めていないので、大きなことは言えないのですが、新卒のときの経験と、沢山の卒業生からの体験談をもとに就活対策を進めています。
自分自身を振り返ることと同じくらい他者からの視点が大切だと思っているので、仲間の手も借りてお互い良い状態に持っていけるよう努力しています。
これも就活が終わったら体験談という形にしてみたいです。

## 実施したこと
仲間が少しでも良い形でエンジニアとしてのスタートを踏めるように沢山の企画等を行ってきました。太字が私の企画によるものです。（ネーミングセンス……）


| 日付 | 出来事 |
|:-:|:-:|
| 6月1日  | DMM WEBCAMP開始  |
| 6月9日  | 1カ月目デイリースクラム開始  |
|  **6月27日** | **1カ月目お疲れ様会**  |
|  7月10日 |  チーム開発スタート |
| 7月16日  |  shuffle参加 |
| **7月17日**  | **現役エンジニアとQA→仲間に共有**  |
| 7月22日  | shuffle交流会  |
| **7月29日**  | **チーム開発振り返り会**  |
| **8月13日**  | **PF進捗報告会**  |
| **8月23日**  | **PF相談会**  |
| **8月28日**  |  **先輩との就活QA会→共有** |
| 8月29日  | shuffle音楽部オフ会  |
| **9月4日**  | **shuffle交流会**  |
| **9月11日～（毎日）**  | **もくもく会**  |
| **9月18日**  | **履歴書添削会**  |
| **9月25日**  | **面接対策会**  |
| **10月4日**  | **職歴を使ったQA会**  |
| **10月5日～（毎日）**  | **有志面接練習**  |
　
結果的にスクールの企画と内容がかぶることも多かったですが、仲間内でお互いを理解しているからはっきり言い合えたり、バックボーンまで踏み込んだりと効果は大きかったように思います。
企画する側としても仲間の進捗具合を見計らって機動的に各企画を実施できたと自負しています。
shuffleという形を得てから動きやすくなった面が多々あり、創設者のhikaruさんには大変感謝しています。

## 就職後の在り方
最近、少し気持ちに変化がありました。
当初、全て自分の手で作れるようになりたいと思っていたのですが、仲間を見て企画立案をするうちに、やり遂げたいことをトータルで達成できればいいという考え方に変わってきました。
前提として、自分自身が研鑽を続けることは変わりません。
ただ、人を巻き込んだり、もしくは巻き込まれたりといった、協力することに魅力を感じてきています。
というより正しくチームで開発をするということがイメージ出来てきたのだと思ってます。
私自身が求められ、最も力を発揮できる部分でチームに貢献し続けたいと考えています。

今いるshuffleというコミュニティについても、卒業したら終わりではなく、お互いの強みを持ち寄り続ける関係でいられたらいいなぁと思ってます。
誰かのこれ作ってみようよ！というのに有志で作ってみるというのは個人的にはちょっと夢ですね。

## あとがき
ただのポエムどころか、所属するコミュニティへの想いを打ち明けるだけになってました。いかにも大きな声で書いてしまったのですが、完全に私見です。
多少の図々しさと自発的な行動が大切だなと思えたことがスクールに通っていて一番実感したことです。
昨今スクールへの見方は厳しくなってきていますが、それすらも結局は自分で考えて何をしたか、それだけなんだろうなと思ってます。
（こいつ、就職してもいないのに偉そうだなぁ。。）

最後まで目を通して頂き、ありがとうございました。
G検定-機械学習の代表的な手法

## 機械学習の種類

* 教師あり学習：正解データが未知であるサンプルに対して、その値を予測するモデルを得る。
* 教師なし学習：データに共通する特徴的な構造や法則を見つけることを目的とする。
* 強化学習：エージェントが自身の報酬を最大化するような行動指針を獲得する。

## 教師あり学習

教師あり学習は大きく「分類問題」と「回帰問題」に分けることができる。
分類問題では正解データが質的変数（カテゴリ）であり、回帰問題では量的変数（連続値）となる。

教師あり学習の代表的な手法：

* 線形回帰
* 正則化
* ロジスティック回帰
* サポートベクターマシン（SVM）
* k近傍法
* 決定木
* ランダムフォレスト
* 勾配ブースティング
* アンサンブル学習
* ベイズの定理
* 最尤推定

## 教師なし学習

教師なし学習は、正解ラベルがないデータを学習し、データに共通する構造や法則を見つけ出すことを目的としている。
その例としては「クラスタリング」や「次元削減」、「確率変数の密度推定」などが知られている。

* クラスタリング：データを複数のグループにまとめる。
* 次元削減：データをより少ない変数で要約する。

教師なし学習の代表的な手法：

* k-means法
* 階層的クラスタリング
* 主成分分析
* オートエンコーダ

## 強化学習

強化学習は、一連の行動の結果の「報酬」を最大化するように学習を行う枠組である。
強化学習では（状態数）×（行動の種類数）のパターンを考慮しなくてはならないため、組合せ爆発への対処が課題となる。
つまり、どのように状態を低次元で表現（縮約）するかが課題となる。
近年では、深層学習における隠れ層（中間層）の出力を縮約表現とみなす「深層強化学習」が注目され、ボードゲームのAIや自動運転に応用されている。
React Native(Expo)用にEslint,Prettierの設定をする

プロジェクト毎に設定するが、毎回忘れてしまうため自分用のメモとして作成
[TypeScript用の設定はこちら](https://qiita.com/icryo/items/9b76ea15bc5dd749daa6)

##ESLintとは
Javascriptの静的検証ツール
ESLintを使用すると、誤字、セミコロン、クオート、未使用の変数やブロックなど開発中に気づきにくいミスが見つけやすくなります。

##ESLintの導入
###VSCodeの拡張機能からESlintをインストールする
![スクリーンショット 2021-09-28 23.25.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927110/caab7eac-85f6-f58a-0bdf-491fffc7feb9.png)

###インストール

```
yarn add -D eslint eslint-plugin-react-hooks
```

###初期設定
初期化して.eslintrc.jsファイルを生成

```
npx eslint --init
```

以下の設定で、質問に答えていく

```
√ How would you like to use ESLint? · To check syntax, find problems, and enforce code style
√ What type of modules does your project use? · JavaScript modules (import/export)
√ Which framework does your project use? · react
√ Does your project use TypeScript? · Yes
√ Where does your code run? · node
√ How would you like to define a style for your project? · prompt
√ What format do you want your config file to be in? · JavaScript
√ What style of indentation do you use? · 4
√ What quotes do you use for strings? · single
√ What line endings do you use? · unix
√ Do you require semicolons? · Yes
```

###.eslintrc.js を修正

```js:.eslintrc.js
module.exports = {
  env: {
    es2021: true,
    node: true,
  },
  extends: [
    'eslint:recommended',
    'plugin:react/recommended',
    'plugin:@typescript-eslint/recommended',
    'prettier',
  ],
  parser: '@typescript-eslint/parser',
  parserOptions: {
    ecmaFeatures: {
      jsx: true,
    },
    ecmaVersion: 12,
    sourceType: 'module',
  },
  plugins: ['react', '@typescript-eslint', 'react-hooks'],
  rules: {
    indent: ['error', 2],
    'linebreak-style': ['error', 'unix'],
    quotes: ['error', 'single'],
    semi: ['error', 'always'],
    'react-hooks/rules-of-hooks': 'error',
    'react-hooks/exhaustive-deps': 'warn',
    'react/display-name': 0,
    'react/prop-types': 0,
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
};
```

##Prettierとは
コードフォーマッター（ソースコードを整形してくれるツール）のこと。読み方はプリティア。

##Prettierの導入
###VSCodeの拡張機能からPrettierをインストールする
![スクリーンショット 2021-09-28 23.27.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/927110/8df93c1e-14ab-24b9-2ba5-47cdbf6f297e.png)

###インストール

```
yarn add -D prettier eslint-config-prettier eslint-plugin-prettier
```
###.prettierrc.js を追加

```js:.prettierrc.js
module.exports = {
  jsxSingleQuote: true,
  singleQuote: true,
  trailingComma: 'all',
  printWidth: 100,
  endOfLine: 'lf',
};
```



##.vscode/settings.json を追加
これを設定することで、Ctrl＋sでファイルを保存する際にコードフォーマットしてくれるので便利

```json:settings.json
{
    "editor.formatOnSave": true,
    "editor.defaultFormatter": "esbenp.prettier-vscode",
    "editor.codeActionsOnSave": {
        "source.fixAll.eslint": true
    },
}
```
pyenv on Mac 忘備録

環境: macOS BigSur 11.4

基本はこの記事を参考

https://qiita.com/crankcube/items/15f06b32ec56736fc43a

# pyenv の環境変数

bash派は `.bashrc` に下記を追記。

```bash:~/.bashrc
#export PATH="${PYENV_ROOT}/bin:$PATH"
export PYENV_ROOT="${HOME}/.pyenv"
export PATH="${PYENV_ROOT}/shims:$PATH"
eval "$(pyenv init -)"
```

(もちろん追記後は `source ~/.barshrc` )
~~`brew install pyenv` でインストールすると `~/.pyenv/bin` ディレクトリの代わりに `~/.pyenv/shims` ができる。~~
以前までは `~/.pyenv/bin` だったディレクトリが最近の pyenv では `~/.pyenv/shims` に変更された（？）。
`export PATH="${PYENV_ROOT}/bin:$PATH"` のままだと pyenv 上でバージョンが切り替わっても実際には切り替わらない。
"SQLSTATE[HY093]: Invalid parameter number"あるある

PHPからPDOのPrepared Statementを使ってMariaDBを操作してると、たまに遭遇するのが表題のエラー。
何がどうあかんのか具体的に教えてくれないので、意外とハマりがちでして。

以下、筆者が経験的にマスターしたエラーの原因あるあるを。

***
#### 1. パラメータ名が間違っている ####
今一度、落ち着いて確認しましょう:sweat_smile:
***
#### 2. （SQL実行を連続で記述しているとき）直前のprepareが抜けている ####
同上。
***
#### 3. SQLの指定が間違っている ####
これ、意外と分かりにくいんですよね。
MariaDBは、下記の方法で再起動することなくクエリーログを取得できます。
ここで実際にPrepareされたSQLの内容が分かるので、実際の値を当てはめて指定内容が正しいか確かめるとよいでしょう。

①Mariadbにrootでログインして、以下のコマンドを実行します。
```
SET GLOBAL general_log = 'ON'
```
:::note warn
該当のMariaDBエンジンを使ってる全データベースでクエリーログを取得する（＝オーバーヘッドが増える）ので、テストサーバーなどを用い、ほかのプログラムに影響を与えないよう配慮の上実行します。
:::
②次のコマンドを実行して、状態やログファイル名を確認します。
```
SHOW VARIABLES LIKE 'general_log%'
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/170624/a483c106-e2ea-8001-214f-4c7a478abeec.png)
::: note info
当該ログは一般に、CentOS7では/var/lib/mysql/配下に、Windowsであればmysql\data\配下に、ホスト名.logのファイル名で出力されます。
:::
③デバッグが完了したら、必ず次のコマンドを実行してログ出力を止めます。
```
SET GLOBAL general_log = 'off'
```
***
#### 4. PDO接続時のATTR_EMULATE_PREPARESオプション：Falseのとき、文字通り実際に実行されるSQLと割り当ててるパラメータの数が異なる ####
以下に２パターン挙げましたが、いずれもATTR_EMULATE_PREPARESパラメータ：Trueの時はパスしました（PDOのデフォルトはTrue）。
不足はまだしも、パラメータを過剰に与えてもあかんようでして、開発途中で上記オプションを変えるときは十分ご注意を。

①よくあるパターン１
``` PHP
$sql  = "SELECT * FROM tbl1 ";
if (条件) {
    $sql .= "WHERE a = :item1 ";
} else {
    $sql .= "WHERE b = :item2 ";
}
$smt->prepare($sql);
$smt->bindvalue("item1", $item1, PDO::PARAM_STR);
$smt->bindvalue("item2", $item2, PDO::PARAM_STR);
・・・
```
ってやりがちなんですが、面倒でも
``` PHP
$smt->prepare($sql);
if (条件) {
    $smt->bindvalue("item1", $item1, PDO::PARAM_STR);
} else {
    $smt->bindvalue("item2", $item2, PDO::PARAM_STR);
}
```
などとせねばならないようです。

②よくあるパターン２
``` PHP
$sql  = "SELECT * FROM tbl1 ";
$sql .= "WHERE id = :id ";
$sql .= "UNION ";
$sql .= "SELECT * FROM tbl2 ";
$sql .= "WHERE id = :id ";
$smt = $mdb=>prepare($sql);
$smt->bindValue("id", 3, PDO::PARAM_INT);
・・・
```
も、面倒＆ブサイクですが
``` PHP
$sql  = "SELECT * FROM tbl1 ";
$sql .= "WHERE id = :id1 ";
$sql .= "UNION ";
$sql .= "SELECT * FROM tbl2 ";
$sql .= "WHERE id = :id2 ";
$smt = $mdb=>prepare($sql);
$smt->bindValue("id1", 3, PDO::PARAM_INT);
$smt->bindValue("id2", 3, PDO::PARAM_INT);
```
としたら解決しました。