OmniAICreator/Qiita-1.07M huggingface dataset:
GitLabをAWS上で動かす(1/3)

# 背景
私「ソース管理でBacklogは嫌です。GitLabが良いです！！」
上司「じゃあGitLabで良いからサーバー立てたり設定したりよろしくね。」

雑な経緯。
ということで、社内開発でBacklogからGitLabを使用することになり、GitLabサーバーをAWS上に建てることになりました。
社内で今までAWS上でGitLabを利用していなかったため、少しでも後続の人たちの手助けになれればと。。。

# AWSでEC2インスタンスを作成する(VPC周りは省略)
いきなり省略していますがEC2インスタンスを作成するところから始めます。

### リージョン選択
アジアパシフィック（東京）を選択

### EC2の管理画面へ
サービスのコンピューティングから「EC２」を選択

### いざ、EC2インスタンスを作成

#### AMIの選択<br>
<img width="1973" alt="スクリーンショット 2019-03-06 8.01.06.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/c7461e72-792e-be8e-d059-3afc640f8066.png">

#### インスタンスタイプの選択<br>
<img width="2218" alt="スクリーンショット 2019-03-06 8.02.35.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/d68a549d-f43f-c439-dc9c-8d0ee8bcdc91.png"><br>
t2.mediumを選択します。<br>
最初に無料利用枠の対象の「t2.micro」を選択してインストールしてーーーと後続の作業をしていたのですが、下の画像のようにインストールが終了しても返ってこない。<br>
<img width="1218" alt="スクリーンショット 2019-03-06 8.05.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/83950d51-3db0-811e-efad-fcf0e6849d16.png"><br>
別タブでssh接続しようとしても接続されないなど完全に応答が・・・(._.)<br>
調べてみるとサーバーのメモリが足りなく、GitLab構築には1GB以上のメモリが推奨されている様で。<br>
なので少し余裕を見て「t2.medium（メモリ4GiB）」を選択しました。

#### インスタンスの設定
「ネットワーク」「サブネット」をVPC作るときに作成したものを選択。<br>
他にも「削除保護の有効化」に☑入れときます。

#### ストレージの追加
<img width="1015" alt="スクリーンショット 2019-03-06 8.16.53.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/3789de8d-aa7e-ac01-47e1-0846a4049870.png"><br>
30GBまで無料とのことなので、30GBで設定。

#### タグの追加
<img width="1283" alt="スクリーンショット 2019-03-06 8.18.45.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/59d819ec-1bc0-9ecc-b43b-876f29a93019.png">
雑にNameを付けていきます。

#### セキュリティグループの設定
<img width="2219" alt="スクリーンショット 2019-03-06 8.24.07.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/59d0de1d-8646-7978-e506-a8314063bcc5.png"><br>
設定は管理者に確認を。

#### インスタンス作成の確認
これまでの設定が一覧で表示されるので、これでいいなと思ったら右下の「起動」ボタンをクリック

#### 既存のキーペアを選択するか、新しいキーペアを作成
こちらも管理者に確認を。

以上で、EC2が作成できました！
インスタンス一覧に作成したEC2インスタンスが表示されているでしょう。
インスタンスの状態が「runnning」に、「ステータスチェック」が終了するまで待ちます。

<img width="2020" alt="スクリーンショット 2019-03-07 8.21.51.png" src="https://qiita-image-store.s3.amazonaws.com/0/218879/51ac629e-2ea4-7f73-df9e-d3e6442b309a.png">
※ Name(test)とインスタンスタイプ(t2.micro)はそれぞれ置き換えてください。

---

今回は以上です。
次回はElasticIPの接続とAWSサーバーにsshログインするところまで

☞ GitLabをAWS上で動かす(1/3)
[GitLabをAWS上で動かす(2/3)](https://qiita.com/C910/items/1c54615f1202d19f2ff1)
[GitLabをAWS上で動かす(3/3)](https://qiita.com/C910/items/217e7df50a37e10b781b)
windowsの環境変数いじってて、OpenSSHのパスを消してしまったとき

# 概要
opencvをVisual stdioで使いたくて、環境変数をいじっていたらシステム環境変数のPathをすべて消してしましました。raspberry pi上のファイルを編集するときに、sshで入り編集したファイルを実行していたので、困ってしましました。解決方法としては、消してしまったのなら、また書いてやるか、直打ちしてあげればSSHできます！

# 実行環境
次に実行環境を示します。

| Soft and Hard       |       バージョン | 
|:-----------------:|:------------------:|
| Windows10         |              1809 |  


# 解消方法
解消方法としては、環境変数を新たに加えるか、直打ちでSSHする方法の2つの方法があります。

- 環境変数を新しく編集する
-　直打ちでSSHする

以下に上記の方法について手順を示します。

## 環境変数を新しく編集する
自分の場合は、システム環境変数のPathを消してしまったので、そこに新しくSSHのパスを通してあげます。環境変数の編集は色々参考になるものがあると思うので、調べながら進めてください。Windowsの上記に示したバージョンのOpenSSHのパスは以下のようになってると思います。このパスを環境変数のPathに追加することによって、sshが実行できるようになります。

```
%SYSTEMROOT%System32\OpenSSH\
```

上記の"%SYSTEMROOT%"とはWindowsの導入フォルダの場所を示す環境変数のことです。つまり、"\C:\Windows"のことです。

## 直打ちでSSHする
コマンドプロンプトで、SSH.exeを実行します。パスを通さないと実行できないので、絶対パスでも相対パスでもexeの前にパスを書いてあげます。

```bash:
PS C:\Users\'ユーザー名'> C:\Windows\System32\OpenSSH\ssh.exe 'いつもの引数'
```

# まとめ
環境変数のPathを消してしまった時は、かなり気分が落ちました。でも、実行できたからOK！
Google スプレッドシートを python3 で 代入・更新

 こちらで行うのと同様のことを python3 で行いました。
[Google スプレッドシートを curl で 代入・更新](https://qiita.com/ekzemplaro/items/af1be5784202508e972d)

```py:sheet_create.py
#! /usr/bin/python
#
#	sheet_create.py
#
#					   Mar/06/2019
#
# ------------------------------------------------------------------
import  sys
import  requests
# ------------------------------------------------------------------
def file_to_str_proc(file_in):
	str_out = ""
	try:
		fp_in = open(file_in,encoding='utf-8')
		str_out = fp_in.read()
		fp_in.close()
	except Exception as ee:
		sys.stderr.write("*** error *** file_to_str_proc ***\n")
		sys.stderr.write(str (ee))
#
	return	str_out
# ------------------------------------------------------------------
sys.stderr.write("*** 開始 ***\n")
#
access_token="*****"
#
spreadsheet_id="*****"
url_sheets="https://sheets.googleapis.com/v4/spreadsheets/"
url = url_sheets + spreadsheet_id + ":batchUpdate"
#
file_in=sys.argv[1]
json_str = file_to_str_proc(file_in)
#
headers = {'Authorization': 'OAuth ' + access_token}
headers['Content-Type'] = 'application/json'
rr=requests.post(url,headers=headers,data=json_str.encode('utf-8'))
print(rr.status_code)
# print(rr.text)
# print(rr.url)
#
sys.stderr.write("*** 終了 ***\n")
# ------------------------------------------------------------------
```

実行結果

```text
$ ./sheet_create.py cities.json 
*** 開始 ***
200
*** 終了 ***
```

次のバージョンで確認しました。

```text
$ python --version
Python 3.12.7
```
Clojure tap のメモ

Clojure 1.10 で **[tap](https://clojure.org/reference/repl_and_main#_tap)** が追加されたのでちょっと試してみる。


```clj
;; `add-tap`で関数を追加していないので何も起こらない
(tap> "foo")
;; => true

;; println を tap に追加
(add-tap println)
;; => nil

;; 標準出力に "foo" が出力される
(tap> "foo")
;; => true

;; もう一度 println を追加してみる
(add-tap println)
;; => nil

;; 標準出力に "foo" が出力される(2回出力されない)
;; 関数は (atom #{}) への conj で追加されるため、１つに保たれる
(tap> "foo")
;; => true

(defn print-class
  [x]
  (println "class:" (class x)))
;; => #'tap-example.core/print-class

;; 他の関数を追加
(add-tap print-class)
;; => nil

;; 標準出力に以下が出力される
;; java.lang.String
;; foo
(tap> "foo")
;; => true

;; print-class 関数を tap から削除
(remove-tap print-class)
;; => nil

;; 標準出力に "foo" のみが出力される
(tap> "foo")
;; => true

;; 関数は (atom #{}) への disj で削除されるため、エラーは発生しない
(remove-tap print-class)
;; => nil

```

現状、利用できる関数は `tap>`, `add-tap`, `remove-tap` のみで、登録した関数のリストを取得したり、一括して削除する方法は提供されていない模様。

----
以上
[Doc] 業務フローを書く

# 業務フローとは

業務フローとは文字のごとく、業務のフローを表すものです。

# なぜ業務フローなんてものに時間をかける？
なぜ、私たちが業務フローなんて気にする必要があるのか。それは既存の業務フローを整理しないと価値あるシステムが提案できないからです（＋業務フローを知らずに要件定義を書くことができないからです）。

# 基本

業務フローは難しく考える必要はありません、基本を抑えれば簡単です。

## 始まりと終わり

まずは業務の始まりと終わりをを明示します。どうやって始まって、どうやって終わるのか。誰が見てもわかるようにしておいてください。

## フロー

当たり前＋文字通りですが、フロー、このタスクが終わったら次どうなるのか、これを明示します。フローには数字やアルファベットなどを振って補足分や説明するときにわかりやすくしておきましょう。

## 条件分岐

どういう条件の時次のタスクへ行けるのか、行くのか。これを明示します。条件は曖昧なく、もれのないように定義してください。 A or Bという分岐なのにCというオプションがないように、網羅が大切です。

## スイムレーン

業務を行うチーム、区分、部署を明示します。業務の量が少ない、もしくは登場回数が少ない部署に関しては、浮島と言って四角で囲って浮かしてしまうような手法をとってコンパクトにすることも有効的です。

## 読み手を考える

読み手のリテラシー、事前知識などをくみ取って、とにかく業務の図をみてわかりやすい用に工夫をしてください。

# 業務フローステップ

## 1. ヒヤリング

業務に関わるメンバーから業務のヒヤリングを行います

## 2. スイムレーンの作成

業務に関わるメンバーをグルーピングし、スイムレーンを作成します。

## 3. 下記の図を使って業務を書き起こします。

簡易な業務フローであればパワーポイントでも簡単にかけます。よりアドバンスなものや、多くの業務フローを書く必要がある場合は、Visioなどの特殊ツールを使うと効率アップです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/ed285c9f-320c-1837-9f2d-7f39cf78eacc.png)

### 始まりと終わり

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/4bc92992-3518-0796-ddcb-10d27c834beb.png)

### 処理

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/84220d19-29c6-75e6-b66c-3d3f5e60c54f.png)


### 分岐

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/c8f7e8f0-8e1a-e4f1-4a3f-7a10cc358929.png)

