OmniAICreator/Qiita-1.07M huggingface dataset:
電気系プログラミングガチ素人学生がC#のクラスを勉強する話　８日目~可変長引数の注意、値渡しと、参照渡し~

#まえがき
このレポートは「独習C＃」で学んだ内容をSkype勉強会での活動日誌として、「書面としてアウトプットする」こと、「電気系の学生の成果物を作るための意識高い系(笑)のレポート」です。完全初心者なので、勉強会参加者の先輩たちから様々なツッコミを頂きながら書いております。それゆえに先輩たちの目から外れた誤字脱字等ございますが、ぜひともツッコミいただいて、私の勉強にさせていただければと思います。

#可変長引数の注意！！
先週書いた可変長引数ですが、これには注意が有ります。
1. 可変長引数はメソッドに一つだけしか宣言が出来ない。さらに、この可変長引数は最後に配置をすること！
2. 想定される引数まで、可変長引数にまとめない。
3. 可変長引数で「一個以上の引数」を表す方法

## 1. 可変長引数はメソッドに一つだけしか宣言が出来ない。さらに、この可変長引数は最後に配置をすること！
以下の書き方はエラーですよ！

```C#
void Hoge(params int[] x, int y) //=>可変長引数が引数リストの末尾でない。
void Hoge(params int[] x, params int[] y) //=>可変長引数が複数ある
```

##2. 想定される引数まで、可変長引数にまとめない。
引数をまとめすぎると他人の手に渡った時に、可読性が死ぬ程落ちます。なので、構造上は可能ですが、絶対やめましょう。

##3. 可変長引数で「一個以上の引数」をあらわす方法
前回書いたコードで、可変長引数派、省略が可能となっています。
しかし、引数なしで呼び出す意味はありませんので、最低でも１個以上の引数を要求したいと思うかもしれません。
そんなときは、"ifで配列長を取得した時にエラーを出せばええやないかい"ってなるんですが、それでは<b>実行時</b>にエラーがスローされるので、問題はもっと早く検知すべきなので、引数を用意してから、可変長引数を入れ、その中で、最初の引数を別の引数に代入すると・・・出来ますが・・・

#値渡しと参照渡し
値渡しと、参照渡しはよくご存知かと。しかし、C＃では、データ型の値型/参照型が絡んでくると、

* 値型の参照渡し
* 参照型の値渡し
* 値型の値渡し
* 参照型の参照渡し

##値型の値渡し

```C#
using System;

namespace Basic
{
    class Program
    {
        public int CountUp(int data)
        {
            data++;
            return data;
        }
        static void Main(string[] args)
        {
            var data = 1; //上のCountUpのdataと、このdataは別物！
            var p = new Program();
            Console.WriteLine(p.CountUp(data));
            Console.WriteLine(data);
        }
    }
}
```

値渡しとは、実引数（呼び出し元の値）をメソッド側の仮引数にコピーすることを言います。

実行結果は以下のようになりました。

```
-------------------------------------------------------------------
You may only use the Microsoft .NET Core Debugger (vsdbg) with
Visual Studio Code, Visual Studio or Visual Studio for Mac software
to help you develop and test your applications.
-------------------------------------------------------------------
2
1
```
値渡しは他にも種類があるので、また次回！！！

#あとがき
最近Qiita Donで宣伝しまくってます！！そのおかげなのか、少し閲覧数は伸びました！
参加してみたいよ、仕方ねぇなぁ、いちやの勉強少しみてやるか・・・と思った方、検討してみてください！
お願いします！
PythonとOpenCVで動画送信

##環境
- Python 3.5.2
- OpenCV 3.1

 ```python:server.py
# -*- coding:utf-8 -*-
# !/usr/bin/python

import socketserver
import cv2
import socket
import sys
import numpy


class TCPHandler(socketserver.BaseRequestHandler):
    videoCap = ''

    # リクエストを受け取るたびに呼ばれる関数
    def handle(self):
        # クライアントからデータを受け取ったらJPEG圧縮した映像を文字列にして送信
        self.data = self.request.recv(1024).strip()

        # readするたびにビデオのフレームを取得
        ret, frame = videoCap.read()

        # jpegの圧縮率を設定 0～100値が高いほど高品質。何も指定しなければ95
        encode_param = [int(cv2.IMWRITE_JPEG_QUALITY), 100]

        # 文字列に変換
        jpegsByte = cv2.imencode('.jpeg', frame, encode_param)[1].tostring()
        self.request.send(jpegsByte)


# このプログラムを起動している端末のIPアドレス
HOST = "192.168.0.100"
PORT = 5569

# ビデオの設定
videoCap = cv2.VideoCapture('C:\test.mp4')

if not videoCap:
    print ("ビデオが開けませんでした。")
    sys.exit()

socketserver.TCPServer.allow_reuse_address = True
server = socketserver.TCPServer((HOST, PORT), TCPHandler)

try:
    server.serve_forever()
except KeyboardInterrupt:
    pass
server.shutdown()
sys.exit()
 ```

```python:client.py
# -*- coding:utf-8 -*-
#!/usr/bin/python
import socket  
import numpy  
import cv2  

  
def getimage():

    # 送信先のIPアドレスとポート番号を設定
    HOST = "192.168.0.100"
    PORT = 5569
    sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)  
    sock.connect((HOST,PORT))   
    sock.send(b'test')  
    
    # バイト型
    buf=b''   
    recvlen=100  
    while recvlen>0:  
        receivedstr=sock.recv(1024*8)  
        recvlen=len(receivedstr)  
        buf += receivedstr
    sock.close()

    narray=numpy.fromstring(buf,dtype='uint8')
    return cv2.imdecode(narray,1)

while True:  
    img = getimage()
    cv2.imshow('Capture',img)  

    # qを入力すれば処理終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
```
Reactボイラープレート2018年版

「[2018年は、reduxとeslintとflowとwebpackを捨ててみようと思う](https://qiita.com/wheatandcat/items/8b7742147588a33937b5
)」に触発されたので最近使っている構成を書こうと思う。割とやりたい放題。

リリース時の複雑性はAPIいくつか叩いて組み合わせて出すようなSPAマッシュアップサイト以上の規模で、後々スケールすることを想定している。

