OmniAICreator/Qiita-1.07M huggingface dataset:
[Rails] Transaction内で条件分岐してrescue

# こちらの記事をもし見られた方への注意事項

もしこちらの記事を見られた方はこの記事のコードをコピペ等はしないでください。
理由はコメントと、そちらにありますyoutubeでの解説動画を御覧ください。
伊藤さん(@jnchito)にぶった切られています！笑
自分と同じように安易にrescueしに来た方は悪い例を見てから、そちらを御覧ください！笑

# そもそもTransactionなぜ必要なのか
複数にまたがるモデルのデータ同時に保存したいときや、`find_each`などで複数回データをいじって保存したいときに、`Transaction`を利用します。

```users_conroller.rb
def create
User.transaction do
    @user.save!

    respond_to do |format|
      format.js { render : 'action名' }
    end
  rescue => e
    logger.debug("failed. because of #{e}")
    redirect_to ~~~path
  end
end
```

上記のようなコードは問題なく動作します。
しかし下記の様にもしcontroller内に渡ってくるparamsによって`if..end`で囲むと、`syntax error`が発生します。

```users_controller.rb
def create
  if user_params[:user_id].present?
    User.transaction do
      @user.save!

    respond_to do |format|
      format.js { render :　'action' }
    end
  rescue => e
    logger.debug("failed. because of #{e}")
    redirect_to ~~~path
  end
  else
    # 処理
  end
end
```

結果

```
SyntaxError (.../hoge/app/controllers/user_controller.rb:96: syntax error, unexpected keyword_rescue, expecting keyword_end
      rescue => e
            ^):
  app/controllers/user_controller.rb:96: syntax error, unexpected keyword_rescue, expecting keyword_end
```

- ただし、rescueを削除するとうまく動作します。

# 解決策

いろんな記事でよく目にすると思いますが、`begin..rescue..end`で書くとOKです！！

```users_controller.rb
def create
  if user_params[:user_id].present?
    begin
      User.transaction do
        @user.save!

      respond_to do |format|
        format.js { render : 'action' }
      end
    rescue => e
      logger.debug("failed. because of #{e}")
      redirect_to ~~~path
    end
  else
    # 処理
  end
end
```

みたいな感じで条件分岐すると、うまく動きます。

# 注意点

最初に`find_each`をcontroller内で使用する場合ですが、何度も`redirect`をしないように書かないと余計に処理を走らせてしまいます。

```users_controller.rb
def create
  User.transaction do
    @users.find_each do |user|
      if user.save
        respond_to do |format|
          format.js { render : 'action' }
        end
      else
        # コード
      end
    end
  end
end
```

だったら駄目なので`find_each`の中からは、`respond_to`を切り分けてください。

```users_controller.rb
def create
  User.transaction do
    @users.find_each do |user|
      user.save!
    end
    
    respond_to do |format|
      format.js { render : 'action' }
    end
  rescue => e
    logger.debug("failed. because of #{e}")
    redirect_to ~~~path
  end
end
```

こんな感じで切り分けて例外処理をしてやると大丈夫かなーと思います。

# まとめ
これはあくまでも今回自分が実装したいものを実現するために書いたコードなので、おかしい部分はあるかと思います。
ほかにもっとキレイなコードがあれば是非教えてほしいです。
【2020年度版】Google Cloud 認定資格 Professional Cloud Developer を取得しました

2020年1月5日に受験し、合格しました

# Professional Cloud Developerとは？
https://cloud.google.com/certification/cloud-developer?hl=ja

2019年1月に新たに追加されたGoogle Cloudの資格で
当初は英語のみでしたが、2019年8月頃？から日本語での受験が可能になったようです

Professional Cloud Developerは
設計・ビルド・テスト・デプロイ・ログの取り扱い。など出題範囲が広く、かつ、実践的な試験となっていました




# 試験について
試験時間: 2時間
試験料: 200米ドル（1USD=110.545円） 22,109円 
設問数: 全50問


# 筆者のスペック
基本情報技術者試験 合格（7年前）
AWS歴: 2年 (構築経験なし。運用経験あり)
GCP歴: 1年6ヶ月（ゼロから構築中。運用経験なし）
サーバーエンジニア6年目

# 勉強方法 ・ 必ず押さえておくポイント

[Associate Cloud Engineer](https://qiita.com/wMETAw/items/f12c0edbdced4b76fb6e#%E5%8B%89%E5%BC%B7%E6%96%B9%E6%B3%95--%E5%BF%85%E3%81%9A%E6%8A%BC%E3%81%95%E3%81%88%E3%81%A6%E3%81%8A%E3%81%8F%E3%83%9D%E3%82%A4%E3%83%B3%E3%83%88)の出題範囲を理解している前提で
下記プロダクトの用語やコンセプトを理解し、クイックスタートをやりましょう

- Cloud PubSub
- Cloud Tasks（特にPubSubとの違い）
- Cloud Dataproc
- Cloud Security Scanner
- Cloud Composer
- Cloud Build
- Service Management API
- AppEngine 基本・自動スケーリングの違いとyamlの記述。どのようなオプションがあるか
- GKE 
- Cloud Datastore （Ancestor Queryやフィルタ、トランザクション。Javaでサンプルコードを動かすのがおすすめ）
- Cloud Spanner （インターリーブするメリット）
- Stackdriver Monitoring
- Stackdriver Logging
- Stackdriver Error Reporting
- Stackdriver Debugger
- Stackdriver Trace
- Stackdriver Profiler
- SQL 
  - UNION
  - UNION ALL
  - WITH
  - INNER JOIN
  - LEFT OUTER JOIN
  - RIGHT OUTER JOIN
  - FULL OUTER JOIN
  - CROSS JOIN
- GDPRとは？
- HIPAAとは？
- COPPAとは？

ページ下部にあるリンクを片っ端から開いて覚える
https://medium.com/@sathishvj/notes-from-my-beta-google-cloud-professional-cloud-developer-exam-e5826f6e5de1

GCPサービス一覧・3行解説を全部覚える（試験前に見ると良いですよ）
https://cloud-textbook.com/37/

<font color="red">※ gcloud や gsutil コマンドはオプションまで覚えるのをお勧めします。とにかく実際に動かしてみるのがベスト</font>
私が受験したときは、４択の中に架空のコマンドが混ざっていました

# 合否発表と合格者特典
2日後に合格メールが届きました

特典として以下のいずれかから選んだ物が貰えます！

<img width="1065" alt="goods.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40799/e981a107-9a76-fbe3-9c0c-70c75ecbf0a7.png">


# さいごに
GCPは最高です :blush:
VBAでRPA

# 目的
RPAに使えそうな機能を使いやすくした実装を作った際の備忘録。
以下３つが比較的有用だったので、記しています

1. SendKeysのWrapper（擬似キー操作用）
2. SendKeysでPrintScreen
3. Processの存在チェック

## 1. SendKeysのWrapper（擬似キー操作用）

VBAからSendKeyを使った場合に、NumLockが外れるという現象があるようなので
それをリカバリする機能を盛り込む必要があったのでそれに対応したWrapperを実装
GetKeyboardState を使って、NUMLOCKキーチェック後、必要であれば{NUMLOCK}を送信する簡易的なものです

```vb
Private Declare Function GetKeyboardState Lib "user32" _
   (pbKeyState As Byte) As Long
Const VK_NUMLOCK = &H90

Function IsNumLockOn() As Boolean
	Dim keys(0 To 255) As Byte
	GetKeyboardState keys(0)
	IsNumLockOn = keys(VK_NUMLOCK)
End Function

Sub SendKeysWrapper(keys)
    Dim wasNumLock
    wasNumLock = IsNumLockOn()
    
    Application.SendKeys keys, True
    If wasNumLock = True Then
       Application.SendKeys "{NUMLOCK}", True
    End If
End Sub
```

## 2. SendKeysでPrintScreen

これが意外に見つからなくてstackoverflowで見つけたので

```vb
Public Sub PrintScreenWrapper()
    Application.SendKeys "%{1068}" , True
End Sub
```

## 3. Processの存在チェック

WIN32APIじゃなくても出来るプロセスチェック
サンプルなので、実際ではword objectはキャッシュした方が無論使い勝手は良いです。

```vb
Function IsProcessAvailable(name)
    Set word = CreateObject("Word.Application")
    IsProcessAvailable = word.Tasks.Exists(name)
    word.Quit
	Set word = Nothing
End Function
```
rails環境構築　gem install sqlite3 エラー

railsを始めようと思い、下記サイトを参考にrailsのインストールを試みたところ、
rails new app名を実行したところで下記エラーがでました。
http://mashiroyuya.hatenablog.com/entry/windows10RoR
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561469/f2d97d3e-d470-0dc1-5f24-02c28e392401.png)

sqlite3のgemがないのがエラーの原因だと思ったため、gem listを実行してみると、確かにsqlite3がありませんでした。

なのでgem install sqlite3でsqlite3をインストールしようとしたところ、次のエラーがでました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561469/9ce97471-072e-a177-858f-3d8cd82e8aef.png)

ここから先の対処法が分からず、わかる方教えていただけると助かります…

参考までに、これまで行った手順は下記のとおりです。

下記サイトからruby+devkit 2.6.5.1(x64)をダウンロード。
https://rubyinstaller.org/downloads/

SQliteも公式サイトからwindows用をダウンロード。下記サイトを参考にsqlite3.exeとsqlite3.dllをrubyをダウンロードしたディレクトリのbinにコピーしました。
https://www.javadrive.jp/rails/install/index2.html

