OmniAICreator/Qiita-1.07M huggingface dataset:
herokuでデプロイ後自動でMigrateさせる

# はじめに

herokuは[Release Phase](https://devcenter.heroku.com/articles/release-phase)という機能があり、デプロイするごとに自動でスクリプトなど発火させる機能があります

今回Laravelのmigrationをデプロイの度に発火させます

対応はProckfileに1行追加するだけで終わります

`relase: {スクリプト}`

### Procfile

```
release: php artisan migrate:fresh --force
web: vendor/bin/heroku-php-apache2 public
```

## 解説

freshオプションは任意で

--forceは、Laravelは本番環境だとyesか聞かれるので強制的にmigrateさせます

# 終わりに

日本語の記事が少なく、--forceとかで少し詰まった・・・

一行追加するだけなので、楽ちん！
FUJITSU Cloud Service for OSS (旧K5)をAnsibleで操作する (2)

#はじめに
[前回](https://qiita.com/dokuyama/items/fec57890e48518d9d378)の投稿をRoleを使って書き直し、可能な限り汎用化しました。

playbookファイルは [github](https://github.com/dokuyama/ansible_fujitsu_K5)に置いています。

※事前準備等は前回のページを参照してください。

# インスタンスを起動してWPを導入するサンプル
できるだけ色々なケースに使いまわせるように、role化しています。
ハードコードをできるだけ避け、メインのplaybookもしくは、varsで変数を与えて実行したいという考えで作成しました。

```
$ git clone https://github.com/dokuyama/ansible_fujitsu_K5.git
```
またはzip等でダウンロードして、ansibleを実行するマシンで展開してください。

clouds.yml.sample、single-web-WP_vars.yml.sample は環境に合わせてリネーム後編集してください。

編集後、

```
$ ansible-playbook single-web-WP.yml
```

で実行します。うまく成功すれば、Wordpressのデフォルトのページが表示できるようになります。

## 実行している内容
role単位で簡単に説明します。

- ansible-ssh-key
SSHの鍵を作成します。既に ./id_rsa_ansible, ./id_rsa_ansible.pub が存在すればそのファイルをimportします。
(一度作ったら上書きはしません)

- openstack-create-basic-network
ネットワーク、サブネット、ルータの作成後、SSHのキーペアを登録します。

- openstack-security-group/get_my_global_ip
ansibleを実行しているマシンのアクセス元になるglobal IPアドレスを取得します。

- { role: openstack-security-group/create, security_group_name: ["web", "mng"] }
web,mng という名前でセキュリティグループを作成します。

- openstack-security-group/add-rule
セキュリティグループにルールを追加します。
追加するルールは single-web-WP_vars.yml に以下のように記載しています。
※ipify_public_ip は前のタスクで取得したglobal IPが入ります。

```
##
## openstack-security-group/add-rule vars
##
security_group_rules:
  - { name: "http", security_group: "web", protocol: "tcp", port_range_min: "80", port_range_max: "80", remote_ip_prefix: "0.0.0.0/0" }
  - { name: "https", security_group: "web", protocol: "tcp", port_range_min: "443", port_range_max: "443", remote_ip_prefix: "0.0.0.0/0" }
  - { name: "ssh", security_group: "mng", protocol: "tcp", port_range_min: "22", port_range_max: "22", remote_ip_prefix: "{{ ipify_public_ip }}/32" }
```
   
- { role: openstack-create-instance, server_lists: ["single-web-WP"],  security_group: ["default", "web", "mng"], auto_ip: yes, volume_size: "35", volume_image: "CentOS 7.3 64bit (English) 01", server_flavor: "P3-1", group: "webservers" }
引数に沿ってインスタンスを作成します。
このroleを並べる事で複数台作成する事もできます。

- check-ssh-port
SSHがつながるようになるのを待ちます。
※waitの秒数が長いのは、SSHのportが開いてからauthorized_keysに登録されるまで、少々遅延があるためです。

- { role: yum/update-all, reboot: yes }
インストール済みのrpmを全てyum update でアップデートします。
updateする対象のrpmが存在し、reboot がyesの場合、実行後OSの再起動を行います。

- { role: yum/install, install_packages_lists: ["httpd", "php", "php-mysql", "mariadb-server", "MySQL-python"] }
引数に従ってyumでパッケージをインストールします。

- { role: php/change-timezone, timezone: "'Asia/Tokyo'" }
phpのタイムゾーンを設定します。

- { role: service/enable, service_name: ["httpd", "mariadb"] }
サービスの自動起動を有効にします。

- { role: service/restart, service_name: ["httpd", "mariadb"] }
サービスの再起動を実行します。

- wordpress/create-database
Wordpress用のデータベースを作成します。

- wordpress/install
Wordpressのインストールを行います。
インストール済みの場合、ファイルの存在をチェックし、スキップされます。
wp-cliを使っています。

- wordpress/update
wp-cliを使ってWordpressのアップデートを行います。

- name: print message
最後に、導入したWordpressが表示できるURLを表示します。

# 今後の予定
Ansibleのアップデートが必要のようですが、loadbalancerの追加、Snapshotの取得等、もっとOpenStackの操作ができるようにしたいと思います。
前回発見したAnsibleの問題が修正されているか確認して、未解決の場合はAnsibleを複数切り替えるという記事も見かけたので、そういった方向も試してみたいと思います。
WolframAlphaで641.01㎡をhaにしてみた。

(参考)WolframAlpha＞641.01㎡
http://www.wolframalpha.com/input/?i=641.01%E3%8E%A1
0.064101 hectares
(参考)WolframAlpha＞641.01m*m
http://www.wolframalpha.com/input/?i=641.01m*m
0.064101 hectares

(参考)wolframalpha＞641.01mm
長さです。
641.01 mm (millimeters)
http://www.wolframalpha.com/input/?i=641.01mm

(参考)google＞単位換算表
https://www.google.co.jp/search?source=hp&ei=O4iKW8TVB8-k-QbDsaHIAw&q=%E5%8D%98%E4%BD%8D%E6%8F%9B%E7%AE%97%E8%A1%A8&oq=%E5%8D%98%E4%BD%8D%E6%8F%9B%E7%AE%97&gs_l=psy-ab.1.1.0l8.977.977.0.4132.1.1.0.0.0.0.99.99.1.1.0....0...1c.1.64.psy-ab..0.1.99....0.eZYSaYVA3jk
googleで換算はできましたが、「お気に入り」はできませんでした。

－－－－－－－－－－－－－－
(2018/09/03)
windows7＋IE11で以下のダイアログがでます。

「
長さ
メートル = センチメートル
」
android+firefox でダイアログがでません。
Rubyで西暦何年に自分が何歳になってるか求めてみよう

#はじめに
Rubyを学び直している中で、「西暦を平成に変換する」プログラムを復習した。
・新元号(2018年9月現在、未発表)と西暦を紐付けるプログラム
・自分が何歳かわかるプログラム
に応用してみたのでご紹介する。

#環境、前提
Rubyのversion
`ruby 2.3.7`
統合開発環境
`Visual Studio Code`
PC
`MacBook Air`

#西暦を平成に変換するプログラム
まずは、西暦と平成を対応させてみる
西暦は、ADとも呼称するので、変数にはadを用いる。
※ラテン語の「アンノドミニ (Anno Domini)」のことである。

また、「平成1年」と表現はせず「平成元年」と表示させたいため、条件分岐で
「元年の場合」「それ以外」に分けた。

```ruby:seireki_to_heisei.rb
for ad in 1989..2018
    print "西暦#{ad}年は、"
    heisei = ad - 1988
    if heisei == 1
        puts "平成元年でござるよ"
    else
        puts "平成#{heisei}年でござるよ"
    end
end
```

実行結果は、下記。
しっかり1年目だけ「元年」と表示されている。

```
西暦1989年は、平成元年でござるよ
西暦1990年は、平成2年でござるよ
西暦1991年は、平成3年でござるよ
西暦1992年は、平成4年でござるよ
西暦1993年は、平成5年でござるよ
西暦1994年は、平成6年でござるよ
西暦1995年は、平成7年でござるよ
西暦1996年は、平成8年でござるよ
西暦1997年は、平成9年でござるよ
西暦1998年は、平成10年でござるよ
西暦1999年は、平成11年でござるよ
西暦2000年は、平成12年でござるよ
西暦2001年は、平成13年でござるよ
西暦2002年は、平成14年でござるよ
西暦2003年は、平成15年でござるよ
西暦2004年は、平成16年でござるよ
西暦2005年は、平成17年でござるよ
西暦2006年は、平成18年でござるよ
西暦2007年は、平成19年でござるよ
西暦2008年は、平成20年でござるよ
西暦2009年は、平成21年でござるよ
西暦2010年は、平成22年でござるよ
西暦2011年は、平成23年でござるよ
西暦2012年は、平成24年でござるよ
西暦2013年は、平成25年でござるよ
西暦2014年は、平成26年でござるよ
西暦2015年は、平成27年でござるよ
西暦2016年は、平成28年でござるよ
西暦2017年は、平成29年でござるよ
西暦2018年は、平成30年でござるよ
```

そして、平成最後の夏は終わったでござる。

#西暦を新元号に変換するプログラム
次に、西暦とまだ見ぬ新元号を対応させてみる

また、2020年には東京オリンピックが開催されるため、これまた条件分岐で
「元年の場合」「2020年東京オリンピック」「それ以外」に分けた。

※仮置きとして、新元号を100年スパンとした

```ruby:new_gengou.rb
for ad in 2019..2118
    print "西暦#{ad}年は、"
    new = ad - 2018
    if new == 1
        puts "新元号元年でござる！新しい時代の幕開けでござる!!"
    elsif new == 2
        puts "新元号#{new}年で東京オリンピックが開催されるでごわす"
    else
        puts "新元号#{new}年でござるよ"
    end
end
```

実行結果は、下記。
オリンピックについても言及されている。

```
西暦2019年は、新元号元年でござる！新しい時代の幕開けでござる!!
西暦2020年は、新元号2年で東京オリンピックが開催されるでごわす
西暦2021年は、新元号3年でござるよ
西暦2022年は、新元号4年でござるよ
西暦2023年は、新元号5年でござるよ
西暦2024年は、新元号6年でござるよ
西暦2025年は、新元号7年でござるよ
西暦2026年は、新元号8年でござるよ
西暦2027年は、新元号9年でござるよ
西暦2028年は、新元号10年でござるよ
（以下略）
```

オリンピックへの楽しみよりも、東京におけるより一層の大混雑への不安の方が絶大でごわす。

#西暦何年に自分が何歳になってるか求める
最後に、西暦と年齢を対応させてみる。

ここでは、平成元年生まれの方が
西暦何年に何歳になっているかを例に書いてみた。

```ruby:your_age.rb
for ad in 1989..2100
    print "西暦#{ad}年は、"
    age = ad - 1989
    puts "自分は#{age}歳です"
end
```

実行結果は、下記。
平成元年である1989年生まれのベイビーは、今や29歳の立派な成人。
来年の新元号には、三十路に突入し、
東京オリンピックを31歳で楽しむことになる。

```
西暦1989年は、自分は0歳です
西暦1990年は、自分は1歳です
(中略)
西暦2018年は、自分は29歳です
西暦2019年は、自分は30歳です
西暦2020年は、自分は31歳です
```

こうしてみると、プログラミングも身近に感じられるです。はい。

#まとめ
いかがだっただろうか。新元号変換や自分の年齢がわかる参考となり、お役に立てる記事となれば幸いでごわす。
ぜひ、新元号が発表された際には、プログラムを書き換えてみたい。
また、新元号何年に自分が何歳かも求めてみよう。それでは、また次回。
Swiftでxibファイルメモ


nib(xib)ファイルから読み込みを行うExtension

```swift 

extension UIView {
    func loadNib() {
        let view = Bundle.main.loadNibNamed(String(describing: type(of: self)), owner: self, options: nil)?.first as! UIView
        view.frame = self.bounds
        self.addSubview(view)
    }
}
```


こう使う

```swift

// クラス名はなんでも良し
class CustomView: UIView {

    // コードから初期化
    override init(frame: CGRect) {
        super.init(frame: frame)
        loadNib()
    }
    
    // Storyboardから初期化
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        loadNib()
    }   
}
```

これ自動的にやってくれないんですかね
シェルスクリプト練習(bash)-文字列の一部を抽出-


#やりたいこと

- 下記のようなログの終了ログの値(カッコ内一つ目)を見て、終了ログ直前のログの値を抽出したい

```log.txt
[2018/08/29 10:10:11]	[INFO ]	START
[2018/08/29 10:10:12]	[INFO ]	AAA SSSSS(123456, 098765, hahahaha)
[2018/08/29 10:10:13]	[INFO ]	END(0, GOOD)
[2018/08/30 10:10:11]	[INFO ]	START
[2018/08/30 10:10:12]	[INFO ]	BAD JOB
[2018/08/30 10:10:13]	[INFO ]	END(1, BAD)
[2018/08/31 10:10:11]	[INFO ]	START
[2018/08/31 10:10:12]	[INFO ]	AAA SSSSS(123456, 098765, hahahaha)
[2018/08/31 10:10:13]	[INFO ]	END(0, GOOD)
```

#やった内容


```readfile.sh
#!/bin/bash -u
LINENUM=0 # 開始行
COMMAND=`tail -n +$LINENUM log.txt`
LINEDATA="" #1行分
FIRSTROW=true #開始行フラグ
while read line; do
    if ${FIRSTROW}; then
        LINEDATA=${line}
        FIRSTROW=false
        continue
    fi

    if [[ $line =~ START ]]; then
        # 開始ログの行は何もしない
        continue
    elif [[ $line =~ END ]]; then
        # 終了ログ
        result=$(echo ${line} | sed -e "s/^.*(\(.*\))/\1/g" | cut -d ',' -f 1) #カッコ内を抽出しカンマ区切りの一つ目を取得
        if [[ $result == 0 ]]; then
            IFS_ORIGINAL=${IFS}
            IFS=, # 環境変数の区切り文字をカンマに変更
            columns=$(echo ${LINEDATA} | sed -e "s/^.*(\(.*\))/\1/g") # カンマ区切りを代入するとそのまま配列扱いに
            IFS=${IFS_ORIGINAL} # 環境変数IFSを元々の区切り文字に戻す
            for v in ${columns[@]}; do
                echo -n ${v}\;
            done
            echo
        fi
    else
        # 開始終了ログのどちらでもなければ行を変数に代入
        LINEDATA=${line}
    fi

done << EOF
   ${COMMAND}
EOF
```

- 開始行は都度変えるようにしたいので変数に
- 開始終了ログに挟まれたログのカッコ内の文字を抽出する
- 抽出したカッコ内の文字はカンマ区切りなので、分割して配列へ

ひとまずはこんなくらいか。
Azure Database for MySQLにアクセスできない件


少しつまったのでメモ。

作成したばかりのデータベースはSSL必須とアクセス許可がデフォルトではないっぽいです。

MySQLクライアントからアクセスしてもIPがブロックされてる的なエラーが出ます。

以下の二箇所に設定変更するとローカルPCからアクセスできるようになります。

ただ全オープンなので疎通確認できたら適宜閉じましょう。

## ファイアウォール規則

* 規則名 AllowAllps
* 開始IP 0.0.0.0
* 終了IP 255.255.255.255

![](https://i.gyazo.com/9f10b298f60c83ba0a09ab4723364fa2.png)

## SSL設定

最初はSSL強制になってるのでオフにします。

![](https://i.gyazo.com/6a0a7c9b99a092e3f6cb92b89f835d3c.png)


## おわりに

[ここ](https://docs.microsoft.com/ja-jp/azure/mysql/quickstart-create-mysql-server-database-using-azure-portal)に乗ってたっぽいけどなかなか調べても出てこなかったんだよなぁ...
Ubuntu18.04.1にGitlab11.2.3インストール＆日本語設定

## 準備

* Ubuntu Server 18.04.1 LTS 日本語版をインストール済みのVirtualBox  
[Ubuntu Server 18.04.1 LTS](https://www.ubuntu.com/download/server)


## インストールと日本語設定
基本的に公式サイトのインストール方法に則って進めます。
https://about.gitlab.com/installation/#ubuntu

1. インストールと必要な依存関係のある設定

    ```bash 
    sudo apt-get update
    sudo apt-get install -y curl openssh-server ca-certificates
    ```

    ```
    sudo apt-get install -y postfix
    ```
postfixのインストールが開始すると画面が変わります。
![1921682173 - ele_admin@gitlab-914 ~workspace VT_2018-09-02_22-38_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/2ae33c0b-00d5-eb9a-740d-8eb23bee41e4.png)

「Internet Site」を選択し、次へ
![1921682173 - ele_admin@gitlab-914 ~workspace VT_2018-09-02_22-38_01.png](https://qiita-image-store.s3.amazonaws.com/0/122879/d4a7442c-49a2-08a9-f292-631cec306286.png)

任意の名前を選択して次へ
デフォルトでPC名になっているはずです。
![1921682173 - ele_admin@gitlab-914 ~workspace VT_2018-09-02_22-39_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/0aa71473-a386-c730-7016-6f39af7af026.png)

正常に完了すると次のような表示となります。
![1921682173 - ele_admin@gitlab-914 ~workspace VT_2018-09-02_22-40_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/4a351fda-eaff-8ea2-bb56-ccf1f9f086d1.png)


2. パッケージのインストール

    ```bash
    curl -s https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
    ```

    ```bash
    sudo apt-get install gitlab-ce
    ```

3. アドレスの変更
    URLはPCのIPアドレスを指定

```bash
sudo vim /etc/gitlab/gitlab.rb
```

```
external_url 'http://192.168.2.173'
```

4. GitLabを起動

    ```
    sudo gitlab-ctl reconfigure
    sudo gitlab-ctl restart
    ```

5. ブラウザでGitLabへアクセスする
初回ログイン時はrootユーザの新パスワードを求められます。
![GitLab - Google Chrome_2018-09-02_23-27_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/0343f3ed-ddc1-e7bd-68c3-11d267b835e4.png)

改めて、変更したパスワードでログインします。
![Sign in · GitLab - Google Chrome_2018-09-02_23-28_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/5f82508c-9e81-4a8a-bab7-09966fa6d480.png)

ログインした後は英語のトップ画面が表示されます。
![Projects · Dashboard · GitLab - Google Chrome_2018-09-02_23-29_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/56463753-9f62-603c-6db9-a3f916bea3ef.png)


6. 日本語設定
Gitlabは9.2以降から多言語対応しており、設定画面からの変更で日本語設定が可能です。
画面右上のアバターをクリック
settingsを選択
Preferred languageで日本語を選択
![User Settings · GitLab - Google Chrome_2018-09-02_23-57_00.png](https://qiita-image-store.s3.amazonaws.com/0/122879/6a99d13d-b8b9-fead-3fef-5d1f2ad34677.png)

一番下の「Update profile settings」を押す
F5などで画面を更新
![User Settings · GitLab - Google Chrome_2018-09-02_23-57_01.png](https://qiita-image-store.s3.amazonaws.com/0/122879/514bed16-3290-4813-6131-3f566bcddc58.png)
[Rails] 別名で外部キー設定して関連付けしたい

#やりたいこと
- 通貨の交換を管理する際、交換モデルから通貨モデルを外部キー設定したい。
- 外部キーは買い通貨と売り通貨の2種類
- 通貨モデルは親通貨モデルCurrencyを継承したActiveRecordで実装
- つまり、参照側はされる側のスーパークラスを参照したい

#参照する側(交換モデルの実装)
##マイグレーション

```ruby:CeateExchanges.rb
create_table :exchanges do |t|
  t.references :buy_currency, foreign_key: { to_table: :currencies }
  t.references :sell_currency, foreign_key: { to_table: :currencies }
end
```

- ポイントは実際のテーブル名と異なる属性名を使用している
- その際は`to_table`キーの値で実際のテーブル名を指定

##モデル

```ruby:Exchange.rb
class Exchange < ApplicationRecord
  belongs_to :buy_currency, class_name: "Currency"
  belongs_to :sell_currency, class_name: "Currency"
end
```

- ポイントは`belongs_to`には参照したい名称を指定
- 実際のクラス名は`class_name`キーの値で指定
- `belongs_to :currency_jpy`とか子通貨テーブルの名称を関連付けに設定してしまうと、exchangeテーブルにレコードを挿入できなくなります。
- なぜなら、実際には親通貨モデルを外部キーとして設定しているにも関わらず、子通貨モデルを関連付けることで、レコード挿入時には子通貨の値がないはずで、バリデーションで子通貨がblankだと怒られるからです


#参照される側(親通貨モデルの実装)
##マイグレーション

```ruby:CeateCurrencies.rb
create_table :currencies do |t|
  t.string :name, null: false
end
```

##モデル

```ruby:Currency.rb
class Currency < ApplicationRecord
  self.table_name_prefix = "currency_"
  has_many :exchanges

  def buy(amounts)
    self.amounts += amounts
  end

  def sell(amounts)
    self.amounts -= amounts
  end
end
```

- 本記事の主旨からズレますが、ダックタイピングを使ってます。総量を表すamountsは親通貨モデルには定義していません。親クラスから継承した子通貨モデル側で総量を定義していれば、問題なく動作します。

```ruby:db/seeds.rb
Currency.create(name: "JPY")
Currency.create(name: "USD")
Currency.create(name: "BTC")
```

- このseedのように親クラスでは扱える通貨一覧を管理する目的でレコードを保有
- その心は```collection_select```フォームヘルパーを使用したいからです

#参照される側(子通貨モデルの実装)
##マイグレーション

```ruby:CeateCurrencyJpy.rb
create_table :currency_jpy do |t|
  t.float :amounts, null: false, default: 0
end
```

- モデルの生成で自動作成されるマイグレーションには複数形のテーブル名が付与されるので、通貨としては扱いづらいために書き換えてます
- 実用的にはユーザーモデルとの関連付けが必要だと思います


##モデル

```terminal:コンソール
$ rails g model Currency::Jpy
```

- この記事では通貨はcurrency名前空間の配下に作成して少し複雑なケースでまとめます

```ruby:currency/jpy.rb
class Currency::Jpy < Currency
end
```

#まとめ
Railsの基本的な使い方をしていると気付かないような動きを確認することができました。
アソシエーションを設定することで普段は気にしていない動作が走っていることなど、勉強になりました。
個人的にはモデルのnamespaceは動きが読めなくて使いづらく、おススメできないです。
App Maker + Google Cloud SQL の組み合わせで使ってみる

App Maker[^1]を少し使ってみたので、最初の導入部分をまとめてみました。
App Maker + Google Cloud SQL の組み合わせで、事前準備～簡単な表示・編集画面の作成までを4回に分けて説明しています。
連載と言うには短いですが、興味のある方は下記からどうぞ。

# 連載目次
1. [App Maker + Google Cloud SQL の組み合わせで使ってみる(事前設定)](https://qiita.com/kamina/items/f9b2591bb806476dc003)
2. [App Maker + Google Cloud SQL の組み合わせで使ってみる(モデル作成)](https://qiita.com/kamina/items/0c26446a173e18966f8e)
3. [App Maker + Google Cloud SQL の組み合わせで使ってみる(テーブルで画面表示)](https://qiita.com/kamina/items/8f6da0dc119e20381704)
4. [App Maker + Google Cloud SQL の組み合わせで使ってみる(フォームでデータ追加)](https://qiita.com/kamina/items/1373977440902235e2b9)

[^1]: App MakerはG SuiteのBusinessプラン以上で使用することができます。
無料でメールアドレスの検証(バリデーション）

メールマガジン発行、キャンペーンや宣伝などで大量のメールアドレスを扱う際のメールアドレスの検証についてです。

ドメイン名の変更や廃止、当人の退職などで既に無効になっているメールアドレスが多いこと、多いこと。このような無効なメールアドレスと、スパムメールに対する対策は、メール一括配信サービスでも厳重に行うのが常で、MailChimpなどはメールアドレスのリスト登録の時に、不着となりそうなメールが一定数あると登録ができなくなったりします。

そこで、メール配信サービスに登録する前に、手元にあるメールアドレスの検証を行い有効なものだけを拾う、という作業が必要なのですが、そのための方法です。

# mailboxlayer について
https://mailboxlayer.com

"Forever Free"のプランでSign Up すると、月に250通まではメールアドレスを検証するAPI が無料で使えます。

Access Key を取得して、以下のように実行します。

```
curl "https://apilayer.net/api/check?access_key=ACCESS_KEY&email=EMAIL&format=1"
```

JSON で以下のような応答が帰ってきます。

```
{
  "email":"hoge@domain.com",
  "did_you_mean":"",
  "user":"hoge",
  "domain":"domain.com",
  "format_valid":true,
  "mx_found":true,
  "smtp_check":true,
  "catch_all":null,
  "role":false,
  "disposable":false,
  "free":false,
  "score":0.96
}
```

mx_found がMX レコードの有無、smtp_check がSMTP サーバの稼働の検証です。これらがtrue ==稼働であるものは妥当、false となるものは既に無効になっている、と判断できます。（他のフィールドの意味は未検討）

#備考

## 活用しているメール配信サービス

* [MailChimp](https://mailchimp.com/)

月に12000通、2000メールアドレスまで無料。Drag & Drop ベースのGUIでのメール本文作成がとっても使いやすい。

* [Sendgrid](https://sengrid.com/)
2000メールアドレスまで無料。一日500通まで。Microsoft Azure からも使える、その場合は1日800通まで。MailChimp と同様、Drag & Drop ベースのGUIでのメール本文作成対応。

* [Mailgun](https://www.mailgun.com)
APIがとっても使いやすい。

## メール配信関連の英語

見慣れない単語が散見されたので、備忘録的に。

* Bounce (Mail)

エラーメールやリターンメールのこと。何等かの理由で目的の送信先に正常に配信されなかった場合に、メールサーバからその旨を送信元に通知されるメールメッセージ。 

* Abuse complaints
スパムメールと判断されること。

* Suppression
抑止。Abuse complaintsやUndelivered Mail を"Suppressor" することがメール配信サービスの重要な機能。

## 参考
Mailgun を使ったメールアドレス検証の方法の記事です。残念ながら有料のサブスクリプションでないと使えないとのことでした。

[メールアドレスのドメインのvalidation](https://qiita.com/ttwwiitttteerr0/items/549f8fe6018d279318aa)

## 余談
同窓会でメールマガジンの運用を引き継いで、これまでのWindowsソフトでの配信から、名簿情報との連動などを見越してクラウドベースの配信サービスを利用し用として、この問題に直面したのがきっかけでした。この10年ほどで集めた1200個ほどのメールアドレスを預かりましたが、このバリデーションで有効ということで残ったのは570通。半分以下でした。
スクリプトの絶対パスを環境変数の参照に置き換える sed コマンド

目新しさはありませんが、たまに使いたくなった時に忘れているのでメモを残します。

シェルスクリプトなどで絶対パス（それも結構長い）が多く含まれている場合に、それを環境変数の参照に置き換えたくなることがあります。

***まず、環境変数は定義済みという前提です。***
***置き換えは以下２点を気をつければ sed で手軽にできます。***

 - 置換パタンはダブルクォート(")で囲む
 - \x24 がドルマーク($)を示す

以下は例です。
***/home1/hoge/fuga/nagai/mohitotsu/***に以下２つのファイルがあります。

```data.txt
2016 9 22
2017 9 22
2018 9 22
2019 9 22
2020 9 22
2021 9 22
2022 9 22
```

```weekday1.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import datetime
import sys

weekday_jp = ["月","火","水","木","金","土","日"]

for l in sys.stdin:
	l = l.rstrip("\r\n")
	d = list(map(int,l.split()))
	print("{}/{}/{}({})".format(d[0],d[1],d[2],weekday_jp[datetime.datetime(d[0],d[1],d[2]).weekday()]))
```	

これを実行するスクリプト***run0.sh***です。

```run0.sh 
cat /home1/hoge/fuga/nagai/mohitotsu/data.txt | python /home1/hoge/fuga/nagai/mohitotsu/weekday1.py
```

こんな風に実行されます。

```
$ ./run0.sh 
2016/9/22(木)
2017/9/22(金)
2018/9/22(土)
2019/9/22(日)
2020/9/22(火)
2021/9/22(水)
2022/9/22(木)
```

ここで、ファイルのあるパスを***FILEPATH***という環境変数に設定します。
その変数に置き換えたスクリプト***run1.sh***を作ります。
***２行目の sed コマンドがこの記事の本題です***

```
export FILEPATH=/home1/hoge/fuga/nagai/mohitotsu
sed -s "s:${FILEPATH}:\x24{FILEPATH}:g" run0.sh > run1.sh
chmod +x ./run1.sh 
```

***run1.sh***の内容です。

```run1.sh 
cat ${FILEPATH}/data.txt | python ${FILEPATH}/weekday1.py
```

ちゃんと同じ実行結果が得られます。

```
$ ./run1.sh 
2016/9/22(木)
2017/9/22(金)
2018/9/22(土)
2019/9/22(日)
2020/9/22(火)
2021/9/22(水)
2022/9/22(木)
```
JavaScript正規表現について

##はじめに
この記事は自分用のメモです。
もし、のぞいてくださる人がいらしたら、みづらい部分があれば、どんどん指摘してください！


##正規表現について
◼︎正規表現を利用するケースは主に３ケース
1. 文字列を部分的に置換するとき
2. 文字列が制約を満たしているか確認するとき
3. 文字列の一部分を抽出するとき
   

| 正規表現       |     効果 |  
|:---------------|:------------------|
|```[a-z]```     |角括弧で囲まれた文字のいずれか 1 個にマッチ              |
|```\d```        |数字にマッチ                          |
|```{n, m}```    |直前の文字が少なくとも n 回、多くても m 回出現するものにマッチ|
|```i```         |大文字・小文字を区別しない検索 |
|```g```         |グローバルマッチで。例えばreplaceメソッドと組み合わせて利用することで文字列の中に指定した文字が複数含まれている場合、全てを置換することができる。 |
|```+```         | 直前の一回以上の文字列にマッチする |
|```-```         | 直後の一回以上の文字列にマッチす |
|```.```         | どの１文字にもマッチする |



##正規表現を利用する際に使用するメソッド：replace、match

####replaceメソッドを使ってみる
replaceメソッドは文字列の指定の部分を別の文字に置き換えるメソッドです。

``` replace.js
> var food = 'ポテチうまい';
=> undefined

> food.replace(/ポテチ/, 'じゃがりこ');　　##操作したい文字列は//で囲みます。第２引数に変換後の文字列を指定します。
=> "じゃがりこうまい"
```
ポテチをじゃがりこに変更することができました。


####グローバルマッチを利用してreplaceメソッドを使ってみる
```global.js
> var address = '東京都-港区-虎ノ門';
=>  undefined

> address.replace(/-/g, ""); ##'g'を
=> "東京都港区虎ノ門"
```
####matchメソッドを使ってみる
matchメソッドは引数の中に指定した文字列がレシーバに存在しているかどうかを確認するためのメソッドです。
指定した文字列が含まれている場合は、返り値に指定した文字列が配列形式で戻されます。
また含まれていない場合は返り値としてnullが返されます。

``` match.js
> var str = 'ポテチ';
=> undefined

> str.match(/ポテチ/);
=> ["ポテチ"]

> str.match(/じゃがりこ/)
=> null
```

####文字数の制約を設定する

```{8,}```を利用して８文字以上の制約をつけています。
その他、```[a-z]```はa~zのアルファベットに合致するもの、

```password.js
> var pass = 'Huga1234';
=>  undefined

> pass.match(/[a-z\d]{8,}/i);
=> ["Huga1234"]
```

補足①
最初の１文字を返します。

```aaa.js
> var aaa.match(/./);
=> ['a'] ##最初の１文字にマッチ
```

補足②
最初のaだけでなくその後に続くaも返します

```aaa.js
> var aaabbb.match(/a+/);
=> ['a'] ##直前の文字で直後に続く文字にマッチ
```
補足③
'.'を指定しているので、全ての文字列を返します。

```aaa.js
> var aaabbb.match(/.+/);
=> ['aaabbb'] ##直前の文字で直後に続く文字にマッチ、この場合は'.'を利用しているので全てにマッチする
```
Android things + Cloud IoT Core + Cloud Pub/Sub

仕事で使う機会があったのでざっくりしたまとめを書きます。

# サービス概要

## IoT Core

https://cloud.google.com/iot-core/

IoT Core とは IoT デバイスを管理するツールです。
IoT デバイスの公開鍵を登録することでセキュアな通信が可能になります。
それからIoT CoreのAPIを叩けば、指定デバイスからデータを取得したり、指定したデバイスの設定を変更ができます。
ブラウザでできることはデバイスの登録とデバイス情報の確認程度で、APIもそうですが割とシンプルなサービスです。

## Pub/Sub

https://cloud.google.com/pubsub/

PublisherとSubscriberの略で、一対多、多対一、多対多のデータのやりとりをするためのハブとなります。
これができて何が嬉しいかと言うと、複数の送信元からあるデータを一つのサーバーに送ったり、もしくは用途ごとに別のサーバに送ったり、ということができます。
IoT 案件の場合は多数のデバイスを使うことが多いですし、Webアプリやストレージなどの様々なサービスにセンサーデータを送ったりできるので相性が良いです。

Pub/Subにまつわる用語として以下があります。

+ Publisher データ送信者
+ Topic 中継地点
+ Subscriber データ受信者

IoT 案件なら、デバイス（Publisher）がAPIを使ってTopicにデータを送信、すると設定したサービス（Subscriber）にデータを転送してくれる、というイメージです。
ブラウザ上ではTopic, Subscriberを設定できます。
Subscriberは以下の2種類があります。

+ pull型 外部からAPIを叩くことでデータを取得
    + App Engine, Functionからリクエスト
+ push型 対応Topicにデータが届き次第、指定したAPIを叩く
    + Pub/Subから送る

例えばApp Engineにpushハンドラーを用意しておいて、自動的にDataStoreに送るとかが出来て便利です。

## Android Things

https://developer.android.com/things/

android の派生 OS です。
ラズパイなどのデバイスに載せることができます。
Androidアプリの要領でデバイスに搭載するアプリの開発が可能です。
ここからセンサーデータを取得、Pub/Subで設定したTopicにデータを送る、というアプリさえ載せれば最低限の機能は使えます。

# よくある（実際あった）質問

## 実際使うとしたら？

+ 大量のセンサーデータを収集、研究利用
+ 工場などに設置して、異常検知

というのがありえそうなパターンですね。
センサーは温度、加速度、磁気、電力などなど多種多様なので応用可能性が高いと思います。

## 実際に開発するとしたら？

### システム構成（アーキテクチャ）

最低限Android things + Cloud IoT Core + Cloud Pub/Subはあるとします。
（Android thingsじゃなくてもAPi叩ければLinux機でも良さそう）

これ以降のアーキテクチャ例を挙げていきます。

**～Pub/Sub → Dataflow　→ BigQuery → Datastudio**

なんとこれだとデバイス以外はブラウザポチポチするだけで可視化ができちゃいます。
Dataflowは前処理とかしてくれるところですが、Pub/SubからBigQueryならテンプレが用意されてるのでそれで終わりです。BigQueryも箱として入れとくだけで、後はDataStudioでカッコイイグラフを作りましょう。
問題としてはDataflowでお金かかっちゃうかもしれないので、Cloud Functionに差し替えるみたいな手法もあります。

**～Pub/Sub → Function → IoT Core**

しきい値超えたらアラート流すとか動作止めるAPI叩くみたいな。
監視系の別のツール使ってもよさそうだけど……。

**～Pub/Sub → AppEngine ↔ DataStore**

とりあえずDataStore入れといてWebアプリ上でなんか色々やる。
これが一番自由度が高い。
DataStudioだと時系列データの区切りが最低でも日ごとなので、
リアルタイム性を求めるとこのように自力でやっていくしかないのだ……。

### IoT Core APIの使い方は？

https://cloud.google.com/iot/docs/reference/rest/?hl=ja

上記のガイドとにらめっこする。あとはgithubに上がってる公式サンプルコードを試してみる。
APIの機能はそんなに多くないので比較的楽なはず。
また実機が無くてもIoT Coreの設定画面で仮想デバイス作れる（実機の公開鍵あるかないかの違い）ので、すぐ始められる。

## 費用は？

IoT Core, Pub/Sub自体はデータ量依存だけど大量にデータやりとりとかしない限りは無料枠なので安心。とはいえもちろん連携サービスで課金発生可能性はあるので各自最高のアーキテクチャを考えましょう。あと無論デバイスは課金不可避。

## AWSと比べるとどう？

AWSでIoTやったことないのでなんとも言えないけど、個人的にはこっちの方がシンプルで安価かなと。

## デバイスからPub/Sub直接叩けばIoT Core要らなくね？これいる？

わかる。
が、一応擁護すると

+ デバイスの公開鍵を登録することでデバイスとのセキュアな通信が可能
+ 複数デバイスに命令送る場合、1つ1つIPとか指定する必要が無い
    + IoT Core上で設定したデバイスIDを指定して操作することは可能
+ デバイスとTopicの紐付けがIoT Core上で設定可能
+ API経由でデバイス操作が可能
+ デバイスへの命令（正確にはupdate config）は1秒に最大1回、などの制限を設けてデバイスの負荷を減らす

といったメリットはあるかなと……。（最後は結構無理ある。）
場合によってはIoT Coreを使わずにやっていくのも1つだと思います。

# まとめ

元々IoTにはそんなに興味なかったのですが、色々応用の可能性があって面白いかなと思います。
また割と最近出来たプロダクトで、僕自身IoT経験（？）が一カ月にも満たないので記述に誤りがあるかもしれませんがご容赦下さい。
PlantUml memo

# PlantUml メモ
- 自分用メモ
- いろいろ追記していく(つもり)

## マクロ
- **!define**でマクロ定義
    - 毎回書くのが面倒な部分とかが楽 (特にスペルミスしやすい箇所とか楽)
    - 決まった書き方する箇所が多い時に、楽
    - 色定義とか、属性ごとに色分けするなら定義しておけば楽ちん
    - マクロの中でマクロ使用みたいなのもできた 

```plantuml
!define hoge(x) :x;
!define 樺色 9C4836

' !definelong ～ !enddefinelongで複数行のマクロ
!definelong Re(x,y,z)
x -> y : z
x <- y : z
!enddefinelong

[hoge] #樺色
```

## インクルード
- **!include**で別のpuファイルをインクルードできる。
    - 最初の定義部分とか作っておけば使い回しが聞く
    - 文中にインクルードして、編集単位を細分化できる
    - 例えば
        - ヘッダー
        - 本体部分
        - 本体部分に使われるこまごま
        - こまごまに使われるなんか
    - マクロも実際定義しておけばインクルードできるんじゃないか？(未確認)

```
!include header.pu

hoge -> foo
!include foo.pu

' 0番目のやつをインクルード
!include hoge.pu!0

```
単回帰と重回帰分析

#単回帰分析とは
y = 5x + 3という式があったとしてxの値がわかればyの値はわかりますよね。一つの値に対して一つの値を予測するのが単回帰分析です。
例えるなら身長が170センチぐらいだと体重は70キロくらいかな。という感じです。
#重回帰分析とは
体重 = 身長　- 100
のように現実世界はそう甘くありません。
身長は190センチあるのに体重が70kgのようなモデルみたいな人もいれば身長が150センチしかないのに100kgくらいあるひともいるでしょう。ではあとなんのデータがあれば体重を予測できるでしょう。例えば体脂肪率やウエストや服のサイズなどです。
体重 = 身長 ? 体脂肪率 ? 服のサイズ ? ウエスト
のように複数の種類の値から一つの値を予測することが重回帰分析です。
jQueryのattr()で属性をセットしたら、一括でvalue値が設定される。

自分用のメモ。

やりたかった処理は、jQueryでDOM要素を取得したら、一つの要素ごとにhref属性のvalue値を入れ替えたかった。

jQueryのattr()を使用した結果、取得したDOM要素全てのvalue値が入れ替わってしまうので、JavaScriptのsetAtribute()を使って、一つずつの要素に属性のvalue値を入れた。

```index.html
!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
</head>

<body>
   <a hret="https://www.yahoo.co.jp">yahoo</a>
   <a hret="https://www.google.co.jp">google</a>
   <a hret="https://in-sec.xyz">uno</a>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
    <script>
        $(function(){
            var a = $('a');
            a.each(function(key,val){
            a[key].setAttribute('href',"https://qiita.com/"); // aタグ一つの要素ごとに処理
            a.attr('href',"https://amazon.com/"); // aタグをまとめて処理
            });
          });
    </script>
</body>

</html>
```
サイゼリヤ1000円ガチャをつくってみた(Heroku + Flask + LINEbot)

Progateを一度やった程度のプログラミング初心者ですが、
何かWebアプリケーションを作りたいなぁと思い、Flaskを学ぶついでに
サイゼリヤのメニューから1000円以内で組合せを出してくれるガチャを作りました。

#### 2022.10.31 追記

Heroku有料化に伴い、以下をお知らせ致します。
- LINE Bot版 サービス終了
- Web版 旧アドレス（herokuapp.com）からのリダイレクト停止


#### 2019.5.10 追記
Twitterで紹介頂いたようで、たくさんの方から反応を頂いていてびっくりしております！
メニューが古いままだと、何かと店舗側にもご迷惑をおかけしそうだったので、
本日時点でのグランドメニューに更新させていただきました。

非公式であることをご了承の上、店舗ではマナーを守って楽しんで頂ければ本望です！
（たくさん注文して食べ残す・・・などが起こらないことを祈ってます）

また、Tweetボタンやガチャ条件を絞る機能など、諸々ご意見いただきましたので
参考にしながらゆったり実装できたらな、と思っていますのでよろしくお願いいたします。

#### 2019.04.01 追記 
2018.9月時点のグランドメニューのみとなります。
メニューの更新に対応する予定はございません

## できたもの
#### Webアプリ
[サイゼリヤ1000円ガチャ](https://saizeriya-1000yen.marusho.io/)
![スクリーンショット 2018-09-22 21.39.14.png](https://qiita-image-store.s3.amazonaws.com/0/208648/8ea50968-91b4-0b1a-b1ef-2180479a5272.png)

#### LINE Bot
~~上限50人のプランなので、登録できないかもしれません。~~
~~内容はWebアプリ版と同じです。~~

*Heroku有料化に伴いLINE Bot版はサービス終了しました*


結構意外な組み合わせでも1000円以下で、改めてサイゼコスパ高！ってなりますね。

どちらもHeroku無料枠でデプロイしているのでアクセスに時間がかかるときがあります。
(30分でスリープしてしまうため)まぁ非公式なのでお楽しみ程度ということで。

## モチベーション
Webアプリ作成の勉強のためにFlaskとSQL使ってみたかった。
LINEbotはちょこちょこ使っていて、インターフェースとして良いなぁと感じていたので
データベースを使って何かをするbotで簡単なもの、ということでガチャかなと。

なんでサイゼリヤかというと、単純に好きだからっていうのもあるんですが、
けっこう「サイゼリヤで何を頼むか」っていうのがネット記事でもネタになってるんですよね↓
実用性＋ネタで面白そうだと感じたためです。

**参考**
* [【対決】とにかく周りをビビらせろ！「サイゼリヤ通ぶり選手権」！](https://omocoro.jp/kiji/109284/)
* [「サイゼリヤ」で1人千円以内で完璧に飲むための極楽メニュー【ヒョイ飲み】](https://www.hotpepper.jp/mesitsu/entry/rio-yasuda/16-00111)
* [【せんべろ企画】千円握りしめて「サイゼリア」で飲み会してみた](https://plan-ltd.co.jp/plog/6739)

## 使ったもの
* Heroku
* LINE Messaging API
* Flask
* SQLAlchemy(SQLite)

ソースコードは[github](https://github.com/marushosummers/Saizeriya_1000yen)に置いてあります。
メニューはグランドメニューで100種類ちょっとなので手打ちでcsv→dbに入れました。
本当は勉強がてらスクレイピングしたかったんですが、画像データだったので・・・。

## 参考にしたページ
:star: **[Flask チュートリアル](https://study-flask.readthedocs.io/ja/latest/index.html)**
めちゃくちゃ参考にした。
一度通してやるだけで掲示板的なWebアプリを作れます。
SQLAlchemyの使い方やHerokuへのデプロイまで解説してくれています。

また、SQLの叩き方などは以下を参考にしました。
* [【PythonのORM】SQLAlchemyで基本的なSQLクエリまとめ](https://qiita.com/bokotomo/items/a762b1bc0f192a55eae8)
* [カラムに格納された値のデータ型の確認](https://www.dbonline.jp/sqlite/type/index2.html#section2)

HerokuとLINEbotの繋ぎこみはこちら
* [LineBot(MessageApi)を試してみる-heroku版](https://qiita.com/skycat_me/items/9f27cbd9354515df744a)

## 感想
初心者でもこんなに簡単につくれるんだ！と思いました。
特にHerokuやLineAPIなどのインフラがあるおかげで、Pythonのコードを少し学ぶだけで
ある程度形にできるちゃうところが凄い。

ガチャで出たメニューを実際に頼んでみた、みたいな人が現れるといいな笑
Windows 10のssh-agentをコマンド プロンプト、WSL、Git Bashで使ってみた

Windows 10（April 2018 Update）に付属の`ssh-agent`を使用してみました。
コマンド プロンプト（cmd）、WSL、Git Bashで使えることを確認しました。
（WSLはOSSの [`ssh-agent-wsl`](https://github.com/rupor-github/ssh-agent-wsl) が必要）

## `ssh-agent` の有効化
### GUIで行う場合
* サービス`OpenSSH Authentication Agent`のプロパティを開く。
* スタートアップの種類を「自動」に変更する。
* 「開始」をクリックしてサービスを開始する。
![service_openssh_property.png](https://qiita-image-store.s3.amazonaws.com/0/27531/0a470753-7680-8d08-f764-3796366df01d.png)

### CUIで行う場合
* コマンド プロンプトを「管理者として実行」する。
* `sc config ssh-agent start=auto`
* `sc start ssh-agent`

## 秘密鍵の登録
例としてコマンド プロンプトで行います。WSL、Git Bashで行っても登録先は同じです。
WSLで行う場合は `$HOME/.ssh` に適切なパーミッションで鍵を用意する必要があります。（ssh-agentを用いない場合と同様）
### 秘密鍵の例
`%USERPROFILE%.ssh\id_ed25519`
（例： `C:\Users\foo\.ssh\id_ed25519`）
### コマンド例
```
C:\Users\foo\.ssh> ssh-add id_ed25519
Enter passphrase for C:\Users\foo\.ssh\id_ed25519:
Identity added: C:\Users\foo\.ssh\id_ed25519 (bar@example.com)
C:\Users\foo\.ssh> ssh-add -l
256 SHA256:XxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxXxX bar@example.com (ED25519)
```

## コマンド プロンプトで使用する
普通にsshするだけです。

```
C:\> ssh bar@example.com
```

## WSLで使用する
### `ssh-agent-wsl` を導入する
https://github.com/rupor-github/ssh-agent-wsl からダウンロードする。
必ず Windows 側に配置する。
（例:　C:\local\ssh-agent-wsl）
### .bashrc に登録する
```bash:.bashrc
eval $(/mnt/c/local/ssh-agent-wsl/ssh-agent-wsl -r)
```

## Git Bashで使用する
Windowsの 環境変数 `GIT_SSH` に `C:\Windows\system32\OpenSSH\ssh.exe` を設定します。
それ以外に特に準備は必要ありません。

![env_git_ssh.png](https://qiita-image-store.s3.amazonaws.com/0/27531/7236058c-670e-d293-500a-f054906c2119.png)

## 気になること
### コマンド プロンプトから ssh すると、リモートから `ssh-add -l` を確認できない
```
$ ssh-add -l
channel 1: chan_shutdown_read: shutdown() failed for fd 8 [i0 o0]: Not a socket
error fetching identities for protocol 1: communication with agent failed
error fetching identities for protocol 2: communication with agent failed
The agent has no identities.
```
ただし使用はできている模様です。
当投稿には記載していませんが、`.ssh/config`の`ForwardAgent Yes`による鍵の転送は行えています。（ローカルで `ssh-add` した鍵をリモートで使用できる。）

### パスフレーズの保存先
`ssh-add`する際に入力したパスフレーズは Windows を再起動しても保存されています。（再入力不要）
これはどこに保存されているのでしょう。
こんな [記事](https://blog.ropnop.com/extracting-ssh-private-keys-from-windows-10-ssh-agent/) もあるようですが、ちょっと読み切れませんでした。

### ssh-agent-wslの注意書き
> SECURITY NOTICE: All the usual security caveats applicable to WSL apply. Most 
> importantly, all interaction with the Win32 world happens with the credentials 
> of the user who started the WSL environment. In practice, if you allow someone 
> else to log in to your WSL environment remotely, they may be able to access the 
> SSH keys stored in your ssh-agent with ssh-agent-wsl. This is a fundamental 
> feature of WSL; if you are not sure of what you're doing, do not allow remote 
> access to your WSL environment (i.e. by starting an SSH server).
Amazon EKS で「aws eks update-kubeconfig」コマンドによる kubeconfig ファイルの自動設定がサポートされました

# はじめに

先月『[Amazon EKS向けの「kubeconfig」設定ツールを作ってみた](https://qiita.com/hideaki_aoyagi/items/eb0267b8c8519c96cf90)』という記事を書きましたが、AWS CLI で公式にサポートされた模様です。

Amazon EKS Simplifies Cluster Setup with update-kubeconfig CLI Command
https://aws.amazon.com/jp/about-aws/whats-new/2018/09/amazon-eks-simplifies-cluster-setup-with-update-kubeconfig-cli-command/

自作ツールは短い命でした。hideaki_aoyagi 先生の次回作にご期待下さい。

― 完 ―


# 公式コマンドを使ってみました

AWS CLI を最新版にアップデートして、早速コマンドを使ってみます。

```
$ pip install --upgrade --user awscli
$ aws --version
aws-cli/1.16.19 Python/3.6.5 Linux/4.14.62-65.117.amzn1.x86_64 botocore/1.12.9
```

```
$ aws eks update-kubeconfig --region us-west-2 --name eks-cluster
Added new context arn:aws:eks:us-west-2:123456789012:cluster/eks-cluster to /home/ec2-user/.kube/config
Warning: aws-iam-authenticator is not installed properly or is not in your path.
Refer to the AWS Documentation to download it at https://docs.aws.amazon.com/eks/latest/userguide/configure-kubectl.html
```

むむ？ なんか警告が出ているようですが・・・

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:17:39Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Unable to connect to the server: getting token: exec: exec: "aws-iam-authenticator": executable file not found in $PATH
```

やっぱりダメですね。

なんか「aws-iam-authenticator」が無い (またはパスが通っていない) って言われてます。


# 上記のようなエラーが出てしまった人は

Amazon EKSのリリース直後にEKSの設定を行った人は、もしかしたら私と同じようなエラーが出てしまうかもしれません。
逆に言うと、最近EKSの設定を行った人はたぶん問題ないと思います。

どういうことかと言うと、以前のEKSユーザーガイドの「[Getting Started](https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/getting-started.html)」の記述では、kubectlを使うために「heptio-authenticator-aws」というツールをインストールするように案内されていました。

ところが、その後「heptio-authenticator-aws」は「aws-iam-authenticator」と名前が変わり、ユーザーガイドの記述内容もそれに合わせて更新されています。

`aws eks update-kubeconfig` コマンドが生成する `kubeconfig` ファイルは、aws-iam-authenticator に依存する作りになっています。

という訳で、EKS設定時に「heptio-authenticator-aws」をインストールした人は、改めて「aws-iam-authenticator」をインストールしましょう。
(heptio-authenticator-aws は削除してもしなくてもOKです)

```
$ curl -LO https://amazon-eks.s3-us-west-2.amazonaws.com/1.10.3/2018-07-26/bin/linux/amd64/aws-iam-authenticator
$ chmod +x ./aws-iam-authenticator
$ sudo mv ./aws-iam-authenticator /usr/local/bin/
```

これでエラーは出なくなります。
(`aws eks update-kubeconfig` コマンドを再実行する必要はありません)

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-21T09:17:39Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
Server Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:13:43Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"linux/amd64"}
```


# おわりに

公式ドキュメントや GitHub の更新はこまめにチェックすべきですね。
Centos7でM5Stack開発

別に大したことはないが「centos7 M5Stack」と検索したらそのものずばりなものがなかったので。私みたいな俄に思いついてスターターキットで買うような人向けに。

# やったこと
* インストール
* スケッチ例「display」を書き込む

## 実施環境
* Linux version 3.10.0-862.11.6.el7.x86_64 (builder@kbuilder.dev.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-28) (GCC) )  
* CentOS Linux release 7.5.1804 (Core)

カーネルの更新を先にやっておいた方が良いのかもしれないが……。
ていうかいつの間にか7.5になってたか。

# インストール
## Arduino IDE
買う時に確認していると思うが、M5StackはArduino IDEで開発できる。

* [Arduino IDEのページ](https://www.arduino.cc/en/Main/Software)あたりからダウンロードする。
  + Linux 64bitとか32bitを選択する。
* tar.xzファイルがダウンロードされるので[このページ](https://qiita.com/ymaru/items/87fbc4e68f5995d3964c)のようなコマンドで展開する。
* 展開したファイル（arduino-x.x.xとかのフォルダになるはず）の中のinstall.shを実行する → アプリ一覧に登録される。

（余談）インストールするときに寄付するか聞かれる。ハードの販売は利益追求してないのだろうか。まあarduinoを買ったわけじゃないしと思って寄付したが……寄付の説明ぐらい多言語にしておいてほしい。

## IDEの環境設定
Arduino IDEで開発できるといってもそのまま対応しているわけではない。
まあここらへんはWindowsや他のOSと似たような感じなのでググれば似たような話は出てくる。例えば下記
> [M5Stack の環境設定（Arduino & MicroPython）](http://blog.akanumahiroaki.com/entry/2018/08/11/083000)
> [M5Stackを試す2 (環境構築編)](http://artteknika.hatenablog.com/entry/2018/07/04/222212)

#### ボードマネージャー / espressif
https://github.com/espressif/arduino-esp32/blob/master/docs/arduino-ide に各OSの手順がある。
ただしcentosそのものはない。fedoraを参考にする。しかし問題は次のステップ。

``` sudo dnf install git python3-pip python3-pyserial ```

dnfがちゃんと設定されればそのままできるのかもしれないが、結局私はできなかった。
git, pip, python3が入っていることを確認して続きを実行。
後になってpyserialが……みたいなことになって下記を行った。

``` pip install pyserial ```

#### M5Stackのライブラリ
Arduino IDEを起動する。
ツール>ボードの一覧の下の方にESP32某が並んでいて、その下の方にM5Stack-Core-ESP32があるはずなので選択。
次にスケッチ>ライブラリをインクルード>ライブラリを管理　でM5Stackと検索してM5Stackというやつをインストール。（M5Stack by M5Stackでも良いらしいが）。

## 試してみる
ファイル>スケッチ例>M5Stack>Basics>Displayを選択。
「→」ボタンを押して「マイコンボードに書き込む」。
ここで私は３件ほど事件が。

1. 「SD.h」に対して複数のライブラリが見つかりました
1. No module named serial.tools.list_ports
1. /dev/ttyUSB0 permission denied

対処は下記。

1. ダウンロード（インストール）したArduinoのlibrariesにSDフォルダがあるので消す（tar.gzで固めて残しておいても良いが）
2. 先述のとおり、pip install pyserialする
3. これが私の頭ではよくわからん。結局```chmod 666 /dev/ttyUSB0```した。OSを再起動するたびにやらないといけないらしいが……

無事書き込めると、M5Stackの電源みたいなボタンを押すたびに赤青緑みたいに色が変わったあと小さな□○△みたいになって、そのあと三角形がわーとなる画面になる。わーとなるのはうざいので試しに下記のようにfillTriangleをコメントにしてみた。

``` 
// the loop routine runs over and over again forever
void loop(){

  //rand draw 
  //M5.Lcd.fillTriangle(random(M5.Lcd.width()-1), random(M5.Lcd.height()-1), random(M5.Lcd.width()-1), random(M5.Lcd.height()-1), random(M5.Lcd.width()-1), random(M5.Lcd.height()-1), random(0xfffe));

  M5.update();
}
```
[備忘録]  MacにLaravelをインストールする

# 概要

PHPで簡単なウェブサイトを開発中にやりたいことができずに詰まっていたので友人のススメで`Laravel`をインストールすることにした。


# 環境について


|    PHP    | Mac OS   |
|:------:|:--:|
|        7.1.16        |  Mac OS High Sierra (10.13.6)  |

### composerインストール

```
$ brew install homebrew/core/composer
```

### Laravelのinstall

```
$ composer global require "laravel/installer"
```

インストール中のログ (操作は`不要`)

```
Using version ^2.0 for laravel/installer
./composer.json has been created
Loading composer repositories with package information
Updating dependencies (including require-dev)
Package operations: 10 installs, 0 updates, 0 removals
  - Installing symfony/process (v4.1.4): Downloading (100%)         
  - Installing symfony/polyfill-ctype (v1.9.0): Downloading (100%)         
  - Installing symfony/filesystem (v4.1.4): Downloading (100%)         
  - Installing symfony/polyfill-mbstring (v1.9.0): Downloading (100%)         
  - Installing symfony/console (v4.1.4): Downloading (100%)         
  - Installing guzzlehttp/promises (v1.3.1): Downloading (100%)         
  - Installing psr/http-message (1.0.1): Downloading (100%)         
  - Installing guzzlehttp/psr7 (1.4.2): Downloading (100%)         
  - Installing guzzlehttp/guzzle (6.3.3): Downloading (100%)         
  - Installing laravel/installer (v2.0.1): Downloading (100%)         
symfony/console suggests installing psr/log-implementation (For using the console logger)
symfony/console suggests installing symfony/event-dispatcher
symfony/console suggests installing symfony/lock
guzzlehttp/guzzle suggests installing psr/log (Required for using the Log middleware)
Writing lock file
Generating autoload files
```

### パスを通す

```
$ export PATH="$PATH:$HOME/.composer/vendor/bin"
```

一度読み込む

```
$ source ~/.bashrc
```

### プロジェクト作成

laravel newコマンドで、プロジェクト。

```
$ laravel new {プロジェクト名}
```

`{プロジェクト名}`の部分を作成したプロジェクト名に書き換える

今回は`Sample`とする

具体例

```
$ laravel new Sample
```

インストール中

### [追記]

2回目以降のプロジェクト作成では作成できなかったので、下記のコマンドでプロジェクトファイルを作成できる。

```
$ composer create-project --prefer-dist laravel/laravel SampleProject
```

or

```
$ composer create-project laravel/laravel SampleProject --prefer-dist
```

これで`SampleProject`を作成できる

### laravelのバージョンを指定してプロジェクトを作成する

laravel 5.5 系のプロジェクトファイルを作成する

```terminal
$ composer create-project "laravel/laravel=5.5.*" sampleproject
```

* `sampleproject` は`プロジェクト名`で任意の名前でOK。

すると 5.5.X のバージョンのプロジェクトファイルを作成できる。

```terminal
$ php artisan -V
Laravel Framework 5.5.43
```

これがしたかった。

### ローカル開発サーバ起動

インストールが終了後

```
$ cd Sample
```

にて、Sampleフォルダに移動してから、

```
$ php artisan serve
```

を叩くと

```
Laravel development server started: <http://127.0.0.1:8000>
```

とログが表示される。

`http://127.0.0.1:8000`にアクセスするとページが表示される

<img width="1040" alt="スクリーンショット 2018-09-22 21.35.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/44392/e7475830-56f9-f167-c6fa-d79b203c172a.png">


インストール完成である。

### バージョンの確認

```
$ php artisan -V
```

もしくは

```
$ php artisan --version
```

で確認できる

```
Laravel Framework 5.7.5
```
現在使っているNuxt.jsのバージョンの調べ方メモ


`package.json`でlatest記載しているとnuxt.jsのカレントバージョンが分からんなぁと思ったのでメモ

```package.json
"dependencies": {
    "nuxt": "latest"
  },
```

色々な記事見てるとlatest表記推奨ってのもあるのでlatest表記で使ってたら気づいたら2系になってた模様。

## nuxt -v

プロジェクトのルートディレクトリで以下のコマンドで調べられました。

```bash
$ ./node_modules/nuxt/bin/nuxt -v
2.0.0
```

## ちなみ

v2になってこちらの内容でエラー起きたりしてました

> Module build failed: TypeError: Cannot read property 'eslint' of undefined
> [Nuxt.jsプロジェクトをv2(nuxt-edge)にアップグレードした際にハマったところ](https://qiita.com/sho_yamane/items/ce0d40450d373152eb18)

先人様に感謝
SPAについて学習


# 参考

## page

PWAとSPA、AjaxとDHTML - 流転の果てに - | SPAはじめてガイドブック | Greative
https://greative.jp/page/guidebook-spa-spa-and-pwa/

APIベースのヘッドレスCMS contentful + nuxt.jsを試してみた（contentful設定編）｜蓮田 健一｜note
https://note.mu/kenhasuda/n/n8c64a658dcfe

Firebaseで動くアプリをReact + Redux + TypeScriptで作るときのアラカルト - Septeni Engineer's Blog
http://labs.septeni.co.jp/entry/2018/02/08/090000#fnref:2

TypeScript と Redux に入門しながら Next.js でサンプルアプリケーションを作ってみた - Qiita
https://qiita.com/monzou/items/8ff07258a42042075d7b#nuxtjs-%E3%81%AE%E6%A9%9F%E8%83%BD%E3%81%8C%E8%B1%8A%E5%AF%8C%E9%81%8E%E3%81%8E%E3%81%9F

## nuxt

データバインディング構文 - vue.js
https://v1-jp.vuejs.org/guide/syntax.html

Nuxt.jsの学習（インストールからビルドまで） - Qiita
https://qiita.com/mrymmh/items/9ad350bbf943aadec7ef

## code

cosmicjs/nuxt.js-website： Nuxt.js website example using Cosmic JS
https://github.com/cosmicjs/nuxt.js-website

## cosmicjs

cliを使うと便利。。
他人のオブジェクトが帰ってきているような。。
トライアルだからかなあ。。

https://github.com/cosmicjs/cosmic-cli

# 所感

* Nuxt.jsについて理解してないけど動いた
	* pagesが起点でアンダーバー付きが動的なのね
	* `nuxt`でホットリロードするとうまくいかないことがあった`nuxt start`とどう違うのかな
* CosmicJSの扱いがなんとなくわかったような気がする
	* 多分ページ以外のデータイプを使ってDB的なことをできなくもなさそうだけどリクエストが料金消費に紐づくのかな
	* twitterのデータタイプもgetPageで扱えた（ちょっと苦労した）
		* 多分、使ったexampleの挙動だと思うけど、twitterのデータタイプだとエラーが起きる
Djangoのmodelでの、eager loading機能であるprefetch_relatedに検索条件を追加する

今更言うまでもないんですが、ORMってとっても便利ですよね。
pythonのフレームワークのDjangoにも実装されているんですが、便利がゆえに地雷になることもあったり。:volcano:
備忘録もかねて対応策を

# やけに負荷のかかっているSQLが発生

```all_prefetch.py
Foo.objects.filter(
    hoge=foo
).prefetch_related('bar')
```

上記のような一見、何の問題もなさそうなSQLを実行していたんですよ。
Fooテーブルから該当の条件のデータを取得して、1:N問題を避けるべく、relation関係にあるbarテーブルの内容をまとめて取得する……という。
ところが、何故かこの処理が呼び出されるAPIだけ処理が重いという事象が発生してみたので早速、調査を:thinking:

# 大量のデータを取得しているッ！？

```check_all_prefetch.py
# ↑↑　この前にログイン中のユーザのデータを取得している

Foo.objects.filter(
    hoge=foo
).prefetch_related('bar') # <- barが1000件ぐらい存在していた

# ↓↓ そしてここより後の処理で、barから引っ張ってきたデータを、
# ユーザが持つ情報に応じてpython側でフィルタリングしている。
```

そう、SQL側でやるべきことをやっておらず、python側でやっていたッ！
データの転送量が多く、アクセスが殺到した際に問題になっていたという新事実が。
ありがちな問題……ではあるんですが、とはいえprefetch_relatedの部分に条件を設定できるような引数はなさそうです:sob:

# prefetch_relatedに検索条件を追加するッ！

```add_filter_prefetch.py
from django.db.models import Prefetch

# barのprefetch内容を設定
p = Prefetch('bar', Bar.objects.filter(id__in=user.hoge))

# prefetchに上記で作成したオブジェクトを渡す
Foo.objects.filter(
    hoge=foo
).prefetch_related(p)
```

こんな感じの修正になりました！
Prefetchを使用することでprefetch_relatedで生成されるSQLにも正しく検索条件を追加できています
これでpython側でフィルタリングするという不毛なこともなく、データの転送量も抑えらるようになりました:blush:
swift - 4.2 では Linux でも Foundation が使える

Swift が正式に 4.2 になりました。

* https://swift.org/blog/swift-4-2-released/

色々いいことがあるのですが、個人的に一番嬉しいのは、 Linux でも macOS 同様に `Foundation` が使えること。これで macOS とのコード共有率が格段に上がります。

<img width="1136" alt="Screen Shot 2018-09-22 at 21.13.30.png" src="https://qiita-image-store.s3.amazonaws.com/0/19227/4314e673-5622-2add-a86c-38eee313820d.png">

なのですが、[公式Downloadページ]の取説のママだと

[公式Downloadページ]: https://swift.org/download/#using-downloads

```sh
Welcome to Swift version 4.2 (swift-4.2-RELEASE). Type :help for assistance.
  1> import Foundation
error: Couldn't lookup symbols:
  _swift_FORCE_LOAD_$_swiftGlibc
```

という具合に使えません。`clang`, `libicu-dev` に加え、 `libcurl4` も必要なのが原因です。以下は Ubuntu 18.04 の例です。

https://gist.github.com/dankogai/52cd6ef645c9fc248547b79dccd8e893

```sh
$ cd ~ # home directory で作業
$ sudo apt-get install clang libicu-dev libcurl4
$ wget https://swift.org/builds/swift-4.2-release/ubuntu1804/swift-4.2-RELEASE/swift-4.2-RELEASE-ubuntu18.04.tar.gz
$ tar xvpf swift-4.2-RELEASE-ubuntu18.04.tar.gz
$ export PATH=~/swift-4.2-RELEASE-ubuntu18.04/usr/bin:$PATH
```

これでうまく行ったという方はその旨コメントしていただけると嬉しいです。Enjoy!

Dan the Safe, Fast and Expressive
「Let's Encrypt」ー CentOS7 nginx

# **実行環境**
- CentOS7
- nginx 1.12.2

## **Step1**
## **certbotのインストール、発行**
「certbot」とは？
Let’s Encryptが提供しているクライアントソフトウェアです。
これを使えば楽々に証明書を取得して更新できるようになります。

```bash
//clone
$ sudo git clone https://github.com/certbot/certbot.git

//ディレクトリ移動
$ cd ~/certbot

//導入
$ sudo ./certbot-auto
```
いろいろ聞かれますので自分に合った環境で設定してください。
しっかりと答えていると設定を自動でやってくれちゃいます。

## **LastStep**
## **自動更新の設定**

Let'sEncryptを利用する上で気をつけたい点があります。
**証明書の有効期限は90日で切れます。**
なので、証明書を自動で更新するようにしましょう。

```bash
$sudo crontab -e

//毎月の1日に更新、再起動を行います
0 1 1 * * root /ホームディレクトリ/certbot/certbot-auto renew --force-renewal && systemctl restart nginx
```
Actions on Google と Alexa Skill での都道府県名、市区町村名の取得 

# 最初に

Actions on Google と Alexa Skill では、ユーザーが発話した内容から、都道府県名や市区町村名を抽出でき利用できますが、同じ発話内容でも、Google Assistant と Amazon Alexa を通してアプリ側に伝わってくる情報に違いがあるのでまとめておきます。なお、2018年9月時点で確認した内容になります。

# Google Assistant (Dialogflow) -> Actions on Google の場合

## 仕様
Google Assistant (Dialogflow) の場合は、都道府県と市区町村の情報が、'admin-area', 'subadmin-area', 'city' の3つのプロパティに分かれて取得でき、'admin-area' には都道府県の情報が、'subadmin-area' には区の情報が、'city' には市町村の情報が格納されています。

## 実際の挙動
各発話パターン別の実際の挙動になります。

| 発話 | 説明 | 認識結果 | 解説 |
|---|---|---|---|
|"東京都"|都道府県名を発話 |{'admin-area': '東京都'}| 都道府県名として認識 |
|"東京"|都道府県名の "都" を省略して発話 (同名の市町村名が存在しない)|{  "city": "東京" }|市町村名として認識|
|"北海"|都道府県名の "道" を省略して発話 (同名の市町村名が存在しない)|-|認識不能|
|"京都"|都道府県名の "府" を省略して発話 (同名の市町村名が存在する)|{'city': '京都'}|市町村名として認識|
|"愛知"|都道府県名の "県" を省略して発話 (同名の市町村名が存在しない)|-|認識不能|
|"山口"|都道府県名の "県" を省略して発話 (同名の市町村名が存在する)|{'city': '山口'}|市町村名として認識|
|"アメリカ県"| 実在しない都道府県名を発話 |-|認識不能|
|"東京都品川区"|東京都と東京23区名を続けて発話 |{'admin-area': '東京都', 'subadmin-area': '品川区'}|東京都と区名を両方認識|
|"品川区"|東京23区名を発話 |{'subadmin-area': '品川区'}|区名として認識|
|"品川"|東京23区の "区" の部分を省略して発話 |{'subadmin-area': '品川区'}|区名として認識、"区"が補完されている|
|"神奈川県横浜市"|都道府県名と市町村名を続けて発話 |{'admin-area': '神奈川県', 'city': '横浜市'}|都道府県名と市町村名を両方認識|
|"横浜市"| 市名のみを発話 |{'city': '横浜市'}|市名として認識|
|"横浜"| 市名のみを "市" の部分を省略して発話 |{'city': '横浜'}|市名として認識|
|"アメリカ市"| 実在しない市名を発話 |-|認識不能|
|"横浜市青葉区"| 政令指定都市の市名と区名をつなげて発話 |{'city': '横浜市'}|市名のみ認識され、区名は認識されない|
|"青葉区"| 政令指定都市の区名のみを発話 |{'subadmin-area': '青葉区'}|区名として認識|
|"青葉"| 政令指定都市の区名のみを "区" の部分を省略して発話|-|認識不能|
|"アメリカ区"| 実在しない区名を発話 |-|認識不能|

## まとめ（注意点）
* 都道府県名は、"都""道""府""県" まで含めて発話しないと都道府県名として認識されない
    * "都""道""府""県" を省略した場合は、いくつかパターンがある
        *  同名の市町村名が存在する場合は、市町村名として認識される（例：京都、大阪）
        *  同名の市町村名が存在しない場合は、認識されない（例：愛知）
        *  "東京"は例外で、同名の市町村名が存在しないが、市町村名として認識される（謎）
* 政令指定都市の場合、"横浜市青葉区" のように、市と区を両方発話しても、市の情報しか取得できない。区の情報は捨てられる
 * "東京都品川区" のように都道府県名と市区町村名を続けて発話した場合は、都道府県と市区町村の両方が情報が取得できる
* "青葉" のように、政令指定都市の "区" を省略して発話した場合は、認識されない
 * "横浜" のように、"市" を省略して発話した場合は、市町村名として認識はされるが、"市" が補完されることなく、"横浜" の形で取得される
 * 東京23区の場合は、"品川" のように "区" を省略した形で発話しても、"品川区" のように "区" が補完された形で取得できる
 
# Amazon Alexa -> Alexa Skill の場合

## 仕様

Alexa の場合は、Google Assistant (Dialogflow) と違って、ユーザーが発話した内容が、何も識別・処理されず、単一の 'City' プロパティにそのまま格納されます。そのため、都道府県名なのか市区町村名なのかということは判別できず、それ以前に、実在しない都道府県名であったり市区町村名であったとしてもそのまま格納されてます。なので、それらの識別を全てスキル側でおこなう必要があります。

## 実際の挙動

前述のとおり、ユーザーが発話した内容がそのまま格納されるため、発話パターンによって挙動は変わりません。

## まとめ（注意点）

Amazon Alexa 側では、ユーザーが発話した内容が、都道府県名なのか市区町村名なのかが識別されないため、スキル側で識別する必要があります。また、実在しない名前を発話した場合でも、そのまま格納されるので注意する必要があります。

# Google Assistant (Dialogflow) と Amazon Alexa の比較

Google Assistant (Dialogflow) では、都道府県、市区町村の情報が識別された状態で取得できますが、Amazon Alexa では、ユーザーが発話した内容そのままなので、スキル側で識別する必要があります。この観点では、Google Assistant (Dialogflow) のほうが、使い勝手がいいかもしれません。


# まとめ
同じ発話内容でも、Google Assistant (Dialogflow) と Amazon Alexa とで、アプリに伝わってくる情報に違いがあるので、アプリケーションロジックを実装したバックエンドを共通にする場合などは、これらの違いを吸収する工夫が必要になります。

また、これは、Google Assistant (Dialogflow) 、Amazon Alexa 共通の話ですが、"横浜市" といったように、"市" をつけてユーザーが発話した場合は、そのまま伝わってくる一方、"横浜" といったように、"市" を省略して発話した場合でも、"市" が補完されず、そのまま伝わってくるので、このようなユーザーによる微妙な発話の違いを吸収する仕組みが必要になるかと思います。
公開鍵と秘密鍵の作成方法【macOSHighSierra】

SSH接続に使う公開鍵・秘密鍵の作成方法について記載します。

#概要
GitHubに使用するので、鍵の作成方法について記載します。
※環境はmacOSHighSierraを想定しています。

##公開鍵・秘密鍵の作成方法

```ruby:コンソール
ssh-keygen -t rsa
Enter passphrase (empty for no passphrase): <-- "パスフレーズを入力(任意)"
Enter same passphrase again: <-- "もう一度、パスフレーズを入力(任意)"
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
```

※id_rsa･･･秘密鍵（クライアントに設置）
※id_rsa.pub･･･公開鍵（GitHubなどに登録）

###コンソールで作成出来ているか確認する
ホームディレクトリ直下に作成された公開鍵・秘密鍵を確認します。

```ruby:コンソール
ls ~/.ssh
id_rsa  id_rsa.pub
```
rubyでclockwork を使ったときのNoMethodError対処方法 

railsで、ではなくrubyでclockworkを使ったときにNoMethodErrorが出たのでその対処法

##環境
* ruby 2.5.1
* clockwork 2.0.3

簡単な処理を動かしてみます

```clock.rb
require 'clockwork'
include Clockwork

def one_minute
  p "minutely job"
end

def one_hour
  p "hourly job"
end

handler do |job|
  self.send(job.to_sym)
end

every(1.minute, 'one_minute')
every(1.hour, 'one_hour')

```
```
$ clockwork clock.rb
...
...
/Users/user/hoge/clock.rb:18:in `<module:Clockwork>': undefined method `minute' for 1:Integer(NoMethodError)
```
と、このようなエラーが

Integerクラスには`minute'なんてメソッドはないよ　というエラーなのでActive Supportをいれてあげます。

## Active Supportとは
Object、String、Array、Hash、DateといったRubyの基本的なクラスに便利なメソッドを追加してくれるライブラリ
railsにはデフォルトでAcrive Supportが組み込まれているので、blank?メソッドなどが使えます。

##対処法
IntegerクラスのminuteメソッドもActive supportが追加してくれるので、gem installしましょう

```:Gemfile
...
...
gem 'clockwork'
gem 'activesupport'
```
```
$ bundle install
```

requireも忘れずに

```clock.rb
require 'clockwork'
#追加
require 'active_support/all'
include Clockwork
...
...
every(1.minute, 'one_minute')
every(1.hour, 'one_hour')
```
```
$ clockwork clock.rb
I, [2018-09-22T20:16:47.890148 #14730]  INFO -- : Starting clock for 2 events: [ one_minute one_hour ]
I, [2018-09-22T20:16:47.890641 #14730]  INFO -- : Triggering 'one_minute'
"minutely job"
I, [2018-09-22T20:16:47.890853 #14730]  INFO -- : Triggering 'one_hour'
"hourly job"
I, [2018-09-22T20:17:47.001826 #14730]  INFO -- : Triggering 'one_minute'
"minutely job"
```

上手くいきました