OmniAICreator/Qiita-1.07M huggingface dataset:
GoogleFormの結果を好きなアドレスに送る

今回はタイトル通り、
GoogleFormで送信した結果を好きな（指定した）アドレスに送る方法を紹介します。

以下記事で詳しく紹介してます！
https://bzbot.work/

## 紹介記事
https://bzbot.work/2019/02/15/form-mail/

GoogleFormから送信すると、Gmailアカウントの自分宛て、もしくは回答者のアドレス宛てにしか送信できません。
しかし、以下コードをスクリプトエディタの中に記載して、回答をすると指定したメールアドレス宛てに結果が届くようになります、
※セキュリティがある会社に対しては送れない場合がございます
![image.png](https://qiita-image-store.s3.amazonaws.com/0/363116/dfe19166-098d-2d4e-b484-f9da433ff0c9.png)

## 実際のコード

```javascript

var itemResponses = e.response.getItemResponses();
  var message = '';
  
  //itemResponsesに入っている分だけ繰り返す
  for (var i = 0; i &lt; itemResponses.length; i++) {
    var itemResponse = itemResponses[i];
    //formの質問内容を取得
    var question = itemResponse.getItem().getTitle();
    //formの選択内容を取得
    var answer = itemResponse.getResponse();
    Logger.log(i + '回目question:' + question);
    Logger.log(i + '回目answer:' + answer);
    
    //ループごとに増えていく情報を改行してくっつけていく（/nは改行）
    message += (i + 1).toString() + '. ' + question + ': ' + answer + '\n'; 
  }
  Logger.log('message:' + message);
  var address = '送信したいアドレスを記載';
  var title = '[評価シートの入力結果です]';
  var content = '評価シート入力結果--------------------\n\n' + message;
  GmailApp.sendEmail(address, title, content);
}
```


##結果のログ

```
[19-02-15 01:43:01:806 JST] 0回目answer:担当A
[19-02-15 01:43:01:864 JST] 1回目question:評価者の◯◯を選択してください
[19-02-15 01:43:01:864 JST] 1回目answer:3,4,5
[19-02-15 01:43:01:925 JST] 2回目question:コメントを入力してください
[19-02-15 01:43:01:925 JST] 2回目answer:テスト
[19-02-15 01:43:01:925 JST] message:1. 評価者を選択してください: 担当A
2. 評価者の◯◯を選択してください: 3,4,5
3. コメントを入力してください: テスト
4. ```
UnityでGamePadの個数を取得する

#はじめに
こんにちは、避雷です。今回は現在開発中の「BoosterBoots」というゲームで複数のコントローラを一つのPCに接続するタイプのマルチプレイを実装する過程で得た知見を公開します。というか助けて…
https://twitter.com/lucknknock/status/1095883926503968768

#実装
##Input.GetJoystickNames().Lengthの利用
[Unityでゲームパッドの接続台数を調べる](https://qiita.com/Ori/items/aeeec92647161494bb3a)
こちらの記事を参考にして接続されたコントローラの個数を取得しようとしました。

```C#
var controllerNames = Input.GetJoystickNames();

Debug.Log(controllerNames.Length);
```

この手法はランタイム中にコントローラの抜き差しが発生しない状態では正しい個数を取得できるのですが、ランタイム中にコントローラの抜き差しが発生すると、「コントローラ名が""(空白)のコントローラが存在する扱いになる」という不具合があり、コレのせいで抜き差しするたびに接続コントローラ数が増えたり増えなかったりします。

##対策方法
誤って生成されるコントローラは常に""(空白)という名称なので、これを除去してあげてカウントすれば正しいコントローラ個数を取得することができます。

```C#
        string[] cName = Input.GetJoystickNames();
        currentConnectionCount = 0;
        for (int i = 0; i < cName.Length; i++)
        {
            if(cName[i] != "")
            {
                currentConnectionCount++;
            }
        }
```

こうすれば正しいコントローラ数を取得できます。
#残る問題点
今回の解決策は決して抜本的なものではなく、その場しのぎの杜撰な対応なので、Unityのコントローラ同時接続周りの滅茶苦茶具合が直ったわけではありません。残るバグの一例として

- コントローラの接続順が入れ替わる
- 存在しないはずのコントローラが接続される
- そもそもキーコンフィグを動的に変更できない

などがあります。Unity2018.3から実装された新しいInputSystemではある程度改善されているらしいのですが、いかんせん資料が少ないです…
Unity2018.2以前でこれをやるにはお高めのアセットを買うしかなさそうで結構辛いです。誰か助けて…
MDNでtemplateとslotの使い方について学ぶ

# ゴール

MDNを見ながらtemplateとslotについて知ったつもりになる。

# 参考

[template と slot の使い方 - Web Components | MDN](https://developer.mozilla.org/ja/docs/Web/Web_Components/Using_templates_and_slots)

# The truth about templates

書いてあるサンプルのHTMLのみ書いてブラウザで表示してみる。

```html
<template id="my-paragraph">
  <p>My paragraph</p>
</template>
```

おー！表示されない(｀・ω・´)
Javascriptを読み込んで.jsに以下を記述。

```js
let template = document.getElementById('my-paragraph');
let templateContent = template.content;
document.body.appendChild(templateContent);
```

おー！表示された(｀・ω・´)
見えないtemplateを用意しておいて、動的に生成できるって感じですかね。

# Using templates with web components

`.js`と`.html`を以下のように書き換えて実行。

```js
// javascript
customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;
      const shadowRoot = this.attachShadow({mode: 'open'})
      .appendChild(templateContent.cloneNode(true));
    }
  }
);
```

```html
// html
<template id="my-paragraph">
  <style>
    p {
        color: white;
        background-color: #666;
        padding: 5px;
    }
  </style>
  <p>My paragraph</p>
</template>
<my-paragraph></my-paragraph>
```

おぉ〜...？ってことで1つずつ見ていきます。 

HTMLの方はtemplateが用意されているだけですね。`.js`の読み込みをしなければ画面上、何も表示されません（`my-paragraph`タグは表示されます）。

続いて`.js`の方を見ていきます。
`customElements.define`でカスタムタグを作成は問題無しですね。`HTMLElement`を継承したクラスを引数に与えているのもOK。`id="my-paragraph"`のcontentを`templateContent`変数に入れてるのもOK。
`cloneNode`をしてるのは複製しないと2度以上使えないから。とは言え動かした結果から言ってるので何で`cloneNode`が必要なのかは理解できてない:no_good:

# Adding flexibility with slots

> ここまでのサンプルでは高々1種類のテキストを表示できるのみで、普通の paragraph よりも使えません。

お、おう。

> slot はその name 属性で区別されており、template の中で任意のマークアップで slot の内容のデフォルト値を埋めることができます。

...なるほど、わからん:thinking:
ということで何となくの雰囲気で試してみる。

```html
// html
<template id="my-paragraph">
  <slot></slot>
  <slot name="hoge"></slot>
</template>
<my-paragraph>
  <p>name無しのslotに追加される</p>
  <p>ここもname無しのslot要素に追加される</p>
  <p slot="hoge">name="hoge"に追加される</p>
  <p slot="piyo">name="piyo"に追加される（piyoが無いので追加されない）</p>
</my-paragraph>
```

```js
// javascript
customElements.define('my-paragraph',
  class extends HTMLElement {
    constructor() {
      super();
      let template = document.getElementById('my-paragraph');
      let templateContent = template.content;
      const shadowRoot = this.attachShadow({
          mode: 'open'
      })
      .appendChild(templateContent.cloneNode(true));
    }
  }
);
```

こういう理解であってるんだろうか...:thinking:

# おわり

何となくわかった気にはなれた。気がする。
Vue.js触ってみようかな。
【Java】Builderパターンで実装されたクラスを使う関数を実装する

# 注釈
何か設定してから自分自身を返すような実装全てをBuilderパターンとします。

# やりたかったこと
`SimpleJdbcInsert`を使ってインサートするため、以下のようなコードが量産されていました。

```java
new SimpleJdbcInsert(Jdbcテンプレート)
        .Builderの処理
        .execute(new BeanPropertySqlParameterSource(挿入するオブジェクト));
```

このコードでは一々`SimpleJdbcInsert`や`BeanPropertySqlParameterSource`を`new`する辺りが非効率で、その他の理由からもプロジェクト全体で効率化への需要があったため、関数で処理をラップすることで効率化を図ろうとしました。

# 問題になったこと
`SimpleJdbcInsert`が`Builder`パターンで実装されているため、関数を実装する初期化済みのインスタンスを渡すぐらいしか実装が思いつきませんでした。
しかし、これでは全く効率化していないに等しいです。

```java:全く効率化していないコード
ラップ関数(new SimpleJdbcInsert(Jdbcテンプレート).Builderの処理, 挿入するオブジェクト);
```

# 解決方法
Fluent Builderパターン（ローンパターン）的な書き方をすることで効率的に実装できました。

```java
//ラップ関数
public int insertExecute(UnaryOperator<SimpleJdbcInsert> builder, Object entity) {
    return builder.apply(new SimpleJdbcInsert(Jdbcテンプレート))
            .execute(new BeanPropertySqlParameterSource(entity));
}

//利用例
insertExecute(it -> it.ビルダー処理, 挿入するオブジェクト);
```

「ビルダーによる生成処理が邪魔ならそれを受け取ってしまえばよい」という発想がとっさに出てこなかったのは勉強不足ですね……。

# 参考にさせていただいた記事
[Javaで書くBuilderパターンのパターン \- Qiita](https://qiita.com/disc99/items/840cf9936687f97a482b)
SwiftでDropBox APIを使ってみる [準備編]

DropBoxを使ってiosアプリからテキストファイルを書き換えができるまで頑張ってみた軌跡です。
ご指摘、改善できる箇所があればご教授いただけると幸いです。

下記のSwiftyDropboxリファレンスを参考に作成していきます。
http://dropbox.github.io/SwiftyDropbox/api-docs/latest/


#環境
MacBookPro

Xcode : Version 10.1 (10B61)
swift : Version 4.2.1

# #1 DropBoxにアプリ登録
*DropBoxアカウントが必要です。

1.DropBoxのホーム画面へ
https://www.dropbox.com/developers/apps

2.My apps画面右上の"Create app"ボタンをクリック
<img width="832" alt="DropBoxメイン画面.png" src="https://qiita-image-store.s3.amazonaws.com/0/316758/dc993e62-e288-9368-8905-96728f42cfcb.png">

3.Create a new app on the DBX Platform　の設定

Choose an API : DropBox API
Choose the type of access you need : Full Dropbox 
Name your app : 好きなアプリ名

<img width="838" alt="DropBoxアプリ登録内容.png" src="https://qiita-image-store.s3.amazonaws.com/0/316758/2e592cb7-822b-5e12-6dfd-fa8f050a7a81.png">

4.App keyを保存(後ほど使います)
<img width="809" alt="App key.png" src="https://qiita-image-store.s3.amazonaws.com/0/316758/889a0421-ed11-0f66-22c1-4e816f9a78d5.png">

# #2 Xcodeプロジェクト作成
次のステップのcocoapodでライブラリをインストールするので作成、起動できるかテストを行う

# #3 cocoapodでDropbox APIのライブラリのインストール
 1.ターミナルで#2で作成したプロジェクトの階層まで移動
 2.Podfileを生成

```
pod init
```
3.Podfile編集

```
target 'アプリ名' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
    use_frameworks!
    
    #追加
    pod 'SwiftyDropbox'

end
```

# #4プロジェクトを設定
1.Info.plistファイルをテキスト編集ソフト（私の場合はvisual studio code）で開く
2.下記のコードを追加

```
<key>LSApplicationQueriesSchemes</key>
    <array>
        <string>dbapi-8-emm</string>
        <string>dbapi-2</string>
    </array>
```

3.CFBundleURLTypes内の配列にCFBundleURLSchemesを追加
db-########となるように記述

```
<key>CFBundleURLTypes</key>
	<array>
		<dict>
			<key>CFBundleTypeRole</key>
			<string>Editor</string>
=============================追加==================================
			<key>CFBundleURLSchemes</key>
			<array>
				<string>db-#1で作成したキー</string>
			</array>
=================================================================
		</dict>
	</array>
```

参考画像
<img width="772" alt="info.lists.png" src="https://qiita-image-store.s3.amazonaws.com/0/316758/01be813e-9c05-f600-7e4c-3ae166730f90.png">

以上で下準備は完了です！
次の記事で実装を行なっていきたいと思います！
db:migrateでalready existだった時の話

## modelが気に入らなくて作り直そうとした

そういうこと、ありません？
開発中に「あれ？この変数忘れてたわ」とmodelを作り直したいなーって思って、rails destroy => rais generate modelしたんですよ。
んでdb:migrateしようと思ったらご覧のありさま。

```
ec2-user:~/environment/circle-list (master) $ rails db:migrate
== 20190216164559 CreateCircles: migrating ====================================
-- create_table(:circles)
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

SQLite3::SQLException: table "circles" already exists: CREATE TABLE "circles" ("id" integer PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar, "space" varchar, "memo" varchar, "url" varchar, "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL)
　　(以下略)
```

SQLite上に作りたいテーブルは既にいるよ！と怒られました。
**うん知ってる。ゴリ押しでどうにかしたいんだよこっちは。**

## つよくてにゅーげーむ

テーブルの中身をふっとばしていいなら「db:migrate」の後ろに「reset」をつけよう

```
$ rails db:migrate:reset
Dropped database 'db/development.sqlite3'
Database 'db/test.sqlite3' does not exist
Created database 'db/development.sqlite3'
Created database 'db/test.sqlite3'
== 20190216164559 CreateCircles: migrating ====================================
-- create_table(:circles)
   -> 0.0020s
== 20190216164559 CreateCircles: migrated (0.0027s) ===========================
```
MySQLでデータベース作成ができない時の対処

###はじめに

SQL文もある程度覚えたし、実際にMySQLの環境を構築してより実践的な学習をしようと思ったら、いきなり詰まったので備忘録として残しておきます。


###何が発生したか

![alt](https://gyazo.com/83b70be60a1d58122710c368d2603d32/raw)

データベース作成がしたいのに、ボタンが押せない状況に。
原因は画像下部にある

```
Could not connect, server may not be running. Can't connect to MySQL server on '127.0.0.1' (10061)
```

この部分でした。
「サーバーに接続してねぇぞ」って怒られているようです。

###どこを確認すれば良いか

答えは`mysqld`というプロセスにありました。

windowsのPCの場合は
タスクマネージャー→プロセスでmysqldのプロセスが動いているか確認する。
(Macの場合については未確認のため分かりません。すみません...）


確認してみると該当するプロセスは見当たらず起動していなかったことが分かりました。



###どのように起動するか。

※下記実行前にMySQLのbinコマンドが使えるようPathを通しているか確認すること。
通していない場合は環境変数に`;C:¥Program Files¥MySQL¥MySQL Server x.x¥bin`を入れること
(x.xにはバージョンを入れる。今回の場合は5.7）

1. 管理者権限でコマンドプロンプト起動
2. `net start mysqlxx`を実行。
(`xx`部分にはバージョンの番号を入力します。5.7のバージョンを使用している場合は`57`)
3. `mysql -u root -p`を実行

以上。

`net start`はサービスの表示／開始を意味し、
`mysql -u root -p`はmysqlにユーザー名rootでパスワード入力を行う宣言です。

![alt](https://gyazo.com/fbe73816a8be0803c650a20e3b1e4d99/raw)]


MySQLサーバーとの接続を切断する場合は`quit`で抜ける。
(`exit`、`\q`でもOK)
TodoistのカルマをRaspberry Pi で可視化する

# はじめに
2019年が始まって早くも１ヶ月が過ぎました。
新年を迎えて、新しく目標を設定する人が多いと思います。

現代のビジネスパーソンなら、誰もがやっているであろうタスク管理アプリも、昨今は色々ありますが私のオススメはTodoistです。

**Todoistは、最高のToDoリスト＆タスク管理アプリです。**

シンプルなUIで無駄がなく簡単に操作でき、目標を定量的に計測することができます。また、面白いのがカルマという生産性を記録して視覚化するパワフルな機能があり、無料でも効果的なタスク管理ができます。

本記事は、タスク管理アプリであるTodoistのカルマを、Raspberry Piで可視化します！

![写真 2019-02-17 23 06 17.jpg](https://qiita-image-store.s3.amazonaws.com/0/221759/99c24ab1-cea8-719d-d221-4f12d1d2de2b.jpeg)

## 全体概要
I2C接続した液晶キャラクタデバイスに、TodoistのAPIで取得したカルマを表示させます。
液晶キャラクタデバイスは、Xiamen Zettler Electronics社製の「ACM1602NI」を使用します。「ACM1602NI」は、1,300円程度で購入できます。

![todoist.png](https://qiita-image-store.s3.amazonaws.com/0/221759/efbbaa11-3c10-9393-7b0b-b1182f185f61.png)

仕組みは簡単で、Todoist Sync APIを使用して、カルマを取得します。
なお、TodoistのAPIを利用するためのライブラリは、公式のpipで提供されているので、以下のコマンドよりインストールできます。

`pip3 install todoist-python`

また、TodoistのAPI トークンは、[TodoistのWeb画面](https://ja.todoist.com/)より、発行できます。

## 構成
必要な部品は以下になります。

- 部品一覧

| 部品      |   数量 |
|:---------|:-----------|:-----------|
|液晶キャラクタデバイス「ACM1602NI」  　|１個　|
|半固定抵抗（10kΩ） 　　|１個　|
|抵抗（100Ω） 　　|１個　|
|ジャンパー線（オス-メス） 　　|5本　|
|ジャンパー線（オス-オス） 　　|6本　|

## プログラム

- kalma_disp.py

```python
#! /usr/bin/env python
# -*- coding: utf-8 -*-

import smbus
import time
from acm1602 import acm1602

import sys
sys.path.append('/home/pi/.local/lib/python3.5/site-packages/')
import todoist
from todoist.api import TodoistAPI

class Karma:
    def __init__(self):
        api = TodoistAPI('<API トークン>')
        api.sync()
        status = api.completed.get_stats()
        karma = str(status["karma"])
        self.karma = karma

# インスタンス生成
karma_ins = Karma()
# デバッグ用
#print(karma_ins.karma)

lcd = acm1602(1, 0x50, 4)

def setup():
    lcd.move_home()
    lcd.set_cursol(0)
    lcd.set_blink(0)
    lcd.backlight(1)

def display():
    value = karma_ins.karma
    value = value.replace(".0", "")
    lcd.write("karma:" + value)
    lcd.move(0x00, 0x01)
    lcd.write(time.strftime("%H:%M"))

setup()
display()
```
プログラムを実行すると、現在のカルマを表示できます。
![写真 2019-02-17 23 06 47.jpg](https://qiita-image-store.s3.amazonaws.com/0/221759/cb135b1d-8d87-cad9-64d0-236caa1b47e4.jpeg)

# おわりに
液晶キャラクタデバイスを購入して、vcgencmdコマンドでCPUの温度を表示して遊んでいましたが、他に何かないかなと思って、Todoistのカルマを表示させてみました。

しかし、液晶キャラクタデバイスの使い道がいまいちなのと、TodoistのAPIはもっと他に使えそうな気がするので、また今度とします。
## 参考
- [API Documentation | Todoist Developer](https://developer.todoist.com/sync/v7/)
- [todoist-python](https://pypi.org/project/todoist-python/)
Elixir~Enum総ざらい4回目~

#Enum.fetch
```elixir

Enum.fetch([2, 4, 6], 0)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], -3)
{:ok, 2}

iex> Enum.fetch([2, 4, 6], 2)
{:ok, 6}

iex> Enum.fetch([2, 4, 6], 4)
:error
Enum.fetch([2, 4, 6, 8],3)
{:ok, 8}
```

これは簡単なようです。リストの引数に対して、ゼロから数えてn番目の値があればokとともに返す関数のようです。

#Enum.find

```elixir
Enum.find([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find([2, 4, 6], 0, fn x -> rem(x, 2) == 1 end)
0

Enum.find([2, 3, 4], fn x -> rem(x, 2) == 1 end)
3
```

こちらは第一引数のなかから2で割ってあまりが1になるという条件式にあてはまる数値を返すようです。ただ、1番目の式の結果がnil、2番目で0が挿入されていると結果が0になるところがやや引っかかるところです。

#Enum.find_index

```elixir
Enum.find_index([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find_index([2, 3, 4], fn x -> rem(x, 2) == 1 end)
1
```

こちらはEnum.findと似ていますが、第一引数のリストのなかから条件式にあてはまる要素の数を返している、、のかな？

#Enum.find_value

```elixir
Enum.find_value([2, 4, 6], fn x -> rem(x, 2) == 1 end)
nil

Enum.find_value([2, 3, 4], fn x -> rem(x, 2) == 1 end)
true

Enum.find_value([1, 2, 3], "no bools!", &is_boolean/1)
"no bools!
```

こちらも条件式に対して結果を返すもののようですが、条件式にあてはまるものがなければnil、ひとつでもあればtrueを返しているのでしょうか。
3番目の式に関してはわたしの知識では図りかねます。

#Enum.flat_map
```elixir

Enum.flat_map([:a, :b, :c], fn x -> [x, x] end)
[:a, :a, :b, :b, :c, :c]

Enum.flat_map([{1, 3}, {4, 6}], fn {x, y} -> x..y end)
[1, 2, 3, 4, 5, 6]

Enum.flat_map([:a, :b, :c], fn x -> [[x]] end)
[[:a], [:b], [:c]]
```

こちらはかなりお手上げに近いのですが、最後のendの前の[x,x]、x..y、[[x]]の違いに着目してみると、ある一定の法則が見いだせそうです。

#Enum.flat_map_reduce

```elixir
enumerable = 1..100
 n = 3
 Enum.flat_map_reduce(enumerable, 0, fn x, acc ->
  if acc < n, do: {[x], acc + 1}, else: {:halt, acc}
 end)
{[1, 2, 3], 3}

 Enum.flat_map_reduce(1..5, 0, fn x, acc -> {[[x]], acc + x} end)
{[[1], [2], [3], [4], [5]], 15}
```

[公式ドキュメント](https://hexdocs.pm/elixir/Enum.html#dedup/1) からの英文を転載しておきます。

Maps and reduces an enumerable, flattening the given results (only one level deep).

It expects an accumulator and a function that receives each enumerable item, and must return a tuple containing a new enumerable (often a list) with the new accumulator or a tuple with :halt as first element and the accumulator as second.

完全にお手上げです。現時点の知識では全くわかりません。

#Enum.group_by

```elixir
Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1)
%{3 => ["ant", "cat"], 5 => ["dingo"], 7 => ["buffalo"]}

Enum.group_by(~w{ant buffalo cat dingo}, &String.length/1, &String.first/1)
%{3 => ["a", "c"], 5 => ["d"], 7 => ["b"]}
```

複雑ですが法則性が見えてきます。

最初の式では、それぞれ綴りの文字数ごとにソートして結果を返しています。
2番目の式では、&String.first/1が付与されているので、それぞれの綴りの文字数ごとに最初の一文字を返しているように思えます。

#Enum.intersperse

```elixir
Enum.intersperse([1, 2, 3], 0)
[1, 0, 2, 0, 3]

Enum.intersperse([1], 0)
[1]

Enum.intersperse([], 0)
[]
```

これは簡単そうです。第一引数のリストに対して、この場合一個ごとにゼロを挿入して、第一引数がひとつか何もない場合はそのまま返しているようです。


#雑感
正直この作業は自助努力というかそういう同期で始めたものではないのですが、まだEnumだけで半分以上ある...
もちろんわからないものを図示するのも含めてあとで貴重な教材になるのでしょうが、わからないものをわからないとネットに書くのもなかなかに抵抗があったりします(苦笑

めげずにやるしかないです。
うまずたゆまず、頑張ります。
Kento Mizuno
Springでbeanプロパティがリスト形式のリクエストパラメータをバインドする方法


#リスト形式のリクエストパラメータをバインドする方法
以下のコードでbeanプロパティがリスト形式の場合のリクエストパラメータをバインドできます。

```html

<body>
	<form action="/sample/bean" method="post">
		<table>
			<tr>
				<td>入力1:price:</td>
				<td><input type="text" name="sampleBean.childBean[0].price"></td>
				<td>入力1:unit:</td>
				<td><input type="text" name="sampleBean.childBean[0].unit"></td>
			</tr>
			<tr>
				<td>入力2:price:</td>
				<td><input type="text" name="sampleBean.childBean[1].price"></td>
				<td>入力2:unit:</td>
				<td><input type="text" name="sampleBean.childBean[1].unit"></td>
			</tr>
		</table>
	</form>
</body>
```


```java
@Controller
public class SampleController {

	@RequestMapping(value="/sample/bean", method=RequestMethod.POST)
	public String goUserCreateErrorPage(SampleBean sampleBean) {
		return "sample";
	}
}
```

```java
public class SampleBean {
  private String childBeanUnit;
  private List<SampleChildBean> childBean;
}
※getter,setterは略

```

```java
public class SampleChildBean {
	private String price;
	private String unit;
}
※getter,setterは略
```

#ポイント
今回の場合はinputのname属性の定義の仕方にポイントがあります。
一つずつ解説していくと、
解説１：Controller側の@RequestMappingメソッドの引数で指定しているバインド対象の引数名
解説２：バインド対象引数のクラスで定義されているプロパティ名を指定 
　　　　更にリストなので、index番号も指定する。
解説３：最後に解説２で指定しているプロパティのクラスが持つプロパティを指定する(ややこしい？)

```html
<input type="text" name="sampleBean.childBean[0].price">
                            解説１      解説２     解説３
```


#終わりに
一旦、忘れないうちに書いてみたのは良いものの、説明がいまいちなので、
時間あるときにもう少しましな説明を考えよう、、笑
ド初心者が初めてのWebサービスを作ってみた

# 概要
普段は組み込み系ソフト開発の仕事をしているのですが、簡単なのでもいいからWebサービスをサクッと作れると
出来ること広がるかなぁと思って挑戦してみました。その過程で思ったこと、遠回りしたことの備忘録です。

# 作ったものと動機
[Latitude and Longitude Unit Converter](http://www.shin-o.net/lat_long_converter)
**2019/4/30　記事修正: Bootstrap4を使って大幅にUI変更、URLも変更**

緯度・経度を種々の単位で相互変換するサイトです。Webサービスというか、ただの便利計算サイトです。

こういう単位変換サイトは既に沢山あるのですが、よく使われる単位を網羅し、かつGoogle Mapで場所を表示できるサイトは意外となかったので作成してみました。（つまり半分自分の本業用です）

なお、入力値の範囲チェックなどが未だちゃんとしてません。今後修正予定です。

# やってみようと思った時点でのスキル状態
- 本業でPython/Linuxはある程度慣れている
- Javascriptは1行も書いたことがない、変数宣言のやり方も知らない
- WebアプリケーションフレームワークとWebサーバの違いが分かっていない
- サーバ管理も経験がない
- HTML/CSSは見たことは流石にあるが自分で書いたことはない

# 困ったこと
とにかく全体像を体系立てて把握できていないことが辛かったです。
QiitaにWeb関連の記事は多いですが、キーワードだけでもNode.js, Javascript, Django, Ruby on Rails, HTML, CSS, Bootstrap, Typescript, Apache, nginx, Laravel, jQuery, Vue.js, React, Gunicorn etc. etc.といろんな情報が溢れていて何がなんだか、という感じでした。

- AngularとかVue.jsとか沢山Qiita記事あるけどWebサイト作るのに必須なの？
- Vue.jsとRuby on Railsは何が違うの？

みたいな感じで見当違いな困惑を持っていました。

# 最初に始めたこと
最初は[Django GirlsのTutorial](https://tutorial.djangogirls.org/en/)から始めました。
明確な意図があったわけではないですが、Pythonは本業で使っていたのでとりあえずPythonの「Webっぽいもの」をやってみようと思った訳です。「左手を伸ばしたら壁があったのでとりあえず壁伝いに歩いてみた」という感じです。

Django GirlsのTutorialはかなり親切で、["How the Internet works"](https://tutorial.djangogirls.org/en/how_the_internet_works)レベルからだったので色々勉強にはなりました。
また、templateを使って実際にHTMLを書いて表示してみて、手触りは得られた気がします。

今になって思えば、今回作ったものはDjangoなんて必要ありませんでした。(DjangoでModelを定義するとそれがDB設計に繋がるようですが、今回のサイトはDBなんて使っていない)
しかしながら、このおかげで世の中の多数のWebサービスが本質的にはDBの更新またはDBの内容表示に過ぎないことを理解できました。
（アタリマエのことをと言われそうですうが、その程度も私にとっては発見でした）

# 作るネタを考える
この時点ではまだ緯度経度の変換サイトを作るつもりはありませんでした。もっと素晴らしい物を作る気でいました笑。しかし調べれば調べる程、一発目は学習コストを最小限にしないとキリがないという気分になってきました。
そこで「本業であったら便利だな」と思っている緯度経度変換に特化して作ろう、と決めました。

# Javascriptで緯度経度変換の実装
緯度経度の変換の実装をJavascriptでやるべきなのか、Django側でPythonでやるべきなのかがわかっていませんでした。
この時「いちいち変換ボタンを押さずに動的に変換したい」と思っていて、どうもそれをやるにはJavascriptで実装しないといけないらしいと分かりました。

Typescriptで書くとJavacriptよりも慣れた形で書けそうだ、ということは分かっていたのですが、
Javascriptを一度も書いたことがない状態ならまずはJavascriptの基本は知っておくべきだろうと思って
素のJavascriptで書くことにしました。その過程でJSテストフレームワークの[Jest](https://jestjs.io)も使ってみました。

# Google Map APIで地図を表示する
Googleの公式説明が充実しているのでそんなに手こずりませんでした。
しかしながら、手違いで無料枠を超えたら怖いのでAPIの各種restrictionsやquota(回数制限)の設定は緊張しました。

# VPSを借りる
Djangoで作ったアプリをlocalhostで動かすことは慣れてきたものの、
ではこれを一般に公開するにはどうしたら良いのか、と調べてみて
どうやらVPS(Virtual Private Server)を借りてそこでnginxを動かせばればよいと理解しました。
(今思うと、先にそっちをやって"Hello worldでいいから先に公開して全体像を掴んでおくべきだった"と思います)

無難にさくらインターネット様かConoHa様かで迷いましたが、[美雲このは](https://conoha.mikumo.com)ちゃん可愛いなーと思ってConoHa様で月額900円のプランをお借りしました。OSは本業で使い慣れているUbuntuにしました。

# nginxとuWSGIでハマる
VPS上でDjangoで作ったWebアプリとnginxを接続するためにuWSGIというものを使う必要があると理解し、
多少苦戦しました。設定ファイル登場し過ぎだよ。エラーメッセージを沢山読んで乗り切った。

# 振り返り、感想
- Djangoを勉強してからVPSを借りてnginxを入れて公開という順序だったが逆だった。先にVPSを借りてHello worldだけでいいから公開すべきだった。
- DjangoじゃなくてFlaskでも十分だった。というかWebアプリケーションフレームワーク使う必要なかった。勉強する過程で気づきもあったので完全に無駄とまでは言えないが。
- やることが広く浅くなので、横着せずにやったことや打ったコマンドはMarkdownでまとめておく。時間が空くと忘れる。
- Javascriptが標準ではCやPythonでいう`#include`, `import`の類を使えないことに焦った。`var`変数のスコープにも衝撃を受けた。
- すいてて長時間滞在を許してくれる喫茶店の確保は重要。コーヒーだけじゃなく食事も注文すること。コーヒーは3時間に1回はおかわり注文すること。
FC2ブログの爆速テンプレートを解析してみた

## 2019年2月 爆速テンプレートが公開された

先日、FC2ブログにおいて「爆速テンプレート」というものがリリースされました。

これはその名の通りタフなニューメキシコの荒野でもブログが爆速で見れるテンプレートで、爆速である代わりにカスタマイズの自由度は通常のテンプレートよりもかなり低い、というもの。

その爆速具合を実際に体感できるようにサンプル用の爆速テンプレートブログが公開されていますので、具体的にどういうものか知りたい方は下記のリンク先で体感してください。

[爆速テンプレート サンプルブログ](https://speedsample.blog.fc2.com/?pr)

この記事はその爆速さに興味をもってその中身を解析してみた結果をここにまとめておいたものです。

ただし飽くまで外部の人間が簡単に解析してみた結果であるため間違いや事実誤認が予想されます、気が付いた方はコメントにてご指摘ください。

なお ServiceWorker や CacheAPI に関する説明はここではするつもりはありませんが、仮にそれらに関する知識がなくても理解できるように書いたつもりです。

それらについての詳細を知りたい場合は下記のリンク先を参照してください。

[Service workeの使用例|MDN](https://developer.mozilla.org/ja/docs/Web/API/ServiceWorker_API/Using_Service_Workers)
[Cache -Web API|MDN](https://developer.mozilla.org/ja/docs/Web/API/Cache)

## 爆速である要因

### リクエストが少ない

最も影響が大きいのがサービスの設計自体が最適化されていることで、具体的には必要な外部ファイルがそもそも少ない。

通常のブログサービスと比較しても1/3から1/5程度のファイル量しか読み込む必要がなく、比較対象をよくあるゴテゴテしたまとめブログにした場合は1/10以下である。

### Instant Click

ページを解析してみたところ「Instant Click」というJSライブラリを利用している、これは [dev.to](https://dev.to/) などのように、「リンクをマウスオーバーした時点でリンク先を裏で読み込んで、BODYの中身を差し替える」というページ先読み＋pjaxを簡単に実現してくれるライブラリです。

これはリンクをクリックする際に、マウスオーバーしてから実際にクリックが確定されるまで200～300ms程度の時間がかかることを利用してページを先読みするもので、想像以上に体感速度が早く感じられるようになります。

ちなみに記事をスクロールした時の追加読み込みもこの Instant Click で実装しているようです。

[InstantClick](http://instantclick.io/)

### データの先読み

ServiceWorker の install 時に9記事分のページのデータが先読みされています。

つまりWEBページにアクセスした時にページの読み込みをしている「裏」で、ServiceWorker が9記事分のデータを取得してキャッシュに追加しているということです。

#### DNSプリフェッチ

これはページ読み込み時に外部ファイルにアクセスするより先にDNSの名前解決をしてしまうもので、100～200ms程度の時間がこれにより短縮できるとされています。

[DNSプリフェッチの制御|MDN](https://developer.mozilla.org/ja/docs/Controlling_DNS_prefetching)

## キャッシュ更新について（推測）

ここで気になるのが「キャッシュ更新のロジック」でブログというサービスの都合上、記事内容が更新されたり削除されたりすることは頻繁にありえる。

その場合キャッシュを保持していると、いつまでも更新前の記事を表示することになってしまうので、なんらかのタイミングでキャッシュを更新する必要があるはず。

ServiceWorker はおそらく動的に生成されており、それにより先読みするページの変更とキャッシュの更新を行っているようだが、具体的にどういうタイミングで更新をかけているのかは不明。

ServiceWorker が install されたタイミングで両者の更新を行っているようなので、記事が追加/更新されたタイミングで ServiceWorker が変更されて install -> キャッシュ更新というロジックで更新されるように推測される。

上記が正しければ、要するに ServiceWorker の更新とキャッシュの更新は一体化しており、キャッシュのみを更新するロジックはないということなる。

## まとめ

爆速の主要因は「リクエスト数の少なさ」と「InstantClick」であるように見受けられる。

ちなみにキャッシュは先読みで最初の9記事だけをもっており、それ以外の記事についてはキャッシュを利用せずに純粋に InstantClick でのみ体感速度を向上させているようで、個人的には後続の記事をキャッシュしていないのは意外だった。

またこの記事ではフロント側に寄った説明をしているが、当然バックエンド側やサービスの設計も最適化されてるので、そもそもこのブログなら”素”でも速い。

実際にカテゴリ一覧や月別記事一覧から記事を閲覧するとキャッシュにない記事のはずだが、それでも十分高速さが体感できるので、フロント側の実装が通常のブログのものと同様であったとしても充分に高速であったはずだと思われる。
xerrors パッケージ - 独自に定義したエラー型はIsメソッドとAsメソッドでデフォルトの振る舞いを変更可能

xerrors パッケージは、 独自に定義したエラー型はIsメソッドとAsメソッドでデフォルトの振る舞いを変更可能です。

## Isメソッドの振る舞いを変えた例


```go
var ErrUserNotFound1 = &ApplicationError{
	code:  101,
	level: "Error",
	msg:   "not found",
}

var ErrUserNotFound2 = &ApplicationError{
	code:  101,
	level: "Fatal",
	msg:   "not found!!!!!!",
}

type ApplicationError struct {
	level string
	code  int
	msg   string
}

func (e *ApplicationError) Is(err error) bool {
	var appErr *ApplicationError
	return xerrors.As(err, &appErr) && e.code == appErr.code
}

func (e *ApplicationError) Error() string {
	return fmt.Sprintf("%s: code=%d, msg=%s", e.level, e.code, e.msg)
}

func main() {
	fmt.Printf("%v\n", xerrors.Is(ErrUserNotFound1, ErrUserNotFound2))
}
```


この例ではErrUserNotFound1とErrUserNotFound2のcodeは同じ `101` でlevelとmsgは異なるものを `xerrors.Is` メソッドで比較しています。構造体の比較という意味では `false` になるはずですが、結果は `true` になります。 これは `func (e *ApplicationError) Is(err error) bool` を定義し、codeだけで判定しているためです。

## Asメソッド

Asメソッドも型に合わせて振る舞いを変えられますが、ユースケースが想像できませんでした。

```go
func (e *ApplicationError) As(target interface{}) bool {
	// ??
}
```

## 関連情報
- [xerrors - 関連情報](https://qiita.com/sonatard/items/802db82e7275f17fe702)
contenteditable でキャレットを先頭と末尾に移動させる

contenteditable でキャレットを先頭と最後に移動させる方法

### キャレットを先頭に移動

```javascript
const target = document.getElementById('example')
const node = target.childNodes[0]
const editorRange = document.createRange()
const editorSel = window.getSelection()
editorRange.setStart(node, 0)
editorRange.collapse(true)
editorSel.removeAllRanges()
editorSel.addRange(editorRange)
```

### キャレットを末尾に移動

```javascript
const target = document.getElementById('example')
const p = target.childNodes[target.childNodes.length - 1]
const node = p.childNodes[p.childNodes.length - 1]
const editorRange = document.createRange()
const editorSel = window.getSelection()
editorRange.setStart(node, node.childNodes.length ? node.childNodes.length : node.length)
editorRange.collapse(true)
editorSel.removeAllRanges()
editorSel.addRange(editorRange)
```
Railsを本番環境で作動させる

## Railsを本番環境で稼働するのに必要なコマンド
作ったプログラムを本番環境で落としてきたときにそのままでは動かなかったので必要だった作業を(覚えている範囲で)まとめておこうと思います。

## Assetファイルのプリコンパイル
静的ファイルについては、サーバを起動する際にhtml,cssなどの必要なファイルを一つにまとめるようになっています。そのため、ある場所のファイルは自動的にコンパイルされます。具体的には、`public/assets`中にあるファイル群については自動的にコンパイルされ、そのコピーが静的なassetとしてwebサーバに保存されます。しかし、いくつかの場所にあるファイルはproduction環境においては自動的にはコンパイルされないので、手動でCSSファイルなどをコンパイルしておく必要があリます。これをプリコンパイルと呼び、次のコマンドで実行することができます。
`bundle exec rake assets:precompile RAILS_ENV=production`
プリコンパイルの際に実際にコンパイルする対象のファイルは、設定ファイルをいじることで指定することができます。


## Secret Keyの設定
重要なファイルなどを暗号化する際に用いるSecret Keyというのがあって、これは手元のPCで作業している際に自動的に生成され、それを元に暗号化・復号化を行なっているようです 
このファイルは他の人に知られてはいけない情報のためGitの管理対象から外れており、従ってGit経由でサーバーに落としてきたときにはこの自動生成されたファイルをコピーすることができず、サーバを起動しようとすると自動的に新たな（間違った)Keyが生成されるため、復号化がうまくいかずエラーが発生します。 ので、手元の環境でSecret Keyをコピーして本番環境にうつしてやる必要があります。どのデータを移行する必要があるかは、エラーメッセージを読めばある程度わかるようになっている（はずです）。
具体的にSecret_key_baseが用いられる対象として、次のものがあげられます。
1. 暗号化cookie
2. 署名済みcookie
3. アプリのmessage_verifier


---
参考にしたWebサイト
[Rails Guid](https://guides.rubyonrails.org/asset_pipeline.html)
[Tech Racho](https://techracho.bpsinc.jp/hachi8833/2017_10_24/46809)
Python の制御フローを少し試してみる

#目的
チュートリアルの条件文とかループを中心に試してみる
※自分用の確認メモ
※switch case の代替実装に関しては TODO
##サンプルコード
```python
# Windows Add env PYTHONIOENCODING = UTF-8 & restart vscode
# if 条件式:
#     if 条件式:
#         処理
#     else:
#         処理
# elif 条件式:
#     処理
# else:
#     処理

month = 4
if (month == 12) or (month == 1) or (month == 2):
    print("冬")
elif 3 <= month <= 5:
    print("春")
elif 6 <= month <= 8:
    print("夏")
else:
    print("秋")
# 春

# リストの要素であるか
print(month in [12, 1, 2])  # False
print(month in [3, 4, 5])   # True

# rangeオブジェクトに含まれるか
# 3 <= month < 6
print(month in range(3, 6)) # True

# タプルの要素であるか
print(month in (3, 4, 5))   # True

# セットの要素であるか
print(month in {3, 4, 5})   # True

# ３項演算子
print("春" if month in [3, 4, 5] else "その他")
# 春
```
##for loop
```python
for n in range(6):
    if n == 2:
        print(n)
        print('continue')
        continue
    elif n == 3:
        print(n)
        print('break')
        break
    else:
        pass # なにも実行しない(サンプルのための例)
        #print(n)
else: # break で loop out すると処理対象外となる
    print('break なしで for loop 終了時のみ出力')
# 2
# continue
# 3
# break
```
##while 文
```python
edval = 4
count = 0
sum = 0
while count <= edval:
    sum = sum + 1
    count = count + 1
else:
    print('while loop 終了')
print('合計 = ', sum)
# while loop 終了
# 合計 =  5
```
##ループごとにインデックスと要素を取得
```python
# enumerate関数
seasons = ["春", "夏", "秋", "冬"]
for index, season in enumerate(seasons):
    print(str(index + 1) + ':' + season)
# 1:春 2:夏 3:秋 4:冬

#set はエラーになる
for num in range(len(seasons)):
    print(str(num + 1) + ':' + seasons[num])
# 1:春 2:夏 3:秋 4:冬
```
#zip関数：複数のリストから要素を順に取り出す
```python
weekday1 = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
weekday2 = ["日", "月", "火", "水", "木", "金", "土"]
for (en, jp) in zip(weekday1, weekday2):
    print(en + ':' + jp)
# Sun:日 Mon:月 Tue:火 Wed:水
# Thu:木 Fri:金 Sat:土

weekday1 = ["Sun", "Mon", "Tue"]
weekday2 = ["日", "月", "火", "水", "木", "金", "土"]
for (en, jp) in zip(weekday1, weekday2):
    print(en + ':' + jp)
# Sun:日 Mon:月 Tue:火
```
##参考にしたのは以下のサイト
[4. その他の制御フローツール](https://docs.python.org/ja/3/tutorial/controlflow.html)
[5.6. ループのテクニック](https://docs.python.org/ja/3/tutorial/datastructures.html#tut-loopidioms)
[Python に switch や case 文がないのはなぜですか？](https://docs.python.org/ja/3/faq/design.html?highlight=switch#why-isn-t-there-a-switch-or-case-statement-in-python)
##参考書
[基礎 Python](https://book.impress.co.jp/books/1115101060)
JavaScript で対象 node すべてを選択する2つの方法

対象の node をすべて選択するには以下の２つのやり方がある。

```html
<div id="example">
  <p>hoge</p>
  <p>hoge</p>
</div>
```

```javascript
const target = document.getElementById('example')
const range = document.createRange()
const sel = window.getSelection()
range.selectNodeContents(target)
sel.removeAllRanges()
sel.addRange(range)
```

```javascript
const target = document.getElementById('example')
const range = document.createRange()
const sel = window.getSelection()
range.setStart(target.childNodes[0], 0)
const endNode = target.childNodes[target.childNodes.length - 1]
range.setEnd(endNode, endNode.childNodes.length)
sel.removeAllRanges()
sel.addRange(range)
```

それぞれ同じように対象の node をすべて選択できるが、range オブジェクトが微妙に異なる。前者の `selectNodeContents` で対象 node を入れた場合は `startContainer` / `endContainer` / `commonAncestorContainer` が自身の node になる。つまり対象 node 自身を含んで選択していることになる。

後者の `setStart` と `setEnd` で指定している場合は、`commonAncestorContainer` は自身の node だが、`startContainer` / `endContainer` はそれぞれ `setStart` と `setEnd` で指定した node になる。これはユーザが手動で文字列を選択したときと同じような range オブジェクトになる。

どちらが良いというよりかは、それぞれ場合によって使い分ける。
チーム開発に混ぜてもらいたい人のための【Git入門】その１

![branching-illustration@2x.png](https://qiita-image-store.s3.amazonaws.com/0/343290/a974d2c5-8932-b949-1961-c33581bbe7fe.png)

#はじめに
技術研修の基礎編を終えて、やっとサービスの一部に携われるようになりました。そこで、__「今まで独学でプログラムの勉強をしてきたけど、まだチーム開発をしたことがない…」__という方々に向けて、チーム開発をする上では欠かせない__【Gitとは何ぞや】__ということを、私なりにまとめさせて頂きます。

[公式サイトはこちら](https://git-scm.com/)

#Gitとは

>Git（ギット）は、プログラムのソースコードなどの変更履歴を記録・追跡するための分散型バージョン管理システムである。

[Wikipediaより](https://ja.wikipedia.org/wiki/Git)

チームで開発をする際に、どこの誰がどのような意図を持ってコードを変更したのかということがすごく大切です。__【Git】__を使うことで簡単にそれらの記録が行えます。


#Gitの用語

###リポジトリ
__Git__は時系列でファイルの記録を整理できます。その管理するデータベースのことをリポジトリと言います。__写真のアルバム__みたいなものですかね！
![database-tuning.png](https://qiita-image-store.s3.amazonaws.com/0/343290/806ad29b-5717-ec15-c073-1f5a539a44de.png)
[画像：Section-9より](https://www.sec9.co.jp/services/database-tuning/)


###コミットとコミットメッセージ
リポジトリにファイルの変更内容を記録すること、その結果作られた記録のことをコミットといいます！アルバム（リポジトリ）の中にある__写真__みたいなものですね！

また、インスタなどで使われる__ハッシュタグ__のように__コミットメッセージ__をつけることで、どのような修正を行ったか詳細に記録に残すことができます。
![Multiple-photographs-of-vacation-scenes-456859205_1255x837.jpeg](https://qiita-image-store.s3.amazonaws.com/0/343290/185073f7-9442-78d4-ca5c-7198164c96b4.jpeg)
[画像：Instagram（インスタグラム）にパソコンから写真を投稿する方法より](https://smatu.net/2018/01/02/instagram-post-photo-mac-windows-pc-google-chrome/
)




###ワークツリー
Gitによって__コードやファイルの変更を監視されているフォルダ__のこと。

ワーキングディレクトリー、ワーキングコピー、作業コピーとも呼びます。

###ステージング
コミットにはコミットメッセージにそぐわない無関係の変更を含むべきではありません。しかし作業によってはワーキングツリーに大量の変更が積まれる場合があります。その時に__コミットに含めたい変更を選別すること__をいいます。

たくさん写真を撮ったけど、__どれをインスタに投稿しようかな〜__ってのと同じ感じですね！

###ブランチとマージ
__ブランチ__とは履歴の流れを分岐して記録していくためのものです。分離したブランチは他のブランチの影響を受けないため、同じリポジトリの中で複数の変更を同時に進めていくことができます！
![capture_stepup1_1_1.png](https://qiita-image-store.s3.amazonaws.com/0/343290/5accdc35-facd-227c-28b0-54b004a80d33.png)
[画像：猿でもわかるGit入門より](https://backlog.com/ja/git-tutorial/stepup/stepup1_1.html)

逆に__マージ__とは枝分かれした変更履歴を一つにまとめることをいいます！
![Merger-II_mvvsdu.png](https://qiita-image-store.s3.amazonaws.com/0/343290/0673288f-454d-e220-3723-d60417c52573.png)
[画像：MARTECHTODAYより](https://martechtoday.com/lithium-and-spredfast-merge-into-a-social-management-customer-care-platform-223687)


###コンフリクト
- 同じ箇所を
- 別々のブランチで
- 別々の変更をかけてしまったのに
- マージする

と起こってしまう「衝突」現象です。どっちの変更を受け入れればいいの？ってことですね！
こうなるとブランチのマージは一旦保留になり、ユーザが手動でコンフリクトを解消する必要があります。

#次回予告
__【Gitとは何ぞや】__ということを簡単にですがご説明させて頂きました。次回は具体的なGitコマンドをまとめさせて頂きたいと思います。

＊説明に不備やおかしな点がございましたらご指摘いただけると幸いです。

#リファレンス
[本当の初心者向け！Git入門のための概念から基本用語まで](https://liginc.co.jp/246190)
[git add ってなんのためにやるの？ Gitの「ステージング」をイラストで解説します！](http://kray.jp/blog/expound-git-add/)
[サルでもわかるGit入門〜バージョン管理を使いこなそう〜](https://backlog.com/ja/git-tutorial/)
[コンフリクトって！？Gitバージョン管理でマージしたときに発生した衝突を解決する](https://tonari-it.com/git-sourcetree-conflict/)
Webアプリでのtry with resources文

##経緯

javaのtry with resources文を書こうとして
sqlserverを使うのでmssql-jdbc-7.0.0.jre8.jarをインポートした。

この時以下のコードがエラーに

```java:dbConnect.java
try(Connection connection = DriverManager.getConnection(url)) {
}
```
と書くと「No suitable driver found for jdbc:sqlserver://〜」とエラーが出ました。

エラーを調べたところ、Class.forNameでドライバを指定するようにと出たので、
以下のコードに修正。

```java:dbConnect.java
try{
//JDBCドライバを指定(JDBC3.0以下）
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
Connection connection = DriverManager.getConnection(url); 
}
```
修正してエラーを無くしたのですが、これではtry with resources文が使用できていないので、どうにか最初のコードで動かす方法を探した。

#解決策

原因はtomcatのクラスパスにjdbcが指定されていない為、Class.forNameなしではjdbcまでのパスがわからないことが原因だった。

eclipseを使用していたので、「tomcat>実行の構成>クラスパス>外部JARの選択」を選択し、libの下にインポートしたjdbcのjarにパスを通すことで正常終了した。

#その後
Azureが好きなので、AppService上にデプロイしたが、tomcatのクラスパスに追加する方法がわからないので、分かったら追記する
「共変性」「反変性」が絶望的にわかりづらいので○○○○性と命名し直してみた

先週、[解説記事](https://qiita.com/CodeOne/items/730480791c2e98b40d66)で書いた内容をもとに、わかりやすく命名し直しました。

- 共変性 → 出力互換性
- 反変性 → 入力互換性

この方がダイレクトに伝わって、解釈する脳の負担が軽くなるはずです。
試しに上記記事「4. 最も短い説明」以降、あるいはほかの共変性に関する解説記事を、この名称に置き換えて読み直してみてください。

今後の展望。

1. 「共変性（出力互換性）」と併記するようにする。
2. 馴染んできたらしれっと入れ替えて「出力互換性（共変性）」に。
3. 括弧がとれて「出力互換性」だけでも通じるよう、独り立ち。

5年くらかけてこれが実現すればいいのにな――というのはもちろん、出力権威性のない、いちプログラマのただの夢想です。原語もありますしね。

わかりづらい名前は人の時間を奪ってしまう。
一度流通した名前を変えるのは難しい。
命名って大事だなとあらためて実感、自戒。

別案があればぜひコメントで。
Unityちゃんが落下する際の設定ミス

#事象
Unityちゃんを動かしてみようとしたところ、開始直後にすり抜けて落下していった

#事象発生までの設定作業
①AssetStoreからUnityちゃんをダウンロード
②Prefabs内からUnityちゃんをドラッグ＆ドロップ
③ControllerをThirdPersonAnimatorControllerに変更
④IdleChangeとFaceUpdateをデタッチ
⑤ThirdPersonUserControlをAddComponent
⑥位置を調整

#原因
コライダーがUnityちゃんの位置より上に位置していたため、当たり判定が上に位置していた

#解決
コライダーのCenterを調整して、Unityちゃんがすり抜けをしないようにした
angularでのバリデーション実装方法

#はじめに
Angularを使用していて、バリデーションをするときに手こずったので、自分用と同じ問題で困っている人のために実装方法を記録しておきたいと思います。
#実装例
```html
<form #loginForm="ngForm" novalidate>
  <label for="mail-address">メールアドレス</label>
  <input id="mail-address" type="email" name="mail"
    [(ngModel)]="login.mail" #mail="ngModel" required email/>
  <div *ngIf="mail.errors && (mail.dirty || mail.touched)"
    class="alert alert-danger">
    <div [hidden]="!mail.errors.required">
      入力してください
    </div>
  </div>
</form>
```

```TypeScript
import { Component, OnInit } from '@angular/core';

@Component({
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.scss'],
})
export class LoginComponent implements OnInit {
  login = {
    mail: '',
    password: ''
  };
  constructor() {}

  ngOnInit() {
  }
}
```

#注意点
以下処理を入れないと、ページ表示時にもバリデーションが働いてしまうので注意する必要がある。
```html
*ngIf="mail.errors && (mail.dirty || mail.touched)"
```


#参考
https://qiita.com/mixplace/items/047f6edfe99d28af1dab
FlutterでFirebaseのメール認証を行う

2019/2/18 の時点では、公式のFlutterFireでは以下の機能がまだ実装されていません。

- `sendSignInLink`
- `signInWithEmailAndLink`
- React Native Firebaseにあるような、「アプリ起動時にDeep linkを受け取る」ような関数(ここでは`onLink`関数)


対象方法自体は簡単です。Native側で対応し、Platform channelで繋げてあげればいいだけです。
とはいえ、わりかしiOS / AndroidのNative開発の知識を必要としますので、以下のコードを参考にしてみて下さい。

[僕がCTOをやってる開発のアプリのコード](https://github.com/Keio-Penmark/penmark-app)

需要があれば、ちゃんと解説しますね。
PHP未経験者が勉強用にDockerで開発環境作ってみた

# やりたいこと

できるだけ自分のPCを汚さずにいわゆるLAMP環境
(Linux, Apache, MySQL, PHP)の開発環境を手軽に構築したい。

Macの場合はMAMPやVirtualBoxがあるけど汚れちゃうし・・・

そうだ、Dockerの勉強も兼ねてDockerを使おう！！！

# 成果物

Dockerを使用してApache, PHP, MySQL, phpMyAdminを連携し、
PHPとMySQLの勉強に注力するための開発環境を作成しました。

https://github.com/MasanoriIwakura/php_study

# 開発環境

|ツール名|バージョン|
|:--|:--|
|OS|macOS Mojava 10.14.3|
|Docker|Docker for Mac 18.06.1-ce|
|Docker Compose|1.22.0|
|PHP|7.2.7-apache (Apacheと連携されているコンテナ)|
|MySQL|8|
|phpMyAdmin|4.7|

## プロジェクト構成
### [PHP]
Dockerコンテナの80番ポートと、ホストOSの80番ポートを紐付け。  
MySQLとの接続には`mysqli`を使用。
Docker ComposeだけではPHPの拡張機能をインストール出来ないため、Dockerfileで対応。

### [MySQL]
Version8からデフォルトの認証方式が`caching_sha2_password`となっているため、
`mysql_native_password`に変更する。  
この設定を行わないとMySQLに接続出来ない。

## 使用手順

### [前提条件]
* Dockerがインストールされていること、起動されていること
* Docker Composeがインストールされていること

Dockerを導入していない場合、Macの場合は以下のコマンドで導入してください。

```bash
# Homebrewがインストールされていること
$ brew install docker
$ brew cask install docker
$ brew install docker-compose
```
```bash
# Clone
$ git clone https://github.com/MasanoriIwakura/php_study.git

# フォルダ移動
$ cd php_study

# コンテナ実行
$ docker-compose up -d

# 全てのコンテナが立ち上がっていることを確認
$ docker-compose ps
         Name                       Command               State               Ports
------------------------------------------------------------------------------------------------
php_study_mysql_1        docker-entrypoint.sh mysqld      Up      3306/tcp, 33060/tcp
php_study_php_1          docker-php-entrypoint apac ...   Up      0.0.0.0:80->80/tcp
php_study_phpmyadmin_1   /run.sh phpmyadmin               Up      0.0.0.0:8080->80/tcp, 9000/tcp
```

### [接続確認]

PHPの表示確認は
http://localhost
にアクセス
<img width="629" alt="スクリーンショット 2019-02-17 23.46.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/199056/2913f9ed-6531-384d-3ec7-af36a694e864.png">

phpMyAdminの表示は
http://localhost:8080
にアクセス

<img width="1440" alt="スクリーンショット 2019-02-17 23.45.01.png" src="https://qiita-image-store.s3.amazonaws.com/0/199056/fdec6c0d-446c-e12f-d7c8-42a792dba399.png">

### [ソース編集方法]
`php/html`直下にフォルダやphpファイルを作成・編集するだけ。

例えば、`php/html/index.php`を編集した場合は`http://localhost`にアクセス、
`php/html/sample/sample.php`を編集した場合は`http://localhost/sample/sample.php`にアクセスすることで動作確認が行えます。

また、ソースを修正して保存し、ブラウザをリロードするだけで反映できるので
Dockerでイメージのリビルドや再展開は不要です。

## その他

### [MySQLの初期化]
起動時に`mysql/sql`内に実行したSQLを配置することで自動的にMySQL内にテーブルを作成したり、初期データを投入することができます。

### [今回作成したDockerコンテナの再構築]
実は今回のリポジトリ直下にShellを配置しています。
実行することで永続化したファイルの削除、コンテナ削除、コンテナ再構築をいっぺんに行います。
永続化したファイルを削除したくない場合は手動でコンテナを削除してください。

```bash
#　リポジトリ直下で使用
./docker-clean.sh

# 永続化したファイルを削除したくない場合(コンテナだけ削除)
docker-compose stop
docker-compose rm
```

今後もっと便利にすることができればこちらの記事も更新します。
プログラムが突然落ちる（swap未設定）

最小構成で使っていると、SWAP領域が設定されていないため、起動したプログラムが、カーネルによって強制的に落とされる。

# SWAPを設定する

```:領域確保
sudo dd if=/dev/zero of=/swapfile bs=1M count=1024
```

```:スワップ作成
sudo mkswap /swapfile
```

```:スワップ有効化
sudo swapon /swapfile
```

```:起動時に自動有効
echo -e "/swapfile　swap　swap　defaults　0　0" | sudo tee -a /etc/fstab
```
Gitでresetコマンドでブランチへの記録をなかったことにして、新しいブランチを作った。

#環境
・Git version 2.20.1.windows.1

#今日の目標
コミットを変更する操作を実践する。

#ひとつ前のコミットに戻る。

前回の記事ではSampleBの内容をmasterにマージした。
今回は、SampleBのブランチを作成する前に戻って、新しくSampleCを作成する
操作を試してみる。

コマンドはresetコマンドを使う。
戻りたい状態のハッシュ値を引数で渡す。

まずはSampleBを作成する前のハッシュ値を調べる。


```
$ git log --graph
*   commit 1ea19865678c353a23dac5168f097d82e760fac1 (HEAD -> master)
|\  Merge: 8381fa5 f41dde9
| | Author: 僕の名前 <僕のメルアド>
| | Date:   Sun Feb 17 17:12:26 2019 +0900
| |
| |     Merge branch 'SampleB'
| |
| * commit f41dde96d8ac51edac62f2faaae97914f60eff26 (SampleB)
| | Author: 僕の名前 <僕のメルアド>
| | Date:   Sun Feb 17 00:11:49 2019 +0900
| |
| |     add SampleB
| |
* | commit 8381fa57775415a1b8b39e841e987de678f8bf88
|/  Author: 僕の名前 <僕のメルアド>
|   Date:   Sun Feb 17 17:11:24 2019 +0900
|
|       swp commit
|
* commit 1e18d76875063f058644bbc2083447bc95aae385 (SampleA)
| Author: 僕の名前 <僕のメルアド>
| Date:   Thu Feb 14 21:41:36 2019 +0900
|
|     テストコミット
|
|     テストしたかったから。
|
* commit 1da12c37794122b58c6c099067c27249c38c24c1
  Author: 僕の名前 <僕のメルアド>
  Date:   Thu Feb 14 21:28:47 2019 +0900

      First commit

```

ハッシュ値が分かったので、引数に指定して実行してみる。

```
$ git reset --hard 8381fa57775415a1b8b39e841e987de678f8bf88
HEAD is now at 8381fa5 swp commit

```

logを確認してみる。

```
$ git log --graph
* commit 8381fa57775415a1b8b39e841e987de678f8bf88 (HEAD -> master)
| Author: 僕の名前 <僕のメルアド>
| Date:   Sun Feb 17 17:11:24 2019 +0900
|
|     swp commit
|
* commit 1e18d76875063f058644bbc2083447bc95aae385 (SampleA)
| Author: 僕の名前 <僕のメルアド>
| Date:   Thu Feb 14 21:41:36 2019 +0900
|
|     テストコミット
|
|     テストしたかったから。
|
* commit 1da12c37794122b58c6c099067c27249c38c24c1
  Author: 僕の名前 <僕のメルアド>
  Date:   Thu Feb 14 21:28:47 2019 +0900

      First commit


```

指定した状態まで戻すことが出来た。

実はコンクリフトの発生まで実験していたのだが、うまく実験できなかった。
もう少し理解を深めてからコンクリフトの解消を実験できたら追加で投稿しようと思う。
【Gitのバージョンを確認・更新する】

# Gitのバージョンを確認・更新する
※Gitのインストール済みを前提とする。

## :black_small_square:バージョンの確認
```
$ git --version 
```
上記（＄より後ろの部分）をターミナルに入力しEnterキー。



#####結果↓
```
git version 2.20.1
```
（2.20.1が現在のバージョンである）

[※Gitの最新バージョンはこちらで確認。](https://git-scm.com/)
![スクリーンショット 2019-02-17 23.12.41.png](https://qiita-image-store.s3.amazonaws.com/0/304384/2eec6f95-8e17-1106-1f32-2f7bda98b114.png)
↑現在のGit最新バージョンは《2.20.1》。


## :black_small_square:バージョンの更新
[brewのインストールはこちらから。](https://brew.sh/index_ja.html)

```
$ brew update
```
上記（＄より後ろの部分）をターミナルに入力しEnterキー。

```
$ brew install git
```
↑こちらも入力しEnterキー。

最後にもう一度【バージョンの確認】を行ない、
最新バージョンになっていたらOK！
Sphero Mini

# Sphero Mini メモ

Sphero MiniはSphero社のロボットの一つ。値段が約6,000円と手を出しやすく、お手軽に試すことができる。各ロボットの比較は下記を参照するとよい。

[ロボットの比較](https://sphero-edu.jp/teaching/compare/)

個人的には、まずはMiniで遊んでみて、水の中で走らせたい！とかもっとスピードを出したい！と思ったら、BOLTやSPRK+に手を出してみるのがよいと思う。Miniでも十分楽しめるので、迷ったらMiniにしておけばよいと思う。

## Books

日本語の本はあまりない。英語の本はもう少しあるので、英語が苦にならない方はAmazonあたりで探してみるとよい。

#### [Sphero 完全ガイド（小学館）](https://www.shogakukan.co.jp/books/09388611)
Spheroシリーズで何ができるかを知るための最初の一歩として読むのに最適な本。Sphero Miniに特化した内容ではなく、Spheroシリーズ汎用の内容だが、Sphero Miniの入門書として十分な内容。ドローとブロックでのプログラミング方法に関して、分かりやすく説明されている。サンプルプログラムを一通り試してみれば、それなりのプログラムを組めるようになる。
JavaScriptを使ったプログラミングに関しては、さらっと流している。JavaScriptで本格的にプログラミングしたい場合、下記のReference等を参照するとよい。

## JavaScript Reference

基本的にJavaScriptでプログラミングできるので、JavaScriptに関する一般的な書籍やWebを参考にできる。公式のReferenceは下記。

#### [Sphero Edu JavaScript](https://sphero.docsapp.io/docs/get-started)

各ブロックに対応したJavaScriptコードの説明あり。
Railsのcredentials.yml.enc起因で502エラーが起こったら

# はじめに
仕事でrails5.2を使ってWebサイトを作り、AWS環境にデプロイする、というごく普通の環境を使っているわけですが、
ある日、ステージングにデプロイし、アクセスしたとき、急に

**502 Bad Gateway**

の一言だけが画面に書かれていました。
え、何これ！？昨日まで普通にアクセスできてたじゃん！と思い、デプロイしたファイルに何か問題があるのかと思いましたが、
特に内容に問題なし...
あれこれ調べても、なかなか当てはまる事例がなく、万策尽きたか...と思ってましたが、
なんでこれだけで！？という方法で直ったので、もし何かの役に立てばということで記事として残しておきます。

# Railsのcredentials.yml.enc

まずはcredentials.yml.encについて軽く触れておきます。
Webサイト内で扱う機密情報について、今まで使われていたsecret.ymlが、Rails5.2で廃止になりました。
その代わりに、credentials.yml.encというファイルで扱うようになりました。
このファイルの中身を見てみると、暗号化されて何も読み取ることができませんが、

```console
$ EDITOR="vi" bin/rails credentials:edit
```
というコマンドを実行すると、
credentials.yml.encファイルが復号化され、viで中身を見ることができます。

```yaml
aws:
  access_key_id: *****************
  secret_access_key: *****************

secret_key_base: ***************************************************
```

参考：[Rails5.2から追加された credentials.yml.enc のキホン](https://qiita.com/NaokiIshimura/items/2a179f2ab910992c4d39)

# credentials.yml.encのエラーについて

では、実際に何が起こっていて、何をしたら解決したのか、調査の経緯を順に説明します。

## secret_key_baseはどこへいった
ステージング環境にsshで入ることはできたので、
var/log内にあるログを見ていったところ、pumaが動いていないとのこと。
なるほどと思い、起動コマンドを叩いてみたら、

```linux
Missing `secret_key_base` for 'staging' environment, set this string with `rails credentials:edit` (ArgumentError)
```

secret_key_baseがないというエラー。
rails credentials:editを実行しろとのことなので、じゃあやってみるかと実行したところ、

```linux
Missing `secret_key_base` for 'staging' environment, set this string with `rails credentials:edit` (ArgumentError)
```

**同じエラーだと...**

とりあえず、credentials.yml.encに原因があることがわかったので、
ローカルで開いてみました（ローカルではrails credentials:editは実行できる模様。）
ですが、そこにはsecret_key_baseがちゃんと定義されてました...

## secret_key_baseが見えてない

あるはずなのに、Missingと言われてしまう...
試しに、コンソールを使って値を取得してみましょう。

```console
$ rails c

irb(main):001:0> Rails.application.credentials.aws[:access_key_id]
=> *****************(ちゃんと中身が取れてます)

irb(main):002:0> Rails.application.credentials.secret_key_base
=> nil
```

他の項目は取得できているのに、secret_key_baseは取得できてない...
おそらく、secret_key_baseが参照できてないのでしょう。
でもなぜ参照できてないのかが全くわかりませんでした...
keyの問題？それなら他の項目も取れないはず...
環境変数とか？いやそれは関係ない...
いろいろ思考を巡らせましたが、とうとう
「とりあえずcredentials.yml.encをいじってみよう」
という安直な選択に。というより半分ヤケになってました笑

## なんとなくやったら動いた

ということで、まずはsecret_key_baseの項目の前にスペースを入れてみましょう！笑
それで動いたら楽だよなぁ...

```yaml
aws:
  access_key_id: *****************
  secret_access_key: *****************

 secret_key_base: ***************************************************
```
わかりにくいですが、secret_key_baseの前に半角スペースが入ってます。
これで動くわけないだろ、みたいな感じで、コンソールで確認しました。

```console
$ rails c

irb(main):001:0> Rails.application.credentials.aws[:access_key_id]
=> *****************(ちゃんと中身が取れてます)

irb(main):002:0> Rails.application.credentials.secret_key_base
=> ***************************************************(ちゃんと中身が取れてます)
```

**え！？**
**なんでこれで取れてるの？**
わけがわからないまま、とりあえずこれでステージングにデプロイしたところ、
502が解消され、Webサイトが無事開けました！

# 最後に
なんでこれで動いたか、正直全くわかっていません。
ただ学んだことは、
**やってみなきゃわからない**
ということでした。
もし同じような現象が起こった方がいたら、
とりあえずいろいろ試してみるといいかもしれません！
HerokuでRubyとSeleniumを動かすための設定

## HerokuでRubyとSeleniumを動かすための設定

次のようにGemfileにgemを追加して下さい。

```ruby:Gemfile
gem 'selenium-webdriver'
gem 'chromedriver-helper'
```

そして、ターミナルで次のコマンドを実行します。

```bash
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-google-chrome
heroku buildpacks:add https://github.com/heroku/heroku-buildpack-chromedriver
heroku config:set GOOGLE_CHROME_BIN=/app/.apt/opt/google/chrome/chrome
heroku config:set GOOGLE_CHROME_SHIM=/app/.apt/opt/google/chrome/chrome
```
これで設定は完了です。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
railsのroutes.rbのmemberとcollectionの違いをわかりやすく解説してみた。〜rails初心者から中級者へ〜

##この記事の対象者

rails tutorialも終わり、resourcesはわかるけどmemberとかcollectionは知らない人。

##内容

routes.rbで使用される、memberとcollectionの違いを解説します。

##memberとcollectionが使用される目的

どちらもresourcesでroutingを設定しているとき、resourcesでは自動で生成されないactionへのroutingを設定するときに使用する。

```
resources :users do
    member do
      get :follow
        #follow_user GET    /users/:id/follow(.:format)            users#follow
      get :like
        #like_user GET    /users/:id/like(.:format)                users#like
    end
end
```

user resourcesをroutingに設定しているとき、users controllerのfollow actionをroutingに設定したいって思ったとき、こんな感じで使用します。

##memberとcollectionの違い
生成するroutingに、:idが付くか付かないか。

memberは付いてcollectionは付かないです。

##memberの特徴
:idが付く。以上。

そんな事言ったら怒られそうなので詳しく書きます。

```
resources :users do
    member do
      get :follow
    end
end
```

```
follow_user GET    /users/:id/follow(.:format)                    users#follow
```

こんな感じでuser resourcesにfollow actionのroutingをmemberで追加したとき、生成されたurlにuserを識別するための:idが自動で追加されます。

##collection
memberの時と同様に、user resourcesにslide actionへのroutingを追加します。

```
resources :users do
    collection do
      get :slide
    end
end
```

```
slide_users GET    /users/slide(.:format)                        users#slide
```

こんな感じで追加されるslide actionのurlにはuserを識別するための:idがつきません。

##最後に
最後までお読みくださりありがとうございました。なんか間違いあれば指摘ください。