仕様環境
windows10 64bit
Slackでランチのお誘いbot

##お誘い
毎日決まった時間にchannel全員をお昼を誘い、出発時間直前に出発をお知らせします。
「[いい感じにランチを決める Slack ボットを作った](https://qiita.com/kimihiro_n/items/7808a56c10700704b9a2)」を使わせていただいています。

```.js
function isHoliday(){
  var today = new Date();
  //土日か判定
  var weekInt = today.getDay();
  if(weekInt <= 0 || 6 <= weekInt){
    return true;
  }

  //祝日か判定
  var calendarId = "ja.japanese#holiday@group.v.calendar.google.com";
  var calendar = CalendarApp.getCalendarById(calendarId);
  var todayEvents = calendar.getEventsForDay(today);
  if(todayEvents.length > 0){
    return true;
  }
  return false;
}
  var holiday = isHoliday()
    if(holiday == false ){
        ~~~
    }
```
で、平日のみ実行するようにしています。

時間になったら声をかけてほしいのでリアクションしてくれた人に声をかけるようにしました（ローカルPCからPythonで無理やり）

![lunch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/322108/22970112-61d1-dad0-aa4d-58023a3a20f9.png)

##ランチ行く人の特定
tokenやらチャンネルIDやらBOTIDやらの準備をします。
チャンネルIDはチャンネルリストから「リンクをコピー」で取得できます。
BOTIDもBotの発言から「リンクをコピー」で取得できます。

```.py
import requests
import json
import math
import time

histurl = "https://slack.com/api/channels.history"
posturl = "https://slack.com/api/chat.postMessage"
token = "SLACKTOKEN"
channel_id = "SLACKCHANNNELID"
bot_id = "SLACKBOTID"
```

channels.historyで帰ってくるタイムスタンプ（ts）がUNIX時間なので

```.py
    #今日取得(UNIX時間)
    now = time.time()
    #3600=1時間 前の時間
    nowd = math.floor(now) - 3600
```

チャンネルの発言をjsonで取得して

```.py
    payload = {
        "token": token,
        "channel": channel_id
        }
    response = requests.get(histurl, params=payload)
    json_data = response.json()
```
botの1時間前の発言にリアクションしてくれた人を特定します。

```.py
    for i in json_data["messages"]:
        try:
            if i["bot_id"] == bot_id:
                if float(i['ts']) >= nowd:
                    for u in i['reactions']:
                        for v in u["users"]:
                            realist.append(v)
        except:
            pass
```
あとは出発をお知らせするメッセージをSlackに投げます

```.py
    if realist != []:
        for ulis in realist:
            atesaki += "<@" + ulis + ">"
        message = atesaki + "お昼いけますか？:airplane:"
        postpayload = {
            "token": token,
            "channel": channel_id,
            "username": "ランチのお誘い",
            "icon_emoji": ':ramen:',
            "text": message
        }
    else:
        postpayload = {
            "token": token,
            "channel": channel_id,
            "username": "ランチのお誘い失敗",
            "icon_emoji": ':kevin:',
            "text": "誰もお昼に行かないようです"
        }
    requests.post(posturl, data = postpayload)
```
あとはどこかで定期実行
全部1つにまとめたいのでそのうち前半部分をPythonにし（てFaaSとかで動かし）ます。
Elmの予約語一覧

ReactでReduxの思想に触れて幾月。
**Elm**という言語を知れば知る程に学びたい欲が湧き上がってくる今日この頃。 

↓

**[超親切な公式サンプル](https://guide.elm-lang.jp/)** を元に写経するも、シンプルすぎるシンタックスのために逆に理解が及んでいるか不安がよぎりまくる。

↓

```elm
-- ~中略~
view model =
 div [
    [
      button [ onClick Increment ] [ text "+" ],
      div [] [ text (String.fromInt model) ],
      button [ onClick Decrement ] [ text "-" ]
    ]
 ]
```

↓
「この`view`の後の半角スペースは **関数呼び出し&引数引き渡しの記述** だから`view`って関数に、`model`を引数に取る関数を渡していて…:thinking:」

↓

```elm
type Msg = Increment | Decrement
```

↓

「こっちの`type`も関す..:thinking:いや違う、この`type`ってのは**予約語**やんけ」~~何故関西弁になるのだ・・・🤔~~
「なるほど、文字通り**type**を定義する予約語っちゅうわけかいな」
![2f86293c.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119363/54e3ab43-b9e5-4dff-88ca-951f4078319d.jpeg)

↓

「・・・予約語くらい調べておくか」

## という事で
予約語一覧
　→[Elmコンパイラの実ソースより引用](https://github.com/elm/compiler/blob/2860c2e5306cb7093ba28ac7624e8f9eb8cbc867/compiler/src/Parse/Variable.hs#L71)

```haskell
reservedWords =
  Set.fromList
    [ "if", "then", "else"
    , "case", "of"
    , "let", "in"
    , "type"
    , "module", "where"
    , "import", "exposing"
    , "as"
    , "port"
    ]
```

　　~~→`Set.fromList`に引き渡されている配列の各要素が**Elmの予約語**になります~~
　　　→**2020/01/26追記 : 上記だけではありませんでした。調べが甘く大変申し訳ありませんでした。** → **alias**が抜けていました。上記コンパイラ周辺のソースを見てもaliasの記述場所が分からず、詳しい方がいらしたらご教授頂きたく存じます。(infix等の、バージョンアップに伴い消された予約語もある?)

```
 if        then    else
 case      of      let
 in        type    module
 where     import  port
 exposing  as      alias   
```

## 感想
・c系統のメジャーどころな言語と比べると全体的に無駄無くシンプルにまとまっている感じがします。
　　→c系統言語では予約語常連な`for`や`while`や`class`なんかも言語思想的に当然無し。
MarkdownでQiitaに投稿を始めるときに役立つ機能・ページまとめ

# はじめに
Qiitaで投稿を始める際に常に役に立ったページをまとめです

私がMarkdown記法での投稿を選択しているため
Markdown関係のことが中心になります


# Markdownで役立つ機能まとめ
- [Markdown記法 チートシート \- Qiita](https://qiita.com/Qiita/items/c686397e4a0f4f11683d)
    - 公式のお作法のページ
    - Markdownで迷ったらまずココ
    - すぐ調べたいときは編集画面の「？」アイコンをクリック！
    <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264248/5c59fa2f-aaa3-d3b5-f446-499625ca5685.jpeg" width="50%">


- [Qiita Markdownのページ内リンクの罠 \- Qiita](https://qiita.com/hennin/items/7ee58dd7d7c013a23be7)
    - 自分の投稿した記事ページ内の見出し（#とか##）にリンクできないときはココでルールを確認
    - 特にハマりそうなのは以下のルール
        - 英字は小文字で指定
        - 見出しのレベルに関わらず##も###も#で指定

## Markdownでは出来ないこと
- [Qiitaの記事の画像のサイズを変えてみた \- Qiita](https://qiita.com/soratyan/items/6c47abaf92dded703d0c)
    - 画像サイズの変更はHTMLのIMGタグでWidth指定

# おわりに
便利な機能、ページを見つけたら随時追加していきます
Markdownのこと以外でもQiita投稿に関する便利機能があればぜひ教えてください
コメントお待ちしております
Unity Organizations(組織)の作り方(2020/1/8時点)

# Unity Organizations(組織)の作り方(2020/1/8時点)


##最初に注意しておくべき点


###  組織を作ったアカウントが組織を抜ける = 組織解体。

**組織を作るアカウントは重要**です。
組織を管理するアカウントを別で作るか、絶対に権限が変わらない人のアカウントを使うのがベストプラクティスだと思います。


## 組織を作るアカウントでサインイン
[Unity ID](https://id.unity.com/ja/conversations/9a952db6-55d1-44cd-9f22-311e9a2be32200cf)でログインする。(アカウントない場合は作りましょう。)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/66451f40-ef95-dd50-3bc2-c0ccb1c853f4.png)




ログインすると自動でマイアカウント設定のページへ飛びます。
表示されたら**[組織]**をクリック。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/8b852868-44fa-a853-fd1c-30c60288f02a.png)




### 実はデフォルトで組織は作られています。
何も設定せず作ったUnityのプロジェクトはこのデフォルトの組織に分類される様です。
自分のアカウントが所属している組織のプロジェクトは左側の**[組織]**から見れるので気になる方は確認してみましょう。
今回は新しく作りますので**[新しく追加]**をクリック。

![05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/4cf0b783-f984-8892-b17e-a8c66a777b7b.png)


以下の様な画面が出る筈。
(1)**組織名**を記入して　　　　
(※組織名は**一意な名称**でなければなりません。)

(2)**業種**を選択しましょう。今回はゲームを選択。

(3)記入したら**[作成]**をクリック。

![06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/3e5b617b-56a2-4aa5-b35e-a118e5e19731.png)



これで組織は作成完了です。(組織名がかぶっていたので名前変更しました。_(┐「ε:)
![07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/d1e34d14-e550-09c1-e4d1-652f4637e617.png)



組織の名前か右側の歯車ボタンを押すとその組織の各種情報の確認や設定が行えます。
![08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/315136/f8d39aa8-438c-5114-250c-838923a3c604.png)




これで組織が作れました。
次の記事ではUnity Teams Advancedの登録方法やCloud Buildの設定方法を記事にしていきます。
npx create-react-appで詰まった時のメモ

##概要
Reactでアプリを作ってみようと考えています。
ローカルでプロジェクトを作成しようとした時に早速詰まったので、メモにしました。

##前提
使うパソコンはmacOSになります。

##エラーを確認します。
ローカルにmy-appというフォルダを作成するコマンドを入力しました。

```
npx create-react-app my-app
```
しかし、実行しても、何も起こりません。
エラーを確認します。

![スクリーンショット 2020-01-08 1.08.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280415/77ea71c4-c53e-4d99-c091-214d6e4d4f35.png)


```
error @typescript-eslint/eslint-plugin@2.10.0: The engine "node" is incompatible with this module. Expected version "^8.10.0 || ^10.13.0 || >=11.10.1". Got "11.8.0"
```

nodeのバージョンが求められているバージョンと違うため怒られているようです。
バージョンアップをしていきます。


##nvmをインストールします。
今回はnvmコマンドを使ってインストールしていきます。
###Githubからcloneします。
```
$ git clone git://github.com/creationix/nvm.git ~/.nvm
```

###nvmコマンドを使えるよう設定します。
ホームディレクトリから、.bash_profileを開きます。
そして、中に以下のコードを追加します。

```
# nvm
if [[ -s /Users/<ホームディレクトリの名前>/.nvm/nvm.sh ]] ; then source /Users/<ホームディレクトリの名前>/.nvm/nvm.sh ; fi
```
使えるようになったか、確認します。

```
$ nvm --version
```

###nvmでバージョンアップして行きます
バージョンを確認できましたら、バージョンアップしていきます。

```
$ nvm install v11.10.1
```
*バージョンはエラー上で求められているバージョンを入れてください。

nodeのバージョンを確認します。

```
node -v
v11.10.1
```

これで完了です。もしバージョンが変わってない場合は、こちらのコマンドを実行します。

```
$ nvm use v10.14.2
```

改めて、npx create-react-app my-appを実行すると正常に実行されるかと思います。

##参考記事
- [【Node.js入門】バージョンアップ手順と管理ツールまとめ！(リンク)](https://www.sejuku.net/blog/82819)
- [nvmの導入と使い方(リンク)](https://qiita.com/tanishi/items/f741e4bebfb6b6d470dc)
SQLのUNIONについて②

前回、UNIONについて簡単に説明したのですが、ちょっと説明し損ねた感があるので補足。
UNIONとUNION ALLの違いについて説明したいと思います。

過去に投稿したメモ書きにも記載していたのですが、UNIONとUNION ALLの違いは、
簡単に言うと重複を表示するか、しないかです。
UNIONは重複を表示しませんし、UNION ALLは重複を表示します。
今回は以下の二つのテーブルを使用します。

|テーブル①| 
|:-----|
|赤   |
|青   |
|黄   |

|テーブル②| 
|:-----|
|赤   |
|緑   |
|橙   |

この二つのテーブルをUNIONで結合してみると、以下の通りになります。

|検索結果| 
|:-----|
|赤   |
|青   |
|黄   |
|緑   |
|橙   |

対して、UNION ALLで結合してみると、以下の通りになります。

|検索結果| 
|:-----|
|赤   |
|青   |
|黄   |
|赤   |
|緑   |
|橙   |

上記のように、UNION ALLの場合は重複している赤が二回表示されているのが分かると思います。
こんな感じの仕様なので、使用頻度が高いのはどちらかというとUNIONの方になると思います。
docker内でhttps化・SSL通信をできるようにする

#はじめに
conohaのvpsでサービス運用を始めようと思います．
ただ，SSL可に意外と苦戦したのでまとめておきます．

#状況
・ubuntu+docker
・ドメイン取得済み
・Golangのbeegoでwebサーバーを立てている．

httpsでの接続をするためには，SSL証明書が必要．
オレオレ証明書はローカル運用でしか，利用できない．
[letsencryptをUbuntu16.04 + Nginxで使ってみた](https://qiita.com/k-yamada-github/items/7314003de7bdcbb2d39b)だと，docker内に作用することができない．
[個人運営サイトのSSLをDockerで良い感じに設定する](https://qiita.com/KappaBull/items/15de7a2bf52a5d38b11e)だと，コンテナが2つあって難しそう．

#結果
https-portalなるコンテナを利用することで，解決できました!!
#####メリット
・既存のコンテナサービスが簡単にSSL可できる
・わかりやすい
・自動で証明書を更新してくれる．
・証明書の切替ができる（オレオレ/production）

・[https-portalで既存のdocker環境をhttps化](https://re-engines.com/2019/03/28/docker-https-portal/)
・[既存環境に手を加えずにサクッとHTTPS化する (NAT配下でもok)](https://amaya382.hatenablog.jp/entry/2017/04/02/002746)
・[【7】SteveLTN/HTTPS-PORTALを使ってLet's Encryptで全自動SSL対応を行う(GCP(GCE),Rails,Nginxリバースプロキシ,Docker)](https://sakura-bird1.hatenablog.com/entry/2019/03/12/034813#7-HTTPS-PORTAL-とは何かを知る)

#実装

```docker-compose.yml
version: '2'
services:
  db:
    build:
      context: ./MySQL
    env_file:
      - prod.env
    container_name: go_db
    ports:
      - "3306:3306"
    tty: true
    restart: always
    volumes:
      - ./MySQL/mysql_init:/docker-entrypoint-initdb.d
      - ./MySQL/mysql_data:/var/lib/mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin --skip-character-set-client-handshake --lower_case_table_names=1
  app:
    build:
      context: ./Go
      dockerfile: Dockerfile.prod
    volumes:
      - "./Go:/go/src/app"
    container_name: go_app
    env_file:
      - prod.env
    ports:
      - "8080:8080"
    tty: true
    restart: always
    depends_on:
      - db
  https-portal:
    image: steveltn/https-portal:1
    container_name: https_portal
    ports:
      - "80:80"
      - "443:443"
    tty: true
    restart: always
    volumes:
      - ./Certs/:/var/lib/https-portal/
    environment:
      DOMAINS: 'domain〇〇 -> http://app:8080'
      STAGE: "production"
      # FORCE_RENEW: 'true'
    links:
      - app
```

この方法だと，ローカルの開発環境もサラッとSSL適用できるので，(・∀・)ｲｲﾈ!!
本日のアウトプット

<h1>HTMLとCSSについて</h1>

divでブロック要素を作る時に、何も指定をしなければブロックは縦に並ぶが、
floatを使用することで横並びにすることが出来る。

横並びにした時にブロックの位置指定をしたい時には絶対を表すabsoluteを用いる。
bottom要素にabsolute,0pxを指定すれば、bottomは画面の一番下に配置が出来る。

以上、本日学んだHTML,CSSについてのまとめでした。
今日も頑張ります:smiley::computer:♪
白石麻衣ちゃん可愛い、、、癒しです。わら
![白石麻衣.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/555307/6f5290f4-88d3-3dc2-8d29-5b374859bc50.jpeg)
【Laravel】Middlewareを使って、ユーザーのアクションログをDBに書き込む

# やりたいこと
ユーザーのログイン回数や資料ダウンロード回数などを取得したい。
つまり、特定のアクションメソッドを通ったら、そのアクションタイプを書き込みたい。

# 流れ
- Middlewareを作成する。
- 後処理として、特定のアクションをDBに書き込む処理を書く
- kernelに登録する

# LaravelのMiddlewareとは(簡単に)
Controllerで行われる処理の前や後に、処理を追加することができる機能?です。
デフォルトで組み込まれているためあまり意識することがないですが、
トークンやセッションの管理などはmiddlewareで処理されています。

# 実装
## Middlewareを作成する。
以下のコマンドで、Middlewareディレクトリ配下にLogActions.phpが作られます。

```
php artisan make:middleware LogActions
```
## 後処理として、特定のアクションをDBに書き込む処理を書く
作成されたファイルには、handleメソッドがあるので、ここに処理を書いていきます。

```php
/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    return $next($request);
}
```
`$next($request)`よりも前が前処理、後ろが後処理になります。
今回は、後処理を追加したいため、`$next($request)`を変数`$response`に格納し、
書き込み処理を行なった後に`$response`を返却します。

なお、今回の処理は簡単なものだったため、メソッドに全て処理を記載しましたが、
プロパティやメソッドを呼んだり、クラスをインジェクションすることも当然可能です。

```php
public function handle($request, Closure $next)
{
    // レスポンスを格納
    $response = $next($request);

    // アクション名を取得
    $action = $request->route()->getActionName();

    // DBに書き込むアクションの配列
    $actions = [
        // ログイン
        'login' => 'App\Http\Controllers\Auth\LoginController@login',
        // 閲覧
        'show' => 'App\Http\Controllers\TestController@show',
        // ダウンロード
        'download' => 'App\Http\Controllers\TestController@download',
    ];

    // 書き込み処理
    if (in_array($action, $actions)) {
        DB::table('log_actions')->insert([
            'user_id' => Auth::user()->id,
            'action_type' => array_search($action, $actions),
            'created_at' => now(),
            'updated_at' => now(),
        ]);
    }

    // レスポンスを返す。
    return $response;
}
```

## kernelに登録する
最後にApp/Http/Kernel.phpに作成したMiddlewareを登録します。
今回は普通のwebアプリケーションのため`$middlewareGroups`のwebグループの一番最後に追加しました。

```php
protected $middlewareGroups = [
    'web' => [
        \App\Http\Middleware\EncryptCookies::class,
        \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
        \Illuminate\Session\Middleware\StartSession::class,
        // \Illuminate\Session\Middleware\AuthenticateSession::class,
        \Illuminate\View\Middleware\ShareErrorsFromSession::class,
        \App\Http\Middleware\VerifyCsrfToken::class,
        \Illuminate\Routing\Middleware\SubstituteBindings::class,
        \App\Http\Middleware\LogTraderActions::class // !!!追加!!!
    ],

    'api' => [
        'throttle:60,1',
        'bindings',
    ],
];
```

これで、アクションログを書き込むことができるようになりました。
処理が重たくなる場合には、キューを使って非同期処理を行う方が良いと思います。

# 参考
[公式ドキュメント](https://laravel.com/docs/6.x/middleware)
[middlewareでHTTPリクエストの前後に処理を入れる](https://re-engines.com/2019/01/17/laravel-middleware%E3%81%A7http%E3%83%AA%E3%82%AF%E3%82%A8%E3%82%B9%E3%83%88%E3%81%AE%E5%89%8D%E5%BE%8C%E3%81%AB%E5%87%A6%E7%90%86%E3%82%92%E5%85%A5%E3%82%8C%E3%82%8B/)
ガンタンクをRaspberry Piで動かすことを目指す#3 タミヤキット作成編

[ガンタンクをRaspberry Piで動かすことを目指す#2 ガンタンク作成編 V作戦](https://qiita.com/never_nothing_jp/items/8656e3883d0759e8034b)
の続き

# タミヤの「CAM-PROGRAM ROBOT」の組み立て
こいつを組み立てる。
ガンタンクの下半身(駆動部)にする。
![CAMPROGRAMROBOT.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/f0794227-72dd-1e9a-9d58-6a9a3ab38029.jpeg)

## 普通に組み立て
まずは普通に組み立てた。

![GUNTANK30.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/c88b4060-6f70-ceb5-c823-86c3c5441d37.jpeg)
![GUNTANK31.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/c9c879ee-0398-36bf-acd8-4022b6819eca.jpeg)
![GUNTANK32.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/d4519baa-d20d-ca6d-b40f-3ce49028c22b.jpeg)

## そしてバラして必要な部分だけ取り出す
ひとしきり遊んだ後、
なんだか不気味な目をした上部と意味不明な腕、使わないカム部分を外す。

![GUNTANK33.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/ceb65360-bb02-55a8-9716-2d8b3a9a532a.jpeg)
![GUNTANK34.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/a3f0f476-34b1-dc1b-65ad-08eac7d94d01.jpeg)
![GUNTANK35.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/125160/c966c847-37ed-70f0-a0c7-f38089167b4b.jpeg)

## 次に
この上にラズパイやモータードライバー、電池などを置いていく。

次は[ガンタンクをRaspberry Piで動かすことを目指す#4 RaspberryPi導入編](https://qiita.com/never_nothing_jp/items/bde1556d3efd2ab47a7a)へ
KubernetesのPodとは

# KubernetesのPodとは
KubernetesのPodは、KubernetesのDeployの単位です。Podは基本的には単一のContainerを含み単一プロセスが動くのですが、複数のContainerが含まれることもあります。

KubernetesのPodはContainerをラップしたもので、Podの中のContainerはメモリを共有するほか、
1. IPアドレスやPort,Routing Tableなどのネームスペース
2. UTS ネームスペース
3. ユニックスドメインソケットなどのIPCネームスペース
などの名前空間を共有します。

KubernetesのPodは特殊なContainerのようなものと思ってよく、Podの中のContainerはContainerの中のContainerのようなものです。

またDockerにおけるContainerは他のContainerとは別のアドレス空間で動きますが、Podの中の複数のContainerはPodと同じアドレス空間で起動するため、localhost経由で通信することが可能です。

# DeploymentとPodの関係
DeploymentはPodの状態を管理していて、正しい状態にない場合はPodの復旧をしたり、Podのネットワークの設定をコントロールしたりします。Pod単体で起動しても状態を管理するプロセスがないため、通常PodはDeployment経由でKubernetes上にDeployします。

# PodとServiceの関係
Podは動的に生成・削除されるため、IPアドレスが定まりません。つまり、Podが安定していることが保証されないため、そのままではPod上で動いているプロセスへのアクセスは信頼できるものではありません。

これを解決するのがServiceです。Serviceは固定IPを保持し、動的に生成されたPodのIPアドレスを検知し、Podへのロードパランサーとして機能してAPIのエンドポイントを提供します。
データサイエンティスト育成講座　Chapter3　1＋2日目

## スコープ
標題的には以下の内容だ

- 記述統計学と単回帰分析
    - 記述統計学
    - 単回帰分析
- 総合問題
    - 統計の基礎と可視化
    - ローレンツ曲線とジニ係数

少ない項目数に対しての意味不明度や危険臭がプンプンするが、基本的には計算はPythonに任せていいはず。

### read_csv
実際に問題を解くに当たって、データをCSVから読む。それには、Pandasでread_csvを使用する。
確か、DataFrameを読み込ませるのには他にもいくつか手段があった気がするけれど、read_csvのパラメータをみていて気が付いたのは、

> ?pd.read_csv
Signature:
pd.read_csv(
    filepath_or_buffer,
    sep=',',
    delimiter=None,
    header='infer',
    names=None

って感じで、セパレータとデリミタの指定ができるということ。
同じ意味では？と思い、

> pd.read_csv("xxx.csv", sep=";")
> pd.read_csv("xxx.csv", delimiter=";")

を比較してみたが、変わらなかった
これに関しては、StackOverflowにいい解説があった

[What is the difference between `sep` and `delimiter` attributes in pandas.read_csv() method?](https://stackoverflow.com/questions/49532873/what-is-the-difference-between-sep-and-delimiter-attributes-in-pandas-read-c)

平たくいうと、`delimiter`が指定されていない場合（=None）は`sep`の値が入る。つまりはどちらを使っても構わないということ。
ただ、互換性や他の関数（`to_csv`など）を考えると、`sep`のほうが好ましいということらしい。
ソースコードにも`delimiter is the annoying corner case` って書いてあるし。`sep`を使いましょう

### データの質
複数列がある場合に、データの質を正しく認識する必要がある。
Nullデータを含んでいるかどうか、量的なデータか、質的なデータなのか。
量的なデータであれば、数学的な計算によって求められる値として使用することができる。
質的なデータであれば、それは量的なデータを分類するためのカテゴリとなったり、順位のようなデータをソートするための値としての使用となる

### 統計解析
統計解析というものは、記述統計と推測統計に分けられるとのこと。

- 記述統計：データをまとめてみやすく整理し、データの持っている概ねの情報を把握することを目的とする
- 推測統計：確率分布に基づいたモデルを用いて精密な解析を行うこと

ざっくりいうと〜って感じの記述統計と、予測モデルを立てておそらくこういうことだ！っていう推測統計というところか。
AI／機械学習を学ぶ目的としていることを考えると圧倒的後者なんだけれど、推測統計は次のChapterらしい。

### 箱ひげ図

> plt.boxplot(student_data_math.G1)

という形で箱ひげ図がかけます。
って、なんじゃそりゃって感じになった。見た目的には株価を示すローソク足に見えなくもない。
ローソクに対してのBox下限、上限が25%タイルと75%タイルという分布を示すものらしい。英語でそのまま box plot という。

これに限った話ではないけれど、出来るだけ関数がなんの英語から来ているのかを覚えておくといい。
今回、boxplot関数が箱ひげ図を描く関数ということを覚えたわけだけれど、そもそも箱ひげ図が英語でBox Plotだということを知っていれば、関数一覧からも発見することができるだろうし。

### 数式、数式、数式
変動係数は標準偏差を平均で割ったもの。

> student_data_math.std() / student_data_math.mean()

分散を導く関数がvar
２変数以上の分散を考えるときに使う共分散を導くのがcov
共分散は数式としては、平均からの偏差の積で求められる

それらの最終形として、２変数に何かしらの関係性があるかどうかを示すために相関係数を算出する。
ここでは、ピアソン関数というものを用いて係数を算出している

> sp.stats.pearsonr(student_data_math.G1, student_data_math.G3)


うーん、今日はここまで！
【初心者向け】Rubyで超簡単な本紹介アプリを作ってみる（日付と時間自動付与）

#require "date"を使って、投稿に今現在の日時を自動表示させる

こちらは、昨日の記事を参考に作成しています。
https://qiita.com/pontarou194/items/37a9c63fe617e3244e19

#3行で日時を表示させることができる
```
require "date"
time = DateTime.now
print(time.hour,"時",time.min,"分",time.sec,"秒\n")
```

putsではなく、printを使用しています。

【理由】
・putsだと改行される。
・printは改行されない
・\nで改行していますが、あとで理由がわかります。

※\nのバックスラッシュは、Macの方はalt+¥でバックスラッシュができます。違ったらスイマセン。

#実際にコードを書いてみる

```
puts "本の名前を登録"
    title= gets.chomp
puts "著者を登録"
    author = gets.chomp
puts "本のカテゴリを入力してください"
categorys = ["小説","ノンフィクション","ビジネス書"]
number = 1
categorys.each do |category|
  puts "#{number}：#{category}"
  number += 1
end
  category = gets.chomp

if category == "1" then
  category = "小説"
elsif 
  category == "2" then
  category = "ノンフィクション"
elsif
  category == "3" then
  category = "ビジネス書"
else
  category = "その他"
end

require "date"
time = DateTime.now
print(time.hour,"時",time.min,"分",time.sec,"秒\n")
puts "以下の通り登録しました"
puts "本の名前は「#{title}」"
puts "著者の名前は「#{author}」"
puts "カテゴリは「#{category}」"

```

#動作確認
```
本の名前を登録
7つの習慣
著者を登録
コビー
本のカテゴリを入力してください
1：小説
2：ノンフィクション
3：ビジネス書
3
11時59分43秒
以下の通り登録しました
本の名前は「7つの習慣」
著者の名前は「コビー」
カテゴリは「ビジネス書」
```
#ポイント

printの代わりにputs使うと、おかしなことになります。

```
本の名前を登録
7つの習慣
著者を登録
コビー
本のカテゴリを入力してください
1：小説
2：ノンフィクション
3：ビジネス書
3
12
時
5
分
42
秒
以下の通り登録しました
本の名前は「7つの習慣」
著者の名前は「コビー」
カテゴリは「ビジネス書」
```
時間がすべて改行されてしまいます。
ざっくりと覚えるとすれば・・・

・putsは改行される
・printは改行されない

参考にさせていただきました、ありがとうございます。
https://qiita.com/naoge/items/f5d84581d3a301a9c22f
RailsのRspecを書いてたらFactoryBotがハマった話

# はじめに
初めまして、うりぼーと申します。
現在プログラミングスクールでWebエンジニアを目指してRubyonRailsを中心に学習中です。

初学者ということもあり、知識不足な点も多いかと存じますが、自分がつまづいた点や勉強になったことを記事にしていけたらと思いますので、同じ初学者の方の参考になればと思います。（もちろん現役エンジニアの方のご指摘もお待ちしております！）

## RspecでFactoryBotを使おうとしたら「Factory already registered」にハマってしまった話
さて本題ですが、スクールの卒業課題として作っていた書籍管理アプリのテストをRspecで書いていたらFactoryBotでハマってしまいましたので反省も込めて書いていこうと思います。

### 環境
ruby 2.6.5
Rails 5.2.4.1

### 概要
書籍(Book)モデルのCRUD機能も一通り出来上がったのでRspecでテストをするべくFactoryBotで書籍のデータを下記のように書いていました。

```ruby:spec/factories/books.rb
FactoryBot.define do
  factory :book do
    title { 'hoge' }
    author { 'fuga' }
    user
  end
end
```
そしてspec.rbにテスト内容を書く上でルーティングを確認しようとターミナル上で「rails routes」コマンドを実行したところ、

```:console
rails aborted!
FactoryBot::DuplicateDefinitionError: Factory already registered: book
```
ということで「Factoryはすでに登録されているよ」というエラーを頂戴することとなりました。
（こうした名前空間のエラーはrailsコマンドなども打てなくなるようです　参考：https://shikasen-engineer.com/error_factorygirl/ ）

### 原因調査
「これしかbookのFactoryは作ってないはずなのでおかしいなぁ」と原因もあまり思い当たらなかったためググってみると以下の記事に出会いました。

rspecとfactorybotを導入するときにハマった時に確認したこと
https://qiita.com/yukiyoshimura/items/ca60a712fb705cf9bf89

まさに同じ悩みだなぁと思い参考にさせていただくことに。
対処方法として書かれている点を私なりに解釈したところ、

1. ターミナルで実行
2. ファイル名の確認（_spec.rbになっているか）
3. factory_bot.rbと二重設定となってしまっている
4. 「rails c」によるデバッグ
5. springに起因

という感じ。ただし、1,2に関しては問題なく、3の「factory_bot.rb」も作成していなかったため該当しませんでした。また、5のspringについては自分の環境で起動はしていたため、当初これが原因かと思い調べはしたものの直接的な解決には至らず…。

そこで、4の「rails c」でデバッグをすることに。現状だとrailsコマンドも使えないため一度spec/factories/books.rbをコメントアウトして試してみることに。

「Factory already registered: book」となっていたので試しに「FactoryBot.create(:book)」をしたらどうなるのかを調べてみることにしました。

```:console
irb(main):001:0> FactoryBot.create(:book)
   (0.2ms)  SAVEPOINT active_record_1
   (0.4ms)  ROLLBACK TO SAVEPOINT active_record_1
Traceback (most recent call last):
        1: from (irb):1
ActiveRecord::RecordInvalid (バリデーションに失敗しました: Userを入力してください, Titleを入力してください, Authorを入力してください)
```
バリデーションに引っかかったものの作成自体はできそう。ということはやはりエラー文通り実際に定義がされている？
全件検索をかけてみることに。

```ruby:test/factories/finished_books.rb
FactoryBot.define do
  factory :book do

  end
end
```
**ありました。**testディレクトリに自動生成されていたファイルを気づかずに放置してしまっていたことが原因でした。testディレクトリはもう一つのテストフレームワークのMinitest用のディレクトリで、specディレクトリを使うRspecでは不要です。~~何を当たり前のことを~~

```:console
$ rm -r ./test
```
上記コマンドでtestディレクトリを削除し、spec/factories/books.rbのコメントアウトを外したところ正常に動作し無事解決となりました。

また、今後こうしたことが発生しないようにconfig/application.rbに以下を記載しtestディレクトリの自動生成を止めることにします。
（参考：https://keruuweb.com/rails-generate%E6%99%82%E3%81%ABtest%E3%82%92%E7%94%9F%E6%88%90%E3%81%97%E3%81%AA%E3%81%84/ ）

```ruby:config/application.rb
class Application < Rails::Application
  config.generators do |g|
    g.test_framework false
  end
end
```


## まとめ
気づいてしまえば非常に単純なケアレスミスでしたが、自動生成の利便性に普段から頼り切ってしまっていたことを猛省するミスとなりました。
不要なものについても生成されないよう管理してアプリ開発していきたいと思います！
初めてのLTで意識したこと、やってよかったこと

# はじめに
- [【2020年達成したいことがある人集まれ！】TECH PLAY女子部＊新年の抱負LT大会＊](https://techplay.jp/event/762213?utm_source=event_762213&utm_medium=social&utm_campaign=feed&utm_content=tw2256623870)で初LTしました
- やる前に初LTどうすればいいの！？ってめっちゃ色々悩んだので、私みたいな悩みを抱える人たちのために、初LT意識したこと、やってよかったことを書き残しておきます
- [発表スライド](https://speakerdeck.com/thetalemon/si-ban-shi-ji-sheng-kiteqi-duita-zi-fen-falsezhi-ming-de-naqian-dian-toxiang-kihe-tuteji-hua-sita-2020nian-falsekanpekinaririsuji-hua)

# 意識したこと
### この発表によって聴衆に何のメリットがあるのか？を大事にした
- 自分の話なんか興味もってもらえるかな…と不安になってしまうタイプなので、その不安の払拭のために聴衆へのメリットを持たせました
- 今回は『飽き性でも習慣化と見える化をすれば目標達成ができる』という結果＆提案を聴衆へのメリットとしました

### 話の流れを意識してスライドを作成した
- 起承転結のうち、承を多めにする
    - 起：私の弱点は飽き性
    - 転：２０２０年の目標がある
    - 承：その目標は今までも目標としてあったけど、達成できてない
    - 転：そんな飽き性の私でも２０１９年に達成できた目標がある
    - 承：それらの目標を達成できた理由を**具体的**に
    - 承：それらの目標を達成できた理由を**抽象化**する
    - 結：**抽象化**から、２０２０年の**具体的**な行動を明示する
- 具体と抽象は意識したわけではないですが、結果としてこの流れにしてよかったと思います

### タイトルスライドで笑いをとれるようにしておいた
- [最初で笑いをとれば気が楽になる作戦](https://qiita.com/kurararara/items/d75789f03a37fb56388a#%E3%82%84%E3%81%A3%E3%81%9F%E3%81%93%E3%81%A8-2)を参考にして、タイトルスライドで笑いをとれるようにしておきました
- <img width="400" alt="名称未設定.001.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379454/4da6a179-6f93-a10b-e484-89dc03cd8ee8.jpeg"> → <img width="400" alt="名称未設定.002.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379454/82ca234c-a187-b2f2-68f9-c6910f8dfea7.jpeg">
    - 『始末する』という過激発言からの、『自分を始末しちゃいかんよね』は準備した発言です（笑ってくれた人たちありがとう！）


# やってよかったこと
### 適度な飲酒
- 申込も発表も酒の勢いでした
    - 酒の勢いと友人のお誘いがなければLTをやるのはもっと先のことになってたと思います

### 聴衆への声かけ
- 飽き性のみんなー！一緒にやろ💕なスライドで、アドリブで飽き性の人🙋！ってやったら、結構手を上げてくれた人がいたの、聞いてもらえてる感があって心強かったです（手をあげてくれた人ありがとう！）
    - 当該スライド： <img width="400" alt="名称未設定.0１１.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/379454/58568bcf-7d88-1058-760f-49e65fa5f6ba.jpeg">

# 結果としてよかったこと
### 話す内容が気負いすぎなくて良い内容だった
- 新年の目標発表だったので、技術的な間違いとか技術レベルとか気にしなくて良いのは気楽でよかった

### LT発表者が集まる卓に座った＆友人が一緒だった
- 始まる前に緊張するね〜〜！って言いあえるのは緊張緩和になりました
- 一緒に参加した友人もはじめてだったので、はじめて同士で心強かったです

# 反省点
### スライドがちょっと多かった
- 5分に対して１１スライドもあると、自分が心配になってしまうのでよくなかった
- 結果何分だったのかは知らないですが、スマホで時間カウントしておけばよかったかなと思います

# おわりに
- やる前はかなり不安でしたが、終わってみると達成感あります✨
- LTスライドの作成は全力でわかりやすさと向き合える良い機会になったと思います

# 謝辞
- 場を提供してくださったTECH PLAY女子部運営のみなさま、イベントの存在を教えてくれた＆LTやろうよ！と言ってくれたまいあめあさん、おかげで人生初LTを体験することができました！ありがとうございます！
- スライドの添削をして『メッセージ性が足りない』と指摘してくれた友人Y、おかげでちゃんと聴衆を意識したスライド作りと発表ができました。飽き性の人🙋！のスライドは、友人Yの指摘無くしては生まれませんでした。いつもありがとう！
- 発表慣れへの一歩を歩ませてくれたO教授、スライド作りの極意を徹底的に教えてくれたI教授、おかげで上手く乗り越えられました。お二人の教えは今も大活躍しています。本当にありがとうございます。
- ７さんの発表の[文章作成３つの準備](https://speakerdeck.com/lucky_7_n/mei-yue-shu-kuzo-burogudeqing-bao-fa-xin-tech-playnu-zi-bu?slide=39)が、この記事を書いたきっかけです！素敵な発表ありがとうございます！
- そして何よりも、聴いて反応してくださったイベント参加者の皆さん！ありがとうございます！
列名の重複で困ったらRenameColumnsで解決

#はじめに
今回はとても短い投稿です。
リストやCollectionを使って、自分自身を参照したFilter, LookUpを行う場合(自己結合的な)や、似たような構造のリスト、コレクション同士をFilter、結合する場合には、どうしても列名の重複が気になります。

例えば、何らかのスタッフリストのようなものがあったとします。
そのスタッフリストにはスタッフのID、名前、上司のIDが含まれています。
この時スタッフリストを自己参照して、上司の名前を解決した表を作りたいとしましょう。
単純に考えれば、「リストに列を追加して、その条件として、リストのIDがManagerIDと一致した行をとる」とすればよいです。(下図)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/f33b2790-5d63-2386-0abd-ae7272791719.png)

しかし、結果としてはManagerのTitleは解決できず、エラーになってしまいます。

それもそのはず。赤く囲んだ部分だけみれば、「自分のIDと上司のIDが一致した行」になっているからです。
本来はLookUpの外側のCol1にあるManagerIDと、LookUp内のCol1のIDが一致した行をとらなければなりません。

#解決方法
解決方法は単純です。いずれかの列名を**RenameColumns**関数で変更してあげましょう。(RenameColumnsにかんしては[こちら](https://docs.microsoft.com/en-us/powerapps/maker/canvas-apps/functions/function-table-shaping))
この場合でいえば、LookUp内のCol1の列名をID,ManagerIDとも変えれば解決します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/202779/6e455da4-d315-a7e1-9e71-d48b3bcdc55e.png)
変更後の名前は何でもよいのですが、rをつけました。これによって、LookUp関数内の、**ManagerID**はLookUp関数の外側から与えられる列の値。そしてrIDはLookUp関数内の元ID という風に一意性を持たせることができました。

# おわり
RenameColumnsは自己結合や外積のような場合にとても有効です。また、参照する・されるリスト間で同じ名前の列がある場合にも、列名の一意性を担保してあげるという観点から重要になります。
ぜひ簡単な例で試してみてください。
nuxtでサイン入力画面を作る

#サイン入力画面の作り方
サイン入力画面の作り方でつまづいたところがあるので記事に残します。

style, template, styleに分けて書きます

##style

```vuejs
<style scoped>
#sign {
  border: #6f6f6f 1px solid;
  display: block;
}
</style>
```

**canvasのサイズをcssで指定しない**

##template

```vuejs
<template>
  <section>
    <h1>手書きサイン入力デモ</h1>
    <canvas id="sign" width="600" height="150" />
    <el-button @click="clear">クリア</el-button>
  </section>
</template>
```

**canvasのサイズはtemplateで指定する**
こうしないとマウスでサイン入力時に画面とサインがずれる

##script

```vuejs
<script>
export default {
  data() {
    return {
      move: false,
      ox: 0,
      oy: 0,
      x: 0,
      y: 0
    }
  },
  mounted() {
    const canvas = document.querySelector('#sign')
    canvas.addEventListener('touchstart', this.start, false)
    canvas.addEventListener('touchmove', this.draw, false)
    canvas.addEventListener('touchend', this.stop, false)
    canvas.addEventListener('mousedown', this.start, false)
    canvas.addEventListener('mousemove', this.draw, false)
    canvas.addEventListener('mouseup', this.stop, false)
    canvas.addEventListener('mouseout', this.stop, false)

    const context = canvas.getContext('2d')
    context.strokeStyle = '#000000'
    context.lineWidth = 2
    context.lineJoin = 'round'
    context.lineCap = 'round'
  },
  methods: {
    start(event) {
      this.move = true
      const canvas = document.querySelector('#sign')
      this.ox = (event.clientX || event.touches[0].pageX) - canvas.offsetLeft
      this.oy = (event.clientY || event.touches[0].pageY) - canvas.offsetTop
    },
    draw(event) {
      if (this.move) {
        const canvas = document.querySelector('#sign')
        this.x = (event.clientX || event.touches[0].pageX) - canvas.offsetLeft
        this.y = (event.clientY || event.touches[0].pageY) - canvas.offsetTop
        this.drawLine()
        this.ox = this.x
        this.oy = this.y
      }
    },
    stop(event) {
      this.move = false
    },
    drawLine() {
      const canvas = document.querySelector('#sign')
      const context = canvas.getContext('2d')
      context.beginPath()
      context.moveTo(this.ox, this.oy)
      context.lineTo(this.x, this.y)
      context.stroke()
      context.closePath()
    },
    clear() {
      const canvas = document.querySelector('#sign')
      const context = canvas.getContext('2d')
      context.fillStyle = '#ffffff'
      context.fillRect(0, 0, canvas.width, canvas.height)
    }
  }
}
</script>
```

##参照
[HTML5のcanvasに手書きやマウスのドラッグで絵を書く](https://mam-mam.net/javascript/draw_js.html)
[Python3 入門 2日目] 2章 Pyの成分： 数値、文字列、変数 （2.1）


#Pythonのデータ型
・ブール型（TrueまたはFalseの値を持つ）
・整数型（43,23000000などの小数点以下がない数値）
・浮動小数点数（π=3.1415....のように小数点以下の部分がある数値、あるいは10e3のような指数表現。10e3は10の3乗という意味で1000を意味する。）
・文字列（文字の並び）

#2.1　変数、名前、オブジェクト
Pythonは全てがオブジェクトとして実装されている。（Rubyもそうだったな）
##オブジェクトとは?
データを入れてある透明な箱のようなもの。
オブジェクトには、上記のようなデータ型があり、そのデータで何ができるかが決まる。
そして、型にはボックスに入っているデータの値を変更できる（ミュータブル）、変更できない（イミュータブル）も決める。

##オブジェクトイメージ（対話インタープリタで実践）
1. 7という値に対してaという名前の変数を与える。　⇨　整数値7を入れたオブジェクトの箱が作られる。
※変数はただの名前であり、代入しても値はコピーされない。あくまでデータを入れているオブジェクトに名前を付けるだけ。名前は値自体ではなく値の参照である。
2. aの値を出力する。
3. bにaを代入し、7が入っているオブジェクトの箱(a)にbも貼り付ける。
4. bの値を出力する。

```py
>>> a = 7
>>> print(a)
7
>>> b = a
>>> print(b)
7
```

#感想
この章はC言語で学習したことがある部分が大半だった。大学時代が懐しく感じた。
2章一通り学習できたが時間配分がよくなったため、分けて書くこととしよう。


######参考文献
「Bill Lubanovic著 『入門 Python3』(オライリージャパン発行)」
io.Readerのファイルタイプを判定する

# 概要
Goでファイルを読み込んでいる時に、そのファイルのタイプを判別したいことがたまにあります。例えばGzipかどうか分からないけど、もしGzipならgzip.NewReader噛ませたい、みたいな場合です。雑にgzip.NewReader噛ませてerr返すかどうかで判定とかやってみたんですが、普通に10バイト読み進められちゃうのでerr返ったあとに別のファイルタイプとして処理しようとするとinvalidなヘッダーになって死にます。実は読み進められたバイトを戻す方法あるよ、という場合は教えて下さい。

そもそもGzip以外の判定をしたいときもあるので、NewReaderの方針も必ず使えるわけではありません。もしファイルがos.Fileとかbufio.Readerの形であればReadしてからSeekしたりPeekしたり出来るのですが、io.Readerの場合どうやるのか分からなかったので調べました。

ちなみに自分では全く思いつかなくて `containers/image` 読んでて見つけました。賢いなーと思ったので書いておきます。よくよく考えると以前も同じようなのを見て賢いなーと思った記憶があり、何度も感動できてお得なのですが時間の無駄ではあるので次の感動が来ないように書いておきます。

解説は良いからコード見せろという人のために先に置いておきます。
https://github.com/containers/skopeo/blob/8f24d281302cc6aaa7ba9301d4a87bfceb7141b6/vendor/github.com/containers/image/v5/pkg/compression/compression.go#L96

# 実装
今回の例ではGzipかどうかの判定をしようと思います。マジックバイトの判定なら何でも同じ方法で行けるはずです。

```Go
func isGzip(input io.Reader) (io.Reader, bool, error) {
	buf := [3]byte{}

	n, err := io.ReadAtLeast(input, buf[:], len(buf))
	if err != nil {
		return nil, false, err
	}

	isGzip := buf[0] == 0x1F && buf[1] == 0x8B && buf[2] == 0x8
	return io.MultiReader(bytes.NewReader(buf[:n]), input), isGzip, nil
}
```

まず、`io.Reader`から普通にReadします。ここでは参考にしたコードに合わせて`io.ReadAtLeast`を使ってますが、len(buf)にしてるので`io.ReadFull`と同じじゃないかなーと思ってます。とりあえず3バイト読み込みます。

次に、その3バイトを使ってGzipかどうか判定します。もちろん他のファイルタイプの場合は違う処理になりますし、3バイトではないかもしれません。

そして最後がポイントですが、`bytes.NewReader(buf[:n])`を使って読み込んだ3バイトを`io.Reader`インタフェースに合わせます。そして`io.MultiReader`を使って残りの4バイト目以降と結合します。こうすることで、`io.MultiReader`によって作られた`io.Reader`は最初のReaderから3バイト読み込み、次のReaderから4バイト目以降を読み込みます。結果として戻り値として返されるReaderは最初のinputと同じ値を読み込むことが可能になります。

下の例ではbytes.NewBufferなのであまり良い例ではないですがサンプルコードということで一応置いておきます。
https://play.golang.org/p/VH19FHQnqdr

**追記（2019/01/12）**
@yamasaki-masahide さんからのコメントにあるように、`io.Copy`使う場合は`MultiReader`に`WriteTo`が実装されていない関係でパフォーマンス的にあまり良くないようです。オシャレさに感動して紹介しましたが、大人しくbufio.Reader使う方が多くのケースでは良さそうです。

# まとめ
io.MultiReaderいつ使うんじゃ！と思っていたのですが普通に便利でした。こうしたちょっとしたテクニックは忘れがちなのでちゃんと書いておきたい所存なのですが、その所存も忘れがち問題があります。
あれ・・・サーバー費用削減したのに・・・っていうハナシ@IDCF

# 何が起きたか
IDCFでサーバーコストが想定より安くなってない！
なぜ！？詐欺なの！？
# 背景
担当のPRJのサーバーのランニングコストを下げるために、
負荷をみてスケールダウンでコストを削減することとした。
# スケールダウンの内容
```
HighMem.XL64 x 4 単価¥60,000/月
↓
HighMem.XL32 x 4 単価¥30,000/月
```
12/10に切り替えたので12月は10万くらい安くなる見込みだった
# 変わらぬ請求
1月に確定した12月請求を見てみると総請求額は変わってない・・・なんで・・・？
# 原因
## IDCFの料金形態は「従量」＋「上限料金」の2段構えである
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/54063/04007e1c-4f90-578f-f3e4-c46415f3cfdf.png)
[IDCF料金表](https://www.idcf.jp/cloud/price.html)
## つまりこういう内訳
```
HighMem.XL64 x 4 単価¥29,760 (240h従量課金) 12/01-12/10
HighMem.XL32 x 4 単価¥30,000 (月額上限) 12/11-12/31
12月総額:¥59,760
```
XL64をまるっとひと月使っててもよかったじゃん・・・
# こうするべきだった
今回は12/10にスケールダウンしたのでほぼ同額で済んだが、
12/15に行っていた場合、¥6,000ほど損をすることになる計算。

**IDCFでスペックダウンする場合は上限課金を有効活用できるタイミング（月末が望ましい）が望ましい**
・・・と学んだのでありました
typescriptで高階関数を使いたくなった時に思い出すための覚書

## 注意

筆者は高階関数に詳しいわけではないので認識が間違っている場合があります。

## 高階関数とは

[Wiki](https://ja.wikipedia.org/wiki/高階関数#関数を呼び出す関数)

> 第一級関数をサポートしているプログラミング言語において、関数（手続き）を引数に取る関数のことである。


と書かれている。また、別の記事によると、戻り値によって関数（手続き）を返却する関数も
該当するらしい。

つまりは、よくみる所の。

* callback
* カリー化

みたいなものだろうか。。。

## callbackの定義方法について

callbackをtypescriptで引数として定義する場合、
どんなふうに書いておいたらカッコいいのかな。と思い、Array Interfaceの`ts.d`を覗いてみた。

<details><summary>Array Interface（抜粋）</summary><div>

```typescript
interface Array<T> {
    forEach(callbackfn: (value: T, index: number, array: T[]) => void, thisArg?: any): void;
    /**
     * Calls a defined callback function on each element of an array, and returns an array that contains the results.
     * @param callbackfn A function that accepts up to three arguments. The map method calls the callbackfn function one time for each element in the array.
     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
     */
    map<U>(callbackfn: (value: T, index: number, array: T[]) => U, thisArg?: any): U[];
    /**
     * Returns the elements of an array that meet the condition specified in a callback function.
     * @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
     * @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
     */
    filter<S extends T>(callbackfn: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
}
```

</div></details>

よく使う、map, filter, forEachあたり

というわけで

## callback

```typescript
const callback = (fn: (arg1: string) => void) => {
  fn("Hello, World")
}
```

```typescript
const str = (fn: (arg1: number) => string | unknown) => {
  const s = fn(100)
  if (typeof s == "string") {
    console.log(s.toLocaleLowerCase())
  }
}
```

悪い例として、`const f = (fn: Function) => {}`のように書くこともできるが、
この場合だと戻り値の型が**any**となってしまう。
特定の型を返す関数以外受け付けないようにするため、上記のような書き方にする。

## カリー化

イマイチカリー化は使いどころがわかっていないので、雑なサンプル。
（今までは、必要があったら後から実行する関数を返すようにしたりしていた）

```typescript
const curry = (num: number) => {
  return (str: string) => {
    return num + Number(str)
  }
}
```

## 脱線

コールバックのところで、戻り値の型を`string | unknown`にしていたかと思うが、
**unknown**ってなんだろうと思って調べたところ非常にわかりやすい記事があった。

[TypeScript 3.0のunknown型 - タイプセーフなany](https://qiita.com/suzuki_sh/items/9b168b44d1d21c127aeb)

簡単に理解するならば、anyの場合は実行時エラーとなっていたものを、unknownとできるならば
実行時エラーではなく、コンパイルエラーとして処理することができるということかな。。。

typescript & プログラミングの世界は奥が深い
AWS DevOps Engineer Professionalに合格したのでレポート

先日AWS DevOps Engineer Professionalに無事合格したので今更ですがレポート、振り返り、備忘をまとめます。

## AWS認定資格　取得状況
こんな感じ↓
ソリューションアーキテクト - アソシエイト (2017年10月)
SysOpsアドミニストレーター - アソシエイト (2017年11月)
デベロッパー - アソシエイト (2019年2月)
セキュリティ専門知識 (2019年7月)
ソリューションアーキテクト - プロフェッショナル (2019年9月)
DevOpsエンジニア - プロフェッショナル (2019年12月)

##試験結果など
850/990でした。
ちなみに受験は2回目です。
1回目の受験は本人確認書類（パスポートなどの顔つきの公的書類）を家に忘れて門前払いを食らいました泣

##補遺：本人確認書類を忘れるとどうなるか
まず、受験会場の人に「我々では判断できないのでここに電話して」と電話番号を渡されます。
電話をすると応対する言語を選べます。(日本語or英語で、日本語を選択しました)
そして、カタコトの日本語で「モーシワケアリマセン」的なことを言われます。
ついでに本人確認書類忘れは不合格と同じ扱い(当然か)で、2週間試験が受けられません。

本人確認書類を忘れると本当に受験できませんのでダブルチェックで受けに行きましょう。
15000円(バウチャーで半額)を一瞬で無駄にしてしまいます。


##試験受験～感想
池袋のスーパーオフィスというところで受験しました。
http://www.superoffice.jp/school/test_center.php

入口へ続くエレベーターが駐車場的なところにあり、少々迷いました。
本人確認はリモートで行い、本人確認書類をスキャナに読み込ませて確認します。
が、スキャナが壊れていたようなのでカメラに本人確認書類をかざす形式で確認しました。

試験は日本語が怪しい問題がチラホラありました。
「CloudFormationでキャッシュを～」みたいなナゾの選択肢があったので英語に切り替えたら
<b>「CloudFrontでキャッシュを～」</b>みたいになっている問題もありました。勘弁してほしい。

DevOps プロフェッショナルに限ったことではないですが、<b>迷ったら英語に切り替えるのが大事</b>だとおもいます。

##勉強方法
AWSのサンプル問題集（10問）と、模擬試験（20問）を解いた後、Udemyの練習問題を解きました。
Udemyは１つのセクションが終わるごとに、できなった問題について解説とホワイトペーパー、<a href= "https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/" >ブラックベルト</a>を読んでメモアプリに書き出し、通勤電車や会社のトイレで復習する感じで勉強しています。
利用したUdemyの問題は↓です
https://www.udemy.com/course/aws-certified-devops-engineer-professional-practice-exams-/

スコアはこんな感じでした。
Exam①→49%
Exam②→51%
Exam③→60%
Exam④→64%
Exam⑤→70%

なお、<a href= "https://aws.amazon.com/jp/aws-jp-introduction/aws-jp-webinar-service-cut/" >ブラックベルト</a>で3回以上読み込んだサービスは以下でした
・OpsWork
・CloudFormation
・SystemsManager
・Code*
・AutoScaling

ちなみに、re:Invent2019にて以下のようなハンズオンが行われていたので、ついでに実施しました。
Fargateのブルーグリーンデプロイを行うCICDパイプライン構築ラボです。
やはりハンズオンは最強で、触って理解するのが一番早いと思います。
手っ取り早くやれば課金も2ドル程度でした。おすすめです。

Building a CI/CD pipeline for blue/green deployments using AWS Fargate
https://cicd-with-aws-fargate-lambda-bg.workshop.aws/en

以上になります。
次はBigData Specialtyでも受けてみます。
CentOS6.5にPetalinux2017.2インストール時 "そのようなファイルやディレクトリはありません(No such file or directory)"とエラーが出る件

#問題内容
RedHat6.X系や，CentOS6.X系にPetalinux2017.2をインストールする際，なぜか以下のようなエラーが発生する．

* 実行コマンド
``./petalinux-v2017.2-final-installer.run (インストール先PATH) ``

* エラー文章 例(以下のようなエラー文章が複数出力される)
`` tar: (特定のファイルPATH情報) utime不能: そのようなファイルやディレクトリはありません``
`` tar: (特定のファイルPATH情報) stat不能: そのようなファイルやディレクトリはありません``

上記エラーは，***ファイルやディレクトリが存在していても出力される***．
エラー原因を探す情報は上記文章しかないため，tarに何か原因があるのではという所までしか分からなかった．

#原因
[Xilinxフォーラム](https://forums.xilinx.com/t5/Installation-and-Licensing/Petalinux-2017-2-on-Red-Hat-Linux-6-9-installation-fails-after/td-p/814853 "Xilinxフォーラム")から下記内容を見つけた．

>We upgraded tar to version 1.29 and now Petalinux 2017.2 installs on Red Hat 6.9 with devetoolset-2 and python27 software collections in case anyone is running across this problem.

つまり，Petalinux2017.2をRedhat6.9にインストールする場合は
・　tar バージョン1.29
・　devtoolset-2（[Petalinuxツール資料リファレンスガイド(UG11444)](https://japan.xilinx.com/support/documentation/sw_manuals_j/xilinx2017_2/ug1144-petalinux-tools-reference-guide.pdf "[Petalinuxツール資料リファレンスガイド(UG11444)")にもインストールすべきライブラリとして記載有）
・　python2.7
が必要との事だった．

自分の場合，devtoolset-2とpython2.7はインストール済みだったが，tarが1,24だった為エラーが発生した．

#修正方法
・ tarのインストールについて
[CentOS6.5で"tar"をアップデートする（パッケージ構成上でもアプデ反映する）](https://qiita.com/usiiiii/items/b013d196a747c179b7a5 "CentOS6.5で"tar"をアップデートする（パッケージ構成上でもアプデ反映する）")に記載している方法でtarの最新バージョン(バージョン1.32）をインストール．

・ devtoolset-2のインストール
[CentOSに新しいバージョンのGCC/G++(4.8/4.9)をインストールする](https://www.task-notes.com/entry/20151114/1447492231 "CentOSに新しいバージョンのGCC/G++(4.8/4.9)をインストールする")にインストール方法記載有り．

・　python2.7のインストール
[Linux(CentOS)にPython 2.7.11をインストール](http://inatim.com/centos-python2-7-11/ "Linux(CentOS)にPython 2.7.11をインストール")にインストール方法記載有り．

上記参考にして，必要なライブラリをインストールすればOK．

#結果
問題なくpetalinux2017.2をインストールすることができた．
petalinuxプロジェクトの作成もできた．

以上！
Visual Studio 2019でWindowsSDKを参照できなくなった話

# 経緯
今までWindows Namespaceに含まれるClassを参照する際には、プロジェクトファイルに以下の記述をすることで参照マネージャーに追加されるWindows参照のタブを利用していた。

```Project.csproj
<PropertyGroup>
    <TargetPlatformVersion>10.0</TargetPlatformVersion>
</PropertyGroup>
```

しかし、WindowsOSのアップデート後、WindowsSDKが見つからなくなり参照が出来なくなってしまった。
<img width="590" alt="windows_sdk_notfound.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153272/5c84853d-68b3-20f0-6f0d-7cfd86923c1d.png">


# Windows Namespaceに含まれるClassを参照する方法

1. Microsoft API Referenceから参照したいClassのAPI Contractを探す。(ハイライト部分)
2. Visual StudioでAPI Contractを参照に含める。

<img width="840" alt="microsoft_docs.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/153272/547b4cf3-b648-317d-8bb8-1a6fd8185b96.png">

#参考
- Windows.Media.Captureの参照が見つからない
https://social.msdn.microsoft.com/Forums/vstudio/ja-JP/e8d8d520-8f15-4fcf-8572-25946ef28cf1/windowsmediacapture?forum=vsgeneralja
- Windows UWP Namespaces - Windows Dev Center 
https://docs.microsoft.com/en-us/uwp/api/
XSS と CSRF って結局何が違うのか？

# XSS と CSRF

セキュリティの文脈で `XSS (cross site scripting)` と `CSRF (cross-site request forgeries)` がやたら出てくると思うのですが、名前も似てるしなんか悪さするスクリプトを埋め込むんだろうなーくらいにしか理解しておらず、明確な違いがわかっていなかったのでこの機会にまとめてみました。

# XSS とは

XSS とは一言で表すと `ユーザー（被害者）の Web ブラウザで任意の JavaScript を実行させることを許す脆弱性または攻撃手法` です。
ちなみに略称が `CSS` ではなく `XSS` なのは、Cascading Style Sheets とかぶってるのでややこしいからのようです。

### XSS を実現する手順

どうやって、被害者のブラウザで JavaScript を実行させるかというと、

1. 攻撃者が**脆弱性のある Web アプリケーション**を見つける。
2. **不正なスクリプト**を含んだ罠を用意する。
3. 罠に誘導するための URL をユーザー（被害者）に SNS / メールなどで配る。
4. 罠にかかったユーザーが URL にアクセスし、脆弱性のある Web アプリケーションにアクセスする。
5. Web アプリケーションから**不正なスクリプトを含んだ Web ページ**が返される。
6. ユーザーの **Web ブラウザで不正なスクリプト**が実行される。

という手順を踏むことによって実行させます。
結果として Cookie や機密情報抜かれたり、偽情報を表示して社会的信用を落とされたりとか色々やられます。

### XSS を防ぐには

`1. 攻撃者が脆弱性のある Web アプリケーションを見つける。` と書きましたが、**HTML 生成時に特殊文字をエスケープしないこと**が XSS を実現させてしまう一因となってしまいます。

例えば、入力フォームに検索条件を入力して、サーバーから返された検索結果を表示するようなサービスの場合、`<` や `>` をエスケープせずにそのまま入力できるようにしてしまうと、`<form method="POST" ...>`みたいな感じで入力情報を別のサーバーに飛ばすフォームをブラウザにレンダリングさせることができるわけです :thinking: 

そのため対策として、**HTML の特殊文字のエスケープ** がとても大切になります。

# CSRF

続いて CSRF です。CSRF を一言で表すと `正規ユーザを誘導し、強制的に特定の処理を実行させる攻撃を許す脆弱性または攻撃手法` と言えます。
`forgeries/forgery` ってあまり聞かないですよね... `偽造` という意味らしいですよ。(サイトをまたがってリクエストを偽造する :thinking: )

### CSRF を実現する手順

どうやって強制的に特定の処理を実行させているかというと、

1. ユーザーが特定の Web サービスに**ログイン**する
2. 攻撃者が用意した**罠ページ**にユーザーがアクセスしてしまう
3. 罠ページから**攻撃コード**が Web サービスに送られてしまう
4. ユーザーは**ログインが完了している**ので、Web サービスにリクエストが届いてしまう

強制的に実行させる`特定の処理`と言っているのは、例えば通販サイトであれば `商品の不正な購入` であったり、掲示板サービスだったら`不正な書き込み`させると言った感じです :thinking: 

### CSRF を防ぐには

CSRF は正常にログインしているのでサーバーでは不正なリクエストかどうかの判定が難しいところを突いてきている手法だと言えます。
なので、対策としては `コメント投稿、商品購入、退会といった副作用が発生する画面の実行時に、想定通りの画面遷移が行われたかどうかを確認する`などして、セッションの管理を不備なく行うことが大切です。
また、事前にユーザーにサーバーからトークンを渡しておいて、`副作用が発生する画面の実行時にトークンが正しいか確認する`ということも有効です。

# まとめ

### XSS

- 不正なスクリプトが実行されるのは**ユーザーの Web ブラウザ**
- 受ける被害は機密情報を抜かれる、偽情報が表示され社会的信用を落とされるなど
- 対策として **HTML の特殊文字のエスケープ**が有効

### CSRF

- 不正なスクリプトが実行されるのは **Web サーバ**
- 受ける被害は通販サイトであれば商品の不正な購入、掲示板サービスだったら不正な書き込みなど
- 対策として、**副作用が発生する画面の実行時に、想定通りの画面遷移が行われたかどうかを確認する**。または、**事前に渡したトークンが正しいものであるかをチェックする**ということが有効