OmniAICreator/Qiita-1.07M huggingface dataset:
SSLを理解する - ウェブサイトの運営者の身元を保証し、通信を暗号化して通信内容を守る

SSLとは、ウェブサイトの運営者の身元を保証し、通信を暗号化して通信内容を守る仕組みです。

SSLは、認証局がウェブサイトの運営者に対して「SSLサーバ証明書」を発行し、運営者がそれをウェブサイトに使用することで機能します。
ウェブサーバにSSLサーバ証明書が使用されることで、ウェブサイトの利用者とWebサーバの間で暗号化通信を行うことが可能になります。

ウェブサイトのURLの先頭がhttps://で始まっているなら、そのサイトはSSLが使用されており、そのサイトとの通信内容は暗号化されます。
昨今、ウェブサイトのSSL使用は必須の流れになっており、Google Chrome 68からはSSL化されていないサイト（http://で始まる）は警告が出るようになりましたし、Appleはアプリの開発者に対してSSL化していない外部との通信は基本的に遮断するとしています。

SSLは、通信しようとする2者の間にセキュアな通信経路を与えることを目指します。
セキュアな通信経路とは、すなわち、相手の身元が保証されていること、機密性が確保されていること、改ざんを検知できることという機能を持っていることです。それぞれについて説明します。

# 1つ目の機能 - サーバの身元保証

仮に通信相手がなりすましの偽物だった場合、通信を暗号化して第三者に盗聴されても大丈夫なようにしたところで、悪意ある相手に情報を渡してしまっているわけですから意味がありません。
つまり、暗号化だけでは不十分で、相手の身元が保証されていることがセキュアな通信には求められます。

SSLサーバ証明書には、サーバ運営者の身元が書かれています。
しかし、その身元が嘘でないことを、クライアントはどのように判断したら良いのでしょうか？
もしかするとその身元は、サーバ運営者が自分自身で書いたもので、信頼できる第三者が身元を保証しているものではないかもしれません（オレオレ証明書）。

身元を確かにするため、SSLサーバ証明書は認証局という機関が発行し、電子署名を施します。
クライアントは、この証明書に施された電子署名を検証することで、身元が確かであることを確認します。
具体的な流れは以下です。

## サーバの身元が、正当な認証局によって保証されているかを確認する

最初にSSL通信での接続を要求するとサーバはSSLサーバ証明書を返しますが、実はこの時セットで「中間証明書」と「ルート証明書」も一緒に返されています。
中間証明書は、SSLサーバ証明書を発行した認証局（中間認証局）の本人証明です。
ルート証明書は、中間認証局に対して中間証明書を発行した、最上位の認証局（ルート認証局）の本人証明です。

クライアントはまず、SSLサーバ証明書に施されている電子署名を、中間証明書の公開鍵を使って検証することで、SSLサーバ証明書が中間認証局によって発行されたものかどうかを確認します。
次に、中間証明書に施されている電子署名を、ルート証明書の公開鍵を使って検証して、それがルート認証局によって発行されたものであるかを確認します。

ルート認証局より上位の認証局はありません。ルート証明書はルート認証局自身が署名しています（自己署名証明書）。
クライアントは、第三者のお墨付きがないそのルート証明書を信頼してしまって良いのでしょうか？

実はブラウザやOSには、信頼できるとされているルート証明書があらかじめ登録されています。

クライアントはこの自身が持っているルート証明書で照合し、サーバから受け取ったルート証明書が信頼できるかを確認します。

照合できれば、ルート認証局は本物であり、本物のルート認証局がお墨付きを与えた中間認証局が、そのSSLサーバ証明書を発行しているということで、クライアントはSSLサーバ証明書の内容を信頼するというわけです。

# 2つ目の機能 - 暗号化による機密性の確保

これは暗号と聞いて多くの方がイメージする機能ですね。
通信する2者だけが内容を知り得ることです。
カード番号や個人情報、パスワードなどは、機密性が確保されるべき情報として分かりやすいですね。

暗号化通信を行うためには、あらかじめ通信する2者が、通信内容を暗号化/復号するための鍵を共有している必要があります。
そのため、SSL通信では、実際の通信の前に、鍵を共有するための通信が行われます。

# 3つ目の機能 - 通信内容が第三者に改ざんされていた場合の検知

SSLを使うと、受信者は、送られてきた内容が途中で第三者に改ざんされていないことを確認することができます。

受信者が改ざんを検知するには、メッセージが作られた時点から途中で変化していることを検出できるような仕組みが必要です。
改ざん検知のざっくりした手順としては、
まず、送信者がメッセージを元に短い文字列を生成し、それをメッセージにくっつけて送ります。
受信者は、送信者がやったのと同じ手順でメッセージから短い文字列を生成し、その文字列と、メッセージと一緒に送られてきた文字列を比べます。

ここでもし2つが異なっていれば、メッセージにくっついてきた文字列が作成時点から変わっていることになり、途中で通信内容が改ざんされたことになるわけです。