ほぼこの3つで業務を表現することができます。その他にもフローチャートグループにある図全てを業務フローでも使うことができますが、それはまた別の機会に説明します。

# 例

簡単な例として、販売サイトから受注してから発送するまでのフローを書いています。

登場人物は、サイト運用チーム、商品梱包チーム、商品配送チーム、配送会社、在庫管理チームになります。　まずはスイムレーンを作成。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/5e7f18b9-9374-a58b-6cdb-2b80b357c7ff.png)

業務フローをまず言葉で表現すると、

1. サイトで注文が行われ、注文受注メールがサイト運用チームへ。
2. サイト運用チームは受注メールを受けて、内容を確認してから倉庫に配送リクエストをメールで送ります。
3. 梱包チームは依頼をうけて、商品を探し梱包、梱包完了した旨配送チームに連絡。
4. 配送チームは宅配会社のシステムより伝票を印字。
5. 配送チームは集荷依頼を宅配会社にかける
6. 配送会社が集荷にきて配送

となりますので、はじめの受注メールから配送が始まるところまでの処理を書込みます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/b69595d6-f805-181c-c291-b5b0056f7a9b.png)

あとは順番にフローを作成します。受注メールを確認して、梱包チームに梱包と配送依頼を出すというフローを追加します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/da2e8f28-4eb3-776f-5fc0-1c5667da1268.png)

次に梱包完了の連絡と配送用伝票を印刷、配送会社の依頼、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/241909/6dd355a9-3450-a041-d66b-317207fc898b.png)


と、こんな感じでございます。今日は以上です。（在庫管理チームのスイムレーンには今回なにもないのですが、次回にもっと複雑なフローを入れていきます）
引数の追加(Add Parameter)