[ソースコード→ HibikineKage/react-boilerplate](https://github.com/HibikineKage/react-boilerplate)

[Redux入り版→ HibikineKage/react-redux-todo-sample](https://github.com/HibikineKage/react-redux-todo-sample)

## Stack

* React
* TypeScript
* Babel v7
* Webpack v4
* Sass
* ESLint
* Prettier
* Jest

以下は規模に応じてオプションで。

* Redux
* Redux Thunk
* Redux Saga

## 意図

Vueが流行っていてNuxt.jsも触って快適さを体感してはいるが、ソースコードの混沌度が高まってきたときのコンポーネントの分割のつらさでいえばReactの方がまだましなのでReactを選択している。

エコシステム周りもReactはVue, Angularと比べればだいぶ枯れてきているのも理由として挙げている。

AltJSはTypeScriptを選択。**型のないJSは1時間で書き捨てるようなコードだけでいいよ**。

Flowを使わない理由としては、単純にTypeScriptの方が型定義ファイルが多いことや、エディタの補完の強さを理由としている。特にVSCode使っている時にはFlowの設定が若干つらい。

TypeScriptのトランスパイラに任せてBabelは食わせなくてもいいが、極力ブラウザ側の機能で動かせるものは動かしたいので`@babel/env`を挟んでいる。

Webpackはv4になってだいぶ速くなった。Parcelは融通が利かないのと、サーバーサイドをTypeScript(Node.js)で書くときにどうしようもなくなるのでよほど書き捨てる場合でもない限りは使っていないし、一度Webpackも環境さえ組めばそれを使い回せばいいので結局使っていない。

最近はCSSはSassで書き、スタイルは[FLOCSS](https://github.com/hiloki/flocss)を採用している。

LinterはESLint, FormatterはPrettierで最近統一している。多少うざいこともあるが、C言語に戻ったときに手作業でフォーマットを直してるのがバカバカしくなるぐらいには快適。

Jestは遅いという点を除けば手抜きできるから使い続けている。エコシステムが一番まともに回っているテストツールだと(個人的に)思っているのが採用理由。

Reduxをオプションとしたのは、ReactのStateやContextで事が済むケースが多いため。型のつらさも倍増するので、必要に応じてReduxは入れれば良いと思う。

## 感想

早くNuxt.jsがもっと快適になってほしい。

何かあればコメントどうぞ。
Google Code Jam 2018 Qualification Round - Trouble Sort

# テンプレート

いろいろ試してみています。

```main.hs
solve :: Data d -> String

parse :: [String] -> [Data d]

main = interact $ unlines.f.lines
f (n:xs) = zipWith g [1..read n] $ parse xs
g i d = "Case #" ++ show i ++ ": " ++ solve d
```

今回はinteractを使ってみました。
solveとparseの型は前回と同じです。

parseの型を [String]->[String]にするのもありな気はしますが、mainのところにparseとsolveをそれぞれ明示的に書きたいと思って今回はこうしています。

# 方針

（こういう系は苦手です）
入力リストを、インデックスが偶数と奇数のリストに分ける
分けたそれぞれのリストをsortする
再度一つのリストにマージ
　=> これがTroubleSortの結果と同じになる
ソートされていない位置を探す

# 実装

```gcj.hs
import Control.Monad
import Data.List

merge [x] [] = []
merge ((a,_):xs) ys@((b,_):_) = (a, b) : merge ys xs

chk (es,os) = findIndex (\(a,b) -> a>b) $ merge (sort es) (sort os)

solve :: [Int] -> String
solve xs = case chk $ partition (even.snd) $ zip xs [0..] of
            (Just i) -> show i
            Nothing  -> "OK"

parse :: [String] -> [[Int]]
parse (_:x:xs) = (map read $ words x) : parse xs

main = interact $ unlines.f.lines
f (n:xs) = zipWith g [1..read n] $ parse xs
g i d = "Case #" ++ show i ++ ": " ++ solve d

```

## merge
引数をひっくり返しながら、それぞれのリストの先頭をタプルにしていく。
タブルにしているのは、後で順序チェックをする為。
ここで"(a,b)"のかわりに"a>b"にしちうのもありかな。

引数を交互に入れ替えながら再帰して行くやり方は面白いので今後も覚えておきたい。

あとこれ、foldrにしてたたみ込んでもよかったかも。

## chk
(偶数Indexのリスト, 奇数Indexのリスト)をそれぞれソートしてからマージして大小順が逆転している要素を探す。

## solve
リストを偶数Indexのリストと奇数Indexのリストに分けてchk関数でチェック。
Index用の[0..]を後ろにzipしているのは、分けたリストをそのままsortに渡してソートする為。
大小順が逆転していたら、Just iが返るのでそれが解答
逆転しているところがなければ、Nothingが返るので"OK"が解答
WindowsでMagic Trackpad2のジェスチャーを使う

githubで公開されているWindows用のドライバを使えば，MacBook or Magic Trackpad2でWindowsのジェスチャーが使えるようになる．
ドライバは以下のリンクから
[Windows Precision Touchpad Driver Implementation for Apple MacBook / Magic Trackpad](https://github.com/imbushuo/mac-precision-touchpad)

ただし，開発途中であるため，まだ対応していない機種があったり動作が不安定であったりするらしい．
また，Issueを見るとBluetooth接続には対応していないようだ．

今回は，Macではない普通のWindows機にドライバをインストールし，Magic Trackpad2のジェスチャーを使ってみた．

#インストール

- PCとMagic Trackpad2をUSBケーブルで繋ぐ
- 上記リンクのreleaseタブを開き，`Drivers.2358.zip`(2018.5.18時点)をダウンロードする
- zipを開き，`Drivers\x64\ReleaseSigned`内にある`AmtPtpDevice.cer`をダブルクリックし，インストールする
- `AmtPtpDevice`フォルダを開き，`AmtPtpDevice.inf`を右クリックしてインストールする

これでMagic Trackpad2のジェスチャーが使えるようになる．
感度やスクロールの向きなどの細かい設定は，`設定->デバイス->タッチパッド`から行える．

まだ感度に難があるが，スクロールや仮想デスクトップの切り替えがスムーズに行えるようになり，大変便利になった．
安定化やBluetooth対応などバージョンアップに期待したい．
React Native「No bundle URL present」エラー対策集

## ビルドキャッシュの削除

```
rm -rf ios/build
```

## パッケージの再インストール

```
rm -rf node_modules/ && yarn
```
## プロセスのkill

```
sudo lsof -i:8081
kill -9 プロセス番号
```
## packagerのキャッシュ削除
```
./node_modules/react-native/scripts/packager.sh --reset-cache
```


## デバッグビルドなのにリリース用の書き方をしている
```
  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
//  jsCodeLocation = [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"]; //こっちはリリース用
```
AWS Webアプリ公開②~Ruby環境構築編~

#前説
最初、環境構築とは作業だと思う。いずれは理解が必要なのでEC2でデプロイするついでに残しておこう。


#EC2使い始め

前回の記事でSSHを行ったかと思いますが、その続きです。

yumが入ってないので。あとその仲間たち。

```:Terminal
$ sudo yum install 
$ git make gcc-c++ patch libyaml-devel libffi-devel libicu-devel zlib-devel readline-devel mysql-server mysql-devel  

----

yes
```

##node.jsのインストール

環境構築で〇〇の動作をさせたいとなった時にnode.jsは結構使う。

```:Terminal
$ sudo curl -sL https://rpm.nodesource.com/setup_6.x | sudo bash -
$ sudo yum install -y nodejs
```

##rbenvの導入
rbenvとはrubyのバージョンを環境ごとに管理してくれるパッケージ。対抗にrvmという奴がいるらしい。

隠しディレクトリ.rbenvにgitからrbenvをクローンしてきます。

```:Terminal
$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv 
```

パス設定を行っていますが、ここで詳細を説明します。
.bash_profile設定ファイルにパス設定「$HOME~」を書き込んでいます。
次にrbenvを初期化していますが、[この記事](https://ja.stackoverflow.com/questions/32043/xxxenv-%E3%81%AE%E5%88%9D%E6%9C%9F%E5%8C%96%E6%99%82%E3%81%AEeval-xxxenv-init-%E3%81%AE%E6%84%8F%E5%91%B3)を見ているととてもわかりやすいです。


```:Terminal
$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bash_profile 
$ echo 'eval "$(rbenv init -)"' >> ~/.bash_profile
$ source .bash_profile
```

ruby-buildとはrbenv installを使えるようにするために必要なプラグイン。
UNIX環境でRubyを使う時に推奨されている。
rbenv rehashについては[こちらの記事](http://dqn.sakusakutto.jp/2014/02/rbenv_rehash_what_it_does.html)を参考に。

ここでは奥深くに眠るコマンド群を使えるようにしてくれているらしい。
環境の再設定と呼ぶのが最も適切なのかもしれない。

```:Terminal
$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build 
$ rbenv rehash
```

##rubyのインストール

rbenvでインストール。

```:Terminal
$ rbenv install -v (version)
$ rbenv global (version)
$ rbenv rehash
$ bundle gem install
$ ruby -v
```
#参考記事
https://qiita.com/yunzeroin/items/33a51c805e60ed5eca0e
新しくRails.env追加したいけどDBやElasticacheの新規インスタンスを作りたくない時

あまり需要のないテーマかもしれませんが、
Production/Staging/Development/Test
という４つの環境があるときに、
「動作確認のため、もう１つStaging環境が欲しい。インスタンス新しく作るとお金かかるし、手軽に実現したい」
というような時のためのメモです。

なお、Rails5, sidekiq, Elasticache, RDSを使っています。

手順は
1, gem 'redis-namespace' 追加
2, config/database.ymlに新しいenv(以後new_envと呼ぶ)
3, config/secrets.ymlにnew_envのsecret_key_baseを追加
4, config/environment/new_env.rbを追加
5, config/settings.ymlにstagingを追加
6, config/initializers/cors.rbでAPIを制御
(2~6は通常のenvを追加する手順、[こちら](https://qiita.com/yusabana/items/a1f4fe2c37b20db2a3f6)を参照)
7, config/initializers/sidekiq.rbを編集
8, envで環境変数を設定

6,7を解説します。

## sidekiq.rbを編集
Elasticacheの新たなインスタンスを立てずとも、以下のようにnamespaceを書くと、redisの〇〇-staging内で勝手に分けてくれるらしいです。すごい。

```ruby:sidekiq
Sidekiq.configure_server do |config|
  config.redis = { url: 'redis://hego', namespace: "sidekiq_#{Rails.env}" }
end

Sidekiq.configure_client do |config|
  config.redis = { url: 'redis://hoge', namespace: "sidekiq_#{Rails.env}" }
end
```

## envで環境変数を設定
新しい環境を作ったからといっても、動作確認用の環境なら新たなDBインスタンスを立てるまでもありません。RDSの〇〇-stagingというDBの中にrds_stagingとrds_new_envというデータベースを作れば、あとは環境変数のRDS_DB_NAMEを変えるだけです。

```.env
RDS_DB_NAME=rds_new_env
```

この辺りの経験値が少ないので、間違いなどご指摘ありましたらよろしくお願いいたします。
Pythonを使って複数画像をPDFに変換する

この記事は、Pythonを使って複数の画像を一つのPDFにまとめたいと考えているユーザーに向けたものです。
以前の公開コードをPython3で試したら動作しなくなっていたので、Python3ユーザー向けに更新しています。
## 前提
macOS Catalina (10.15.6)
python 3.7.5

## 事前準備
img2pdfをインストールします。
https://pypi.org/project/img2pdf/

```py
pip3 install img2pdf
```
インストールに成功したことを確認

```
Installing collected packages: Pillow, img2pdf
    Running setup.py install for img2pdf ... done
Successfully installed Pillow-7.2.0 img2pdf-0.4.0
```

## 画像をPDFに変換する

以下のスクリプトを記述します。ここではファイル名を convert2pdf.py とします。

```py:convert2pdf.py
import os
import img2pdf
from PIL import Image # img2pdfと一緒にインストールされたPillowを使います

if __name__ == '__main__':
    pdf_FileName = "/tmp/png/output.pdf" # 出力するPDFの名前
    png_Folder = "/tmp/png/" # 画像フォルダ
    extension  = ".png" # 拡張子がPNGのものを対象

    with open(pdf_FileName,"wb") as f:
        # 画像フォルダの中にあるPNGファイルを取得し配列に追加、バイナリ形式でファイルに書き込む
        f.write(img2pdf.convert([Image.open(png_Folder+j).filename for j in os.listdir(png_Folder)if j.endswith(extension)]))
```
python3で上記コードを実行します。output.pdfが生成されます。

```py
python3 convert2pdf.py
```

最後までお読みいただきましてありがとうございました。

### 参考
https://pillow.readthedocs.io/en/stable/
https://www.geeksforgeeks.org/python-convert-image-to-pdf-using-img2pdf-module/


# 以前の記事

以下の内容は Windows7, Python2.xで確認した内容です。

複数の画像を一つのPDFに変換する方法を説明します。


```py
pip install img2pdf
```

次に以下のスクリプトを記述します。このスクリプトは、特定のフォルダ（例 c:\python\pdf）にある png ファイルを output.pdf に追加します。

```py
import os
import img2pdf

if __name__ == '__main__':
    pdfFileName = "output.pdf"
    path = "C:\\python\\pdf"
    ext  = ".png"

    with open(pdfFileName, "wb") as f:
        f.write(img2pdf.convert([i for i in os.listdir(path)if i.endswith(ext)]))
```
DialogflowからSlackのBotとして動かす

簡単に制御するための覚え書き
![download.png](https://qiita-image-store.s3.amazonaws.com/0/122121/093c0cfc-1f6e-0d50-03f0-9e5ddca615e4.png)
前回の「まずはDialogflowを触ってみる」をSlackのBotとして動作させます。
https://qiita.com/sanoh/items/efd99ebbdee294a7beb3
■使用するSlackの確認
---
今回テスト用に「dialogflowBotTest」 というのを用意しました。
![2018-05-18 (2).png](https://qiita-image-store.s3.amazonaws.com/0/122121/a44ccfb3-5c85-22e6-7810-87b07abcf04c.png)
■Dialogflowから設定
---
Dialogflowの左メニューの「Integrations」を選択し、Slackの下のスイッチをOnにします。
![2018-05-18 (3).png](https://qiita-image-store.s3.amazonaws.com/0/122121/03394e7e-1eab-295b-8e15-22c5c6dff090.png)
■Slackの設定をOnにすると以下のような画面が現れるので「Slack app」を押します。
---
![2018-05-18 (4).png](https://qiita-image-store.s3.amazonaws.com/0/122121/a9302405-c0b7-0dc4-4c8b-cd2af687541b.png)
■Slackとのつなぎこみ
---
以下のような画面がでてきたら
App Nameに「foodtest01」これはDialogflowのAgentの名前です。
Development Slack Workspaceには今回しようするSlack「dealogflowBotTest」を設定 
その設定ができたら「Create App」を押し、設定情報を作成します。
■設定情報取得
---
以下のような画面がでてきたら、下の方に
![2018-05-18 (9).png](https://qiita-image-store.s3.amazonaws.com/0/122121/59f51fae-b820-fd0c-844f-909b3a11af53.png)
このような画面があるので、今回、「Client ID」「Client Secret」「Verification Token」が必要になります。
![2018-05-18 (12).png](https://qiita-image-store.s3.amazonaws.com/0/122121/8930f486-effb-0319-0391-1350c6a19500.png)
■
---
Dialogflowの画面にもどりSlackの設定部分で先ほど取得した「Client ID」「Client Secret」「Verification Token」
を設定し「START」させます。
![2018-05-18 (13).png](https://qiita-image-store.s3.amazonaws.com/0/122121/d492fc8c-3b92-73f5-d267-a1e039d87cf7.png)
■つなぎこみテスト
---
DialogflowのSlack設定の「TEST IN SLACK」を押すことでテストを開始できます。
![2018-05-18 (15).png](https://qiita-image-store.s3.amazonaws.com/0/122121/b48b18b6-83f9-99da-dd56-3dd1e4150570.png)
この画面が出たら「許可する」を押すとSlackにつながります。
Slackにんな「Dialogflow Bot」が追加されていれば成功です。
![2018-05-18 (18).png](https://qiita-image-store.s3.amazonaws.com/0/122121/b614cd55-1f9a-7b0e-27f8-210cc8c59856.png)
■Botで遊ぶ
---
「Dialogflow Bot」に個別チャットをすれば、いままでと同じ反応をします。
![2018-05-18 (19).png](https://qiita-image-store.s3.amazonaws.com/0/122121/3a29e302-cf8c-a945-8730-ccb09a2e3729.png)
Progateでは教えてくれなかったRuby on Railsのリレーションを調べてみた

## はじめに
30歳のフリーランスのエンジニア ゆっけ([@prg_yukke](https://twitter.com/prg_yukke))です。
生粋のPHPerでしたが、クライアントからRuby on Railsの案件の打診があっため、最近はやっているらしい[Progate](http://prog-8.com/)のRubyとRuby on Railsコースを学習してみました。
が、本当に初心者用の内容だったのか、リレーションの説明がないまま終わってしまったため、もやもやしていたので調べてみました。
つたない文章なので30歳のエンジニアがなんか言ってたなくらい覚えていてください。

## 読者想定
- 私と同様に、ProgateにてRoRを学習を終了した人

## RoRのリレーションについて
まず、RoRではリレーションとは言わず、アソシエーションと言います。
Laravelerな私にはあまり言い慣れませんが、CakePHPでもアソシエーションでした。

という事で改めて、

## RoRのアソシエーションについて
### Progateにおけるモデルの関連付け
ProgateのRoRレッスンでは、
`User`モデルが所有する`Post`モデルの取得については、`User`モデル内の`where`で、
`Post`モデルを所有している`User`モデルの取得については、`Post`モデル内の`find_by`で定義しています。

`User`モデル

```
class User < ApplicationRecord
  has_secure_password

  validates :name, {presence: true}
  validates :email, {presence: true, uniqueness: true}

  def posts
    return Post.where(user_id: self.id)
  end

end
```

`Post`モデル

```
class Post < ApplicationRecord
  validates :content, {presence: true, length: {maximum: 140}}
  validates :user_id, {presence: true}

  def user
    return User.find_by(id: self.user_id)
  end

end
```

### アソシエーションへの書き換え
RoRでは、このようなモデル同士の関連付けをするのに便利な機能があります。
それがアソシエーションです。
モデルの定義に下記の6種類を使用することで、モデル同士の関連付けを簡単に行なえます。
- belongs_to
- has_one
- has_many
- has_many :through
- has_one :through
- has_and_belongs_to_many

今回のモデルを再確認してみると、
`User`は`Post`を複数所有し、`Post`は`User`に所有されています。
つまり、`User`対`Post`は一対多の関係です。

#### `has_many` : 他モデルを複数所有している場合
他モデルを複数所有している際のアソシエーションには、`has_many`を使用し、
`has_many :モデル名の複数形`の形で記載します。

このため、`User`モデルは下記の形に書き換えられます。


- `User`モデル

```
class User < ApplicationRecord
  has_secure_password

  validates :name, {presence: true}
  validates :email, {presence: true, uniqueness: true}

  has_many :posts

end
```

#### `belongs_to` : 他モデルに所有されている場合
逆に今回の`Post`モデルの様に他モデルから所有されている場合、
`belongs_to`を使用し、`belongs_to :モデル名の単数形`の形で記載します。

`belongs_to`を使用した`Post`モデルは下記のとおりです。


- `Post`モデル

```
class Post < ApplicationRecord
  validates :content, {presence: true, length: {maximum: 140}}
  validates :user_id, {presence: true}

  belongs_to :user

end
```

## まとめ
LaravelやCakePHPがRoRを参考にしただけあり、言語仕様による書き方の際はありますが、リレーションの形はほぼ変わらずでした。

アソシエーションを使用することで、モデル内にクエリビルダを記載せずに他モデルとの関連付けが可能になりますので積極的に使用してみてください。

`has_many`と`belongs_to`の他、
一対一のアソシエーションには`has_one`を、
結合モデルが介在する場合は`has_many :through`, `has_one :through`、
多対多の場合には`has_and_belongs_to_many`を使用しアソシエーションの定義が可能です。

詳しくは、Rails Guideの[Active Record の関連付け (アソシエーション)](https://railsguides.jp/association_basics.html#has-and-belongs-to-many%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%81%AE%E8%A9%B3%E7%B4%B0)を御覧ください。
MetaMask のアカウント（アドレス）切り替えを検知

* MetaMask は複数アカウント（アドレス）を管理できる
* web3 に MetaMask が inject しているとき、ユーザがアカウントを切り替えたことを検知したいことがある
* いろいろ方法しらべてみたけど、次のような原始的な方法を使う感じになりそう。

# サンプルコード

```js
var web3 = new Web3(web3.currentProvider);
var account = '';
var accountInterval = setInterval(function() {
  if (web3.eth.accounts[0] !== account) {
    // MetaMask のアカウント（アドレス）が切り替わった
    account = web3.eth.accounts[0];
  }
}, 300);
```

# デモ
* [https://piyolab.github.io/playground/ethereum/getMetaMaskAddress/](https://piyolab.github.io/playground/ethereum/getMetaMaskAddress/)

# Note
- Ethereum 関連の情報は https://scrapbox.io/sushiether/ に集約することにしました。
- この記事の内容に変更・更新がある場合は、以下の URL を更新します。
- https://scrapbox.io/sushiether/MetaMask_のアカウント（アドレス）切り替えを検知
"Error : 413 Request Entity Too Large"が出たときに

pythonのwebアプリ用フレームワークbottleに関するエラーのメモ。
<br>
POSTでサーバにデータを送った時に、

"Error : 413 Request Entity Too Large"

容量でかすぎて送れないよ！
と怒られたので、調べてみたら

https://stackoverflow.com/questions/16865997/python-bottle-module-causes-error-413-request-entity-too-large

この記事の通り

```python

bottle.BaseRequest.MEMFILE_MAX = バイトサイズ
```

でデフォルト（102400）より大きい値を設定したら怒られなくなりました。
【PowerBI】構造が同じ複数のCSVファイルを簡単に一元化して管理する

#はじめに
PowerBIではデータ構造が同じ複数のCSVファイル等を簡単に一元化して取り扱う事ができます。

対象となるCSVファイルを特定のフォルダにまとめておく事で可能となるのですが、そのフォルダに後からどんどんファイルを追加しても、PowerBIのデータ更新ボタンを押すだけでデータが反映されるようになります。

例えばこのような複数のExcelファイルが…

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/0ae3057a-8453-fc2d-0de1-dbb60a32cf3d.png)|
|:-:|

PowerBIで結合するとこうなります ↓↓↓↓↓

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/545d89c7-2e59-8619-62c8-a35647104ff0.png)|
|:-:|

毎月集計が必要なデータなどを取り扱う際、そのままひと月分のデータをフォルダに入れるだけなので楽ですね。

#やり方
PowerBIを起動したら「データを取得」を選択

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/80a380d3-46a1-d51e-e566-f708d3b461ff.png)|
|:-:|

データ取得画面で「フォルダー」を選択

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/cde4960f-1ffb-aeb2-2690-8cb114e0943c.png)|
|:-:|

対象ファイルがまとまっているフォルダーを指定

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/65d6a61c-8668-e41c-f84e-625b0f87b35b.png)|
|:-:|

とりあえず何も考えずに「結合および編集」を選択

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/317e0b0e-ae20-c49e-a02f-d22e6a482242.png)|
|:-:|

対象とするデータオブジェクトを選択してOKを押す
※モデルとして最初のファイルが表示されているので、今回はテーブル1を選択
　今後追加するファイルからもテーブル1が参照されます

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/a173f1fe-6832-6dcb-7452-469da980aafa.png)|
|:-:|

これで↓のように複数のデータファイルから一つのテーブルが作成されます。

|![image.png](https://qiita-image-store.s3.amazonaws.com/0/253746/545d89c7-2e59-8619-62c8-a35647104ff0.png)|
|:-:|

今後は先ほど指定したフォルダにCSVファイルを追加⇒「最新の情報に更新」ボタンを押すだけで一元化されます。
部分適応とカリー化

## 部分適用
部分適用とは一部の引数を固定化して新しい関数を作り出すこと

```js
function add(a, b) {
    return a + b
}

// 部分適用
function newAdd(a) {
    return add(1, b)
}

newAdd(2) // 3
```

## カリー化
関数を引数1つずつに分割してネストさせること
カリー化すると部分適用が簡単に出来る

```js
// カリー化
function add(a) {
    return function(b) {
        return a + b
    }
}

add(1)(2) // 3

let newAdd = add(1)

newAdd(2) //3
```
BackstopJSを使って、CSSをテストをする

# こういうときに便利
* 軽微だけれども影響範囲が広い修正の確認（コンポーネントレベルの修正がどこまで影響するか…というような）
* リファクタリングを実施した場合に、修正前後で表示に差異がないかの確認
* 既存ページのスクリーンショットの取得

# BackstopJSとは
修正前後のスクリーンショットを比較して、差分を検出するツール

# 使い方

## 1. グローバルにインストールする（homeディレクトリ推奨）

`$npm install -g backstopjs`

## 2. backstopJSを初期化する
BackstopJSが設定されていない場合は、以下のコマンドでデフォルトの設定ファイル（`backstop.json`）を生成出来る。
既に設定されている場合は、上書きされるので注意すること。

`$cd toYourProject`
`$backstop init`

## 3. `backstop.json` に、テストを設定する

#### 必須項目

##### `id` - 生成されるスクリーンショット名
##### `viewport` - スクリーンの大きさ、最低1つ以上を設定

```
  "viewports": [{
      "label": "phone",
      "width": 375,
      "height": 480
    },
    {
      "label": "pc",
      "width": 1280,
      "height": 768
    }
  ],
```

##### `scenarios` - テスト項目
`label` と `url` が必須項目で、それ以外はオプション

```
"scenarios": [{
      "label": "TOP", // [必須]画面名、日本語だと化けるので英語推奨
      "cookiePath": "backstop_data/engine_scripts/cookies.json",　// cookie
      "url": "http://localhost:8888/index.html", // [必須]対象となるURL
      "referenceUrl": "", // 修正前（公開されている)同じ画面のURL
      "readyEvent": "",
      "readySelector": "",
      "delay": 0, // 表示後、数秒経った後でスクリーンショットを撮る場合の秒数（ミリ秒）
      "hideSelectors": [], // visibility: hidden したいセレクタ、iframeとかに便利
      "removeSelectors": [], // display: none したいセレクタ
      "hoverSelector": "", 
      "clickSelector": "",
      "postInteractionWait": 0,
      "selectors": [],
      "selectorExpansion": true,
      "misMatchThreshold": 0.1,
      "requireSameDimensions": true
    }
]
```

## 4. 修正前の状態でテストを実施して、スクリーンショットを取得する
`$backstop reference`

→ `backstop_data/bitmaps_reference` にスクリーンショットが保存されていく

## 5. 修正後の状態でテストを実施する
`$backstop test`

`backstop_data/bitmaps_test/yyyymmdd-hhmmss`にスクリーンショットが保存されていき、
最後に`bitmaps_reference`との比較が行われ、ターミナル上とブラウザで差分が確認出来る


# 雑感
画面数が多いと、実行時間が10分以上になり、その間結構暇…。目視することを考えれば100倍マシ。
テストの設定のために複数回事前に実施して、想定している結果が得られるように設定を調整すると良さそう。


# 参考URL
BackstopJS を利用した Visual Regression Testing の感想と工夫ポイント - upinetree's memo
http://upinetree.hatenablog.com/entry/2018/05/13/231951

Visual RegressionテストによるWebデザイン崩れの防止 - LCL Engineers' Blog
http://techblog.lclco.com/entry/2017/01/02/204804
エリック・エヴァンスのドメイン駆動設計　第3部~第8章まとめ

# 第3部 より深い洞察へ向かうリファクタリング

---

## 第2部の振り返り

モデルと実装との一致を保つための基礎の説明。
　→　こんな感じでプログラム作ったら良い感じになるよ的な感じ

## 第3部でやること

DDDで一番大事なのは的確なモデルを実際に**見つける**(作成する)こと
また、見つけたモデルをみんなで**リファクタリング**し続けなくてはならないよ
だから第3部ではそのやり方を実際の例とか見せながら説明するよ！

---

## 各章のざっくり概要

|章|タイトル|概要|
|:-----:|:-----:|:-----:|
|８章|ブレイクスルー|[導入]成功体験紹介|
|９章|暗黙的な概念を明示的にする|ドメインの中心となる モデルを探しだす|
|10章|しなやかな設計|モデルを設計に取り込む方法|
|11章|アナリシスパターンを適用する|見出した概念のモデル化に既存のパターンを利用する|
|12章|デザインパターンを方法の紹介|モデルに関連づける|
|13章|より深い洞察に向かう|リファクタリングまとめ|
> 引用：https://www.slideshare.net/akimicyu/20141025-ddd

---

# 第8章 ブレイクスルー

---

## ブレイクスルーとは

リファクタリングをすると基本的には小さい努力に対してわずかな収穫がある
でもたまにプロジェクトに衝撃を与えるほどの収穫が得られる時がある
　→　それが**ブレイクスルー**　

---

## 実際にあったブレイクスルー例(1/4)

- 事例：投資銀行のシンジゲートローン管理

シンジケートローンとは、お客さまの資金調達ニーズに対し複数の金融機関が協調してシンジケート団を組成し、一つの融資契約書に基づき同一条件で融資を行う資金調達手法です
　→　金額がでかすぎるので複数の金融機関が金を出して金を貸す的なこと
　→　合計10億貸すうち、A社が5億、B社が3億、C社が2億とか

---

## 実際にあったブレイクスルー例(2/4)

- 最初は貸し手の分担率を固定にしていた

合計10億貸すうち、A社が5億、B社が3億、C社が2億だったら。
「A:B:C = 5:3:2」でずっと固定
![IMG_2223.JPG](https://qiita-image-store.s3.amazonaws.com/0/70276/2797a0ee-ebcc-f240-35fa-44c8fa21d82d.jpeg)

---

## 実際にあったブレイクスルー例(3/4)

- しかし、実際のビジネスだと途中で分担率が変更される
- なので新しく[ローン調整]というモデルを作成した。
- そうすると、分担率に変化があるたびに[ローン調整]が複雑になっていく
- なんか辛くない？
![IMG_2224.JPG](https://qiita-image-store.s3.amazonaws.com/0/70276/3eb87cad-8c20-b75f-8890-06f736397947.jpeg)

---

## 実際にあったブレイクスルー例(4/4)

- 分担率が変化していくのではなく「ファシリティの分担率」、「ローンの分担率」、「手数料の分担率」などの様々な分担率が存在している
- **変更前のモデル：**分担率から算出された各社のローン出資額について、各社で金額調整を行う。
- **変更後のモデル：**ファシリティ分担率に応じた出資額を 負担するかの意思決定を、毎回の出資ごとに各社が行う。その結果としてローンの分担率が確定する
- この洞察が大きなブレイクスルー

---

## 実際にあったブレイクスルー例まとめ

- しかし、ブレイクスルーが起きたハッピー！とはならない
- なぜなら**ブレイクスルー = モデルの大幅な改善**だから
- つまりブレイクスルーを実装に落とし込むのは結構つらい
- 実際にあった例ではPMとMTGして、3週間時間をもらい歯を食いしばって実装したらしい
- ただ、プログラムが簡潔になっただけでなくビジネス側の説明も簡潔になったので様々な部門での説明コストがめっちゃ減ったよ

---

## 最後に

- ブレイクスルーは適度なリファクタリングを繰り返すことで発生する。狙ってやることではない。
- ブレイクスルーを起こすためには、ユビキタス言語を育成したり、ドメインを探求してそれをモデルで明示したり(9章)、設計を改良したり(10章)、モデルを蒸留したり(15章)する必要がある　
- **ブレイクスルー ≠ ゴール**　ブレイクスルーの先にもまたブレイクスルーがある

---

# 参考
エリック・エヴァンスのドメイン駆動設計 読書メモ3 - Qiita
https://qiita.com/kawachi/items/8da66cda3fb63c098a78
エリック・エヴァンスのドメイン駆動設計 第３部〜８章まで
https://www.slideshare.net/akimicyu/20141025-ddd
VagrantでWordpressの環境構築をする

## 概要
Wordpressのサーバー移転（ローカル→本番）を行った際の作業メモになります。
まずはローカルの構築編。
※表現等に誤りがあるかもしれませんが、その点についてはご容赦いただき、暖かくご指摘のコメントをいただければ幸いです。

## 作業環境
- macOS High Sierra 10.13.3

## 前提
- VirtualBox
- Vagrant
をインストールしていること。

※インストール方法がわからない場合はドットインストールさんの[「ローカル開発環境の構築　Windows編」](https://dotinstall.com/lessons/basic_localdev_win_v2), [「ローカル開発環境の構築　macOS編」](https://dotinstall.com/lessons/basic_localdev_mac_v2)を参考にしていただければ割とすんなり行くのではないでしょうか？

## ローカル環境構築
[VCCW](http://vccw.cc/)に書いてある通り進めていきます。


```
$ pwd
/Users/個人毎に異なります/myvagrant/vccw
```

```
$ vagrant plugin install vagrant-hostsupdater
Installing the 'vagrant-hostsupdater' plugin. This can take a few minutes...
Installed the plugin 'vagrant-hostsupdater (1.0.2)'!
```

```
$ vagrant box add vccw-team/xenial64
```

[zipファイルをダウンロード](https://github.com/vccw-team/vccw/releases/download/3.17.0/vccw-3.17.0.zip)（今回は「vccw-3.17.0.zip」がDLされます）
/Users/個人毎に異なります/myvagrant/vccwの配下で解凍してあげます。
解凍すると「vccw」というファイル名のものが出てくるので「vccw-3.17.0」としてあげます。

```
$ cd vccw-3.17.0
```

```
$ vagrant up
```
初回だとおそらくPCの管理者権限のパスワードをパスワードを求められます。
5分ほどで諸々が完了します。うまく言ったかどうかは[こちら（http://192.168.33.10/）](http://192.168.33.10/)で確認できます。
エラー等がなく、「Welcome to the VCCW」というメッセージとともにWordpressの画面が出てきていればOKです。

今回自動でされる設定は

```
Wordpress Default user
Username: admin
Password: admin
```
```
MySQL
MySQL Host: 127.0.0.1
Username: wordpress or root
Password: wordpress
Port: 3306
```
```
vagrant ssh
Host: vccw.test or 192.168.33.10
Username: vagrant
Password: vagrant
Port: 22
```

provision/default.ymlをコピーして、コピーしたものをsite.ymlにリネームするコマンドを打ちます。

```
$ pwd
/Users/個人毎に異なります/myvagrant/vccw/vccw-3.17.0
$ cp provision/default.yml site.yml
```

作ったsite.ymlの中身を確認し、以下の部分で該当する部分を修正・追記していく

```
hostname: example.com
ip: 192.168.33.11
lang: ja
plugins:
  - contact-form-7
  - jetpack
```

再度```$ vagrant up```を実行。
ipが変わっているので、また少し時間がかかりパスワードも求められると思います。
完了したら、確認のために今度は[こちら（http://192.168.33.11/）](http://192.168.33.11/)にアクセスします。
うまく変更が効いていれば、サイトの右側あたりが日本語表記になってるかと思います。

wordpressの管理画面へは[こちら](http://192.168.33.11/wp-admin)からいけます。

ローカルの構築編は以上になります。
皆様のお役に立てれば幸いです。
HTML5とjQueryでrequiredでチェックを行った後、formをsubmitする

- requiredが動いた後、formをsubmitしています。
- また、二重submitできないようにbuttonのdisabledをtrueにしています。

``` test.html
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta http-equiv="X-UA-Compatible" content="ie=edge">
  <title>Document</title>
</head>
<body>
  <form method="post" id="hogeForm">
    <input type="text" name="hoge1" required>
    <input type="text" name="hoge2" required>
    <button type="submit" class="btn-send">送信</button>
  </form>
</body>
<script src="/js/jquery.min.js"></script>
<script>
  $(function() {
    $('#hogeForm').submit(function(e) {
      $('.btn-send').prop('disabled', true);
    });
  });
</script>
</html>
```
CentOS7系 + nginx keep-aliveをoffにした話

# はじめに

### 環境

- asianux7（※CentOS7.2相当）※ゲストOS（検証用）
- Windows10 Professional ※ホストOS（検証用）
- VirtualBox5.2.6
- Vagrant2.0.1
- nginx 10.12.2
- Apache httpd 2.4.29（比較用）
- Apache JMeter 4.0 （負荷ツール）

### 長文なのでひとことで（忙しい人向け）

APIサービス提供など軽量なデータを扱うwebサーバではkeep-aliveはoffにした方が良いと思うよ。

### 本記事の目的

本番で起きたリクエストエラーの対策としてkeep-aliveをoffにしました。その際の経緯などを備忘録として記載します。
事象が起きたのはnginxですがApache httpdでも同様の事象が起きるかどうか検証しました。

# 本番作業時におきたこと

### nginxの設定ファイル変更を反映させたよ

nginxの設定ファイルを少し変更したのでnginxをリロードしました（合計4回実施）

`$ sudo systemctl reload nginx`

夜間作業でしたが、特にトラブルもなく（と思った）作業終了しました。

### 翌日クライアントサイドから連絡があったよ

クライアント側（お客様）からリクエストが数件エラーとなった旨のメール連絡がありました。
エラーのタイミングは計2回で発生時刻はnginxリロードの時刻と同じでした。やってもうたか！

### nginxのaccessログを確認してみたよ

accessログをみましたがHTTPステータスは全て200で特にエラーはみつかりませんでした。
errorログも出ていません。

### 事象をまとめてみるよ

事象は以下です。

- クライアント側には正常なレスポンスが返っていない。（クライアント側からは詳しいエラー情報を聞き出せなかった）
- サーバ側はリクエストを受け取っていない。
- 何度かリロード作業を行っているが必ず発生するわけではなく通信流量が多いときに発生する傾向があった。

# 再現試験実施

### 再現試験準備

事象から負荷が高い時にnginxをreloadすると起きると仮定しました。
※高いといっても秒間数件程度です
負荷をかけるツールは色々あると思いますが、昔から慣れ親しんだApache JMeterを使いました。
nginxとは別にApache httpdでも同じ条件で実施して比べてみました。

### 負荷設定

1TPSと10TPSの負荷設定で60秒間リクエストを投げる。その間に各webサーバのリロードを実施してみる。
①nginx 1TPS
②Apache httpd 1TPS
③nginx 10TPS
④Apache httpd 10TPS

### 再現試験結果

①nginx 1TPS ⇒ 再現せず
②Apache 1TPS　⇒　再現せず
③nginx 10TPS　⇒　再現！
④Apache httpd 10TPS　⇒再現せず

### エラー内容

JMeterで発生しているエラーは `org.apache.http.NoHttpResponseException` でした。
3スレッド使ってリクエストしていますが3件エラーということは各スレッドのリクエストがリロードのタイミングでエラーとなっているということ。
nginx側のログに記録がないという事と合わせ、この結果はサーバ側からコネクションが一方的に切られている様にみえます。乱暴だなnginx君！

### 考察

HTTP1.1の場合、デフォルトでkeep-alive（持続的な接続）が有効となります。
この場合webサーバからのレスポンスヘッダでConnection:keep-aliveを返して同じコネクションを使う様にクライアントに指示をしていますが、上記の結果からクライアントはnginxに裏切られている（勝手にコネクションを閉じられる）形です。

# 対策

### keep-aliveをオフにする

今回の対象のサーバは1リクエストあたり100バイトほどのデータのやり取りしかしてなく、スループットも最大100TPS程度なのでkeep-aliveで性能向上を求める必要もなく、運用重視で迷うことなくkeep-aliveをoffにすることにしました。
Apache JMeterでの試験でもエラーは起きなくなりました。
本番環境でその後何度もnginxのreloadを実施しましたが同様のエラーが再現することはなくなりました。

### nginxの設定

nginxのkeep-aliveのON/OFFとkeep-aliveタイムアウトの設定は同じディレクティブで行います。0がOFFです。
該当ディレクティブ省略時のデフォルト値は75（75秒間同じ接続を使いまわす）です。

```
    keepalive_timeout  0;
```

### Apache httpdの設定

Apacheのkeep-aliveの設定は素直にOn/Off。
ディレクティブ省略時のデフォルトはOnです。

```
    KeepAlive Off
```

keep-aliveタイムアウトの設定は別のディレクティブで設定します。
省略時のデフォルト値は5（秒）です。

```
    KeepAliveTimeout 65
```

# おわりに

nginxは軽量で性能面ではApacheより優秀なwebサーバと思いますが、思わぬ罠が潜んでいることを思い知りました。
エラーになってもブラウザから再リクエストすれば良いサービスであれば問題ないですが、絶対エラーが許されないサービスの場合は安全サイドに倒して設定を見直す必要があると思います。
MySQLのインデックスとデータ型

今回も可能な限り手短にいきたいと思います。

```sql
DESC users;
```

|Field|Type|Null|Key|
|:----|:----|:----|:----|
| id | char(5) |NO|PRI|
| name | varchar(100) |NO| |

```sql
SELECT * FROM users WHERE id = 12345;
```

```sql
SELECT * FROM users WHERE id = "12345";
```

この場合、それぞれインデックスはどのように働くでしょうか？
穴を掘って入りたいぐらいに恥ずかしい話ですが、この挙動について今日初めて知りました。

**結論**
検索条件の値はカラムのデータ型と揃えましょう。
obnizで家の猫にリモートで餌をあげてみた

# リモート餌やりマシーン

旅行中でも、家の猫に餌をあげたい！
どうせならお家IoT化の一環としてobnizを使ってスマホから使える餌やり機を作ってみました。

## 必要なもの

### obniz(オブナイズ)

[obniz](https://obniz.io/)はjavascriptから操作できるので、ボタンを押したらモーターを回すというWebページを1つ作るだけで済んじゃいます。
しかもモーターもそのまま繋がるのでobnizを使って作ってみました。

詳細は以下
[https://obniz.io/](https://obniz.io/)

![](https://obniz.io/images/index/DSC02032-half-min.png)

### 無限回転サーボ
餌をあげるのにスクリューとモーターを用意します。
DCモーターだと作りにくいので無限に回転するサーボモーターを買ってきました。

[http://akizukidenshi.com/catalog/g/gM-08305/](http://akizukidenshi.com/catalog/g/gM-08305/)

![](http://akizukidenshi.com/img/goods/C/M-08305.jpg)

### 木工材料
パイプとか、箱が必要でした。あげたい餌の量でサイズは変えたほうがいいかも。

## 組み立てる

まずは適当なパイプを買ってきて、スクリューは3Dプリンタで作りました。STLは[こちらです](https://web.obniz.io/images/cookbook_3.stl)。

次にobnizにモーターをつなぎます。 今回はこのようにしました。

io0: GND,
io1: VCC,
io2: signal

繋いで電源入れてみたところ。

![](https://storage.obniz.io/images/ebd129f34296beed1526175958060)

試しに回してみると、これがなかなかうまく動かず、なんどかスクリューを削ったりしました。（もっと粒の大きな餌なら問題なかったかも）

![](https://storage.obniz.io/images/ae7e71d7c3cc4f7c1526175976756)

## コード

あとはHTMLのコーディングです。
まずはobniz.jsをunpkgから持ってきます。

```html
<script src="https://unpkg.com/obniz@1.2.2/obniz.js"></script>
```
そして、ボタンを押したら何秒かサーボを回すようにしました。
下にあるのが全体のHTMLです。

```html
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
 
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
  <script  src="https://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4="  crossorigin="anonymous"></script>
 
  <script src="https://unpkg.com/obniz@1.2.2/obniz.js"></script>
</head>
 
<body>
<div id="obniz-debug"></div>
<br>
<div class="text-center">
  <h1> Pet Feeder </h1>
</div>
 
<button id="meal">Feeding</button>
<div id="dispMeal"></div>
 
<script>
 
function getTime(){
  var dateTime=new Date();
  var hour = dateTime.getHours();
  var minute = dateTime.getMinutes();
  return hour + ":" + minute;
}

var obniz = new Obniz("OBNIZ_ID_HERE");
 
obniz.onconnect = async function () {
  var numberOfMeal = 0;
  var lastTimeMeal;
  $("#dispMeal").text("Number of feeding : "+numberOfMeal)
  var servo = obniz.wired("ServoMotor", {gnd:0, vcc:1, signal:2});
 
  $("#meal").click(async function(){
    numberOfMeal++
    lastTimeMeal = getTime();
    $("#dispMeal").text("Number of feeding : "+numberOfMeal+", The last time : "+lastTimeMeal)
    servo.angle(0.0);
    await obniz.wait(10000);
    servo.angle(6.9);
  })
}
    
</script>
</body>
</html>
```

このHTMLを開いてボタンを押したら回る回る！
餌をあげる長さを調整して、ちょうどいい量が出るようにしました。

[![](http://img.youtube.com/vi/hxVx4Slo9kY/0.jpg)](https://www.youtube.com/watch?v=hxVx4Slo9kY)
Cognos Analytics でのTLS1.2対応

#Cognos Analytics でのTLS 1.2対応
Cognos AnalyticsのTLS 1.2への対応について、最近調査した結果を忘れないうちに投稿しておきます。

こちらのTechnoteの中で、以下の記載があります。
　Cognos 11 supports TLS 1.2
　Cognos 10.2.2 with FP5 supports TLS 1.2

**Cognos BI and TLS 1.2 support**
http://www-01.ibm.com/support/docview.wss?uid=swg21986882

この意味ですが、Cognos AnalyticsでのSSLのプロトコルは、デフォルトで「TLS1.0,TLS1.1,TLS1.2」がMixで使用されているので、TLS 1.2も使用できますよ、という意味で、TLS 1.2のみ使用しますよ、という意味ではありません。

SSL 3.0の使用は無いので、POODLE(Padding Oracle On Downgraded Legacy Encryption）の対応とかは大丈夫なのですが、TLS 1.0、TLS 1.1も使用される可能性があるため、万全なセキュリティを求める環境では、TLS 1.2のみの使用が要望として出てくる事があるかと思います。

TLS 1.2のみの指定は、Cognos Analytics 11.0.8から可能になりました。
Cognos Configurationの「暗号化」のところで、以下のように「SSL プロトコル」指定が可能になってます。
![001.JPG](https://qiita-image-store.s3.amazonaws.com/0/147246/e631ce8a-7276-8f2b-5604-c1e7c5e69b8c.jpeg)

残念ながらこの機能は、Cognos Analytics 11.0.7以前およびCognos 10 BIには存在しません。

**How to change the Transport Layer Security (TLS) version of Cognos Analytics**
http://www-01.ibm.com/support/docview.wss?uid=swg22011122

マニュアルのこちらにも記載があります。
https://www.ibm.com/support/knowledgecenter/ja/SSEP7J_11.0.0/com.ibm.swg.ba.cognos.inst_cr_winux.doc/t_cnfg_crypto_general.html#cnfg_crypto_general

TLS 1.2 onlyに指定して、Cognosの開発元ではしっかり動いたそうですが、まだ実際のプロジェクトで設定しているのを見たことが無いので、設定経験のある方は是非フィードバック頂けるとうれしいです。
fastlane で upload_to_testflight するときに「Could not start delivery: all transports failed diagnostics」エラーが発生した場合の対策

* 実行環境
    * Xcode 9.3
    * Swift 4.1
    * Ruby 2.5.0
    * fastlane 2.95.0

このようなエラーが発生したら、

```
[16:02:15]: ----------------------------------
[16:02:15]: --- Step: upload_to_testflight ---
[16:02:15]: ----------------------------------
[16:02:15]: Login to iTunes Connect (xxxxxx)
[16:02:17]: Login successful
[16:02:18]: Ready to upload new build to TestFlight (App: xxxxxx)...
[16:02:19]: Going to upload updated app to iTunes Connect
[16:02:19]: This might take a few minutes. Please don't interrupt the script.
[16:04:28]: [Transporter Error Output]: Could not start delivery: all transports failed diagnostics
[16:04:28]: Transporter transfer failed.
[16:04:28]: 
[16:04:28]: Could not start delivery: all transports failed diagnostics
[16:04:28]: [iTMSTransporter] 	at com.signiant.interactivetransfer.engine.TransferEngine.access$1200(TransferEngine.java:149)

[16:04:28]: [iTMSTransporter] 	at com.signiant.interactivetransfer.engine.TransferEngine$8.run(TransferEngine.java:4060)

[16:04:28]: [iTMSTransporter] 

[16:04:28]: [iTMSTransporter] [2018-05-18 16:04:28 JST] <Transport Protocol> DEBUG: Received failed transfer notification; aborting

[16:04:28]: [iTMSTransporter] [2018-05-18 16:04:28 JST] <Transport Protocol>  INFO: The Signiant transfer engine's status is DISCONNECTED

[16:04:28]: [iTMSTransporter] [2018-05-18 16:04:28 JST] <main> ERROR: Could not start delivery: all transports failed diagnostics

[16:04:28]: [iTMSTransporter] 

[16:04:28]: [iTMSTransporter] 

[16:04:28]: [iTMSTransporter] 

[16:04:28]: [iTMSTransporter] Package Summary:

[16:04:28]: [iTMSTransporter]  

[16:04:28]: [iTMSTransporter] 1 package(s) were not uploaded because they had problems:

[16:04:28]: [iTMSTransporter] 	/var/folders/r9/d6rp3mpj7kd67v3l2yvjmzk115mv2r/T/d20180518-25422-1y6vo9r/1356060418.itmsp - Error Messages:

[16:04:28]: [iTMSTransporter] 		Could not start delivery: all transports failed diagnostics

[16:04:28]: [iTMSTransporter] [2018-05-18 16:04:28 JST] <main> DBG-X: Returning 1

[16:04:28]: iTunes Transporter output above ^
[16:04:28]: Could not start delivery: all transports failed diagnostics
Return status of iTunes Transporter was 1: Could not start delivery: all transports failed diagnostics
The call to the iTMSTransporter completed with a non-zero exit status: 1. This indicates a failure.
```

`Fastfile` の先頭に以下の記述を追加する

```ruby
ENV['DELIVER_ITMSTRANSPORTER_ADDITIONAL_UPLOAD_PARAMETERS'] = '-t DAV' # <--

default_platform(:ios)

platform :ios do
  desc "Push a new beta build to TestFlight"
  lane :beta do
    build_app(workspace: "xxxxxx", scheme: "xxxxxx")
    upload_to_testflight
  end
end
```

* 参考
    * https://docs.fastlane.tools/actions/pilot/#firewall-issues
    * https://github.com/fastlane/fastlane/issues/2294
IEは自画面へのPOSTでダウンロード処理させると履歴が消える

##履歴が消える！

IEにおいて、表示中のURLと同じURLへのpostでダウンロード処理をさせると、その画面の履歴が無くなります！
（ブラウザの戻るボタンで戻った時に、さっき見ていたはずのページが表示されません）

##どういうこと？

ページ１→ページ２→ページ３とページ移動させるようなリンクが貼ってあるとしましょう。ページ２にはダウンロードボタンがあります。ダウンロード処理はページ２と同じURLで行います。

ページ１からページ２へ移動し、そこでダウンロードボタンを押してファイルをダウンロードしてから、ページ３へ移動します。

ブラウザの戻るボタンを押すと、ページ２に戻るはずがいきなりページ１に戻ってしまいます。

##解決方法

ダウンロード処理を表示中のURLと違うURLにしましょう。末尾に「？」を付けるだけでもOK。

以下はColdFusionの例ですが、post先が`action="dltest2.cfm"`と自分のURLになっている箇所を`action="dltest2.cfm?download"`などダミーのパラメータを付加してやります。
本当はダウンロード処理を別モジュールにするべきなんでしょうけど、既に作ってしまって修正が面倒なときは参考にしてください。

```html:dltest2.cfm
<CFIF isDefined("form.btnSubmit")>
	<CFHEADER name="Content-Disposition" value="attachment; filename=testfile.txt">
	<CFCONTENT type="text/comma-separated-values" file="e:\testfile.txt" deleteFile="no">
</CFIF>

<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>2番目のページ</title>
</head>
<body>
	<h3>2番目のページ</h3>
	<a href="dltest1.cfm">前へ</a> <a href="dltest3.cfm">次へ</a>
	<form method="post" action="dltest2.cfm">
		<input type="submit" name="btnSubmit" value="download">
	</form>
</body>
</html>
```
OSXのQGISv3.xでgdalが動かない方への助け舟

（になればいいなあ）


## はじめに
タイトルの日本語がなんかルー大柴みたいで、すみません。
OSX10.12.6にQGIS3.02をインストール後gdalでヒャッホイ！ラスタ処理と思ったらうんともすんともいかなくなりまして、なんとか解決できたのでメモ
※2018/11/7 追記　OSX QGIS3.4.0でも同様の症状が出ていたので、やはり必要かと

<img src="https://qiita-image-store.s3.amazonaws.com/0/100567/411050b7-0724-30eb-d786-d38eb910b690.png" width=30%>

## 症状
上記環境（OSX10.12.6+QGIS3.02）で、gdalの処理、たとえばgdalinnfoなどをやろうとすると
設定ウインドウなどもでて、いざ実行！とすると

```

プロセッシングアルゴリズム...
AlgorithmDialog
Input parameters:
{ 'INPUT' : '/Users/hogehoge/hoge.tiff', 'MIN_MAX' : False, 'NOGCP' : False, 'NO_METADATA' : False, 'OUTPUT' : '/var/folders/6hogehoege/OUTPUT.html', 'STATS' : False }

GDAL command:
gdalinfo Users/hogehoge/hoge.tiff
GDAL command output:
/bin/sh: gdalinfo: command not found

Execution completed in 0.06 seconds
Results:
{'OUTPUT': '/var/folders/6m/hogehoege/OUTPUT.html'}

出力レイヤの読み込み
Algorithm 'ラスター情報' finished
HTML output has been generated by this algorithm.
Open the results dialog to check it.
```

などと仰って処理が進まない。というか ***gdalinfo: command not found***ってなんですか。お父さんの顔忘れたのですか。さっきのウインドウはウソなのですか。

インストーラーでちゃんとgdal順番通り入れたのにおかしい。再度インストーラーで入れたり、pipとかAnacondaでgdalで無理やりねじこんでも変化なし。
[バグレポート](https://issues.qgis.org/issues/18704)も上がってるのを発見したけど未対応（てかGRASSもかよ！）

## 対応
社内の方の助言で、OSXのQGISがgdalを見つけきれていないことなどが原因らしく、[ここ](https://www.kyngchaos.com/blog/2018/20180406_qgis_tools_processing_workaround)を参照にgdalのパスを無理くり押し付けることで対応
(てかKyngChaosさん症状わかってるなら…ええまあ、ありがとうございますいつも)

1. ”QGIS3”メニューからPreferences...を選択
<img src="https://qiita-image-store.s3.amazonaws.com/0/100567/b718470f-2a95-bf6e-ebc8-ee729cb92bfa.png" width=50%>



2. オプション|システムメニュー->（下の方にスクロール）->環境
<img src="https://qiita-image-store.s3.amazonaws.com/0/100567/c051a770-0263-91c2-acf5-8b4ea658e0c0.png" width=90%>




3. カスタム変数を用いるにチェック、＋マークを押して、適用-> *追加*　変数-> *PATH* 
値には

`/Library/Frameworks/Python.framework/Versions/3.6/bin:/Library/Frameworks/GDAL.framework/Versions/2.2/Programs:`

![Kobito.uFASzF.png](https://qiita-image-store.s3.amazonaws.com/0/100567/5528aace-faf6-f9d8-51f7-ab9e5f4b9736.png "Kobito.uFASzF.png")


を入力し



4.QGISを再起動



で、gdalが使えるようになります。
世界中の陰影図でも投影変換でも[餃子の王将スペシャル定食](https://www.google.co.jp/search?lr=lang_ja&safe=off&hl=ja&biw=1777&bih=851&tbs=lr%3Alang_1ja&tbm=isch&sxsrf=ACYBGNR0fe9WvEtfiMwyL9cm6EdANdpl8Q%3A1580196899834&sa=1&ei=I-QvXrO2MoXr-QbOmJ3ABQ&q=%E9%A4%83%E5%AD%90%E3%81%AE%E7%8E%8B%E5%B0%86%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AB%E5%AE%9A%E9%A3%9F&oq=%E9%A4%83%E5%AD%90%E3%81%AE%E7%8E%8B%E5%B0%86%E3%82%B9%E3%83%9A%E3%82%B7%E3%83%A3%E3%83%AB%E5%AE%9A%E9%A3%9F&gs_l=img.3...9093.10020..11873...0.0..0.186.716.1j5......0....1..gws-wiz-img.......35i39.6DNiawFZnj4&ved=0ahUKEwjz046X5KXnAhWFdd4KHU5MB1gQ4dUDCAc&uact=5)でもおすきなようにお楽しみ下さい



```
（ ´-｀）。o O（あーまー、そのうち改善されるとは思うんですが、念のため日本語で書いておきます…
（ ´-｀）。o O（QGIS1.8のときのqgis.batファイル書き換え並の衝撃…
（ ´-｀）。o O（GRASSも動かない、パスなんだろか…
（ ´-｀）。o O（こんなことでQGISを嫌いにならないでください…昔は(ry
（ ´-｀）。o O（サンタさん一発でOSXにQGIS入るインストーラーください…
（ ´-｀）。o O（ぐーだるか、じーだるかはいろいろ意見がわかれるところ…
```
エフェクトプリセットの設定値は、プレイが終了した後も引き継がれる。アニメーションの変化も、STOPした後自動では戻らない。

これは、実際に起こったことを、わざわざ再現したものである。　　***環境:UnrealEngine4.19***

#エフェクトプリセット編
##ＵＩ
![SS_UIEF_1-1.png](https://qiita-image-store.s3.amazonaws.com/0/239082/d4640104-065e-a26b-cc8c-6298aec85c2d.png)

特に何の変哲もないＵＩである。
Pannerの下のSliderを動かせば、左右の音の聞こえ方が変化する。


##Pannerのスライダーを動かしたあと
![SS_UIEF_1-2.png](https://qiita-image-store.s3.amazonaws.com/0/239082/f46b92df-35d9-b7b9-627a-2d07d6c1ac1d.png)
片方からのみ（今回は左側）音が聞こえる。

##一旦プレイを終了して、再起動する
![SS_UIEF_1-3.png](https://qiita-image-store.s3.amazonaws.com/0/239082/25a7c809-2cf7-de7b-9356-f93756463205.png)
本来ならば、左右から音が聞こえるはずである。
しかし、片方からのみ音が聞こえるのである。おかしい。

##あれれ、おかしーぞー？
![SS_UIEF_1-4.png](https://qiita-image-store.s3.amazonaws.com/0/239082/8392a779-a60b-bcff-831d-4a3af8c66a5a.png)
設定を確認したところ、Panの値は0.0、ちょうど真ん中。
片方からのみ音が聞こえるのは、明らかにおかしいのである。

#アニメーション編
##初期状態
![SS_UIEF_1-3.png](https://qiita-image-store.s3.amazonaws.com/0/239082/25a7c809-2cf7-de7b-9356-f93756463205.png)
勘がいい人なら気付いていただろうが、NightRiderの下のＬＥＤはアニメーションしているのだ。
左右に色を変えながらＬＥＤが動いているのである。これは初期状態（ＬＥＤの位置は左端）である。

##ＳＴＯＰ後
![SS_UIEF_2-1.png](https://qiita-image-store.s3.amazonaws.com/0/239082/6bd7c193-877b-0922-8038-ee8a0f2cbc4e.png)
ＬＥＤの位置が右端になった時にＳＴＯＰすると、このような状態となった。
本来なら初期状態に戻るだろうが、まあ、元の状態には戻らないのだ。

#対処法
![SS_UIEF_3-1.png](https://qiita-image-store.s3.amazonaws.com/0/239082/99c8066e-b5c9-09b5-c696-ef825f591ba4.png)

**デフォルトに戻すための関数を設定して、ゲーム起動時・アニメーション終了時に呼び出せば解決できる。**

##エフェクトプリセット
![SS_UIEF_1-5.png](https://qiita-image-store.s3.amazonaws.com/0/239082/5c683d92-49ad-300e-f706-63cab461c3ac.png)

エフェクトプリセットについては、SetSettingで明示的に初期化（InSettingsPanを0.0に設定）すれば良い。

##アニメーション
![SS_UIEF_2-2.png](https://qiita-image-store.s3.amazonaws.com/0/239082/9910d0c8-b021-51bf-34f4-1dfd78fb4415.png)

アニメーションについても、変更が行われた箇所を変更前に戻せば良いのだ。

![SS_UIEF_2-3.png](https://qiita-image-store.s3.amazonaws.com/0/239082/0be3004f-7e10-5240-d9be-1a8127525e47.png)

この例では、いったん配列に格納してから、一括で処理を行っている。
クロスドメイン制約を回避するChromeショートカットを作る

```
No 'Access-Control-Allow-Origin' header is present on the requested resource.
```
のエラーのせいでドメインを跨いだファイル読み込みの検証ができなかったので、
Chrome起動オプションによる無効化をショートカットで作成してみました。

まずはChromeのショートカットを普通に作成し、
[プロパティ]から、「リンク先」に**--disable-web-security** と **--user-data-dir**を追加する。

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C:\Users\ユーザ名\Local\Google\Chrome\User Data"
```
![property.png](https://qiita-image-store.s3.amazonaws.com/0/143784/aa797081-37b6-83a0-9cd6-9f795f876653.png)

ショートカット作成ができたら、一度Chromeを完全に終了させてからショートカットキーよりChromeを起動する。

起動画面に「サポートされていないコマンドライン フラグ --disable-web-security を使用しています。これにより、安全性とセキュリティが損なわれます。」と表示されていれば成功です。
![68747470733a2f2f71696974612d696d6167652d73746f72652e73332e616d617a6f6e6177732e636f6d2f302f3134333738342f30663162396566612d636661322d383831662d646638662d3330656331393137316137622e706e67.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/143784/f821fa9d-3fc2-9a81-3e7b-8dbc492b0e4d.png)


これで毎度コマンドを叩かなくても起動できるようになりました！

# 追記（2018/08/29）
ユーザ以下のパスを合わせる必要のない`--user-data-dir="C://Chrome dev session"`でも可能だとコメント頂きました。
[@khitago](https://qiita.com/hkitago)さん、ありがとうございます！

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --disable-web-security --user-data-dir="C://Chrome dev session"
```
※chromeからログアウトされた状態で開くため、ブックマークや拡張機能などの設定は引き継げません。

# 参考サイト
[【解説付き】chromeでXMLHttpRequestをローカルのファイルで行う方法](https://qiita.com/growsic/items/a919a7e2a665557d9cf4)
データベースとSQL 初学者用 まとめ

# データベースとSQL 初学者とは？
以下のサイトで初学者判定された人。(自分)
[データベースとSQLの業務スキルレベル 判別表](http://language-and-engineering.hatenablog.jp/entry/20110320/p1)

各項目に関して調べたことを、忘れないように簡単にまとめておく。

## (テーブルやカラムの) 「論理名」と「物理名」の違い
- 論理名：人間向けの名称
    - ex.) <br>従業員
- 物理名：コンピュータ向けの名称
    - ex.) <br>employee

## 「論理削除」と「物理削除」の違い
- 論理削除：実際にはデータを削除せずに、削除されたと見なすフラグをカラムとして設定すること
    - ex.) <br>あるテーブルにdelete_flagというboolean型のカラムを追加<br>削除イベントの時に値をセットすることで、削除されたデータとして扱う
- 物理削除：実際にデータを削除。SQLでのDELETE実行と同義。

## 「WHERE カラム名 = NULL」の正しい書き方
- 結論：「WHERE カラム名 IS NULL」
    - 備考：「WHERE カラム名 IS NOT NULL」もある

## ORDER BY, LIMIT, OFFSETを使った絞込み
- ORDER BY句
    - 抽出したデータを並べ替る時によく使用される<br>昇順：ASC<br>降順：DESC
- LIMIT句
    - 抽出する行数を制限する<br>指定した行数より多くの行数が返されることは無い（少ない場合はある）
- OFFSET句
    - 返す行の開始位置を飛ばす<br>LIMITと両方指定した場合は、OFFSET分の行を飛ばしてから、LIMIT行を数え始める
- 例文（無理矢理3つ使いました感が否めない・・・。）

```sql:抽出した結果を○順に並べ替え、num1番目からnum2数分レコード欲しい
SELECT select_list
 FROM table
 [ ORDER BY ASC|DESC ]
 [ LIMIT num1] [ OFFSET num2 ]
```

## M・V・Cの3層構造について
- プログラムのデザインパターンの1つ。あくまで1つなので正解ない。
    - M(Model)：表示や入力に関連しない処理
    - V(View)：表示や入力に関する処理
    - C(Controller)：MとVを使った処理、橋渡し役
        - モデルはデータAPI的に設計すると良いらしい

## DAOについて
- Data Access Objectの略。プログラムのデザインパターンの１つ。<br> データアクセスに関わる操作やロジックの役割をもつ処理の集まり

## マスタデータとは何か それを格納するテーブルがアプリ内でどういう性質を持つのか
- 正直しっくりきた説明が見つからない。その中でも少し納得したのが以下。
    - マスタデータ：固定的なデータ。管理者のみが更新するようなデータ。
    - トランザクション：流動的なデータ。ユーザが更新するようなデータ。
- アプリ内でどういう性質を持つのか？
    - 誰か教えてください

## JOINを使いこなすには？
- JOINとは「テーブルの結合」という意味合い<br>複数の表(テーブル)を組み合わせる処理のこと
    - 内部結合：連結キーで複数テーブルを結合し、両テーブルに共通して存在するカラムのみ出力する結合
    - 外部結合：内部結合に加え、どちらかのテーブルにしか存在しないカラムも出力する結合
- 以下のサイトがわかりやすかったです<br>
[SQL素人でも分かるテーブル結合(inner joinとouter join)](https://qiita.com/naoki_mochizuki/items/3fda1ad6594c11d7b43c)
- 使いこなすとは・・・？
    - どういうときに使えば良い、メリットデメリット教えてください。


## テーブル定義書やER図といったもの全てを、一緒に自動で管理してくれるツール
- [A5:SQL Mk-2](https://a5m2.mmatsubara.com/)（有名どころらしい）
- 以下のサイトが導入まで分かり易い<br>[A5:SQL Mk-2を使ってDB定義書を自動生成](https://qiita.com/Esfahan/items/39509da435da4821cdc7)

## GROUP BYとHAVINGを正しく組み合わせて使う方法 & WHEREとHAVINGの違い
- **GROUP BY句**
    - カラム名を指定すると、そのカラム名に格納されている値が同じデータをグループとしてまとめる
    - 複数のカラム名を指定した場合、複数のカラムの値の組み合わせが同じデータをグループとしてまとめる
- **HAVING句**
    - GROUP BY句でグループ化されたデータに対し、検索条件を指定して絞り込むことができる
- **組み合わせて使う方法**

```sql:例文
SELECT 列名
 FROM 表明
 [ WHERE 条件 ]
 [ GROUP BY 列名 ] [ HAVING 条件]
```
- **WHEREとHAVINGの違い**
    - 結論：
        - WHERE句は「SELECT句の結果から(WHERE句で)指定した抽出条件を実行する」
        - HAVING句は「GROUP BY句の結果から(HAVING句で)指定した抽出条件を実行する」
    - 以下のサイトが分かり易い<br>
[[SQL] Where句とHaving句の違い](https://dev.classmethod.jp/server-side/db/difference-where-and-having/)
Redisがコネクションタイムアウトした話

# 環境情報
OS: CentOS Linux release 7.5.1804 (Core)
Redis : 2.6.5

# きっかけ
mattermost + hubotの構成でチャットボットを作成して  
coffeescriptをいじっていた時に、突然以下のようなメッセージが  
出現した。  

[Fri May 18 2018 11:02:22 GMT+0900 (JST)] ERROR Error: Redis connection in broken state: connection timeout exceeded.
    at RedisClient.connection_gone (/home/matter-bot/node_modules/redis/index.js:645:19)
    at RedisClient.on_error (/home/matter-bot/node_modules/redis/index.js:406:10)
    at Socket.<anonymous> (/home/matter-bot/node_modules/redis/index.js:280:14)
    at Socket.emit (events.js:182:13)
    at emitErrorNT (internal/streams/destroy.js:82:8)
    at emitErrorAndCloseNT (internal/streams/destroy.js:50:3)
    at process._tickCallback (internal/process/next_tick.js:63:19)

# 原因

原因となったソースの箇所はここ。
ソース名：redis/index.js

this.connect_timeout = +options.connect_timeout || 3600000; // 60 * 60 * 1000 ms

周りのコメントや処理を見る限り、どうやら1時間までは再接続をするが、
それを超えると接続を切るらしい。

# 対処
個人の環境なので、以下の通り修正。
this.connect_timeout = +options.connect_timeout;

ちなみに、options.connect_timeoutはfalseが指定されているので、  
timeoutしないようになるはず。

＃結果
一応、不具合なく動いており、タイムアウトも発生していないですが、  
こんな雑な修正は個人レベルのみにとどめておきたいなぁ。。。
たぶん、負荷とかメモリ消費とかがすごいことになりそう。