# 参考
[RFC 8446](https://tools.ietf.org/html/rfc8446)
[WEB+DB PRESS Vol.110](https://gihyo.jp/magazine/wdpress/archive/2019/vol110)
[スラスラわかるネットワーク&TCP/IPのきほん](https://www.amazon.co.jp/%E3%82%B9%E3%83%A9%E3%82%B9%E3%83%A9%E3%82%8F%E3%81%8B%E3%82%8B%E3%83%8D%E3%83%83%E3%83%88%E3%83%AF%E3%83%BC%E3%82%AF-TCP-IP%E3%81%AE%E3%81%8D%E3%81%BB%E3%82%93-%E3%83%AA%E3%83%96%E3%83%AD%E3%83%AF%E3%83%BC%E3%82%AF%E3%82%B9/dp/4797377038)
[Transport Layer Security - Wikipedia](https://ja.wikipedia.org/wiki/Transport_Layer_Security)
[メッセージ認証符号 - Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%83%E3%82%BB%E3%83%BC%E3%82%B8%E8%AA%8D%E8%A8%BC%E7%AC%A6%E5%8F%B7)
iOSのビルドで"Command PhaseScriptExecution failed with a nonzero exit code"のエラーになった場合

キーチェーンアクセスをいじったことが原因で、実機にiOSアプリをビルドするときにこのエラーが発生するようになってしまいました。

## エラー内容

```
PhaseScriptExecution [CP]\ Embed\ Pods\ Frameworks /Users/xxxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Intermediates.noindex/xxxx.build/Debug-iphoneos/xxxxx.build/Script-0426CA04FD4250D615669FA8.sh (in target: xxxx)
    cd /Users/xxxxxxxx
    /bin/sh -c /Users/xxxxxxxx/Library/Developer/Xcode/DerivedData/xxxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Intermediates.noindex/xxxx.build/Debug-iphoneos/xxxx.build/Script-0426CA04FD4250D615669FA8.sh
mkdir -p /Users/xxxxxxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/xxxx.app/Frameworks
rsync --delete -av --filter P .*.?????? --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers" --filter "- PrivateHeaders" --filter "- Modules" "/Users/xxxxxxxx/Library/Developer/Xcode/DerivedData/xxxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/AFNetworkActivityLogger/AFNetworkActivityLogger.framework" "/Users/xxxxxxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/xxxx.app/Frameworks"
building file list ... done
deleting AFNetworkActivityLogger.framework/_CodeSignature/CodeResources
deleting AFNetworkActivityLogger.framework/_CodeSignature/
AFNetworkActivityLogger.framework/
sent 191 bytes  received 26 bytes  434.00 bytes/sec
total size is 136481  speedup is 628.94
Code Signing /Users/xxxxxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/xxxx.app/Frameworks/AFNetworkActivityLogger.framework with Identity iPhone Developer: xxxx (xxxxxxxx)
/usr/bin/codesign --force --sign 8C735B207EDD972534079574F2E919DB7006A1BF  --preserve-metadata=identifier,entitlements '/Users/xxxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/xxxx.app/Frameworks/AFNetworkActivityLogger.framework'
/Users/xxxx/Library/Developer/Xcode/DerivedData/xxxx-egmbprsfygoaxpbubiqyorcmejpn/Build/Products/Debug-iphoneos/xxxx.app/Frameworks/AFNetworkActivityLogger.framework: errSecInternalComponent
Command PhaseScriptExecution failed with a nonzero exit code
```

## 解決方法

Xcode > Preferences > Accounts > {team} / Manage Certificats... を開きます。
![Screen_Shot_2019-04-04_at_19_33_18.png](https://qiita-image-store.s3.amazonaws.com/0/92539/ffb758ec-be7f-434e-746b-fa401d70f566.png)

+ボタンからiOS Developmentを選択し、証明書を新しく作成します。
![Screen_Shot_2019-04-04_at_19_33_38.png](https://qiita-image-store.s3.amazonaws.com/0/92539/f671b30d-4d0c-2064-f443-76f1a7e6d41d.png)

証明書を展開し、秘密鍵の"情報を開く"から、アクセスコントロールを開き、Xcode.app、codesign、productbuildがあることを確認します。
![Screen_Shot_2019-04-04_at_19_36_47.png](https://qiita-image-store.s3.amazonaws.com/0/92539/dcd71f87-f6a0-f732-7d2f-1197e8288751.png)

**私の場合は、既存のiOS Developerの証明書がここに何もセットされていない状態になっており、古い方を削除しました。
ちなみに、古い証明書の"この項目の使用をすべてのアプリケーションに許可"にチェックを入れても解決しませんでした。**

同じエラーで苦しんでいる方の参考になればと思います。
Windowsキーボードの日本語変換キーをMac風に変える

環境
- Windows10


## 設定

以下, Windows10の設定箇所までの遷移です。
結構たどり着くまで大変です。

1
![SnapCrab_設定_2019-4-4_19-38-13_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/4f7ee49e-137f-dc58-7f47-ccf7e1090471.png)

2
![SnapCrab_設定_2019-4-4_19-38-36_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/991d20af-7f9f-c871-e41a-979e843987f2.png)

3
![SnapCrab_設定_2019-4-4_19-38-41_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/8a6be170-1010-7c84-87d0-b2aa36acb7fc.png)



4
![SnapCrab_設定_2019-4-4_17-57-51_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/502e1f23-dc40-f10f-a9d2-c10eddfcadde.png)


---
ここからはwindows7と同じです。

Microsoft IMEの詳細設定 -> 編集操作 変更

5
![SnapCrab_NoName_2019-4-4_17-53-22_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/428c85da-48fb-a963-bc5f-cc093e0b3850.png)


6
![SnapCrab_NoName_2019-4-4_17-50-50_No-00.png](https://qiita-image-store.s3.amazonaws.com/0/62413/64299199-1eda-2726-3430-65d0529155a7.png)


## 結果

これで、
1. スペースキーの左の「無変換」=> 「半角英字」
2. スペースキー右の「ひらがな/カタカタ」=> 「ひらがな」

となります。

以上
Railsで「新規ユーザー登録後にログイン（セッション）状態にする」方法

Webアプリケーションでは、ユーザーの新規登録時の際は自動的にログイン状態が保たれて欲しいですよね？

僕が通うプログラミングスクールのカリキュラムでは、上記のような実装はしておらず、ユーザーの新規登録時にログイン状態が保たれておらず、新たにログインし直さなければいけない仕様でした。

よりユーザービリティを向上したいと考えて、「ユーザーの新規登録時の際は自動的にログイン状態を保つ」ための実装を行ったので、整理がてら投稿いたします。

結論から申し上げますと`users_controller.rb`に`session[:user_id]=@user.id`を追加するだけですよ！

#前提

`sessions_controller.rb`は下記の通りです。

`login`メソッドでは、session[:user_id]にユーザーのidが保持されている状態を「ログイン状態」として定義しています。ここが重要なポイントです。

```ruby:sessions_controller.rb
class SessionsController < ApplicationController
  def new
  end

  def create
    email = params[:session][:email].downcase
    password = params[:session][:password]
    if login(email, password)
      flash[:success] = 'ログインに成功しました。'
      redirect_to @user
    else
      flash.now[:danger] = 'ログインに失敗しました。'
      render 'new'
    end
  end

  def destroy
    session[:user_id] = nil
    flash[:success] = 'ログアウトしました。'
    redirect_to root_url
  end

  private

  def login(email, password)
    @user = User.find_by(email: email)
    if @user && @user.authenticate(password)
      # ログイン成功
      session[:user_id] = @user.id
      return true
    else
      # ログイン失敗
      return false
    end
  end
end
```

#実装

`users_controller.rb`に`session[:user_id]=@user.id`を追加します。

session[:user_id]にユーザーのidが保持されている状態が「ログイン状態」なので、`session[:user_id]`に`@user.id`を代入します。

たったこれだけです。

```ruby:users_controller.rb

class UsersController < ApplicationController
  before_action :require_user_logged_in, only: [:show]
  
  def show
    @user = User.find(params[:id])
  end

  def new
    @user = User.new
  end

  def create
    @user = User.new(user_params)

    if @user.save
      session[:user_id] = @user.id #ここを追加
      flash[:success] = 'ユーザを登録しました。'
      redirect_to @user
    else
      flash.now[:danger] = 'ユーザの登録に失敗しました。'
      render :new
    end
  end
  
  private

  def user_params
    params.require(:user).permit(:name, :email, :password, :password_confirmation)
  end
end

```

#まとめ

以上が、Railsで「新規ユーザー登録後にログイン状態にする」方法となります。

ログイン（セッション）状態についてあらためて学び直す良いきっかけとなりました。
CodeDeployでtask definitionが読み込めない時の対処法

CodePipelineからCodeDeployを使用し、ECSのブルーグリーンデプロイメントを検証していたら「Exception while trying to read the task definition artifact file from: app-source」と出て失敗した。

サポートに問い合わせたところ、以下のように対応して欲しいと返ってきた。

1. taskdef.json を含むアーティファクトのサイズを 3MB 未満にする
2. ビルドステージにて taskdef.json と appspec.yml を含むアーティファクトを作成し、デプロイステージから
このアーティファクトを参照するように CodePipeline の設定を変更する

CodePipelineのソースにはS3が選択できるので、S3にtaskdef.jsonとappspec.ymlをアップロードし、そこから渡すことで対応できる。
RESTとルーティング

#はじめに
今回はRailsアプリを開発する上で大切なRESTについて学んだことをまとめていきます。
RESTに基づいた開発を行うことによって、モデルを扱うコントローラの効率の良いパターンやセキュリティに考慮したアプリケーション開発ができます。

#リソースベースのルーティング
RESTとは、リソースを操作するアプリケーション作成のスタイルです。
Railsにおけるリソースとは、コントローラが扱う対象に名前を付けたものです。
Railsアプリの成果物に会員情報をリソースとして扱います。

```config/routes.rb
resources :members
```

これだけでMembersControllerに対して7つのアクションを設定できます。


7つのアクション以外にも、任意のアクションをを追加できます。

```config/routes.rb
resouces :members do
  collection { get "search" }  #メンバーの検索
end
```

その際、会員一覧のようにリソースの集合を表すアクションはcollectionブロックで囲みます。

また7つのアクションのうち、特定のアクションを使わないときはresourcesメソッドにonlyオプションを追加します。

```config/routes.rb
resources :members, only: [:index, :show]
```


#パスとHTTPメソッド
7つのアクションを呼びだすには、パスとHTTPメソッドの組み合わせで使います。

| アクション |パス | HTTPメソッド |
|:-:|:-:|:-:|
|index  | /members  | GET  |
| show  | /member/10  | GET  |
| new  | /members/new  | GET  |
| edit | /members/10/edit  | GET  |
| create  | /members  | POST  |
| update  | /members/10  |  PATCH |
| destroy  | /members/10  |  DELETE |

show,edit,update,destroyアクションを呼ぶときは、/members/10の[10]のように、モデルの主キーを示すidパラメータが必須です。idパラメータは、コントローラの中でparams[:id]で取り出せます。

PATCHメソッドとDELETEメソッドは、実際のリクエストではPOSTメソッドで送信されます。
Railsの隠しパラメータ_methodを使い、_method=patch、_method=deleteをリクエストに加えることでメソッドの種類を表します。

#RESTの原則
RESTとは大まかにいえば、機能ではなくリソースを中心にして物事を考えることです。
・URLで表す一意なアドレス
・リソースに対する基本操作は、取得、追加、更新、削除の4つであり、対応するHTTPメソッドGET,POST,PATCH,DELETEでリクエスト
・クライアントもサーバーもセッション状態を記憶する必要がない


#参考文献
改訂4版 基礎 Ruby on Rails
https://www.amazon.co.jp/改訂4版-Ruby-Rails-IMPRESS-KISO/dp/429500460X
【Mac版】node.jsのアンインストールと再インストール手順メモ

## 目的
* いま入っているnode.jsを綺麗にしたい!nodebrewでバージョン管理をしたい！と思ったときにコマンド叩くだけで再現できるようにメモ

## 1. Node.jsをアンインストールする
#### 1-1. npmをアンインストール
```
$ npm uninstall -g npm
$ rm -rf .npm \
>    node_modules
```
#### 1-2. nodeをアンインストール
##### パッケージ（pkg）版の場合
```cl:homebrewを使っている場合
$ brew uninstall node
```
```cl:その他
$ lsbom -f -l -s -pf /var/db/receipts/org.nodejs.node.pkg.bom \
> | while read i; do
>  sudo rm /usr/local/${i}
> done
$ sudo rm -rf /usr/local/lib/node \
>     /usr/local/lib/node_modules \
>     /var/db/receipts/org.nodejs.*
```
##### ソース版の場合
node実行ファイルの存在場所を確認し、ファイル削除。

```
$ which node
/usr/local/bin/node
$ rm -rf /usr/local/bin/node \
>     node_modules
```

## 2. Node.jsを再インストールする
#### 2-1. nodebrewをインストールして環境変数を設定する
```
$ curl -L git.io/nodebrew | perl - setup
$ export PATH=$HOME/.nodebrew/current/bin:$PATH
```
#### 2-2. nodeをインストール
```cl:バージョン指定
$ nodebrew install-binary v{使いたいバージョン}
```
```cl:最新版
$ nodebrew install-binary latest
```
#### 2-3. インストールしたバージョンの確認
```
$ nodebrew ls
v11.10.1

current: none
```
#### 2-4. バージョンを設定
```
$ nodebrew use v{使いたいバージョン}
```
#### 2-5. 動作確認
```
$ node -v
v11.10.1
```


## 参考

* [MacにpkgでインストールしたNode.jsをアンインストールする手順](https://qiita.com/yoshikoba/items/4906829faaaae8c73e56)
* [macのnodeのバージョンが上がらない!?ブラックボックス化したmacのnode環境を作り直してみる。](https://blog.websandbag.com/entry/2018/01/21/000000)
* [nodebrewでnodeのバージョンを切り替える方法](https://qiita.com/kuriya/items/36ae29366df0b7c95dec)
あなたの会社ヤバすぎ❓ 一瞬でSlackで全社員のメールアドレス漏洩チェック☝🏻

# Have I been pwned?
突然ですが、「Have I been pwned?」というサイトをご存知ですか?

**メールアドレスの漏洩状況をチェックできるサイトです。**
メールアドレスのほかにもパスワードの漏洩チェックもできます。

このサイトでは、過去にあった**大規模なメールアドレスなどの流出**を起こしたウェブサービスのデータが登録されています。
ということは、漏洩があったデータはどこかで取得することができるので、辞書攻撃などの**被害にあう可能性が非常に高く**なります。

実際に`hogehoge@gmail.com`でやってみると、↓

![image.png](https://qiita-image-store.s3.amazonaws.com/0/91558/6e49b075-4295-7b8e-7baf-2e7afe126c7c.png)

**画像下部が流出したWebサービスの一覧です。**

だいぶ漏洩してますね。(まぁhogehogeなんでなんともいえないですが...)

ちなみにこのサイト「Have I been pwned?」にはAPIが用意されています。
今回はそのAPIを使ってSlackにいる全社員のメールアドレスをチェックします。

# セキュリティとバケツの話

会社でのセキュリティ対策は大変です。どんなにきっちりした対策をしていても、**たった1人の社員のアカウントのパスワード設定がゆるかったりするとそこがセキュリティホール**となり、攻撃することできます。

これをバケツと穴の話で例えられたりします。

バケツに社員分の穴を空けます。そして水を注いで、水の水位がその会社のセキュリティ対策レベルということです。

- バケツの穴: 社員1人のセキュリティ対策 (対策をしているほど位置が高い)
- バケツの水位: 会社全体のセキュリティ対策度合い

低いところに穴が空いたバケツにどんなに水を注いでもバケツの水は低いままですよね。

つまり、一部の社員のセキュリティ対策をしっかりしても意味がなく、**全社員のセキュリティ対策をしないといけない**ということです。

![souji_baketsu.png](https://qiita-image-store.s3.amazonaws.com/0/91558/089290b3-90bb-1fbd-af2d-99e1a54683af.png)

# 本題: 全社員のメールアドレスの漏洩をチェック
ということで、全社員のメールアドレスの漏洩のチェックをしましょう!

まず以下のアドレスにアクセスして、
(hogehoge-companyはよしなに変えてください)

`https://hogehoge-company.slack.com/stats#members`

列の編集ボタンを押して、メールアドレスを表示するようにしてから、`CSVのエクスポート`をしましょう。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/91558/47d56a48-0f28-87b2-aea9-60eaf76472d5.png)

これで、(Slackに登録されている)全社員のメールアドレスが取得できました。

**あとは以下のスクリプトを実行するだけ!**
(落としたCSVファイルを`slack_user_list.csv`に名前を変えてスクリプトと同じディレクトリに入れて実行してください。)

```python:check.py
import csv
import requests
import time

CSV_PATH = "slack_user_list.csv"
MAIL_COLUMN_INDEX = 2

def get_mail_list_slack_csv(file_path):
    mail_list = []

    with open(CSV_PATH, 'r', encoding="utf-8") as f:
        reader = csv.reader(f)
        header = next(reader)
        for row in reader:
            mail_list.append(row[MAIL_COLUMN_INDEX])

    return mail_list

def is_leaked(mail_address):
    time.sleep(5)

    endpoint = "https://haveibeenpwned.com/api/v2/breachedaccount/%s" % mail_address
    res = requests.get(endpoint)
    if res.status_code == 429:
        time.sleep(5)
        return is_leaked(mail_address)
    else:
        return res.status_code != 404

if __name__ == "__main__":
    mail_list = get_mail_list_slack_csv(CSV_PATH)
    leaked_mail_list = []

    for idx, mail_address in enumerate(mail_list):
        leaked = is_leaked(mail_address)
        print(idx+1, mail_address, "pwned!" if leaked else "no pwnage found!")
        if leaked:
            leaked_mail_list.append(mail_address)
        time.sleep(5)
    print()

    for mail_address in leaked_mail_list:
        print(mail_address)
```

# 最後に
「Have I been pwned?」で漏洩がわかってもそこまで焦ることではないです。(メールアドレスが漏洩しているだけなので)

ただ、漏洩してて単純なパスワードなどだと**結構危ない**です。
さらに、**パスワードの使い回し**をしていると**漏洩したサイト以外も不正アクセスされます**。

- パスワードの使い回しを避ける
- 多要素認証を使う
- 必要であればパスワード管理ソフトを使う

など対策を行いましょう。

ちなみに結構な割合で漏洩してます。

# その他

今回使ったスクリプトのレポジトリ↓

[GitHub: redshoga/slack-members-email-leak-checker: Leak checker from csv file that is written slack member](https://github.com/redshoga/slack-members-email-leak-checker)
pyenv + pipenv + direnvでpython環境構築[macOS Mojave]

# 概要
新品のmacOS Mojaveにpython環境をセットアップしてみる．
最近のpython環境事情を調べてみると，pyenv + pipenv + direnvというのが良さそうだったので自分へのメモがてら記事にしてみます．

今回構築する環境は

* どうでもいいディレクトリ内ではpython3の環境で適当にスクリプトを実行できるようにしたい
* ある程度重要なプロジェクト内ではPipｆileを使ってしっかりパッケージ管理したい

というモチベーションでセットアップしていきます．

## pyenvのインストール
```bash
$ brew install pyenv
```

さらに`.bashrc`に以下のように追加

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

## pipenvのインストール
```bash
$ brew install pipenv
```

さらに`.bashrc`に以下のように追加

```bash:.bashrc
### pipenv ###
eval "$(pipenv --completion)"
```

## direnvのインストール
```bash
$ brew install direnv
```

さらに`.bashrc`に以下のように追加

```bash:.bashrc
### direnv ###
eval "$(direnv hook bash)"
```

## コケた箇所
pyenvで新しい環境をインストールする際に

``` :terminal
zipimport.ZipImportError: can't decompress data; zlib not available
make: *** [install] Error 1
```

というエラーが発生．
[別のQiita記事](https://qiita.com/zreactor/items/c3fd04417e0d61af0afe)を参考に

``` bash
$ sudo installer -pkg /Library/Developer/CommandLineTools/Packages/macOS_SDK_headers_for_macOS_10.14.pkg -target /
```
を実行したら解決しました．

# ワークフロー
## デフォルトでpython3環境を設定
何も考えずに`python`を実行したら３系pythonが実行されてほしいので，pyenvでグローバルにpython3.7.2(執筆時最新）を設定します．

```bash
$ pyenv install 3.7.2
$ pyenv global 3.7.2
＄ which python
/Users/USER_NAME/.pyenv/shims/python
＄ pyenv versions
  system
* 3.7.2 (set by /Users/USER_NAME/.pyenv/version)
```

これで新しく作ったディレクトリの中では3系で実行されるようになりました．

## pipenvで新しいプロジェクトの環境を作る
```bash
$ mkdir new_project
$ cd new_project/
$ pipenv install --python 3.4.3   # python3.4.3の環境を作る
$ pipenv install sklearn numpy scipy    # パッケージのインストール
$ echo 'layout_pipenv' > .envrc && direnv allow    # direnvの設定
```
これで`cd`でnew_projectに移動した際に自動で仮想環境に入れます．

```bash
$ cd ..
direnv: unloading
$ cd new_project/
direnv: loading .envrc
direnv: export +PIPENV_ACTIVE +VIRTUAL_ENV ~PATH
$ which python
/Users/USER_NAME/.local/share/virtualenvs/new_project-T0Dp86UW/bin/python
```
WatchDogチェック

IoT(Internet of Test)でThingspeakにアクセスしているログでWatchdogリセットを確認するrubyスクリプトです。ThingspeakのExportのDownloadはTimezoneがUTCから変えられないので、[こちらのページ](https://qiita.com/semind/items/9614ded891d6154e9a06)を参考にしてみました。追記：2019/4くらいにJSTでダンプできるようになりました。


```ruby
#!/usr/bin/ruby

require 'csv'
require 'time'

class Time 
  def timezone(timezone = 'UTC')
    old = ENV['TZ']
    utc = self.dup.utc
    ENV['TZ'] = timezone
    output = utc.localtime
    ENV['TZ'] = old
    output
  end
end

csv_data = CSV.read(ARGV[0])

lastval = 0
lastdate = ""
count = 0

csv_data.each do |data|
  if data[2].to_i < lastval
    print "---\n"
    p Time.parse(lastdate).timezone('Asia/Tokyo')
    p Time.parse(data[0]) - Time.parse(lastdate) 
    p lastval
    p count
    count = 0
  end
  count = count + 1
  lastval = data[2].to_i
  lastdate = data[0]
end

print "---\n"
p lastval
p count
```

アクセス毎にインクリメントした数値を書き込んでいるので、逆転したところを探しています。

JSTでダウンロードできるようになったので、awkで簡単に確認する方法を考えました。シリアルを1番目のフィールドにします。これはチャンネルによってフィールド数が変わってくるので、シリアルを固定の位置にして確認しやすくするためです。

```
$ awk 'BEGIN{FS=","} NR>1{if(NR != 2 && last+1 != $3){sa=$3-last-1;print $1" "last" "$3" "sa};last=$3}' feeds.csv
```
基本的なSQL文について

#SQL文は指令！

こんにちは。未来電子テクノロジーでインターンをしている西尾です！

今回は、データベースを使う際に使用したSQL文についてのアウトプットをします！

□SQL文とは
SQL文とは、言語ではなく、その名前通り一文です。
この文で、データベースエンジンに指令を出すという仕組みになっています。

では、実際にどのように使うのかを見ていきます。

□SQL文を使ってみた
INSERT INTO mst_staff(name,password)VALUES("めい","12345") 

と表示した場合、最初のINSERT INTO mst_staffが、「mst_staffテーブルにレコードを追加しなさい。」という指令です。

その後の(name,password)VALUES("めい","12345") 
は、どうやって？の部分になります。
この場合、「VALUESの左側のフィールドに右の値をセットしなさい。」となります。

これで、指定したテーブルに、指定された値が入る仕組みになります。

SQL文は非常に深い世界です。
簡単なウェブシステム上では難しいものは使いませんが、興味のある人はさらに奥まで調べてみてください。

お読みいただき、ありがとうございました！
Azure VM(Linux)でスワップファイルを使用する

Azure VMのLinuxは、デフォルトではスワップファイルが設定されていません。
CentOSとUbuntuで設定方法が若干違ったので、設定方法を残しておきます。

# 環境
* CentOS-based 7.5
* Ubuntu Server 18.04 LTS

# 事前確認

* まずはVMデプロイ直後の状態を表示します。Swapが0Byteになってます。

```
$ free -m
              total        used        free      shared  buff/cache   available
Mem:           1918         140        1607           8         170        1561
Swap:             0           0           0
```

# 設定

* waagent.confを開きます。

```
$ sudo vi /etc/waagent.conf
```

* 以下のように編集します。

```
ResourceDisk.EnableSwap=y
ResourceDisk.SwapSizeMB=[スワップサイズ]
```

* Ubuntuの場合は上記に加えて以下の設定をします。

```
ResourceDisk.Format=y
```

* OSを再起動します。

```
$ sudo shutdown -r now
```

# 結果確認

* Swapサイズが増えてたらOKです。

```
free -m
              total        used        free      shared  buff/cache   available
Mem:           1918         139        1634           8         144        1576
Swap:          2047           0        2047
```
Powershellで定時でSlack投稿する

# Powershellで定時でSlack投稿する

## 想定読者

- 会社でWindows環境しかない (cronが使えない)ひと
- 会社の事情により, 仮想化環境でLinuxも利用できないひと
- とりあえずWindowsだけですませたいひと
- 定時でSlackに投稿することで、意識付けとかしたいひと

## 利用するツール

- Powershell
- タスクスケジューラ

## Slackでの設定

基本的にはPowershellからSlackのIncomming webhookをコールして、投稿を実施する。  
設定手順は下記の通り。（だいぶ端折ったが、様々な記事で公開されている無いようなので簡素にする）

1. ``https://{workspace-name}.slack.com/apps``にアクセスする
2. ``Incoming Webhooks``に移動し、``Add cofiguration``をクリック。適切な情報を入力してWebhookのURLを入手する。

## Powershellの設定

Powershellは専用のScriptを書いて実行することが可能だが、少し設定をupdateする必要があり少しめんどくさい。
そこで、この記事ではスクリプトは利用せずに実行する。  
また、Webhookをコールするためには、``cURL``ではなく``Invoke-RestMethod``なるものを活用する。

### Powershell上でのSlack webhookコール

下記のコマンドを実行することで、WebhookからSlackに投稿できることを確認する。

```
powershell -Command "Invoke-RestMethod -Method Post -Body \""{ 'text':'hello world!' }\"" -Uri \""https://{webhook-uri}"""
```

-Command移行を直接powershell上で実行することでも同様の実行はできるが、後続のタスクスケジューラではこの形式での呼び出しになるため、この方式でトライをする。

## タスクスケジューラの設定

手順は下記

1. タスクスケジューラを起動し、タスクの作成をクリック。
2. 操作タブをクリック、新規ボタンを押下
3. プログラム/スクリプトに``%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe``を入力
4. 引数の記載に``powershell -Command "Invoke-RestMethod -Method Post -Body \""{ 'text':'hello world!' }\"" -Uri \""https://{webhook-uri}"""``を入力

以上で、定時実行でSlackにポストされるはずである。
フォント毎にEUDCを設定したWindowsServer2016にパッチを当てるとBSoDになった件

# はじめに

・WindowsServer2016でEUDCを使うとBSoDを引き起こすとの噂を聞いた。
・上記の条件を満たす業務があった
・事象確認⇒対処⇒動作確認まで行った

# 概要
- KB4489882は自動アップデート対象
- KB4489889は任意アップデート対象（BSoDが発生する元凶）

※ 2019/04/03 にWindowsUpdateを走らせると、KB4489882までは自動で入る。KB4489889に関してはwindowsupdateカタログからモジュールをダウンロードして手動でインストールした。

# 事象確認
- パターン１　自動アップデート(KB4489882のインストール)→外字のインストール→手動アップデート(KB4489889)
- パターン２　自動アップデート(KB4489882のインストール)→手動アップデート(KB4489889)→外字のインストール

## パターン1
![image.png](https://qiita-image-store.s3.amazonaws.com/0/392192/bdd599d0-f290-57c3-c807-c7a78f0fa829.png)
→外字をインストールしたマシンにKB4489889を適用後再起動する。その後のログインしようとするとBSoD→再度ログイン画面（以下ループ）

## パターン2
![image.png](https://qiita-image-store.s3.amazonaws.com/0/392192/2312d1c2-864b-1db2-415d-8c7520322aeb.png)
→KB4489889を適用したマシンに外字をインストール。その後再起動させ、ログインしようとするとBSoD→再度ログイン画面（以下ループ）

**⇒KB4489889に外字が当たった状態以降で再起動させると、マシンにログインできなくなる。**

# MicroSoftからアナウンスされた対処法([こちら](https://support.microsoft.com/en-us/help/4496149))
1. コントロールパネル-インストールされた更新プログラム から手動で対象のKB4489889削除
2. レジストリエディタで「,TestFont」の追加
![image.png](https://qiita-image-store.s3.amazonaws.com/0/392192/968b0b60-4fd9-226a-0403-76b152d7616e.png)
3. 再起動
4. ログインできた！

# 動作確認
1. ログイン後、メモ帳を開く
2. 「がいじ」と入力しF5でIMEパッドを開く。
3. IMEパッドからインストールした外字を入力
4. 入力できた！

![image.png](https://qiita-image-store.s3.amazonaws.com/0/392192/2d609356-f14f-8f0a-c1aa-6791803b70bf.png)



# 参考
この調査をするきっかけとなったもの
https://yamanxworld.blogspot.com/2019/03/windows-update-2019-3-20-c-net-cu-1-b.html

EudcBrowser
https://www.vector.co.jp/soft/winnt/writing/se360228.html
→tteファイルに何の外字が入っているか確認するツール
API Gateway: AWS CLIを使ってAPIのパスを変更する

# `/v1/hoge/moge` というパスを `/v1/sage/moge` のように移動したい場合

`moge` というリソースを移動させる（親をつけかえる）ことになる。


1. API一覧を表示

    ```
    aws apigateway get-rest-apis
    ```
APIのidを確認する。

2. 指定APIのリソース一覧を表示

    ```
    aws apigateway get-resources --rest-api-id h4548bg9g9
    ```

    移動したいリソースのidと移動先（親）のリソースidを確認する。

3. 移動

    ```
   aws apigateway update-resource \
      --rest-api-id h4548bg9g9 \
      --resource-id tvfwpe \
      --patch-operations op=replace,path=/parentId,value=6a65mm
    ```

（上記例では `tvfwpe` の親を `6a65mm` に変更している）


# `/v1/hoge` を `/v1/moge` のようにリソース名を変更したい場合

前述の1, 2により `<api-id>` と `<resource-id>` を確認しておいて、下記でリネーム。

```
aws apigateway update-resource --rest-api-id <api-id> --resource-id <resource-id> --patch-operations op=replace,path=/pathPart,value=<new-name>
```

# 注意

変更したあとAPIのデプロイが必要。
また、この方法で変更するとLambdaの呼び出し許可をつけ直す必要があるので注意（マネジメントコンソールを使っていいなら、メソッドの編集のところで`統合タイプ` `Lambda 関数` のラジオボタンをつけ直せば許可をつけ直せるはず）。

# 参考
https://stackoverflow.com/questions/36973234/move-resource-in-aws-api-gateway
https://medium.com/@onclouds/aws-api-gateway-rename-a-resource-name-77470ea57ce9
[Vue.js/Nuxt.js] <nuxt-link>に@clickを付ける場合は@click.nativeの記述にしなければ動かない

## 概要

nuxt-linkの拡張元のrouter-linkではv-on:clickをサポートしていないため、ネイティブイベントを呼び出す必要があるみたいです。

タイトルの通り、`@click` でなく `@click.native` を使用しましょう。

### 動かない

```vue
@click="method"
```

### 動く

```vue
@click.native="method"
```

## イベント修飾子を使用したい場合

また、クリックイベントの[イベント修飾子](https://jp.vuejs.org/v2/guide/events.html)を使用したい場合はnativeに続けて記述します。

```vue
@click.native.stop
```

のように書けばOKです。

動作しているか確認したい場合は以下のように記述すれば大丈夫だと思います。

```vue
@click.native.stop="handler"

~略~

methods: {
  handler() {
    console.log('stop');
  }
}
```

## ネイティブイベントについて

検索してもなかなか情報が転がっていなかったのですが、ネイティブイベント=DOMが基本的にサポートされているイベントのことなんですかね？

[イベントリファレンス | MDN](https://developer.mozilla.org/ja/docs/Web/Events)

## 参考リンク

検索すると結構情報が転がっていました。

ここが一番詳しいかも

[カスタムイベント — Vue.js](https://jp.vuejs.org/v2/guide/components-custom-events.html#%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%AB%E3%83%8D%E3%82%A4%E3%83%86%E3%82%A3%E3%83%96%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%82%92%E3%83%90%E3%82%A4%E3%83%B3%E3%83%87%E3%82%A3%E3%83%B3%E3%82%B0)

[How do we v-on:click nuxt-link? · Issue #1786 · nuxt/nuxt.js](https://github.com/nuxt/nuxt.js/issues/1786)

[【Vue】router-linkのv-on:clickを有効にする方法【vue-router】 - The sky is the limit](http://www.sky-limit-future.com/entry/router-link-click-event)
ABC - 112- A&B&C

#AtCoder ABC 112 A&B&C
[AtCoder - 112](https://atcoder.jp/contests/abc112)

#A問題

```java
	private void solveA() {
		int age = 0;

		age = Integer.parseInt(next());
		switch (age) {
		case 1:
			out.println("Hello World");
			break;
		case 2:
			int numA = nextInt();
			int numB = nextInt();
			out.println(numA + numB);
			break;
		}

	}
```

#B問題

 - 時間$T_i$でソートして$T_i \leq T$の$C_i$を比較する
 - ソートした結果、一番低い$C_i$が解答

```java
	private void solveB() {
		int numN = Integer.parseInt(next());
		int numT = Integer.parseInt(next());

		int[][] wk = new int[numN][2];

		for (int i = 0; i < wk.length; i++) {
			for (int j = 0; j < 2; j++) {
				wk[i][j] = nextInt();
			}
		}

		Arrays.sort(wk, (x, y) -> Integer.compare(x[1], y[1]));

		int cnt = 9999999;
		for (int i = 0; i < wk.length; i++) {
			if (wk[i][1] <= numT) {
				cnt = Math.min(wk[i][0], cnt);
			} else {
				break;
			}
		}

		out.println(cnt != 9999999 ? cnt : "TLE");
	}
```

#C問題

 - $(x,y)$はそれぞれ100以下の整数なので総当りを試す
 - $(0,0),(1,0),(2,0) ・・・  (100,100)$
 - 総当りするために、基準となる場所 $(x_i,y_i)$ をピックアップする
    - 条件は
        - Hが0ではないものを選択する
            - 問題文 $max(H−|X−CX|−|Y−CY|,0) $ より、H=0のものはHが-または0の地点であるため。正確なHが算出できない。

```java
	private void solveC() {
		int numN = Integer.parseInt(next());

		long[][] wk = new long[numN][3];

		for (int i = 0; i < numN; i++) {
			for (int j = 0; j < 3; j++) {
				wk[i][j] = nextLong();
			}
		}

		int referenceIndex = 0;
		//Hが-のものは0にされてしまっているため、Hが0でないものを基準にする必要がある。
		while (wk[referenceIndex][2] == 0) {
			referenceIndex++;
		}

		long h = -1;
		for (int i = 0; i <= 100; i++) {
			for (int j = 0; j <= 100; j++) {
				boolean isRes = true;
				//0でないものを選択しているので、maxが不要
				h = Math.abs(wk[referenceIndex][0] - i) + Math.abs(wk[referenceIndex][1] - j) + wk[referenceIndex][2];
				for (int k = 0; k < numN; k++) {
					//Hが-のものは0に合わせてあるためmaxを入れないといけない
					if (wk[k][2] != Math.max(h - Math.abs(wk[k][0] - i) - Math.abs(wk[k][1] - j), 0)) {
						isRes = false;
						break;
					}
				}
				if (isRes) {
					out.println(i + " " + j + " " + h);
					return;
				}
			}
		}

	}
```
条件式のカンマについて(Swift)

## はじめに

私が実際にやってしまった失敗です。

SwiftLintで [Unused Optional Binding](https://qiita.com/uhooi/items/7f5d6cf2b240f60ba1ed#unused-optional-binding) のルールに引っかかり、以下のように修正しました。

```diff_swift
- guard let _ = foo, let _ = bar else {
+ guard foo != nil || bar != nil else {
     return
}
```

こちらの修正に何の疑問も抱かない方は、 __本記事を最後まで読むことをおすすめします__ 。
すぐに気づいた方は、本記事を読まなくても大丈夫です。

## 結論

先に結論を述べます。
Swiftの条件式において、__`,` と `&&` はほぼ同義__ なので、先ほどの修正は以下が正しいです。

```diff_swift
- guard let _ = foo, let _ = bar else {
+ guard foo != nil && bar != nil else {
     return
}
```

## 証明

簡単なプログラムを組み、上記の結論を証明します。

```swift
func exampleBefore(foo: Int?, bar: String?) -> Bool {
    guard let _ = foo, let _ = bar else {
        return false
    }
    return true
}

func exampleAfter(foo: Int?, bar: String?) -> Bool {
    guard foo != nil && bar != nil else {
        return false
    }
    return true
}

exampleBefore(foo: nil, bar: nil) // false
exampleBefore(foo: 1, bar: nil) // false
exampleBefore(foo: nil, bar: "example") // false
exampleBefore(foo: 1, bar: "example") // true

exampleAfter(foo: nil, bar: nil) // false
exampleAfter(foo: 1, bar: nil) // false
exampleAfter(foo: nil, bar: "example") // false
exampleAfter(foo: 1, bar: "example") // true
```

このプログラムをプレイグラウンドで実行してみます。

![スクリーンショット 2019-04-04 18.09.20.png](https://qiita-image-store.s3.amazonaws.com/0/138245/2e12f154-3b62-07b8-9110-48859d2d34fa.png)

`exampleBefore` と `exampleAfter` の戻り値が同じになり、先ほどの結論が正しいことを証明できました。

## おまけ

条件式に `,` を多用すると可読性が落ちることがあるため、if-letまたはguard-let文以外では使わないほうがいいと思いました。

`,` を使える言語は私の知る限りSwiftのみなので、他の言語から入った方は `&&` のほうが読みやすいはずです。

## おまけ2

他の方が `,` と `&&` をどう使い分けているか気になったので、Twitterでアンケートを取ってみました。

https://twitter.com/the_uhooi/status/1602117859345575936

結果は私と同じくif-letまたはguard-let文のみで使う方が45.9%で最も多かったです。

ただ「できる限り `,` を使う」というkoherさんの意見が興味深かったので紹介します。

https://twitter.com/koher/status/1602124496718434304

https://twitter.com/koher/status/1602128350843375616

https://twitter.com/koher/status/1602133139224416257

`,` を優先して使う理由を丁寧に言語化されており、私も真似しようか検討中です。

「 `,` は小さくて見づらいから、使うときは必ず改行する」という意見もありました。

https://twitter.com/at_aka/status/1602361443680419840

こちらの意見もなるほどと思い、私も `,` を使う際は改行しようと思いました。
28日目、ポートフォリオを作りました

ボートフォリオは自分ができることをアピールする為のホームページ（らしい）

まだまだへっぽこですが、勉強会やハッカソンに行ってみたいので、
今こんな感じですって説明するために、まとめページを作ってみようと思います。


###作業前の状態
HerokuでHTMLを動かすために、ダミーでindex.phpを読ませていました。
中身は`echo 'Hello　PHP on Heroku!';`と`phpinfo();`　です。

![スクリーンショット 2019-04-04 15.11.55.png](https://qiita-image-store.s3.amazonaws.com/0/356263/2f766a6a-a45e-f73f-651f-5e6698c1e896.png)


Herokuはなんでもいいのでトップにindex.phpを置いておけばhtmlとJavaScript，PHPが動くので、これでProgateや小物作りをしていました。

しかし、このままでは自己紹介しにくいので、まとめページっぽくしていきたいと思います。


###index.phpにindex.htmlを読ませてみる
ためしに、Progateで作ったindex.htmlを読ませてみました。

```php
<? include('./index.html'); 
//echo 'Hello　PHP on Heroku!';
//$dbinfo = parse_url(getenv('DATABASE_URL'));
//$dsn = 'pgsql:host=' . $dbinfo['host'] . ';dbname=' . substr($dbinfo['path'], 1);
//$pdo = new PDO($dsn, $dbinfo['user'], $dbinfo['pass']);
//var_dump($pdo->getAttribute(PDO::ATTR_SERVER_VERSION));
//phpinfo();
?>
```

OKOK、動作しました。
スマホではスマホ版がうごいています。レスポンシブな感じです。

###画像を差し替える
トップ画像を変えてみます。ぱくたそでフリー画像をさがしてアップロード、URLを書き換えます。明るい画像だったので、文字は白から黒に変更しました。

```stylesheet.css
.top-wrapper {
  padding: 180px 0 100px 0;
   /*background-image: url(https://prog-8.com/images/html/advanced/top.png);*/
  background-image: url(4IS_aozoratoshiroisakura_TP_V.jpg);
  background-size: cover;
  /*color: white;*/
  color: black;
  text-align: center;
}
```

いい感じです！

###ボタンを変更します。
新規登録が緑だったので、そのままQiitaボタンに改造。
はてなとTwitterのボタンを追加しました。

```index.html
<div class="btn-wrapper">
   <a href="https://qiita.com/robamimim" class="btn signup">Qiita</a>
   <p>or</p>
   <!--<a href="#" class="btn facebook"><span class="fa fa-facebook"></span>facebook</a> -->
   <a href="https://robamimim.hatenablog.com/" class="btn facebook"><span class="fa hatena"></span>facebook</a>
   <a href="https://twitter.com/robamimim" class="btn twitter"><span class="fa fa-twitter"></span>Twitter</a>
</div>
```

```stylesheet.css
.qiita {
  background-color: #239b76;
  margin-right: 10px;
}

.hatena {
  background-color: black;
  margin-right: 10px;
}
```

###100daysofcodeのクラスを作る
.lesson-wrapperをコピーして.Days-wrapperクラスを作り、文字を左に揃えました。
.lessonをコピーして.Dayクラスを作り、4段組みを1段にしました。

```stylesheet.css
.Days-wrapper {
  padding-bottom: 80px;
  padding-left: 5%;
  padding-right: 5%;
  background-color: #f7f7f7;
  text-align: left;
}

.Day {
  float: left;
  width: 100%;
}
```
###アイコンを作る
アイコンをProgateからロバへ。
フリー画像もいいけど、ちゃんとしたロゴを作りたいなあ。

```index.html
<!-- <img src="https://prog-8.com/images/html/advanced/footer_logo.png"> -->
<img src="roba.jpg">

```

###完成！
なんとかどうにかできました！
トップページにアクセスしたとき`phpinfo()`じゃかっこ悪いもんね。
アイコンとデザイン。どうやったらカッコよく見せられるかとかは、おいおい・・・。
これで、今こんだけの事ができますって説明するのに使ってみようと思います。

robamimimのポートフォリオ
https://appdays.herokuapp.com/

![スクリーンショット 2019-04-04 18.07.43.png](https://qiita-image-store.s3.amazonaws.com/0/356263/de4209d9-d484-71b2-c7fa-b386d846a6a4.png)


(所要時間 3時間)
JSONは義務教育

#### JSONとはデータ記述言語（文字列）である

JavaScript Object Notation（JSON、ジェイソン）は軽量なデータ記述言語の1つである。構文はJavaScriptにおけるオブジェクトの表記法をベースとしているが、JSONはJavaScript専用のデータ形式では決してなく、様々なソフトウェアやプログラミング言語間におけるデータの受け渡しに使えるよう設計されている。

JSONはJavaScriptにおけるオブジェクト表記法のサブセットであるが、JavaScriptでの利用に限られたものではない。

(Wikipediaより)

----

## Javascriptの書き方だけど、これ標準化しようぜ

----

#### JSON基礎

- 名前/値のペアの集まり 
- 順序付きリスト（配列）

##### 記載例

```json
{
  "user" : {
    "name": "Nishida",
    "age": 17,
    "languages": ["Japanese", "English", "Spanish"],
    "active": true
  }
}
```

----

#### 名前/値のペア

- 名前は必ず`"`で括る
- 名前と値の間は `:` で区切る
- 名前と値のペアのことを **メンバー** と呼ぶ

##### JSONトークン

構造 `{` `}` `[` `]` `:` `,`
定数 `null` `true` `false`
`"文字列"` `数値`

※ トークン間に空白文字を入れてもよい

----

#### 値のデータ型

- **number** 10進法の数値（負数、浮動小数点、指数表記可）
- **string** `"`で括った文字列。特殊文字は必ずエスケープする。
- **array** `[]` 内に値を `,` 区切りで記載 順序は保持される
- **object** `{}` オブジェクト（連想配列）順序は保証されない
- **true** `true` 小文字で表記
- **false** `false` 小文字で表記
- **null** 小文字で表記

※日時はありません

----

#### JSONの利点

**プレーンテキストである**

- ログとして残しやすい
- 人間への可読性を残している
- 再利用しやすい

----

### JSONの利点

対応するプログラミング言語の多さ

JSONは多くのプログラミング言語で利用可能である。例えば、ActionScript, C, C++, C#, ColdFusion, Common Lisp, Curl, D言語, Delphi, E, Erlang, Groovy, Haskell, Java, JavaScript (ECMAScript), Lisp, Lua, ML, Objective-C, Objective CAML, Perl, PHP, Python, R, Rebol, Ruby, Scala, Squeakなど。

RESTful APIによるAjax通信に広く利用されている

----

### すべてのデータフォーマットを過去にする

----

#### 過去にされた方々

固定長バイト氏
「昔はがんばっていたんですが、UTF-8さんとどうしても折り合いがつかなくてね。古い顧客だけとやっていくことにしたよ。」

CSV氏
「私って仕様がまちまちなところがあって、いろんな人を困らせていたと思います。最近Excelさんと不仲になってきたこともあるし、あとはJSONさんに任せて引退しようと考えています」

----

#### 過去にされた方々

XML氏
「自由度の高さと属性を売りにがんばってきましたが、さすがに若者はついてこれなくなりましたね。今後は活動を縮小していこうと思います」

PDF👦🏾「Adobe先生の都合でだいぶ乖離しちまったけど、これからもよろしくな。」

HTML👧🏻「ウチで飼ってるCSS🐁とJavascript🦌が迷惑をかけるかもしれませんが、よろしくおねがいします。」

XML（はやくこいつらと縁を切りたい…）

----

### すべてのシリアライズを過去にする

----

### Comming Soon!

----

#### JSONの仕様

以下が定義されている

RFC 4627 (2006)
RFC 7159 (2014)
RFC 8259 と ECMA-404 (2017 ★最終)

ECMA-404は（正味）5ページのみ！

----

#### 参考にしました

json.org （公式サイト）
https://www.json.org/json-ja.html

Wikipedia JavaScript Object Notation
https://ja.wikipedia.org/wiki/JavaScript_Object_Notation

Gixo blog データフォーマットの変遷について考える
https://www.gixo.jp/blog/3965/

マネーフォワード エンジニアブログ JSON仕様（ECMA-404） を眺めてみる
https://moneyforward.com/engineers_blog/2016/03/29/json-ecma-404/
scikit-learnによる機械学習実装の本質部分

# 目的
　機械学習ライブラリscikit-learnは非常に少ないコード量で機械学習モデルを実装できる。しかし、多くの解説記事においては学習モデルの評価、グラフ描画等を同時に解説するがゆえに、何が機械学習の本質なのかが見えにくい。そこで本記事では、scikit-learnによる機械学習モデル実装の本質部分のみを抽出して解説する。

# 概要
　scikit-learnを使ったpythonでの機械学習について、必要最小限の流れをまとめる。必要最小限とは、モデルを実装、使用するまでに必要な最小限の作業を指す。必要なデータを集めた状態からスタートし、以下の流れを書く。

1. 入力データの整形
2. モデルの選択
3. 学習（フィッティング）
4. モデルの使用（実際の予測）

# 1. 入力データの整形
  使用するデータ例は下記2つのテーブルのものとする

訓練データ

| 説明変数1 | 説明変数2 | 目的変数 |
|:-:|:-:|:-:|
| 1  | 6  | 7  |
| 2  | 7  | 9  |
| 3  | 8  | 11  |
| 4  | 9  | 13  |
| 5  | 10  | 15  |

予測データ

| 説明変数1 | 説明変数2 |
|:-:|:-:|
| 50  | 100  |

　訓練データの説明変数を $X$ 、訓練データの目的変数を $y$($X$は行列で$y$はベクトルなのでそれぞれ大文字と小文字を使用する) 、予測したいデータを $X_{\rm pred}$ として以下の形式で用意する。

```math
X=\begin{bmatrix}
x_{11} & x_{12} & \cdots & x_{1n}\\
x_{21} & x_{22} & \cdots & x_{2n}\\
\vdots &        &        & \vdots\\
x_{n1} & x_{n2} & \cdots & x_{nn}\\
\end{bmatrix}
,~~
y= \begin{bmatrix}
y_1 \\
y_2 \\
\vdots \\
y_n \\
\end{bmatrix} 
,~~
X_{\rm pred}=\begin{bmatrix}
x'_{11} & x'_{12} & \cdots & x'_{1n}\\
x'_{21} & x'_{22} & \cdots & x'_{2n}\\
\vdots &        &        & \vdots\\
x'_{n1} & x'_{n2} & \cdots & x'_{nn}\\
\end{bmatrix}
```

　行方向（縦）に各サンプル、列方向（横）に特徴量となるように配列を作ることに留意する。例のデータでは以下のようになる。コード上では内側配列が列方向、外側配列が行方向となる。

```python

X = [[1, 6], [2, 7], [3, 8], [4, 9], [5, 10]]
y = [7, 9, 11, 13, 15]
```

# 2. モデルの選択
　使うモデルは[こちら（チートシート）](https://scikit-learn.org/stable/tutorial/machine_learning_map/index.html)を参考にすると良い。例では簡単のため、線形回帰モデルを使用した。
sklearnライブラリから該当クラスをインポートし、インスタンスを生成して使用する。

```python

from sklearn.linear_model import LinearRegression

model = LinearRegression()
```

# 3. 学習（フィッティング）
　訓練データを元にモデルを学習（フィッティング）する。scikit-learnではモデルによらず一般に`fit`メソッドを用いる。2で生成したインスタンスの`fit`メソッドを、第1引数を訓練データの説明変数($X$)、第２引数を訓練データの目的変数($y$)として呼び出す。教師無し学習の場合、目的変数は無いので第2引数は無い。
　以上で機械学習モデルが完成した。

```python
model.fit(X, y)  #modelインスタンスの学習
```

# 4. モデルの使用（実際の予測）
　3の機械学習モデルを使用して実際に予測を行う。予測には、モデルによらず一般に`predict`メソッドを使用する。3でfitを行なったインスタンスを使うことに注意する。引数には予測したいデータ($X_{\rm pred}$)を使う。

```
X_pred = [[50, 100]]
print(model.predict(X_pred))

>> [150. ]
```

訓練データでは
説明変数1 + 説明変数2 = 目的変数
の関係があり、正しく学習・予測できた。

# まとめ
1. 説明変数 $X$, 目的変数 $y$を用意
2. sklearnからモデルをインポート、インスタンスを生成
3. `インスタンス.fit(X, y)` で学習
4. 予測したいデータ`X_pred`について、`インスタンス.predict(X_pred)`で予測。
Fultter環境構築：SDKのパスを通す(永続化)

#FlutterのSDKパスを通し永続化する

###開発環境(Android studio等)を立ち上げるたびにFlutterのSDKパスが切れているので永続化するためのメモ


まず、普通にパスを通す方法として
ターミナルを開き以下でパスを通す


```
export PATH="$PATH:FlutterSDKのbinまでのパス"
```

ホームディレクトリにあるなら

```
export PATH="$PATH:~/flutter/bin"
```

毎回ターミナルでこれを記述すればパス通せるけどめんどくさい。


##パス永続化する

.bash_profileに上のコマンドを記述しておくとターミナル起動時に勝手にパスを通してくれる


.bash_profileを編集する
ターミナルを開いて

```
vi ~/.bash_profile
```
を実行する。

これでviを起動し.bash_profileを編集する。

viは起動した時コマンドモードというモードになっていて中身を書き換えられない。

"i"を押すとviが編集モードに切り替わる(下にInsertとでる)ので


```
export PATH="$PATH:FlutterSDKのbinまでのパス"
```

を記述し、次に"esc"を押してコマンドモードに戻す。(Insertが消える)

次に":w"そして"return"で記述した内容を保存することができる。

保存できたら":q"そして"return"でviを閉じる。

これでターミナルを起動した時勝手にパスが通るようになる。
#docker + #MySQL 5.7 で、コンテナを終了・再起動してもデータが消えないように volume mount しながら port 指定でDBサーバーを作る  docker-compose の例

# ./docker-compose.yml

```yml
version: '2'
services:
  db:
    image: mysql:5.7
    volumes:
      - ./db/mysql_data:/var/lib/mysql
    environment:
      - MYSQL_ALLOW_EMPTY_PASSWORD=yes
    ports:
      - "10000:3306"
```

# exe

通常実行

```
$ docker-compose up db
```

バックグラウンド実行はこちら

```
$ docker-compose up --detach db
```

# MySQL への接続

```
$ mysql -u root -h 127.0.0.1 -P 10000
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 3
Server version: 5.7.25 MySQL Community Server (GPL)

Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> 
```

# 動作検証

db や テーブル作ってから `docker-compose down` したり up したりして、データが残っていることを確認

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/1076








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Railsのローカル開発環境でPostgreSQLのデータをダンプ&リストアしてみた

## 環境

```
$ postgres --version
postgres (PostgreSQL) 10.5

$ ruby -v
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin18]

$ bin/rails -v
Rails 5.1.7
```

## データベースのダンプ

`pg_dump`コマンドで以下のようにダンプできます。

```
pg_dump データベース名 > バックアップファイル名
```

ローカル開発環境のデータベースをダンプしたい場合は、以下のようになります。

```
$ pg_dump hoge_development > hoge_development.txt
```

以上の例では、hoge_development.txtというファイルに標準出力しています。

## データベースの削除

サーバーを起動している場合は、シャットダウンします。データベースに接続している場合は、遮断します。
以上が完了していれば、`dropdb`コマンドでデータベースを削除します。

```
$ dropdb hoge_development
```

## データベースの作成

`db:create`でデータベースを作成します。ここでは、`RAILS_ENV=development`と開発環境を指定しています。
データベース作成後、念の為確認します。作成したデータベース名が表示されていればOKです。

```
$ bin/rails db:create RAILS_ENV=development
$ psql -l
                                   List of databases
        Name         | Owner | Encoding |   Collate   |    Ctype    | Access privileges
---------------------+-------+----------+-------------+-------------+-------------------
 hoge_development    | banri | UTF8     | en_US.UTF-8 | en_US.UTF-8 |
```

## リストア

`psql`コマンドで以下のようにリストアできます。

```
psql データベース名 < バックアップファイル名
```

ダンプしたデータをローカル開発環境のデータベースにリストアしたい場合は、以下のようになります。

```
$ psql hoge_development < hoge_development.txt
```

`bin/rails s`でサーバーを起動し、データが復元されていたら無事リストア完了です。
IPアドレスのブラックリストを作ってLaravelのミドルウェアでブロックする話

最近クラウドIaaSを使うようになって、FWで遊ぶことが減ってきましたね。
特定のIPアドレスからのアクセスを止めるなら、AWSのセキュリティグループやVPCのACLを使えばできるのですが、たくさんあると設定数上限になったりして、不便ですよね。

今回はRedisにブラックリストを入れて、リクエスト元のIPアドレスがブラックリストにいるかどうかチェックするミドルウェアを作ってみました。

## Redisにブラックリストを入れる

まず `blacklist.txt`(名前は何でもいい) を作ります。
フォーマットは下記のような感じです。事前にブロックしたいIPアドレス範囲の下限と上限を出しておいてください。

```
zadd blacklist IPアドレス範囲上限 同下限
```

私はipcountとphpを組み合わせてシェルスクリプトを作って作りました。

```shell-session
$ ipcount 192.168.0.0/24
      192.168.0/24        192.168.0.0 - 192.168.0.255   [256]
$ php -r "echo ip2long('192.168.0.0');"
3232235520
$ cat calc.sh
#!/bin/sh

_calc() {
    for i in $(cat -)
    do
        aaa=`ipcount $i | awk '{print $2}'`
        bbb=`ipcount $i | awk '{print $4}'`
        from=`php -r "echo ip2long('$aaa');"`
        to=`php -r "echo ip2long('$bbb');"`
        echo "zadd blacklist $to $from"
    done
}

if [ -p /dev/stdin ]; then
    cat -
else
    echo $@
fi | _calc
$ head sourcedata.txt
192.168.0/24
$ cat sourcedata.txt | sh calc.sh > blacklist.txt
$ head blacklist.txt
zadd blacklist 3232301055 3232235520
```

上記の操作で出来上がった、 `blacklist.txt` をredisに投入します。

```
$ cat blacklist.txt | redis-cli --pipe
All data transferred. Waiting for the last reply...
Last reply received from server.
errors: 0, replies: 999
```

## ソースコード



```
<?php

namespace App\Http\Middleware;

use Closure;
use \Illuminate\Http\Request;
use \Illuminate\Http\Response;
use \Illuminate\Support\Facades\Redis;
use Log;
use App\Exceptions\ErrorService;

class IpBasedAcceccControlMiddleware
{

    /**
    * Handle an incoming request.
    *
    * @param  \Illuminate\Http\Request  $request
    * @param  \Closure  $next
    * @return mixed
    */
    public function handle($request, Closure $next)
    {
        $ip_address = $request->header('X-Forwarded-For') ?: '127.0.0.1';

        if (env('ACL_ON', false) && $this->isBlackListed($ip_address)) {
            // ACLがオンで、ブラックリスト対象のIPアドレスだったらワーニングを吐く
            Log::warning('IpBlocked', [
                'FromIp' => $ip_address,
            ]);
            exit;// exitしてるけどホントは好きにしてください。
        }

        // ACL問題なかったので進める。
        return $next($request);
    }

    /**
    * ブラックリストに含まれるIPアドレスかどうか返す
    *
    * @param  string $ip_address
    * @return boolean
    */
    public function isBlackListed(string $ip_address) : bool
    {
        // IPアドレスの文字列をlong変換する
        $ip_address = ip2long($ip_address);

        $hit = Redis::zrangebyscore('blacklist', $ip_address, '+inf', 'withscores', 'LIMIT', '0', '1');

        foreach($hit as $address_range_first => $address_range_last) {
            // ホントはforeachじゃなくてもいいのだけど、ifでnullチェックしてreturnしたくなかったのでforeachにした
            if ($address_range_first <= $ip_address && $ip_address <= $address_range_last) {
                // ブラックリストに登録されてるIPアドレス範囲内になっていたのでtrue返す
                return true;
            }
        }

        return false;
    }
}
```

# まとめ

`blacklist` へ `zadd` するのを動的にすれば、動的に防御できるようになりますね。海外からの不正アクセスの防御する際にご参考になれば幸いです。
Smarty 連想配列のキーを変数で指定

```
{function name=getString id=''}
    {assign var="arr" value=['1' => 'C', '2' => 'B', '3' => 'A', '4' => 'S', '5' => 'SS']}
    {assign var="res" value=$arr[$id]}
    {$res}
{/function}
```
Unity 2017.4でのGoogle Play Games plugin for UnityのARM64対応

[Unity 2017.4にも64bit対応がバックポートされた](https://blogs.unity3d.com/jp/2019/03/05/android-support-update-64-bit-and-app-bundles-backported-to-2017-4-lts/)ので [Google Play Games plugin for Unity](https://github.com/playgameservices/play-games-plugin-for-unity) を更新して64bit対応したら少し手間取った

## 環境
Unity 2017.4.24f1
Google Play Games plugin for Unity v0.9.62

## ARM64を指定しても arm64-v8a/libgpg.so が追加されない
v0.9.51以降であれば64bitに対応しているが、Unity2017.4.24f1でライブラリが正しく追加されなかった
これは同梱されている[Play Services Resolver](https://github.com/googlesamples/unity-jar-resolver) が2017.4の64bitに対応していないため (v0.9.62 時点)

Play Services Resolverのv1.2.103で対応が入っているので、反映されるのを待つか直接更新する必要がある
今回は自分で更新した

### Play Services ResolverのImport
https://github.com/googlesamples/unity-jar-resolver からclone/downloadしてくる
ルートに`play-services-resolver-1.2.103.0.unitypackage`があるので
これを対象のUnityプロジェクトにimportして更新する

### 確認
Player SettingsでARM64が設定してメニューから`Assets/Play Service Resolver/Android Resolver/Force Resolve`で更新する
`Plugins/Android/com.google.games.gpgs-plugin-support-0.9.62.aar`の中に`jni/arm64-v8a/libgpg.so`があることを確認する
Androidのビルド後、apkの中を直接確認してもいい
VirtualBoxのおひっこしメモ

#前提条件
1. システムドライブにいくつかの仮想PCファイルがある
2. データドライブにも仮想PCファイルがある。
3. 実験的にぼこぼこ増やしているのでエクスポート／インポートは正直面倒くさい

#バックアップするファイル・フォルダ
##必要なファイル
C:\Users\%username%\.VirtualBox\VirtualBox.xml
##必要なフォルダ
前提条件1がない場合は不要（のはず）
C:\Users\%username%\VirtualBox VMs

#インストール
引っ越し先のPCにVirtualboxをインストール

#リストア
引っ越し先の上記ファイル・フォルダと同じところにリストアする。
もそ、プログラミングを学ぶ【Ruby & Rails復習編】〜アソシエーションを克服しよう〜

ロープレで頭をフル稼働させ、すでに力尽きかけている もそ。
まじで頭から湯気が出そうになります...そのうち知恵熱出すんじゃないかこれ...。

今日はエラー解決シリーズを一旦お休みして、**アソシエーション**について書いていこうと思います。


#アソシエーションとは？
一言で説明すると、ずばり**モデルとモデルを結びつけること。**
これがアソシエーションです。


たとえば、"Tweetモデル"と"Usersモデル"という２つのモデルがあるとします。
この２つはそれぞれtweetsテーブル、usersテーブルの情報を取りだしてコントローラに渡す役割をします。

いま、コントローラがtweetsテーブルとusersテーブルの中身を渡してもらう処理を出したとします。

すると、

1.Tweetモデルに指示を出す
2.Tweetモデルがtweetsテーブルから情報を探す
3.探した情報をコントローラに情報を渡す

という処理の流れが発生します。

同様に、Userモデルにもデータを渡してもらって...という処理が発生します。

<img width="375" alt="無題1189.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/372174/c3d689cd-3192-74f2-b25e-30783f8a7148.jpeg">


今回はモデルは２つだけですが、たとえばモデルがたくさんある場合だと、情報が欲しいテーブルに結びついているすべてのモデルを呼び出すため処理が重くなってしまいます。

そこで**アソシエーション**で、モデルともモデルを関連つけておきます。
そうすると、あるモデルが呼び出された時に紐付いたほかのモデル配下のデータも引き出せるというわけです。

今回の場合であればTweetモデルとUsersモデルをアソシエーションにしておくと、**tweetsテーブルの情報とusersテーブルの情報をコントローラに渡すことができます。**

<img width="375" alt="無題1188.jpeg" src="https://qiita-image-store.s3.amazonaws.com/0/372174/4262d804-e164-3fc5-4971-6f6b1118f309.jpeg">


##コードを確認してみよう！
ではアソシエーションの記述はどのようにされているか、実際のコードを確認してみましょう。

```users_conrtoller.rb
1. class UsersController < ApplicationController
2.  def show
3.    user = User.find(params[:id])
4.    @nickname = user.nickname
5.    @tweets = user.tweets.page(params[:page]).per(5)
6.  end
7. end
```

ここで、上から５行目の

```rb

5. @tweets = user.tweets.page(params[:page]).per(5)
```

この記述に注目してみましょう。
中の要素を分解していくと、`tweets`という記述が出てきます。
この`tweets`がどこから出てきたかと言うと、**モデルファイル**で定義されています。

```users.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable
  has_many :tweets
  has_many :comments
end
```

こちらのモデルファイルの上から４行目で、**「一人のuserは複数のtweetsをもつ」**と定義しています。
これによって、コントローラファイルで`tweets`の記述が使えるようになりました。

##テーブルで確認してみよう！

テーブル間の結びつきを図にしてみました。
同じ色の線で結ばれているのが、あるユーザーのもつ複数の情報になります。

![無題1190.jpeg](https://qiita-image-store.s3.amazonaws.com/0/372174/8501805b-fc6f-6e60-fcf6-d81edec2ff63.jpeg)

たとえばusersテーブルのid 3の情報を指定すると、tweetsテーブルのid 4,5,6の情報も一緒に取得できます。

--
いかがだったでしょうか？
ファイルをまたぐと変数や定義された記述の動きがわからなくなってしまいますが、図解も駆使して理解していこうと思います。
もその修行はまだまだ続く...。