![image.png](https://qiita-image-store.s3.amazonaws.com/0/257568/fdaf5b9d-a029-52fa-35b6-44022684defa.png)


1つずつリファクタリング技法まとめ
個人的に簡単かつ取り入れ易いと思うものから

## 目的
すぐ引き出せるようにする

## 基本作業サイクル
- システムを動かして仕様を精査
- テストメソッドを作成
- テストの失敗を確認
- テストの成功を確認
- 小さい変更、随時テスト実行(パターン追加失敗確認->成功確認)
- 最後テスト実行
- 最後動作確認

## 引数の追加(Add Parameter)とは
メソッドを変更するにあたって以前渡されていなかった情報が必要になり、引数を追加するもの
 
## ポイント
- 他の選択肢があることが多く、その場合は他の選択肢を選択した方が良い
- 既存で引数がある状態から追加する場合、「引数オブジェクトの導入」が適用できないか検討する
- 同じシグネチャのメソッドが存在しないか確認する(同じように追加する必要がある可能性がある)

## 例

```
def load_file
  local = make_local_file
  load(local)
end
```
　　　↓

```
def load_file(local)
  load(local)
end
```

## 書籍情報
Jay Fields (著), Shane Harvie (著), Martin Fowler (著), Kent Beck (著),
長尾 高弘(訳), リファクタリング:Rubyエディション
https://amzn.to/2VlyWML

## 雑感
処理の債務的に外から引数として渡るべき、という時くらいでそれ以外はもう少し大枠の設計に改善点がありそう
TypeScriptでswitch式を実装する。 

## 背景

switch文が好きじゃなかったのでTypeScriptでswitch式を書いてみる。

## switch文のイケてないところ

- 値を返せない
- 一致条件しか使えない
- なんかかっこわるい

値を返せないのは関数型スタイルで書きたいときにつらい。
あとなんかとりあえずかっこわるい。

## 劇的ビフォーアフター

### Before

普通にswitch文でこう書くところを、

```typescript
const hoge = 1

switch (hoge) {
  case 1:
    console.log("A");
    break;
  case 2:
    console.log("B");
    break;
  case 3:
    console.log("C");
    break;
  default:
    console.log("default");
    break;
}
```

### After

こう書けるようにする。

```typescript
const hoge = 1

const result = when(hoge)
  .on(v => v === 1, () => "A")
  .on(v => v === 2, () => "B")
  .on(v => v === 3, () => "C")
  .otherwise(() => "default")

console.log(result)
```


もちろん型の恩恵も得られる。型注釈を省略せずに書くとこうなっている。

```typescript
const result: string = when(hoge)
  .on((v: number) => v === 1, (): string => "A")
  .on((v: number) => v === 2, (): string => "B")
  .on((v: number) => v === 3, (): string => "C")
  .otherwise((): string => "default")
```


ケースごとに異なる型を返してみると、型の恩恵を得られている感がある。

```typescript
const result: string | number | string[] = when(hoge)
  .on((v: number) => v === 1, (): string   => "A")
  .on((v: number) => v === 2, (): boolean  => 100)
  .on((v: number) => v === 3, (): string[] => ["aaa", "bbb"])
  .otherwise((): string => "default");
```
  
マッチする条件は関数で書くので、switch文と違って好きな条件で書ける。

```typescript
const result = when("abcde")
  .on(v => v.length < 3, () => "length less than 3.")
  .on(v => v.startsWith("a"), () => "start with 'a'.")
  .otherwise(() => "default")

console.log(result) // -> start with 'a'.
```


`otherwise()`を呼ぶ前に値を使うとコンパイルエラーになるので、switch文でいうdefaultを強制されている感じ。

```typescript
const result = when(hoge)
  .on(v => v === 1, () => "A")
  .on(v => v === 2, () => "B")
  .on(v => v === 3, () => "C")
  // .otherwise(() => "default")

result.startsWith('a') // string型ではないのでコンパイルエラー！！！
result.otherwise(() => 'default').startsWith('a') // OK
```

`v => v === 1`みたいにアロー関数を毎回書くのが面倒なら、比較用に関数を作るとシンプルになる。

```typescript
const eq = <T>(val1: T) => (val2: T) => val1 === val2

const result = when(1)
  .on(eq(1), () => "A")
  .on(eq(2), () => "B")
  .on(eq(3), () => "C")
  .otherwise(() => "default")

console.log(result) // -> "A"
```



## ソースコード

```typescript
type ChainedWhen<T, R> = {
  on: <A>(pred: (v: T) => boolean, fn: () => A) => ChainedWhen<T, R | A>;
  otherwise: <A>(fn: () => A) => R | A;
};

const match = <T, R>(val: any): ChainedWhen<T, R> => ({
  on: <A>(pred: (v: T) => boolean, fn: () => A) => match<T, R | A>(val),
  otherwise: <A>(fn: () => A): A | R => val
});

const chain = <T, R>(val: T): ChainedWhen<T, R> => ({
  on: <A>(pred: (v: T) => boolean, fn: () => A) =>
    pred(val) ? match(fn()) : chain<T, A | R>(val),
  otherwise: <A>(fn: () => A) => fn()
});

const when = <T>(val: T) => ({
  on: <A>(pred: (v: T) => boolean, fn: () => A) =>
    pred(val) ? match<T, A>(fn()) : chain<T, A>(val)
});
```

ざっくり説明:  

- when: マッチしたら`match()`、しなかったら`chain()`を返す
- chain: マッチしたら`match()`、しなかったら`chain()`を返す。`otherwise`つきで返すのが`when()`との違い。
- match: 「マッチしてもしなくても関係なく渡された値を返す」関数を返す。

## 参考

https://codeburst.io/alternative-to-javascripts-switch-statement-with-a-functional-twist-3f572787ba1c
NSISについて

# NSISについて

Windowsのインストーラー。

正式名称 Nullsoft Scriptable Install System

インストールのウィザードをある程度自動で作成可。
インストールするシステムはPowershell等でスクリプト可。

インストーラーの作成は独自言語（拡張子.nsi）で作成する。
Rubyで2分探索

#はじめに
この記事では2分探索についてRubyで解説していきます。
#2分探索とは
`2分探索`は要素がキーのの昇順や降順に整列(ソート)している配列から効率よく探索を行うアルゴリズムです。
2分探索は`バイナリーサーチ`とも呼びます。

##実装例
2分探索をRubyで実装していきます。

```binary_search.rb
#配列aの先頭number個からtargetと一致する要素を2分探索(探索が失敗したら-1を返す）

def binary_search(a , number, target )
  first_index = 0 #探索範囲先頭の要素
  last_index  = number - 1 #探索範囲末尾の要素

  begin
    center_index = (first_index + last_index) / 2 #中央の要素
    if a[center_index] == target
      return center_index #探索成功
    elsif a[center_index] < target
      first_index = center_index + 1 #探索範囲を後半に絞り込む
    else
      last_index  = center_index - 1 #探索範囲を前半に絞り込む
    end
  end while first_index <= last_index

  -1 #探索失敗
end

puts "要素数を入力してください。"
print "要素数："
number = gets.to_i
a = []

puts "昇順に入力してください。"
print "a[0]：" #先頭の要素を先に読み込む
a[0] = gets.to_i

#昇順に入力する
(1..number - 1).each {|i|
  print "a[#{i}]："
  a[i] = gets.to_i
  redo if a[i] <= a[i - 1] #1つ前の要素より同じか小さければ再入力
}


puts "探す値を入力してください。"
target = gets.to_i

result = binary_search(a, number, target)

if result == -1
  puts "その値は存在しません。"
else
  puts "その値はa[#{result}]にあります。"
end
```

##コードの解説
では上記のコードの解説をしていきます。

###1.昇順の配列aを用意する
まず最初に昇順で数字が並んでいる`配列a`がを用意します。
ここでは、配列は標準入力を利用して用意しています。
###2.配列の中央にある要素を調べる。
次に`binary_searchメソッド`で配列の中央にある要素を調べます。
`先頭の要素(first_index)`と`末尾の要素(last_index)`を足して2割ったものが`中央にある要素(center_index)`となります。
###3.探索する
では、いよいよ探索を開始します。
####中央の要素が目的の値の場合
中央の要素(center_index)が`目的の値(target)`の場合はそこで探索が終了します。
####目的の要素が中央の要素より小さい場合
探索範囲を配列aの後半に絞り込み探索を続けます。
####目的の要素が中央の要素より大きい場合
探索範囲を配列aの前半に絞り込み探索を続けます。
####探索が失敗する場合
探索を繰り返していき先頭の要素(first_index)が末尾の要素(last_index)以上になってしまった場合、その時点で配列aのなかに目的の要素が無いということが分かるので探索失敗です。

以上でコードの解説を終了します。
#最後に
以上で2分探索についての解説を終了します。
何か間違っていることがあったらご指摘ください
#参考
以下の書籍を参考にしました。

新・明解 Javaで学ぶアルゴリズムとデータ構造
https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3-Java%E3%81%A7%E5%AD%A6%E3%81%B6%E3%82%A2%E3%83%AB%E3%82%B4%E3%83%AA%E3%82%BA%E3%83%A0%E3%81%A8%E3%83%87%E3%83%BC%E3%82%BF%E6%A7%8B%E9%80%A0-%E6%9F%B4%E7%94%B0-%E6%9C%9B%E6%B4%8B-ebook/dp/B0722XVC7D/ref=tmm_kin_swatch_0?_encoding=UTF8&qid=&sr=
Ruby_写経中の残りページ数を調べるメソッド

```
def nokori(x,y)
    return x-y+1
end

p nokori(49,28)
#=>22
```


# 参考

def addの記事
URLは忘れました。

# 次にやること

写経、標準入力受け取りからのメソッド、requireできるようにする。桁を出すメソッド(100,000を十万にするもの)も作りたい。

# あとがき

初めて自問自答した後に自作したメソッド。達成感があった。
Ruby,Java持っている、いた、弟が持っている参考書

#持っているRuby

[3ステップでしっかり学ぶ Ruby入門 | WINGSプロジェクト 竹馬 力, 山田 祥寛 |本 | 通販 | Amazon]
(https://www.amazon.co.jp/3%E3%82%B9%E3%83%86%E3%83%83%E3%83%97%E3%81%A7%E3%81%97%E3%81%A3%E3%81%8B%E3%82%8A%E5%AD%A6%E3%81%B6-Ruby%E5%85%A5%E9%96%80-WINGS%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88-%E7%AB%B9%E9%A6%AC-%E5%8A%9B/dp/4774195022
"")
whileについてもっと詳しく書いて欲しかった。break,exit等。

[Ruby逆引きハンドブック | るびきち |本 | 通販 | Amazon]
(https://www.amazon.co.jp/Ruby%E9%80%86%E5%BC%95%E3%81%8D%E3%83%8F%E3%83%B3%E3%83%89%E3%83%96%E3%83%83%E3%82%AF-%E3%82%8B%E3%81%B3%E3%81%8D%E3%81%A1/dp/4863540221
"")

二版とどう違うのかしら…

#持っているJava


[新・明解Java入門 (明解シリーズ) | 柴田 望洋 |本 | 通販 | Amazon]
(https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3Java%E5%85%A5%E9%96%80-%E6%98%8E%E8%A7%A3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%9F%B4%E7%94%B0-%E6%9C%9B%E6%B4%8B/dp/4797387602)
写経中

##持っていた

Java

[Head First Java 第2版 ―頭とからだで覚えるJavaの基本 | Kathy Sierra, Bert Bates, 島田 秋雄, 神戸 博之, 高坂 一城, 夏目 大 |本 | 通販 | Amazon]
(https://www.amazon.co.jp/Head-First-Java-%E7%AC%AC2%E7%89%88-%E2%80%95%E9%A0%AD%E3%81%A8%E3%81%8B%E3%82%89%E3%81%A0%E3%81%A7%E8%A6%9A%E3%81%88%E3%82%8BJava%E3%81%AE%E5%9F%BA%E6%9C%AC/dp/4873112796/ref=sr_1_1?s=books&ie=UTF8&qid=1551816010&sr=1-1&keywords=head+first+java
"")
引っ越しの際に止む無く捨てたが

> また変数をコップにたとえ、「ダブルモカ下さい。intサイズで」は名言だと思います。「変数には型があります」とただいわれるよりも、コーヒーショップでカップのサイズを選んで注文するように、変数に種類があることを説明されれば、日常生活の思考とリンクして、より「納得」に近づけると思います。

コーヒ屋のたとえは今でも覚えている。

###弟が持っているRuby
[たのしいRuby 第5版 | 高橋 征義, 後藤 裕蔵, まつもと ゆきひろ |本 | 通販 | Amazon]
(https://www.amazon.co.jp/%E3%81%9F%E3%81%AE%E3%81%97%E3%81%84Ruby-%E7%AC%AC5%E7%89%88-%E9%AB%98%E6%A9%8B-%E5%BE%81%E7%BE%A9/dp/4797386290/ref=sr_1_1?s=books&ie=UTF8&qid=1551816925&sr=1-1&keywords=%E3%81%9F%E3%81%AE%E3%81%97%E3%81%84ruby
"")
まず、これを薦めといた。6版買わねば…

[Amazon.co.jp: ゼロからわかる ruby 超入門: 本]
(https://www.amazon.co.jp/s/ref=nb_sb_ss_ime_i_2_8?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&url=search-alias%3Dstripbooks&field-keywords=%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%82%8F%E3%81%8B%E3%82%8B+ruby+%E8%B6%85%E5%85%A5%E9%96%80&sprefix=%E3%82%BC%E3%83%AD%E3%81%8B%E3%82%89%E3%82%8F%E3%81%8B%E3%82%8B%E3%80%80%2Cstripbooks%2C256&crid=1U9WWT9J1VZGL
"")
結構初歩から書いてあったのでやりやすそう。

# 次にやること

写経後に
[改訂2版 パーフェクトRuby | Rubyサポーターズ |本 | 通販 | Amazon]
(https://www.amazon.co.jp/%E6%94%B9%E8%A8%822%E7%89%88-%E3%83%91%E3%83%BC%E3%83%95%E3%82%A7%E3%82%AF%E3%83%88Ruby-Ruby%E3%82%B5%E3%83%9D%E3%83%BC%E3%82%BF%E3%83%BC%E3%82%BA/dp/4774189774/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&psc=1&refRID=PDJJEAJR37XYC7BBZ7XZ
"")
勧められるのかしら…
データが少ない、GPUもない環境でCNNにチャレンジ（転移学習)

# 記事の要約
### 転移学習とfine tuningを使って少ないデータで画像認識をおこなったという話。
### ソースコードは→https://github.com/yuushiokamura/cnn_trainfer_learning

# アウトライン
### ・想定する読者
### ・個人でDLする際の難点
### ・あらかじめ学習されたモデルを使おう
### ・転移学習をfine tuning
### ・顔画像で試してみよう

# 想定する読者
### CNNの原理がなんとなくわかる方
### ちまちましたデータ集めの苦手な方
### 仕事で画像認識に始めたばかりの方
### 転移学習・fine tuning　という手法について知りたい方
### 文章ばっかの記事に飽きない方
# 個人で（自分のPCで）DLするときの障壁
#### これはまず大きい壁にぶち当たります。
### <font color="Red">GPUが搭載されていない！</font>
#### これはどうにもならないですよね。まさかプライベート用のPCをdeep learningように買い替えるわけにもいきませんし。。。GPUなしには学習に時間がかかってしょうがないです。。。
### 解決策としては・・・
#### ・クラウドコンピューティングサービスを使う←ぶっちゃけおすすめ。googleやamazonはdeep learning　の学習用に無料でGPUが一部使えるようなので、それを使う。例えばgoogle colablatryでは１２時間まで使えるはずです。
#### ・外付けできるGPUをかう。←あんまりおお勧めしませんが、こういった手段もあります。
####・計算量を減らす。←これができれば一番いいわけで、そのためにどうしましょうというのが今回のメインテーマ。
#### deep learningをやるうえでもう一つ大変なのが<font color="Red">データ集め</font>です。
#### 何千枚ものデータを集める作業、~~くそめんどくさいですよ~~できればやりたくないですよね？データ量が減れば学習時間もへるので一石二鳥でもあります。
#### 少ないデータで学習する方法として、データの水増しがありますが、今回はアルゴリズム側の改善策、<font color="Red">転移学習</font>を紹介します。


# 転移学習とfine tuning
### 転移学習・fine tuningはどちらも似たような意味で、混同されがちですが、どちらもあらかじめ学習されたモデルを利用して効率よく学習しようという手法です。

![vgg16.png](https://qiita-image-store.s3.amazonaws.com/0/265548/24bc2643-dfd6-be0f-1f61-87a25c130b8b.png)
##### 出典　http://cs231n.stanford.edu/syllabus.html
### 一般的に転移学習は特徴量抽出層をそのまま使い、全結合層のみを学習しなおします。一方fine tuningは特徴量抽出層の一部も学習し直す手法のことです。
### 例えばVGG16というモデルはImageNetという膨大な画像データセットで学習されており、1000クラス分類を行うことができるモデルです。このモデルを使うと、どんなメリットがあるかというと、VGG16は膨大で多様な画像データから、1000クラス分類を行うことのできる特徴量を抽出できるので、それを利用すれば、未知の分類も少ないデータでもできる、ということです。あとメリットといえば、実装が楽です
###　kerasで学習済みのVGG16モデルを読み込むには
```
from keras.applications.vgg16 import VGG16
```
### で読み込むことができます。
### モデルに組み込むには
```
vgg = VGG16(weights='imagenet', include_top=False,
           input_tensor=Input(shape=(224, 224, 3)))
```
### inputのサイズは(224,224,3)で固定のようです。ここで読み込まれるのは、全結合層を除く層なので、全結合層を作って、くっつけてください。
```
for layer in self.vgg.layers[:non_train_layers]:
                    layer.trainable = False

```
### non_train_layersで指定した層までの学習を止めることができます。（重みパラメータの固定）

# 顔画像で試してみよう

### cnnで手書き文字認識を試された方は、つぎは実際の画像データで試したくなるでしょう。その際に、犬猫でもいいんですが、少ないデータでは難易度の高い顔認識をやってみたいと思います。
### 今回学習用につかったデータは石原さとみさんの画像と長瀬智也さんの画像です。選んだ理由は特にありません。しいて言えば超美人な石原さとみさんと、もう一方はあんまり似てると識別がむずかしいかなと思ってわりとごつい方にしました。。。
### 顔部分のトリミングは~~めんどくさい~~時間不足のため、行っていません。顔メインの画像だけを抽出しました。だいたい300枚ずつくらいあります。それにしても石原さとみさんはクローリングしたら顔メインの画像が多かったですね。。美人だからでしょうか。。？


# 結果

### 結果というほどのグラフもないですが、転移学習、fine tuning フル学習での精度と学習時間を記載しておきます。
|   |  フル学習 | 転移学習 | fine tuning |
| ---- | ---- | ---- | ---- 
|    学習時間|  3時間程度 |1時間  |50分  |
|  精度（val acc)|  70%程度  |92.2%  |94.7%  |

### 学習済みモデルを利用するメリットがわかっていただけたと思います。精度もそうですが、学習時間の低下はうれしいですね！
### フル学習では三時間を過ぎても終わりが見えず、精度も頭打ちになってきた感があったので止めました。
RailsでPostgeSQLを使うときに大文字・小文字を区別しないカラムを追加する方法（citext）

https://nandovieira.com/using-insensitive-case-columns-in-postgresql-with-citext

ここに書いてあった。
これを忘れがち　→　**enable_extension 'citext'**

```ruby:20190222064557_create_users.rb
class CreateUsers < ActiveRecord::Migration
  def change
    enable_extension 'citext'

    create_table :users do |t|
      t.text :name, null: false
      t.citext :username, null: false
    end

    add_index :users, :username, unique: true
  end
end
```

これを忘れがち　→　**enable_extension 'citext'**
HTMLとCSSで立体的なボタンを作る方法

こんにちは。
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしているueken0403です。
今回はサイトなどで、申し込む際に使うボタンを作る方法を説明していきます。
ただボタンを設定するのではなく、カーソルを上に持っていったらカーソルの形が変わったり、クリックするとボタンが押し込まれたように見えるようにプログラミングできたら楽しいですよね。
僕はプログラミング初心者です。
そのため、この記事にも間違っている部分が含まれる可能性が高いです。
間違いを指摘されたれすぐに修正しますので、どんどん指摘してください！


#基本的なボタンの作り方
いろいろな工夫をする前に、まずは基本的なボタンを作りましょう。
ボタンは＜a＞タグで指定します。
この時、初期の＜a＞タグはインライン要素になっているため、displayプロパティでインラインブロック要素に変換しておきましょう。
ついでに角を丸めておきましょう。
ボタンの角を丸めるには、border-radiusプロパティを使います。
border-radius:10px;のように指定します。
数字が大きいほど過度の丸みは大きくなります。


#カーソルが乗ったときに変化するようにしよう
続いて、ボタンにカーソルを乗せる前と乗せた時で変化を作る方法を説明します。
カーソルが乗った状態をhoverといいます。
CSSでセレクタhoverとすると、カーソルが乗った時だけのCSSを設定できます。
例えば、div:hoverのCSSをbackground-color:blue; という風にすると、カーソルを乗せた時だけ背景の色が青になるようになります。

#ボタンを立体的にしよう
ここからは、ボタンをよりリアルに、立体的にしていく作業に入ります。
まずは、box-shadowプロパティをつかい、ボタンに影を作ります。
また、セレクタactiveを使用すると、ボタンをクリックしている時だけ変わるCSSを設定することができます。
さらにposition: relative;を使用します。
この三つを組み合わせ、ボタンをクリックしたときに、影が消え、ボタンがその影の分だけ下にさがるようにします。
こうすることで、ボタンが押し込まれたように見えます。
具体的には、activeセレクタを使いbox-shadow:none;でクリックしたときに影が消えるようにします。
次に、position: relative;で影の大きさの分だけボタンを下に移動させます。

#まとめ
今回は、HTMLとCSSで立体的なボタンを創る方法を説明しました。
簡単に少しリアルな動きを作れるところがプログラミングの面白いところですね。
#udemyメモ　パスワードのハッシュ化

Final Ruby project 2 - Text follow-up
Section 2, Lecture 54
We created a crud.rb file and filled it in:

```rb
require 'bundler/inline'
 
gemfile true do
 source 'http://rubygems.org'
 gem 'bcrypt'
end
 
require 'bcrypt'
 
users = [
          { username: "mashrur", password: "password1" },
          { username: "jack", password: "password2" },
          { username: "arya", password: "password3" },
          { username: "jonshow", password: "password4" },
          { username: "heisenberg", password: "password5" }
        ]
 
def create_hash_digest(password)
#BCryptは文字列にソルトを付与？してハッシュ化する
#createでハッシュを保存
  BCrypt::Password.create(password)
end
 
def verify_hash_digest(password)
#newは保存しない
  BCrypt::Password.new(password)
end
 
def create_secure_users(list_of_users)
  list_of_users.each do |user_record|
    user_record[:password] = create_hash_digest(user_record[:password])
#user_record[:password]は{ username: "mashrur", password: "password1" } の "password1"を取り出している。
#create_hash_digestメソッドを送って"password1"をハッシュ化
  end
  list_of_users
#users配列の:passwordがハッシュ化されたものが改行されて戻り値に
end
```
質問です 初心者です

ubuntu初心者です。wifiのUSBアダプタ設定中に端末にて以下のエラーがでました。
カーネルの問題？いろいろ試行錯誤してますが、初心者なもので困っております。よろしければどなたかご教授願います


error: ‘_timer {aka struct timer_list}’ has no member named ‘data’

error: implicit declaration of function ‘init_timer’; did you mean ‘_init_timer’? [-Werror=implicit-function-declaration]
  init_timer(ptimer);
  ^~~~~~~~~~

error: implicit declaration of function ‘allow_signal’; did you mean ‘do_signal’? [-Werror=implicit-function-declaration]
  allow_signal(SIGTERM);
  ^~~~~~~~~~~~
error: implicit declaration of function ‘signal_pending’; did you mean ‘timer_pending’? [-Werror=implicit-function-declaration]
  if (signal_pending (current))
      ^~~~~~~~~~~~~~
error: implicit declaration of function ‘flush_signals’; did you mean ‘do_signal’? [-Werror=implicit-function-declaration]
   flush_signals(current);
   ^~~~~~~~~~~~~
error: void value not ignored as it ought to be
  #define _seqdump seq_printf
                   ^
error: void value not ignored as it ought to be
  #define _seqdump seq_printf
Ruby_1から10までの2のべき乗

```:ruby
puts [*1..10].map{|i| 2**i}* " "
#=>2 4 8 16 32 64 128 256 512 1024
```

# 参考

参考にしたWebサイトや技術書などを列挙する

- [Ruby - 1から10までの2のべき乗を求めたい｜teratail
](https://teratail.com/questions/164188)

# 次にやること

記事を読んだあとに読んだ方が良いWebサイトなどがあれば書く

[新・明解Java入門 (明解シリーズ) | 柴田 望洋 |本 | 通販 | Amazon]
(https://www.amazon.co.jp/%E6%96%B0%E3%83%BB%E6%98%8E%E8%A7%A3Java%E5%85%A5%E9%96%80-%E6%98%8E%E8%A7%A3%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E6%9F%B4%E7%94%B0-%E6%9C%9B%E6%B4%8B/dp/4797387602
"")の写経をする
自分用メモ~php~

#1.注意事項
**初心者のメモです．**

#2.環境
- windows 10
- PHP 7.3.2

#3.本文
自分が知らなかったことをまとめます．
##3.1.foreach
配列に対して繰り返し処理を行う際に使用します．

###3.1.1具体例
```php:foreach.php
<?php
   $fluit = array('apple','orange','lemon');
   foreach ($fluit as $value) {
       print($value.'<br>');
   }
?>
```
###3.1.2結果
apple
orange
lemon

#4.追伸
勉強している最中なので，更新する予定です．
rails cをした時に、Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError)というエラーが吐き出される

#開発環境
- macOS Mojave 10.14.3
- Ruby 2.5.0
- Rails 5.2.2

#問題
- Railsを使っていて、 `rails c` でコンソールを開始しようとしたら、下記のようなエラーが吐き出された 

```
Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError)
```

#原因
- エラー文をよく見ると、「readlineが見つからないよ」的なことが書いてあったので、何かが不足しているレベルという認識であった

#対応
- とりあえずググって見ると、下記のような記事が見つかった
  - https://github.com/rails/rails/issues/26658
- どうやら、原因は2つの目星があるそうで、1つは `シンボリックリンクが正しく設定されていない` 、もう１つは `rb-readlineというgemがインストールされていない` ぽいので、とりあえず後者を先に実行した
  - 実際に実行したのは、[この記事](https://qiita.com/alohaoe/items/9b20a6b549c80991ef21)の内容 

#結果
- 無事コンソールが動いた
- 原因がいまいちハッキリできていないので、次に同じ現象が起きたら、シンボリックリンクを変更する方向で対応が必要そう
何回閉じても無駄ですよ in Swift

むしゃくしゃしてやった、後悔はしていない．

![mudadesuyo.gif](https://qiita-image-store.s3.amazonaws.com/0/35592/71a66a73-cb9a-bfc4-7786-22562434d765.gif)

## 作り方

次のようなビューコントローラを作る．

```AsciiAlertController.swift
import UIKit

class AsciiAlertController: UIAlertController {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        for label in findLabels(in: view) {
            label.textAlignment = .left
            label.font = UIFont.monospacedDigitSystemFont(ofSize: label.font.pointSize, weight: .regular)
        }
    }
    
    func findLabels(in view: UIView) -> [UILabel] {
        return view.subviews.flatMap({ subview -> [UILabel] in
            if let label = subview as? UILabel {
                return [label] + findLabels(in: label)
            } else {
                return findLabels(in: subview)
            }
        })
    }
}

```

次のように呼び出す

```swift:ViewController.swift
    func showAlert() {
        let message = """
　∧_∧　ババババ
（ ・ω・)=つ≡つ
（っ ≡つ=つ
`/　　)
(ノΠＵ
何回閉じても無駄ですよ?ww
m9（＾Д＾）プギャー！！
"""

        let dialog = AsciiAlertController(title: nil, message: message, preferredStyle: .alert)
        dialog.addAction(UIAlertAction(title: "閉じる", style: .default, handler: { _ in
            self.showAlert()
        }))
        show(dialog, sender: nil)
    }
```

## 工夫したところ

* AAを表示するために，UIAlertViewControllerのUILabelを全部左寄せにした
* また，等幅フォントにした（これはやらなくても変わらなかったかも）

## 環境

* Xcode: 10.1
* macOS 10.14 (Mojave)
大好きだった○○リオが終了してしまうので再びRSSリーダーを使ってみる

# きっかけは
発表されてからずっと使っていた[「カメリオ」](https://shiroyagi.co.jp/)というニュースキュレーションアプリがあったのですが、2019/3末に個人向けのサービスが終了してしまうとのことです。余計なクーポンとか広告とかもなく個人的には本当にお世話になったアプリなのですが仕方ないですね。次の代替えを探さなければと思っておりました。

![kamerio.jpg](https://qiita-image-store.s3.amazonaws.com/0/24418/ab14adb2-301d-0ea5-ead6-911987ee8095.jpeg)

# 今まで何を見ていたのか
自分がキーワードとして登録していたのは PWA,Watson,AIスピーカー,Rust,機械学習,Google Home,Azure,Vue.js,Java,Node.js,JavaScript,ラズパイ,IoT そして Perfume

技術ネタ、中でもプログラム言語に関してキュレーションされていたものは、日本語の情報に関して言えばほとんどがQiitaまたはスタックオーバーフローという状態でしたので各サイト、アプリを見ればよさそうですがやっぱり一つのアプリで見たいなと今出ているニュース・キュレーションアプリも試しましたが、ざっくりしたカテゴリでしか購読できないしピンポイントの情報を見るのには合わなそうでした。

# 今さらRSSリーダー？
以前は、Googleリーダーや [feedly](https://feedly.com/i/welcome) などのRSSリーダーを使用して情報を集めていたのですがGoogleリーダー終了とともにfeedlyに移行した後しばらくするとニュースアプリ [gunosy](https://gunosy.com/) が出た時すぐに飛びつき、その後「カメリオ」に移行し今に至ります。
情報を一か所で見るには、やはりRSSリーダーが良いのではと、見つけたのが [Inoreader](https://jp.inoreader.com/)です。 

Inoreaderの使用方法はこちらのブログ [JDSブログ](https://jds-blog.net/category/inoreader/) に連載されていました。

# 主なRSSフィード
とりあえず、最近気になって勉強始めたRustについてプログラミング記事が集められそうなサイトのRSSフィードを登録します。

## Qiita
[記事をrssリーダーで読む](https://qiita.com/tukiyo3/items/5b1051e63c7a32bfa48b) に紹介されていた方法でタグに関するRSSフィードを取得できます。

> タグ: Rust
> URL:  https://qiita.com/tags/docker/feed.atom

## スタックオーバーフロー 日本版
以下のようにタグに関するRSSフィードを取得できます。

> タグ: Rust
> URL:  https://ja.stackoverflow.com/feeds/tag?tagnames=Rust&sort=newest

## teratail
以下のようにタグに関するRSSフィードを取得できます。

![teratail.jpg](https://qiita-image-store.s3.amazonaws.com/0/24418/a4de6b14-83ba-524d-cb59-5e68139ec0d7.jpeg)

> タグ: Rust
> URL:  https://teratail.com/rss/feed/all/649

## はてなブックマーク
スター50以上のタグ rust を含むブックマーク
> タグ: Rust
> URL:  http://b.hatena.ne.jp/search/tag?q=rust&safe=on&sort=recent&users=50&mode=rss

## twitter検索
最近はtwitter検索で情報を集めることも増えているようなのでtwitterの検索結果も同じように見てみたいですね。
twitter自身ではRSSフィードを出力してくれないので、外部サービスを使用します。よく使われているのは以下のサイトのようです。

### Queryfeed
- [Queryfeed](https://queryfeed.net/)

> キーワード: Rust
> URL:  https://queryfeed.net/tw?q=Rust+プログラミング


### TwitRSS
- [TwitRSS.me](https://twitrss.me/)

> タグ: Rust
> URL:  https://twitrss.me/twitter_search_to_rss/?term=Rust+プログラミング

これらのURLをinoreaderに登録します。一つのキーワードについてフォルダを作成して、その中にfeed追加するとこんな感じになります。
![inoreder.jpg](https://qiita-image-store.s3.amazonaws.com/0/24418/5b3067f6-daaa-0f58-bb53-734d76f6af6e.jpeg)

このようにするとフォルダ名のキーワードで複数のフィードを縦覧できます
<img width="414" alt="IMG_1945.JPG" src="https://qiita-image-store.s3.amazonaws.com/0/24418/12df8ed6-e1b8-b53e-4fbe-6ab2b26005cc.jpeg">

フィード探したり手間はありますが、自分で育てていくのもよいかと思います。
カメリオの代替えを探している方はお試しください。
create-react-appで作成したReactアプリをWebサーバにデプロイする手順

## 目的
Reactで作ったWebアプリケーションをWebサーバにアップロードしたい。

## 手順
1. `npm install -g create-react-app`
2. `create-react-app app_name`
3. `cd app_name`
4. `vim package.json` ([解決方法](#解決方法)の変更を適用する)
5. `yarn build` または `npm run build`
6. build/* をサーバにアップロード(コマンドの例: `scp -r build/* example.com:~/PathToDocumentRoot/`)

## 発生した問題
ReactアプリのURL/index.htmlにアクセスしても何も表示されない。404エラーになる。

### 原因
静的ファイルの読み込み箇所が絶対パスになっていた。

### 解決方法
Reactアプリのディレクトリルート/package.jsonに下記の一文を追加する。

```json
"homepage": "."
```

具体的な***ビフォー・アフター***は以下の通り。

```json:package.json(ビフォー)
{
  "name": "app2",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.8.3",
    "react-dom": "^16.8.3",
    "react-scripts": "2.1.5"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ]
}

```

```json:package.json(アフター)
{
  "name": "app2",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "react": "^16.8.3",
    "react-dom": "^16.8.3",
    "react-scripts": "2.1.5"
  },
  "scripts": {
    "start": "react-scripts start",
    "build": "react-scripts build",
    "test": "react-scripts test",
    "eject": "react-scripts eject"
  },
  "eslintConfig": {
    "extends": "react-app"
  },
  "browserslist": [
    ">0.2%",
    "not dead",
    "not ie <= 11",
    "not op_mini all"
  ],
  "homepage": "."
}
```

これだけです。***劇的***に簡単ですね。
docker for macでコンテナ内からローカルホストにつなぐ方法

dockerコンテナ内からlocalhostのMySQLにつなぐときに少しつまずいたので、自分用備忘録。

## コンテナ内からローカルホストにつなぐ方法
解決策：DNS名に`host.docker.internal`を用いる。

## 実際に試す方法
ローカルになんらかの方法でmysql-serverがインストールされていて、起動されていることを前提に進める。

まず、mysql-cliの入ったubuntuのコンテナイメージを作成するため、以下のDockerfileを作成。

```dockerfile:Dockerfile
# 利用するイメージ
FROM ubuntu

# mysql-clientをインストール
RUN apt-get update && apt-get install -y mysql-client
```

そして、localhost-testという名前でbuild。

```shell
$ docker build -t localhost-test .
```

以下のコマンドで

```shell
$ docker image ls
```
image listを見てみるとlocalhost-testというイメージができていることが確認できる。

よってコンテナを起動して、中に入ります。

```shell
$ docker run -it localhost-test /bin/bash
```

そして、mysqlコマンドを実行し、ホスト名`host.docker.internal`でローカルホストのMySQLに繋がるか確認。

```
# mysql -u root -h host.docker.internal -p
Enter password: [パスワードを入力]

mysql>
```

このようにローカルホストのMySQLに繋がるはず。 ホスト名を`localhost`や`127.0.0.1`にしても、繋がらないということを確認してみても面白いはずです。
もんじゃ屋店員からテスターになって数ヶ月

皆さんこんばんわ
世の中に履いて捨てるほどいるSES業界の1テスターです
テスターになって数ヶ月経ってわかった事や大事そうなところを書いていきたいと思います
この記事を見てこんなんでもIT業界ってやっていけるんだなって安心してもらえれば幸いです
ちなみにこの記事を読んでも一切技術的な事は学べません

#今まで何して来たの？
大学を中退し、ゲーセンやパチ屋やもんじゃ屋でバイトしたり数ヶ月パチプロのような事をしてました
接客業ずっとしてきていたので、基本的なコミュニケーションは取れます
IT系のスキルとしてはネトゲで鍛えたタイピング力、わからない事があったらググる癖、そして営業の時に覚えたじゃばとじゃばすくりぷとはなまえがにてるけどどうやらちがうらしい、それぐらいのレベルです


# 未経験でもIT業界入れるの？
IT業界に入るのなんて簡単です、どこでもいくらでも未経験でも、大量に募集してます
なぜ未経験でも入れるのかは後述したいと思います
入ったら入ったで、軽い研修を受けて営業の人に頑張ってもらえればめでたく現場が決まります
何回も面談に行って決まらなかったら営業の人に相談し、自分なりのやり方を見つけるといいでしょう


#未経験で入ってやっていけてるの？
ITと言うと映画で見るような長いプログラムを組んでたり、凄いチップを1から作ってたり、と言うようなイメージを持つ人もいるかもしれません~~Qiitaにはいなさそう~~
そんな業界に未経験でも入れるのは、目が二つあって手と足があって普通に生活できるくらいの人なら誰でもいいよ、ってレベルの仕事を募集してる所が沢山あるからです
電話を取り次ぐコールセンターだったり、言われたとおりに決まった手順を行うテスターだったり、問題が起きたら報告する運用保守だったり
生きていくだけなら問題なくはやっていけると思います

#結局どういうこと？何が言いたいの？
未経験で入っても生きていくだけの事は出来ますが、そのままでは何も身につかず時間だけが過ぎていきます
それを脱却する為には「力」が必要です
技術力だったりコミュニケーション能力だったり

文を書くのが難しくなってきたのでここからは大事だと思う事を簡潔に書きます

・わからないことは調べる癖をつけよう
わからない事を全て人に聞くのでは無くGoogleで調べる癖をつけましょう
調べてるうちにググるコツだったり調べたい事に付随した知識も身につけることができます
有難い事に自分たちレベルでの悩みなら先人たちがインターネットに記してくれている事が多いです

・現場では積極的にコミュニケーションを取ろう
現場に入ってしまえば後はそこの人と良い関係を築ければスキルは無くても長く現場にいる事が出来る可能性もあります
（自分も最初は2ヶ月だけという話だったのが6月末まで延長をいただく事が出来ました）

・「単価」「商流」といった言葉を意識してみよう
これについては自信の給与に大きく関わってきます、未経験で入り言われるがままだと給料なんてほとんど上がりません
特に「単価」について意識するのは非常に大事です
現場に入る際に「単価」の話をしてこない営業が多いと思いますが（自分も昔はエンジニアの人に教えないように言われた）仲良くなった現場の人や、営業の人に取り入って聞いたりGoogle先生に教わってみるといいと思います
色々な物が見えてくると思いますので

・モチベーションとなるものを見つけよう
やっている間にこの言語に関わりたいとか資格を取りたいとかそういう意識が出てきた場合はそれを目指す事によりスキルアップに繋がります
仕事なんて金を稼ぐだけのツールだぜって人は仕事に飽きないために趣味や恋愛に打ち込んで生活に張りをつけましょう

・自分の強みを理解しよう
人それぞれ色々な強みがあると思います
面談の際にその強みをうまくアピール出来るよう面談練習はしっかりやっておきましょう、そんなに美少女じゃなくても愛嬌がある子が可愛く見えるのと一緒です
どんなに顔がよくても性格に難があったり会話もまともに出来ない人は恋愛対象に入らなくなりますよね
自分はコミュニケーション能力ともんじゃ屋で働いてた事を軽くアピールして食いついてもらって面談上手くいきました

#まとめ

なんかもっと良い感じの事を書きたかったんだけど全然纏められなかった
本当は面談のコツとかコミュニケーションのコツとか書いたりしたかった
転職タグをつけたのに転職についてほとんど触れられなかった

とりあえず今の自分の手取りが15万と安すぎるのでこんな新人テスターでもスカウトするよって人待ってます
もんじゃとお好み焼き作るのは任せてください
Error: Command '['/opt/eff.org/certbot/venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']' returned non-zero exit status 1

ハマった…

https://vogel.at.webry.info/201903/article_2.html

パソコン鳥さんに感謝…
趣味でやってたサーバだけど友人に迷惑かけるところだった…(=人=;)
systemdチートシート

# systemd関連のmanがいっぱいあってどれを読めばいいのかわからない

`関連語 + man` でgoogle検索するのもいいかもしれないが、systemdのリリース方針的に https://www.freedesktop.org/software/systemd/man/ で公開しているのは最新版のmanだし、自分のシステムにインストールされているバージョンのsystemdのmanを見たければローカルのmanを見るしかない。（他に適切な方法があれば教えてください）

ローカルでmanを探すには、

```shell-session
$ man systemd.index
```

で「systemdのmanの目次」を見ることができるので、これをとっかかりに探すのがよさそう。
（なんていう恐ろしいことになってるんだ）


# systemd edit を自動化する

`SYSTEMD_EDITOR`でエディタとして使うコマンドを指定できるので、目的の設定内容を引数で与えられたファイルに書き出すコマンドを指定すれば`systemd edit`を自動化できる。
ここでは`cp`コマンドであらかじめつくっておいた設定内容を、渡されたパスに書き込む。

```sh
cat > "/tmp/systemd-nspawn_override.conf" <<EOF
[Service]
ExecStart=
ExecStart=/usr/bin/systemd-nspawn --quiet --boot --link-journal=try-guest --network-veth -U --settings=override --machine=%i
EOF
SYSTEMD_EDITOR="cp ${tmp}/systemd-nspawn_override.conf" systemctl edit "systemd-nspawn@${machine}.service"
```

参考: https://unix.stackexchange.com/questions/459942/using-systemctl-edit-via-bash-script


# serviceファイルの文法チェック

```sh
sudo systemd-analyze verify /path/to/service_file.service
```


# `ExecStartPre=`はroot権限で実行して`ExecStart=`は指定したユーザで実行する

実行パスの頭に`+`をつける。

```systemd.service
[Service]
ExecStartPre=+/bin/mkdir -p /var/run/hoge
ExecStartPre=+/bin/chown pi /var/run/hoge
ExecStartPre=+/bin/chgrp pi /var/run/hoge
User=pi
Group=pi
ExecStart=/opt/local/hoge/main.sh
```

参照: [systemd.service](https://www.freedesktop.org/software/systemd/man/systemd.service.html)の`ExecStart=`の項
オセロ

- [オセロ](https://onlinejudge.u-aizu.ac.jp/beta/room.html#RitsCamp19Day1/problems/C)

## 考察

- 全探索？手数がたくさんあって終わりそうにない
- メモ化したりできる？無理っぽい
- サンプルを見ると、全範囲を選んだときの答えが48になっている。
- なので、とりあえず答えが左上が(1, 1)で右下が(8, 8)の時に答えが48になるようにシミュレーションしてみる
- すると、以下のようになる（シミュレーション方法によって盤面にばらつきありそうだけど）。全体の石の個数は全盤面からドットの個数を引いた$8^2 -4^2=48 $となる。

```
o.o.x.o.
xxxxxoox
x.o.x.o.
xxooxxoo
o.o.o.x.
oooxoooo
o.o.x.o.
oooooooo
```

- とりあえず答えと一致する盤面ができた。この盤面が答えかどうかはさておき、なんかあってそう（ほんまか？）
- この盤面の規則性は、奇数行かつ偶数列のマス目が`.`になっていること。
- 規則性に従ったコードを書くとサンプルケースが全部通る。そんで、そのコードを投げるとACする



## 証明

- よくわかりません。



## [コード](https://onlinejudge.u-aizu.ac.jp/beta/review.html#RitsCamp19Day1/3412322)

```cpp
#include <bits/stdc++.h>
using namespace std;

int q;

int main() {
  cin >> q;
  while (q--) {
    int a, b, c, d;
    cin >> a >> b >> c >> d;
    int ans = 0;
    for (int yi = a; yi <= c; yi++) {
      for (int xi = b; xi <=d; xi++) {
        if (yi % 2 == 1 and xi % 2 == 0) {
        } else {
          ans++;
        }
      }
    }
    cout << ans << endl;
  }

  return 0;
}
```



## 要点

- ゲーム問題はシミュレーション！！！って強い人が言ってた



## めも

- オセロみたいに書き換えがたくさん発生するシミュレーションは、紙じゃなくてエディタでやったほうがいいっぽい。って強い人が言ってた。
- なんか自分で解いた風に書いてるけどHecさんが考察した問題だった
[Notch] StandAloneで頑張るために その３

（無駄が多いので、お忙しい方は最後のまとめをご覧ください！）

ガスト ノッチ!!!!!!!! はい、千田です。

そういえば、先日　3月3日でした。
何気なくyouTubeをみてたら、なんと303Day!!!!!と書いてるじゃないですか！！！！
そうなの？知らなかったよー。

3月3日はTB-303の日なのだそうです。

そう、ACIIIDDDDD!!!!!!!!な日なのだそうです！
僕はHARDFLOORで楽しみましたよ！！！テクノ！！！！！！

はい。勝手にひと盛り上がりしましたので、始めます。


##StandAloneで頑張るために その３

さて、今回の内容は、
前回、後半で「チキショーーーー」などと言いながら、割と盛り上がりを見せた、
マルチストリーム取り込み（HD-SDIの複数回線取り込み）の話です。

前回書いています通り、StandAlone Appではマルチストリーム取り込みができません。
なんと、メディアサーバーでは、その気になれば８回線も取り込めるんですって。すごいーーーー。
（じゃあ、、その半分くらいは取り込めてもいいのにね、、、）

じゃあ、どうするのよ？あきらめる？もうメディアサーバー無いと戦えない？？？？
いや、、、方法はあるはず。。。。考えるのだ、、、、、


思いついた方法　その１
マニュアルにある通り、HD-SDIを[マルチウインドウレイアウター(いわゆる分割機)](https://www.blackmagicdesign.com/jp/products/multiview)などを使って、
4分割で並べて、HD-SDIで取り込む。

ん、、、送出先の画面の解像度が960ｘ540以内だったらいい方法かもしれません。
が、、、、やはり遅延が発生します。1フレーム程度はあるでしょう。
この条件がOKな現場ならいいかも。
４Kのレイアウターとか使って４Kキャプチャーできれば、画質的にはクリアですね！

でもなぁ、、、遅延の問題が、、、（この話は次回詳しく）
となりまして、却下。ただし最終手段としてキープ。

思いついた方法　その２
じゃあさ、OpenframeworksとかTouchDesignerとか、BlackSpoutあたりの他のソフトウェア使ってキャプチャして、Spoutで送ったらいいじゃん！！！！！！
そう、思いついたときはうれしかったけど、現実問題、どうよ？？となりました。

理由として、
・遅延の問題　ソフト側でバッファするだろうから、
早くても１フレーム、多ければもうちょいかかりそう。。。。（試してないけど、実際どうなんでしょう？）

・また、現場導入時に誰かにお任せする際、手順がちょっと煩雑。。。すぐ電話が来そう。。。

・トラブル発生時のシューティングがちょっと厄介かも、、、
となりまして、却下。


で、、、悩みに悩んでマニュアルを読んでいるところ、目に飛び込んできた文字。
「 NDI 」
なにーーー、そうきたか、fairlight、さすがヨーロッパ。NDIですか。

NDIとは
”NDIは、NewTek社によって開発された複数の映像システムをネットワークを介して認識・コミュニケーションができ、リアルタイムに大量の高品質、低遅延かつ高フレーム精度でエンコードし、双方向の伝送を可能とするIP利用における新しいビデオ制作ワークフロー支援プロトコルです。” D-storm Webサイトより

そういえば、この間　NDIをえらい押してたよ。。
そうか、そうなのか。
fairlightさまは、「SDIを捨てよ、NDIへ進め！！！」　そういうメッセージを込めてるんだ、きっと。
StandAlone Appを通して、僕たちを次世代規格へ導こうとしてらっしゃるのだ！！！！
やるなぁ、、、、さすがっす。

でも使ったことないしなぁ、、、すっごく不安。。。
[NewTekのweb](https://jp.newtek.com/ndi/)に行って勉強してみると、いろんなツールが配布されている。
そのなかで、環境チェックに良さそうなPluginを発見。VLCからNDIを出せる!
これいいじゃん！！！！！！

ということで早速実験。んーーーNDIいいのか？？なんか、ちょっと、かくつくような、、、気のせいか？？
いや、、、んーーーどうなんだろ。。Builder画面ではどうもかくつくような。。。

だめかぁ、、、と思いながら、一応StandAlone Appを吐き出してみたところ、

いいじゃん！！！イケてるじゃん！！！かくつかない！

ただ、ちょっと問題も。黒に近い帯域の画質がちょっと圧縮強いかも、、気のせい？？
ただ、まぁ、、大丈夫じゃない？？といった感じ。

さて、ここまで来て、本題のマルチストリーム取り込み。
NDIは取り込み制限ないのです！！！！！！
マニュアルには「メディアサーバ使えば？」って書いてない！！！
きっとLANが許す限り、行けるはず！！
早速複数のPCでVLC TO NDIを起動してテスト。
Notchへ送り込みます。

どうだ？？？？？？？？？
きましたーーーーーーーーーー。マルチ来ました。できますマルチ！！！！ひとまず2回線は行けるぜ！
やったーー！
と、表示された2画面をよくよく見ると。。。んーーーちょっとかくつくような、、、、
またそれかぁ、、、、と。
しばらくいろいろやって見ても、なんかちょっとかくつく感じがある。
だめかぁ、、、と思ったその時です。

一つのレイヤーですべてキャプチャせずに、1レイヤー１NDI取り込みにして、複数レイヤーに分けてみれば？
そして、各画面をLayerPrecompで受け取ったらどう？

という神のお告げが、、、、、

まぁ、うまくいくかわからんけど、やってみよう。。と。。。
BuilderでStandAlone App書き出ししたところ、、、、、

できました！！！かくついてないかも！！やっっったー！！

さて、ここで、詳しい方に質問です。
Notchのレイヤーって、そのレイヤーごとでスレッドが分かれてたりするんでしょうか？
もしそうならば、FPSの問題はあれど、マルチスレッド的な処理はレイヤー分けでいけるのかなぁと。
もしご存知の方がいらっしゃいましたら、教えてください。

と、ここまで来てです。さて、HD-SDIってさぁNDIに変換できるんだっけ？？
と、機材を捜索。するとありました。

[BirdDog Studio NDI](http://tricaster.jp/ndi-hardware/birddog-studio/)

聞いたことない機材。、、でも、なんかいいかも。かっこいいかも。光るし。
ということで、ひとまず3台入れてみました。
結果　3回線取り込み成功！！！！！
そしてさらに、先日のMageWellのUSBキャプチャ繋いだら、トータル4回線！！！！やったーーー！

ということで、現在4回線まで取り込めることがわかりました。
でもさぁ、、、、NDIに変換してるんでしょ？
遅延、、、、すごいんじゃないの？？？？
というところは、また次回。
マニアックにレイテンシーの話をします。
それではーー

##本日のまとめ
Notch　StandAloneでは、正攻法では1回線しか取り込めない。
でもNDIを使えば、もしかしてかなりの回線数取り込めるかも？？？？

現在Birddog3台＋MageWellのUSBキャプチャで　4回線まで取り込めることがわかりました。
バージョンを+1するpull requestを作る

バージョンを+1するだけのpull requestを毎回作っていたが、GitHub APIで自動化できた。

(GitHub API v3)
https://developer.github.com/v3/pulls/reviews/#create-a-pull-request-review

Xcodeのプロジェクトでxcconfigを使っているが、他の環境でも同じようなものではあると思う。

Rubyのスクリプトで、以下のようなことをする。

- 書き換えるファイルはApp.xcconfig (すでにgit管理下にあること)
- 書き換える内容はAPP_VERSIONをx.x.xにする
- base_branch(master)からhead_branch(feature/...)を作り、pull request化する
- 環境変数MY_GITHUB_TOKENにGitHub tokenを設定しておく
- WindowsなどHTTPS通信に失敗する場合はhttp.verify_mode = OpenSSL::SSL::VERIFY_NONEをコメントアウト



```ruby:bump_version.rb
#!/usr/bin/env ruby

require 'net/https'
require 'uri'
require 'json'

version = ARGV[0]
if !version || version.empty?
  puts "Please specify version"
  exit
end
unless /^(\d+\.)*\d+$/ =~ version
  puts "Invalid version format"
  exit
end

base_branch = 'master'
head_branch = "feature/bump-version-to-#{version}"
repository = 'username/repository'
version_filename = 'App.xcconfig'
system("git checkout #{base_branch}")
system("git checkout #{version_filename}")
content = open(version_filename, 'r').read.gsub(/APP_VERSION=(.*)/, "APP_VERSION=#{version}")
File.open(version_filename, 'w') { |f| f.write(content) }
diff = `git diff #{version_filename}`
if diff.empty?
  puts "No diffs"
  exit
end
system("git checkout -b #{head_branch}")
system("git add #{version_filename}")
system("git commit -m 'Bump version to #{version}'")
system("git push origin #{head_branch}")

github_token = ENV['MY_GITHUB_TOKEN']
endpoint = "https://api.github.com/repos/#{repository}/pulls"
uri = URI.parse(endpoint)
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
#http.verify_mode = OpenSSL::SSL::VERIFY_NONE
req = Net::HTTP::Post.new(uri.request_uri)
req["Authorization"] = "token #{github_token}"
req.body = {'title' => "Bump version to #{version}", 'body' => '', 'head' => head_branch, 'base' => base_branch}.to_json
res = http.request(req)
if res.code.to_i >= 300
  puts "Faied: #{res.code}, #{res.body}"
  exit
end
json = JSON.parse(res.body)
puts "SUCCESS: #{json['url']}"
```
具体的な値でモナド則を確認する - Maybe編

モナド則に具体的な値をいれて理解を深めてみましょう。
今回はMaybeモナドを使ってみます。

# モナド則

モナド則を確認しておきましょう。

```haskell
return x >>= f == f x
m >>= return == m
(m >>= f) >>= g == m >>= (\x -> f x >>= g)
```

# Maybeの実装

Maybeモナドの実装を確認しておきます。

```haskell
return x = Just x

x >>= f = case x of
  Just y -> f y
  Nothing -> Nothing
```

# モナド則に具体的な値をいれてみよう

## `return x >>= f == f x`

### xが1の場合

#### 左辺

```haskell
return x >>= f

-- xは1である
return 1 >>= f

-- return を適用
Just 1 >>= f

-- >>= を適用
case (Just 1) of
  Just y -> f y
  Noting -> Nothing

-- Just yにマッチするので
f 1
```


#### 右辺

```haskell
f x

-- x は1である
f 1
```

右辺と左辺が一致した

### まとめ

関数fに使う値をreturnしてから使うのと、そのまま使っても結果は変わらないことがかくにんできました。returnした値にfを使う方法が>>=と読めそうですね。

## `m >>= return == m`

### `m`が `Just 1`の場合

#### 左辺

```haskell
m >>= return

-- m はJust 1である
Just 1 >>= return

-- >>= を適用
case (Just 1) of
  Just y -> return y
  Nothing -> Nothing

-- caseを処理する。 Just y にマッチする
return 1

-- returnを適用
Just 1
```

#### 右辺

```haskell
m

-- mはJust 1である
Just 1
```


### `m`が `Nothing`の場合

#### 右辺

```haskell
m >>= return

-- mはNothingである
Nothing >>= return

-- >>= を適用
case Nothing of
  Just y -> return y
  Nothing -> Nothing

--- caseを処理する。Nothingにマッチする
Nothing
```

#### 左辺

```haskell
m

-- mはNothingでらう
Nothing
```

左辺と右辺が一致した。

### まとめ

returnを使っても値が変化しないことが確認できました。

## (m >>= f) >>= g == m >>= (\x -> f x >>= g)

### `m` が `Just 1`の場合

#### 左辺

```haskell
(m >>= f) >>= g

-- m は Just 1である
(Just 1 >>= f) >>= g

-- 左の >>= を適用
(case Just 1 of
  Just y -> f y
  Nothing -> Nothing) >>= g

-- caseを処理する。Just y にマッチする
f 1 >>= g
```

#### 右辺

```haskell
m >>= (\x -> f x >>= g)

-- m は Just 1 である
Just 1 >>= (\x -> f x >>= g)

-- >>= を適用
case Just 1 of
  Just y -> (\x -> f x >>= g) y
  Nothing -> Nothing

-- caseを処理。 Just y にマッチする
(\x -> f x >>= g) 1

-- ラムダ式を処理する
f 1 >>= g
```

左辺に一致した

### `m` が `Nothing`の場合

#### 左辺

```haskell
(m >>= f) >>= g

-- m はNothingである
(Nothing >>= f) >>= g

-- 左の >>= を適用
(case Just 1 of
  Just y -> f y
  Nothing -> Nothing) >>= g

-- caseを処理する。Nothing にマッチする
Nothing >>= g

-- >>= を適用
case Nothing of
  Just y -> f y
  Nothing -> Nothing

-- caseを処理する。Nothingにマッチする
Nothing
```

#### 右辺

```haskell
m >>= (\x -> f x >>= g)

-- mはNothingである
Nothing >>= (\x -> f x >>= g)

-- >>= を適用
case Nothing of
  Just y -> (\x -> f x >>= g)
  Nothing -> Nothing

--- caseを処理する。Nothingにマッチする
Nothing
```

右辺と左辺が一致した

### まとめ

どちらの`>>=`を先につかっても結果が一致することが確認できました。

# 最後のまとめ

モナド則は `>>=` と `return` の性質を説明しているのに過ぎません。
`>>=` は `m a` を `a -> m a` という型の関数と組み合せて使えるようにする演算子です。
`return` はもっとも基本的な `a -> m a`です。

第１法則は `return x >>= f == f x >>= return` と書くと交換法則のようにみえますね
第２法則は `return`が単位元のようにみえますね。
第３法則は どちらの`>>=`を先に計算しても結果が一致する結合法則のようにみえますね。

ところで、登場した値は `m a`と `a -> m a` です。 `a -> m a` な値に、`m a`を使うと`a`をおきかえて `m a ->  m (m a)` になります。`m (m a)`という型が登場していますが、モナド則に現れません。`>>=`をつかって `a -> m a`を使うと `m (m a)`にならず、`m a`のままになるのがポイントです。
CakePHP3でSQLを直接実行した際に気がついたこと

過去に書いた記事のタイトル一覧を見ると、ニッチなものばかりですね。。
そうでもしないとtipsとして残せないのが悪いクセ。

# 今回のお題
表題の通りです。

CakePHP3でクエリビルダを使わずにSQL直書きでデータを取得するやり方は
すでにたくさんのブログなどで共有されていますが改めて。

## CakePHP3で直接SQLを実行する

```php:sss.controller.php

<?php

namespace App\Controller;

use Cake\Datasource\ConnectionManager;

class UserController extends AppController
{
    public function detail($id) {
        $sql = "SELECT * FROM users WHERE id = '${id}'";

        $connection = ConnectionManager::get('default');
        // 複数行を取得する場合はfetch → fetchall('assoc')にします
        $user = $connection->execute($sql)->fetch('assoc');
    }
}

```

ここまでは問題なくできました。
ハマったのはここから。
結合した複数テーブルからデータを取得しようとした際に起きました。

## CakePHP3で複数テーブルを結合したSQLを直接実行する

取得したい内容は以下のSQLを実行したものです。

```sql:console
mysql>
SELECT * 
FROM users 
LEFT JOIN companies ON companies.id = users.company_id
LEFT JOIN payments ON users.id = payments.user_id
WHERE users.id = 1;

+----+-------------+-----------+------------+---------------------+---------------------+----+-------------+---------------------+---------------------+----+---------+---------+---------------------+---------------------+
| id | family_name | last_name | company_id | created             | modified            | id | name        | created             | modified            | id | user_id | payment | created             | modified            |
+----+-------------+-----------+------------+---------------------+---------------------+----+-------------+---------------------+---------------------+----+---------+---------+---------------------+---------------------+
|  1 |         ○田 |        ○郎 |          2 | 2019-02-01 12:00:00 | 2019-03-01 10:00:00 |  2 | ほんにゃら商事 | 2019-02-01 13:00:00 | 2019-03-01 11:00:00 |  3 |       1 |   10800 | 2019-02-01 14:00:00 | 2019-02-01 14:00:00 |

```

これをCakePHP内で実行します。。。

```php:user.controller.php

<?php

namespace App\Controller;

use Cake\Datasource\ConnectionManager;

class UserController extends AppController
{
    public function detail($id) {
        $sql = "SELECT * FROM users "
             . "LEFT JOIN companies ON companies.id = users.company_id "
             . "LEFT JOIN payments ON users.id = payments.user_id "
             . "WHERE users.id = '${id}'";

        $connection = ConnectionManager::get('default');
        // 複数行を取得する場合はfetch → fetchall('assoc')にします
        $user = $connection->execute($sql)->fetch('assoc');
    }
}

```

実行結果をvar_dumpした結果がこちら。

```php:var_dump
array(1) { 
    [0]=> array(8) { 
        ["id"]=> string(1) "3"
        ["family_name"]=> string(6) "○田"
        ["last_name"]=> string(6) "○郎"
        ["created"]=> string(19) "2019-02-01 14:00:00"
        ["modified"]=> string(19) "2019-02-01 14:00:00"
        ["name"]=> string(21) "ほんにゃら商事"
        ["user_id"]=> string(1) "1"
        ["payment"]=> string(5) "10800"
    }
}
```
あれ、テーブルで共通したカラムがpaymentテーブルの内容になっている。。

ちなみに、joinの順番を入れ替えるとcompaniesのidなどが取得されました。
どうやら一番最後のテーブルの内容が反映される模様。
じゃあ、usersテーブルのidを取るには。。？

`SELECT companies,*, payments.*, users.* FROM users `

このクエリにするとjoinではなく、selectの順番で一番最後のテーブルの内容が反映されました。

本来であれば、全件取得するのならクエリビルダを使えば良いのですが、
あくまでも例文ということで。。
【Android】リリース後に課金できなくなっている事に気づく恐怖

# あらすじ(3/5の出来事)
 - 14:15　GooglePlayにAPKを公開。
 - 16:30　ストアに反映。ちょっと反映遅かったなとドキドキする。
 - 17:30　課金できない不具合発覚。盛大に慌てる:fearful:
 - 18:42　緊急的に前回までの課金がうまくいっている状態にbranchの状態を戻し再リリース。
 - 19:22　ストアに反映。とりあえず安堵する:relieved:
 
# しかしながら。。。
 - 19:22　ストアに反映されたもので確認したところ課金できず。
 - 19:30　試行錯誤をはじめる。(β版ってどうなってたっけ？アイテムID合ってる？)
 - 20:00　なぜか課金できない不具合が出てしまった最初のアプリで課金がうまくいくようになる
 - 21:10　**何もしていない**が**課金できる状態**になる:scream:

# 結果として課金はできるようになったが・・・
**「何もしてないのに直った」**の恐ろしさ。
**「さっきまで部屋にいたゴ◯ブリがいない」**の恐怖:scream:

画像がBadRequestで貼れなかったのですが、「指定したアイテムは購入できません」といったエラーでした。
何事も落ち着いて待つことが大事なのかもしれないと考えさせられた1日でした。

もしも同様の現象で悩まれた方には共有を・・・。GooglePlayってこういう事が結構あるんですかねぇ？僕は初めてでした。

ちゃんとした解決方法がわかる方いらっしゃいましたら教えていただけると嬉しいです。