OmniAICreator/Qiita-1.07M huggingface dataset:
TerraformのBackend機能を利用して.tfstateを管理する

## Backend機能とは
* .tfstateファイルをどこで管理するか設定できる機能
* Gitで管理しない理由は[How to manage Terraform state](https://blog.gruntwork.io/how-to-manage-terraform-state-28f5697e68fa)を参照
* 今回はS3とDynamoDBを利用する設定を行う

## S3とDynamoDBを作成

### S3の設定

* まずはプライベートバケットを作成する
* このバケットに.tfstateファイルを保存していく
* 設定を戻す時のためにバージョニングを有効にすること

```
resource "aws_s3_bucket" "terraform-state-storage" {
  bucket = "terraform-state-storage"
  acl    = "private"

  versioning {
    enabled = true
  }
}
```

### DynamoDBの設定

* 次にロックテーブルを作成する
* 最低限でいいのでRC/WCは1にする

```
resource "aws_dynamodb_table" "terraform-state-lock" {
  name           = "terraform-state-lock"
  read_capacity  = 1
  write_capacity = 1
  hash_key       = "LockID"

  attribute {
    name = "LockID"
    type = "S"
  }
}
```

### 実行

* 上で設定した分を実行する

```
terraform init
terraform apply
```

## Backend設定

* 先にS3とDynamoDBを作っておかないとエラーになる
* bucketに上で作ったバケット名、dynamo_tableにテーブル名
* keyに設定した名前で.tfstateファイルが保存される
    * 環境毎に名前を変更することで環境毎に保存することも可能

```
terraform {
  required_version = ">= 0.11.7"

  backend "s3" {
    bucket         = "terraform-state-storage"
    key            = "terraform.tfstate"
    region         = "ap-northeast-1"
    dynamodb_table = "terraform-state-lock"
  }
}
```

## 実行・確認

* init, applyした後、S3を確認すると、keyで設定した名前でファイルが登録されている
Cognitoでfailed to satisfy constraintエラーが出る場合

Lambda + CognitoでEメール検証メッセージをカスタマイズ使用とした場合に以下のようなエラーが出ることがある。

```bash
1 validation error detected: Value '...' at 'emailBody' failed to satisfy constraint: Member must satisfy regular expression pattern: [\p{L}\p{M}\p{S}\p{N}\p{P}\s*]*\{####\}[\p{L}\p{M}\p{S}\p{N}\p{P}\s*]*
```

# 原因
全角のスペースが上記の正規表現に含まれてないための模様。

# 対応
全角スペースを除却することで解決。
Xcode9でSimulatorのUserDefaultsの中身をplistで確認する

該当のsimulatorが起動していることが前提です。

```
~/Library/Developer/CoreSimulator/Devices/デバイスID/data/Containers/Data/Application/起動履歴？/Library/Preferences/アプリのBundleIdentifier.plist
```

※1
「デバイスID」はWindow -> Devices and Simulatorsから起動しているSimulatorを選択したら表示されています。

※2
「起動履歴？」はよくわからないので、一つ上の階層にChangeDirectoryしてから「find . -name アプリのBundleIdentifier.plist」でfindすると経験上一つだけHITしました。

あとはこのplistをXCodeでひらけばお目当のものが確認できるはず。
KUSANAGI for VMware から KUSANAGI for さくらのクラウドへ WordMove で push する

# 手順
## 1. rbenv のインストール
[rbenv を使って ruby をインストールする\(CentOS編\) \- Qiita](https://qiita.com/inouet/items/478f4228dbbcd442bfe8)
上記を参考に、rbenvを入れる。ただ、**readlineがない**ってエラーが出るので、予め、yumで入れておこう。ちなみに、gitははじめから入っていた。

```bash
[GUEST KUSANAGI]$ sudo yum install -y readline-devel
[GUEST KUSANAGI]$ git clone https://github.com/sstephenson/rbenv.git ~/.rbenv
[GUEST KUSANAGI]$ echo 'export PATH="$HOME/.rbenv/bin:$PATH"' >> ~/.bashrc
[GUEST KUSANAGI]$ echo 'eval "$(rbenv init -)"' >> ~/.bashrc
[GUEST KUSANAGI]$ source .bashrc
[GUEST KUSANAGI]$ git clone https://github.com/sstephenson/ruby-build.git ~/.rbenv/plugins/ruby-build
[GUEST KUSANAGI]$ rbenv install 2.5.1
[GUEST KUSANAGI]$ rbenv rehash
[GUEST KUSANAGI]$ rbenv global 2.5.1
```

## 2. WordMoveをインストール
[welaika/wordmove: Multi\-stage command line deploy/mirroring and task runner for Wordpress](https://github.com/welaika/wordmove)
上記、WordMoveのgithubのReadMeを見ながら、wordmoveを入れる

```bash
[GUEST KUSANAGI]$ gem install wordmove
[GUEST KUSANAGI]$ rbenv rehash
```

## 3. movefile.ymlを作成
普段```wordmove```コマンドを打ちそうなディレクトリに移動して、movefile.ymlを作る

```bash
[GUEST KUSANAGI]$ cd ~/project_name/
[GUEST KUSANAGI]$ wordmove init
```

## 4.movefile.yml を書き換える
movefile.yml自体の記述については、別の人の記事を参照いただくとして、KUSANAGI宛にテーマファイルをpushする際に気をつける設定をする

```yml
global:
  sql_adapter: wpcli

local:
  vhost: http://example.com
  wordpress_path: /your/wp/path

  database:
    name: wordpress_db_name
    user: wordpress_db_user
    password: "wordpress_db_pass"
    host: 127.0.0.1

staging:
  vhost: http://staging.example.com
  wordpress_path: /your/wp/path/at/remote

  database:
    name: remote_db_name
    user: remote_db_user
    password: remote_db_pass
    host: localhost

  exclude:
    - '.git/'
    - '.gitignore'
    - 'node_modules/'
    - 'bin/'
    - 'tmp/*'
    - 'Gemfile*'
    - 'Movefile'
    - 'movefile'
    - 'movefile.yml'
    - 'movefile.yaml'
    - 'wp-config.php'
    - 'wp-content/*.sql.gz'
    - '*.orig'
    - 'gulp/'

  ssh:
    host: ssh_host_name
    rsync_options: --verbose --itemize-changes --chmod=Da=rwx,Fu=rw,Fg=r,Fo=r # Add chmod param
```

追加するのは、 ```--chmod``` オプション。普通にpushすると、なぜかすべてのファイル/ディレクトリが770になり、ページが表示されなくなるので、```--chmod=Da=rwx,Fu=rw,Fg=r,Fo=r```を追加し、「ディレクトリは777に、ファイルは644に」なるようにしておく。

ただ、このコマンドはプラグインなどの転送にも利用されるので、**もしかしたらファイルのパーミッションも777のほうがいいかもしれない**。

# 参考サイト
- [rsync でコピー先のパーミッションを統一する \- それマグで！](http://takuya-1st.hatenablog.jp/entry/2016/02/06/232728)
- [rsync(1) - Linux man page](https://linux.die.net/man/1/rsync)
ulimit で nofile に大きい値を設定したい

ulimit で詰まった。のでメモ。

# 環境
- Arch Linux x64

# 詰まったところ

``` :shell
user $ ulimit -n
1024
user $ ulimit -Hn
4096
user $ ulimit -Sn 12000
user $ ulimit -n
4096
user $ ulimit -Hn 12000
ulimit: Permission denied when changing resource of type 'Maximum number of open file descriptors'
user $ 
```

nofile に 4096 までしか設定できない。

# 対応

``` :shell
user $ sudo su
[sudo] password for user:
root # ulimit -n
1024
root # ulimit -Hn
4096
root # ulimit -Hn 12000
root # ulimit -Sn 12000
root # ulimit -n
12000
root # su - user
user $ ulimit -n
12000
```

一応できたが、良い方法ではないかもしれない。
いくつかのOSでマシンタイプとシリアルを取得

# いくつかのOSでマシンタイプとシリアルを取得

　資産管理やサポート問い合わせなどで必要な情報なのに、取得するときどうやるのだったか……と毎回迷うのでまとめ。
（私が）よく使うOSについて記載しましたが、これ以外のOS上でのマシンタイプとシリアル取得方法も募集中です。


## Windows
　wmicを利用すると表示できます。wmicは色々できる強力なコマンドなので、これ以外も知っておくと便利です。

| 要素 | コマンドのオプション |
|:-:|:-:|
| マシンタイプ | Name |
| シリアル | IdentifyingNumber |

```CMD:wmicの例
C:\>wmic csproduct get identifyingnumber, name
IdentifyingNumber  Name
xxxxxxxx           xxxxxxxxxx
```


## Linux
　dmidecodeコマンドにより取得可能です。```#```付きでコメントを書いておくと、後からhistoryを検索するときに便利なので足しています。
　以下はRed Hat Enterprise Linux Workstation release 6.8 (Santiago)で確認した結果になります。

```bash:dmidecodeの例
$ dmidecode --type system | grep -i serial   # Serial
	Serial Number: xxxxxxxx
$ dmidecode --type system | grep -i product   # Machine Type
	Product Name: xxxxxxxxxx
```


## AIX
　prtconfコマンドにより取得可能です。

```bash:prtconfの例
$ prtconf | grep . | head -2   # Machine Type & Serial
システム・モデル: IBM,xxxx-xxx
マシンのシリアル番号: xxxxxxx

$ prtconf 2>&1 | head -2   # Machine Type & Serial
システム・モデル: IBM,xxxx-xxx
マシンのシリアル番号: xxxxxxx
```

　間に```grep .```などをはさんでるのは、prtconfの結果をパイプでheadに渡そうとするとエラーとなってしまったため、その暫定回避策として入れています。

```bash:prtconfでエラー
$ prtconf | head -2   # Error
システム・モデル: IBM,xxxx-xxx
マシンのシリアル番号: xxxxxxx
/usr/sbin/prtconf: パイプに書かれたデータを読み取るプロセスがありません。
```



# 参考
- [Windows 7からThinkPadのプロダクト番号とシリアル番号を調べる方法](http://d.hatena.ne.jp/EijiYoshida/20130410/1365595617)
- [\[Linux\] ハードウェアのシリアル番号やモデル名を確認する](http://unyouchan.blog.jp/archives/2272229.html)
- [IBM Knowledge Center - prtconf コマンド](https://www.ibm.com/support/knowledgecenter/ja/ssw_aix_72/com.ibm.aix.cmds4/prtconf.htm)
intellijでspring bootをdebugする

# はじめに

- mavenでspringを起動する時にデバッグ用のパラメタを付ける
- intellijのremoteデバッガを起動する
- socketを経由してspring-boot:runの実行状態をintellijのデバッガでブレークポイントを扱えるようになる。

# spring-boot:run

```console
mvn clean spring-boot:run -Drun.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"
```
or

intellijのmaven実行画面に下記を設定して実行

- Parameters > Command line: > `spring-boot:run`
- Runner > VM Options: > `-Drun.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=5005"`

# intellij remote

remote実行をパラメタをいじらずに追加後、実行。spring-boot:runが待機状態にならないうちに、remoteを実行するとエラーが出る。
Udacity Full Stack Web Developer Nanodegreeを受講して１ヶ月のまとめ

タイトルのNanodegree programを受講して1ヶ月ほどが経ったのでQiitaに初投稿をしながら、これまでの記録を書いていきたいと思います。
# Udacity Nanodegreeとは
[Udacity](https://www.udacity.com/)はプラグラミングなどをオンラインで学習できるサイト(英語)です。コースを取るだけならば基本的には無料なのですが、Nanodegreeといってweb、AI、VRなどの技術を学びたい人がUdacityの定める複数のコースを順番に受講し、途中の課題をクリアしていき技術をマスターするというものです。
特徴としては、課題はUdacityのスタッフの方がコードレビューやアドバイスをくれるという点です。あと、困ったときにチャットなどでメンター(コースを受講するとメンターが一人つく)に質問できることです。
<img width="1308" alt="Screen Shot 2018-04-15 at 2.09.14.png" src="https://qiita-image-store.s3.amazonaws.com/0/250294/180d430c-8d11-f670-ac4e-12efbaf36e52.png">
(Nanodegreeのトップページ)
# Full Stack Web Developer Nanodegree
今回、僕が受講しているコースは[Full Stack Web Developer Nanodegree](https://www.udacity.com/course/full-stack-web-developer-nanodegree--nd004)で、フルスタックウェブエンジニアの技術習得も目的としたコースです。
学ぶ内容は大きく分けて以下の５つです。

- PythonやHTML、CSSの基礎
- Gitやその他開発に必要なツールの使い方
- バックエンド開発(データベース、SQL、ログインシステムなど)
- フロントエンド開発(Javascript、AJAX)
- Linux Server

Udacityのスタッフによるチェックがある課題は合計で以下の6つです。

- Movie Trailer Website
- Build a Portfolio Site
- Logs Analysis
- Item Catalog
- Neighborhood Map
- Linux Server Configuration

今回の記事では、すでに完了した最初の2つの課題についての概要を書きたいと思います。

# Movie Trailer Website(課題)
題名からしてWebサイトを作るような印象を受けるのですが、実際に私たちが実装をするのは、Pythonのコードを書くことだけなので、Webの知識が実際になくても出来るような内容になっています。
この課題は、その前に受けるpythonの講座を順を追って学習すれば、1時間もかからずににできます。
<img width="250" alt="Screen Shot 2018-04-16 at 16.44.40 copy.png" src="https://qiita-image-store.s3.amazonaws.com/0/250294/f0dcddba-f11d-ce97-77ae-f0c581517aed.png">
(実際に作ったサイト)

１つ注意することですが、書いたpythonのコードはPEP8というコーディング規約を守る必要があります。
[PEP8 online check](http://pep8online.com/)というサイトに自分の書いたコードを貼り付けるとcheckできます。
その他にもPEP8に準拠しているか調べるツールがあるので、[こちら](https://qiita.com/ynakayama/items/8616f4c0c6e372de9a42)も試してみるといいと思います。
ちなみに、私自身は２回ほどPEP8の規約に反しているということでやり直し提出をしました。

# Build a Portfolio Site(課題)
この課題はWebのFrontend開発のコースを受けたあとに行う課題です。ウェブページのデザインがpdfファイルで渡されるのでそのデザインをみながら、html、cssを使って再現するものです。Media Queryを用いて、自分なりにブラウザのサイズ毎に表示を変えるカスタマイズを考えなければなりません。
私の場合は３つの状態を考えて実装しました(モバイル、デスクトップ中サイズ、デスクトップ大サイズ)。
こちらの課題は最初の課題と比べるとすこし時間がかかりますが、コースの内容をしっかりと理解できるようならば、そこまで難しくはないと思います。私の場合は３時間ほどで作りました。
<img width="200" alt="portfolio_mobile.png" src="https://qiita-image-store.s3.amazonaws.com/0/250294/c6ef4f29-773b-0574-2aec-8a3a1326bb76.png">
(モバイル)

# まとめ
今回の記事ではUdacity Full Stack Web Developer Nanodegreeの紹介と自分の進捗のまとめを書きました。
現在は3つ目の課題であるLogs Analysisを行っていますが、SQLを使った経験がほとんどないため、コースの内容を何回か見たり、色々調べながら進めているところです。
[GAS]実行時間6分の壁を越えよう(不死鳥関数編)

# Google Apps Scriptの限界を越えよう
GASでは、実行時間6分の壁があります。
でっかい処理を行ったときに、タイムアウトするというやつですね。
本稿では、タイムアウトする前にいったん処理を中止して、トリガーセットで再度実行させるという方式で立ち向かってみます。

## と、その前に
こういうやり方もありますよ、とお見せする前に。

- 余計なAPI呼び出ししてないですか?
    - 無意味なデータ読み書き
- 冗長なAPI呼び出ししてないですか?
    - データ読み書きがまとまっていない
- それ、まじでGASでやる必要ありますか?

データの読み書きにフォーカスしているのは、非エンジニアにとってスプレッドシートを触る機会が圧倒的に多く、かつGASの中でシートデータの読み書きは **圧倒的に時間がかかる** からです。
正直、計算とかはすぐ終わります。数秒です。
読み書きはデータの大きさによっては数分かかります。

## 不死鳥のように蘇らせよう

### 道具
- スクリプトのプロパティ  
    スクリプトには、それぞれデータを溜めておけるデータストア的なものがあります。  
    スクリプトのプロパティというやつです。こいつを使って、実行を中断するときの必要情報を残しておきます。  
    [@tanabee様のGAS ビギナーが GAS を使いこなすために知るべきこと 10 選](https://qiita.com/tanabee/items/2c51681396fe12b6a0e4#5-%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88%E6%AF%8E%E3%81%AE%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B9%E3%83%88%E3%82%A2%E3%81%8C%E3%81%82%E3%82%8B)  
- スクリプトトリガー

### 実行イメージ
1. スクリプトのプロパティから必要な値を引っ張ってくる
2. 関数実行開始時間を取得
3. ループ
    1. 現在時刻の取得
    2. difference = { 現在時刻 - 実行開始時刻 }
    3. ◯分経過しているか
        - している  
           スクリプトプロパティの更新を行う  
           次回実行のためのトリガーの設定  
        -  していない
           処理を行う  
4. ループ後処理(必要なら)
5. スクリプトプロパティの初期化
6. トリガーの削除(しないと永遠に回り続けるぞ?)

### スクリプト例
```javascript
/*
* GAS5分実行を越える!!
* スクリプトプロパティを活用
*/
function phoenix(){
  var properties
    = PropertiesService.getScriptProperties();
  // 例はint
  var prop
    = parseInt( properties.getProperty("<name_of_property>") );

  // 関数実行時点の時刻取得
  var start_time = new Date();

  for( i ){
    // 現在時刻を取得する
    var current_time = new Date();
    // 実行時間取得
    var difference
      = parseInt( (current_time.getTime() - start_time.getTime()) / (1000 * 60) );

    //4分を超えていたら中断処理
    if(difference >= 4){
      /* 値の書き込みとか必要ならやる */

      // スクリプトプロパティの更新
      properties.setProperty("<name_of_property>",i);
      
      // ここはもうちょっと利口なやり方がありそう。
      ScriptApp
      .newTrigger("phoenix")
      .timeBased()
      .everyMinutes(5)
      .create();

      return ;
    }else{
      /* 通常処理 */
    }//if_escape
  }//ループ処理

  // スクリプトプロパティの初期化
  properties.setProperty("<name_of_property>",<initial_value>);

  //特定関数のトリガーのみ削除
  delete_specific_triggers("phoenix");

  return ;

}//func_phoenix

// 特定関数のトリガーを全て削除
function delete_specific_triggers( name_function ){
  var all_triggers = ScriptApp.getProjectTriggers();

  for( var i = 0; i < all_triggers.length; ++i ){
    if( all_triggers[i].getHandlerFunction() == name_function )
      ScriptApp.deleteTrigger(all_triggers[i]);
  }//for_i
}//func_deleteSpecificTriggers
```

## 備考
もっと利口なやり方があると思われますので、編集リクエストお待ちしております。
[Class ClockTriggerBuilder - after](https://developers.google.com/apps-script/reference/script/clock-trigger-builder#after(Integer))とかうまくつかえないかなぁ。
docker上でkeycloakを動かしてみる。

#jboss/keycloak
https://hub.docker.com/r/jboss/keycloak/

#実行
```
docker run -d -p 18080:8080 -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=admin --name keycloak jboss/keycloak

```
#このままだとSSLで怒られるので設定変更
```
cd $KEYCLOAK_HOME/bin/
sh kcadm.sh config credentials --server http://localhost:8080/auth --realm master --user admin
sh kcadm.sh update realms/master -s sslRequired=NONE

```
npm install 時の「Update available」出力の対処方法の流れをメモ

# こんなやつ

```shell:CLI
# npm install vue-form-generator
npm WARN gentlyRm not removing /farmer/node_modules/.bin/semver as it wasn't installed by /farmer/node_modules/semver
npm notice created a lockfile as package-lock.json. You should commit this file.
+ vue-form-generator@2.2.1
added 1 package and removed 1072 packages in 7.371s


   ╭─────────────────────────────────────╮
   │                                     │
   │   Update available 5.3.0 → 5.8.0    │
   │     Run npm i -g npm to update      │
   │                                     │
   ╰─────────────────────────────────────╯
```

# 指摘された通りに

```shell:CLI
# npm i -g npm 
/usr/bin/npm -> /usr/lib/node_modules/npm/bin/npm-cli.js
/usr/bin/npx -> /usr/lib/node_modules/npm/bin/npx-cli.js
+ npm@5.8.0
updated 1 package in 6.764s
```

# 再び試す
```shell:CLI
# npm install vue-form-generator
+ vue-form-generator@2.2.1
updated 1 package in 0.442s
```
【tutorial】AWS EC2にApacheをインストール→テストページを表示

2018/4/16に実施。

１．EC2のインスタンスを作成。
https://qiita.com/d778980/items/956a4cd57b82c0428739

２．SSHでEC2に接続。

３．↓のコマンドを実行。

```
sudo yum -y install httpd
sudo service httpd start
```

４．EC2ダッシュボードを開き、「セキュリティグループ」をクリック。
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/f6f14a0c-3c4f-8a03-f9df-e6372d9a9fbc.jpeg)

５．セキュリティグループを選択して「アクション」→「インバウンドルールの編集」をクリック。
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/980fca01-b9ea-6d59-e2f0-e9709a67e498.jpeg)

６．「ルールの追加」をクリック。
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/0b1c37e0-bd2e-f1e9-9a08-3048e87cf18c.jpeg)

７．タイプをHTTPに変更して「保存」をクリック。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/145699c7-e16e-51fd-67f9-e4c19d2e9a2e.jpeg)

８．ブラウザでテストページを表示。
http://(パブリックDNS)
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/69b7468b-bbc6-dfb3-afee-11c28b33e8c4.jpeg)

終わり。
【VSCode】MacでC/C#/C++の開発をする


VSCodeと[Runner](https://marketplace.visualstudio.com/items?itemName=mattn.Runner)を使用したこちらの記事通りにやっただけ。
[[Visual Studio Code][Mac] C言語をビルド(コンパイル)＆ステップ実行する](https://gabekore.org/vscode-c-mac)

プロの開発には物足りないかも。学習用には軽くて最適。

以下、追加のメモ書き。


## シェルスクリプト

各言語でコンパイルと実行のコマンドが微妙に違う。

```sh:crun_gcc.sh
#!/bin/sh
 
if [ -z "$1" ]
then
    echo "need argument"
    exit
fi
 
#-------------------------------
# 一時的に使う実行ファイル名を作る
#-------------------------------
tempfile=`date '+%m%d%H%M%S'`
 
#-------------------------------
# コンパイル実行
#-------------------------------
gcc -o $tempfile $1
 
#-------------------------------
# 実行
#-------------------------------
./$tempfile
 
#-------------------------------
# 実行ファイル削除
#-------------------------------
rm $tempfile
```

```sh:csrun.sh
#!/bin/sh
 
if [ -z "$1" ]
then
    echo "need argument"
    exit
fi
 
#-------------------------------
# 一時的に使う実行ファイル名を作る
#-------------------------------
tempfile=`date '+%m%d%H%M%S'`
 
#-------------------------------
# コンパイル実行
#-------------------------------
mcs -out:$tempfile $1
 
#-------------------------------
# 実行
#-------------------------------
mono ./$tempfile
 
#-------------------------------
# 実行ファイル削除
#-------------------------------
rm $tempfile
```

```sh:cpprun.sh
#!/bin/sh
 
if [ -z "$1" ]
then
    echo "need argument"
    exit
fi
 
#-------------------------------
# 一時的に使う実行ファイル名を作る
#-------------------------------
tempfile=`date '+%m%d%H%M%S'`
 
#-------------------------------
# コンパイル実行
#-------------------------------
g++ -o $tempfile $1
 
#-------------------------------
# 実行
#-------------------------------
./$tempfile
 
#-------------------------------
# 実行ファイル削除
#-------------------------------
rm $tempfile
```

## Permission denied

`chmod +x xxx.sh` を一回叩いておけば、そのあとは通る。
Oracle WerckerでGithubにpushされたら自動でCIが動くようにした

## TL;DR

Githubに`git push`すると自動CIがテストしてくれるようにしたら最高でつよいエンジニアの人たちが「自動CI/CDは当たり前」と言ってる意味を完璧に理解した。

[Oracle + Wercker](http://www.wercker.com/)

現在は自動CDまでは行っていなくて`git push`→`CI(Wercker)`→`Slack通知`という流れになっている。

Wercker導入以前は誰かが書いたコードの一部がテストを通ってなかったり、rubocopが怒るようなコードの書かれ方をしていてその状態でマージされてしまって他人のコードに影響がでるということが起こっていた。

pushする前に手元でテストしろ！とかrubocop動かせ！問題あれば自動フォーマットしろ！とかレビューできちんと問題のあるコードを指摘しろ！というのはある。

だがしかし、人間はだいたい自分にとって都合よく忘れたり、「これくらいならいいだろ」と思ってミスを起こす生き物なので自動化することの効果の大きさを実感した。

## 参考にさせていただいたサイトなど:
その節はお世話になりました、ありがとうございました！　:)

- [Dockerベースになったwercker v2でRailsアプリをCIしてSlackに通知、herokuにデプロイする手順](https://qiita.com/mikage014/items/b89b1113b4e88009da18)
- [wercker v2 で Rails + RSpec のビルドを高速化する](https://ryota-ka.hatenablog.com/entry/2016/06/28/022332)

## 自動CI導入して得たもの:

レビューする前に問題のあるコードであるのか？ということを意識しなくていいというのは非常に大きいということを実感した。
この精神的なコスト感が大きく自動CI導入によって軽減された、これはレビューを行う開発スタイルにおいて大きな効果がある。

テストは通っているのでコードの書き方や設計などの部分にフォーカスしてレビューできる、この感覚が導入当初と導入後で大きく変わったなと感じた点だと思う。
また当たり前だが動かないコードやレビュー以前の質の低いコードが紛れにくくなるというのがある。

## 何故CircleCIやSideCIでないのか？

ぶっちゃけお金の問題、できるだけ無料のサービスでやりたいというのが最優先事項だった。

いまのところCIが無料枠で遅くて困る！ってレベルには至っていないので問題ないが将来的にどこかでCircleCIやSideCIなどのサービスに課金しないといけないかなとは思ってる。
最近`npm install`したりとだんだんWerckerが行うstepが多くなってきており、徐々に速度的な問題をじわじわと感じている。
遠くない未来に「もう無料枠ではつらいね」という話しがでそう。

なお、エンジニア全員が「Jenkins氏はメンテしたくない」という統一見解により早々に選択肢から脱落しました、南無。

## 困ったこと:
### CLIの存在を知らなくてgitのログを汚染した。

[wercker-cli](http://www.wercker.com/cli)

CLI、便利ではあるのだがモリモリとバッテリーを消費しており大変厳しい。

### `wantedly/pretty-slack-notify`や`bundle-install`がわからなくて非常に困った。

当初Qiitaのエントリを書いてる方をWantedlyの中のひとなのかと思って`wantedly/pretty-slack-notify`と名前を付けたのだと本気で思っていた。
いまもきちんと理解はしていないのだが[StepStore](https://app.wercker.com/steps)にあるものをプラグイン？的に使えると認識している。
当初手探り状態だったので`luccafort/pretty-slack-notify`としていないと駄目だと思って書き換えており盛大にエラーが出ていた

[wantedly / pretty-slack-notify](https://app.wercker.com/steps/wantedly/pretty-slack-notify)

特にハマったというか困ったのが`bundle-install`で、前述した通りStepStoreのことを認識していなかったためコマンドで`bundle install`しないといけないと思っていたので何故`bundle-install`だけコマンド実行する他のステップと違うのかがわからなくて非常に困った。

最終的には↑のStepStoreのおかげでそういうプラグイン的なものが公式から提供されているのだと理解した。
とはいえ`wercker/bundle-install`という記述にしてくれたほうが変に困らなかったので直してほしいと気持ちが強い。
(aliasで公式のものだけ省略可能なのかもしれないが検証していないのでわからない)

### Wercker関係の情報が少ない&ググラビリティーが低い

ググラビリティーが低いため欲しい情報にたどり着けないことが多くて大変苦戦した。
また英語記事/日本語記事ともにどうしてもSideCIやCircleCIに比べて少なく困ったときの情報源を探すのに苦労した。

## まとめ:

導入前までは「テストコードがある」、「レビューする」、「自動CIがある」はそれぞれ独立した手法だと思っていたのだがこれらは1つの大きな手法の中の項目なのでまずこの中で最初に着手すべきはテストコードだろうと思う。

テストコードを書きながらレビュー文化を導入するのは可能だが自動CI/CDはそれらが揃ってないとかなりつらそうだなと思った。

CIの導入によって手元の環境でテスト実行してストレスになったり、「この実装そもそも動くのか？」みたいな無意味なところで悩まなくなったので非常によい。
またSlackに通知するようにしたので誰が活発に開発してるのか？みたいなものが感じられてなんとなく頑張らないと！みたいな励みになった。

個人アプリ開発なんかでheroku使ってるならCI/CDの導入で楽になりそうだなーと開発していて感じた。
…というようなことを書こうと思っていたがいろいろあって後回しになってしまったせいで情報の欠落が激しい。

恐らくツッコミどころが満載だと思うので訂正箇所ある場合は編集リクエストください。
【Ruby】Methodオブジェクトの小さなサンプルメモ

```ruby
# 普通の配列の操作
arr = [1,2,3]
result = arr.shift
p result
p arr

# Methodオブジェクトの使用
arr_shift = arr.method(:shift)
result2 = arr_shift.call
p result2
p arr

# 自作クラスでのMethodオブジェクト

class Test
  def test
    p "test"
  end
end

test_method = Test.new.method(:test)
test_method.call
```

```sh:実行結果
1
[2, 3]
2
[3]
"test"
```
pgAdmin4 version3を日本語で使う

#pgAdmin4 version3について
4/13にリリースされたばかりのpostgreSQL用のGUIツール。
-
-V1: PostgreSQL9.6にバンドル。レスポンスなどに大きな課題があった
-V2: PostgreSQl10.xにバンドル。大きく改善している
-V3: 4/13にリリース。各PCにてローカルサーバとして起動し、ウェブブラウザから利用する

Version3では構成はいろいろ変わっていてインストール時に言語を選ぶ形ではなく、起動後の設定変更を行う

#変更方法
ブラウザ起動した画面の上部のメニューから選択していく。
>File - Preference

＜追記＞
* **変更したら英語に戻せなくなった。注意**

これで設定用ダイアログがオープン。
ツリー上の設定項目の中から"Miscellaneous"を選択すると"User Language"が選択項目にあるのでここで"Japanese"を選択。

動的には変更されないので、一度ウィンドウをクローズして新しいウィンドウを開くと日本語化されている。
KUSANAGI を VirtualBox に入れた時のネットワーク設定をブリッジネットワークからNATに変える

[VirtualBoxにKUSANAGI for VMwareを入れるまとめ \- Qiita](https://qiita.com/kkotaro0111/items/40670e21dad0511d2709)にて、[KUSANAGI for VMware](https://kusanagi.tokyo/cloud/kusanagi-for-vmware/)をVirtualBoxに入れたのだけれども、1点問題があって、それが「ネットワーク設定がブリッジネットワークになっている」というものである。
ブリッジネットワークになっていることで、動作不良がおきたりはしないのだが、MacBook ProなどのラップトップPCに環境を構築している場合、いつもと違う場所でネットワークに繋ぐと、サブネットマスクの違いや、指定したIPアドレスがすでに使われているなどの問題が起き、ブラウザはもちろん、SSHからも接続ができなくなるし、なによりそのローカルネットワークに迷惑がかかる。

今回は、このVirtualBoxに入れた[KUSANAGI for VMware](https://kusanagi.tokyo/cloud/kusanagi-for-vmware/)のネットワーク設定をNATに変える方法を記録する

# 参考サイト
- [VirtualBox CentOS7\.2 64bitでNAT、ホストオンリーアダプターを使用 \| kakiro\-web カキローウェブ](http://www.kakiro-web.com/memo/virtualbox-create-virtual-machine-2.html)
- [CentOS7\.2 64bit インストール後にVirtualBoxでNAT、ホストオンリーアダプターに変更する場合のネットワークの設定 \| kakiro\-web カキローウェブ](http://www.kakiro-web.com/memo/centos-network-setting-nat-hostonly-2.html)

# 手順
## 1. VirtualBoxマネージャからネットワーク設定を変える
1.1. VirtualBoxマネージャから、対象の仮想マシンを選び、設定を開く。
1.2. ネットワークタブを開き、「ブリッジネットワーク」になっている「アダプター0」の「ネットワークアダプターを有効化」のチェックを**外す**。
1.3. アダプター2とアダプター3の「ネットワークアダプターを有効化」のチェックをONにする
1.4. アダプター2は「割り当て」を「NAT」に、アダプター3は「割り当て」を「ホストオンリーアダプタ」にする

## 2. ゲストOS側のネットワーク設定を変える
詳細については、[参考サイト](http://www.kakiro-web.com/memo/centos-network-setting-nat-hostonly-2.html)を参考にしてください。下記は、ざっくりと手順だけ説明します。

2.1. ゲストOS起動
2.2. アダプター0のネットワーク設定ファイルが邪魔なので、削除する。（削除しなくてもいけるかもしれないけど、未検証）

```bash
[GUEST ROOT]# rm /etc/sysconfig/network-scripts/ifcfg-eth0
```
2.3. 設定ファイルを用意する

```bash
[GUEST ROOT]# nmcli connection add type ethernet con-name eth0 ifname eth0
[GUEST ROOT]# nmcli connection add type ethernet con-name eth1 ifname eth1
```
2.4. 不要な設定を削除する
まずは設定の確認。

```bash
[GUEST ROOT]# nmcli connection show

名前        UUID                                  タイプ          デバイス
eth0      xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  802-3-ethernet  --
有線接続 2  nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn  802-3-ethernet  eth0 <- 不要な設定
有線接続 1  mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm  802-3-ethernet  eth1 <- 不要な設定
eth1      xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx  802-3-ethernet  --
```
「有線接続」で始まるやつが「不要な設定」らしいので、それを削除する

```bash
[GUEST ROOT]#  nmcli connection delete nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn
[GUEST ROOT]#  nmcli connection delete mmmmmmmm-mmmm-mmmm-mmmm-mmmmmmmmmmmm
```

2.5. ホストオンリーアダプタの方を固定IPアドレスにする
固定するIPアドレスは、VirtualBoxマネージャの「ホストネットワークマネージャ」をみて、適切に設定しよう。例えばそこに「vboxnet0 192.168.33.1/24」と書かれていたら、下記のようになる

```bash
[GUEST ROOT]# nmcli connection modify enp0s9 ipv4.method manual ipv4.addresses 192.168.33.123/24
```

2.6. ネットワークを再起動

```bash
[GUEST ROOT]# systemctl restart network.service
```

## 3. 接続の確認

```bash
[GUEST ROOT]# curl ifconfig.co

***.***.***.***
```

```bash
[HOST]$ ssh kusanagi@192.168.33.123


     __ ____  _______ ___    _   _____   __________
    / //_/ / / / ___//   |  / | / /   | / ____/  _/
   / ,< / / / /\__ \/ /| | /  |/ / /| |/ / __ / /
  / /| / /_/ /___/ / ___ |/ /|  / ___ / /_/ // /
 /_/ |_\____//____/_/  |_/_/ |_/_/  |_\____/___/

    Version 7.8.3, Powered by Prime Strategy.

[kusanagi@kusanagi ~]$
```
【PHP】PDOを利用したDB操作をクラス化する時は『テーブル単位』？『DB単位』？

# 前書き

　Webシステムを構築する際、Rubyを使おうがPHPを使おうが、ほぼ間違いなくMVCデザインパターンを意識しなければならない。それに伴い、DB操作をクラス化する必要性が出てくる。
(でないと、モデルを介さずに、コントローラが直接データを整形し、ビューへ送る仕組みになってしまい、MVCデザインパターンが実現できないため)
　で、実装～テストが終わった段階で、ふと思ったのが本記事のタイトル。

**クラスの作成単位は『テーブル単位』？『DB単位』？**

Railsはテーブルを作った時(db:migrateした時)に自動でクラスが付いてくる＆メソッド定義済みなのでそこまで考えなかったが、PDOを利用した際のDB操作手順(後述)を考えると、「DB単位でクラスを作成するのもアリなのでは？」と思い始めた。

# 考察

　PDOを利用した方ならお分かりかと思うが、PDOオブジェクトはDB単位で作成される。
RubyOnRails等ではテーブル単位でモデルに対応するクラスが作成されるので若干不自然さはあるものの、PDOオブジェクトの性質上、DB単位でまとめてクラスを作成するという方法もありなのでは？

- メリット
 1. PDOオブジェクトの定義単位と一致している
 2. クラス名を気にすることなく、テーブル間の結合を行うことが出来る。
     - PDOからDB操作を行う場合、「DB単位で操作用オブジェクト定義→SQLを作成→実行」という3ステップであり、どこにも「テーブル単位の制約」が存在しない。

 
- デメリット
   - クラス自体が肥大化してしまう
      - テーブル単位で分けていてもそこそこの行数になるクラスが、扱うテーブル数に合わせて単調増加する。(僕の携わったものでさえ、テーブル2つに対してそれぞれ200行弱)
      - 保守性の損失が大きい
 

# 先輩の意見

　同じ案件の先輩に本議題をぶつけたところ、『テーブル単位派』という意見でした。
理由として、「クラスが肥大化する。」「PDOオブジェクトはあくまで『操作用オブジェクト(ただのコントローラ)』であり、クラス作成単位に影響を及ぼさない。」「仮にDB単位で一つにまとめているのを見かけたら、もうサボってるようにしか見えない」等など。。。確かにそうですよね。
　一方で、メリットの2つ目については「実装の度にどうすればいいか考えている部分」「もうある程度のクラス名称と扱うテーブルとの齟齬は仕方ないのでは？」とのこと。


# 意見を踏まえた上での考察

　先輩の意見の中にもあった、「PDOオブジェクトはあくまで『操作用オブジェクト(ただのコントローラ)』」は盲点だったなと。PDOオブジェクトの単位にあわせる必要はないのであれば、DB単位でクラスをまとめる必要もなく、テーブル単位でクラスを分ければよい。
　結論、他の実装方法と同じ『テーブル単位でクラスを作成するほうが良い』という流れになったため、ほぼ無意味な議題となったが、「テーブル操作用クラスの中でInnerJoinする際の不自然さをどうするか？」という部分に触れられただけ有意義だったかなと。
php -v  で dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.xx.dylib というエラーが起きた

とつぜんPHPコマンドでエラーが起き出して調べてみました。

## 環境
* macOS High Sierra 10.13.4
* homebrew 1.6.0
* phpenv v0.0.4-dev

## 現象
php -vやcomposer -vで下記のようなエラーが起きた
`dyld: Library not loaded: /usr/local/opt/icu4c/lib/libicui18n.xx.dylib`

xxのところのバージョンを失念してしまいました。
58かなー、61かなー。

なのでphpをインストールしなおそうとしたら
`$ phpenv install 7.2.0`

下記のようなエラーが

```
-----------------
|  BUILD ERROR  |
-----------------

Here are the last 10 lines from the log:

-----------------------------------------
                        ^
/var/tmp/php-build/source/7.2.0/ext/intl/intl_convertcpp.cpp:59:40: error: unknown type name 'UnicodeString'; did you mean 'icu_61::UnicodeString'?
zend_string* intl_charFromString(const UnicodeString &from, UErrorCode *status)
                                       ^~~~~~~~~~~~~
                                       icu_61::UnicodeString
/usr/local/Cellar/icu4c/61.1/include/unicode/unistr.h:286:20: note: 'icu_61::UnicodeString' declared here
class U_COMMON_API UnicodeString : public Replaceable
                   ^
22 warnings and 4 errors generated.
make: *** [ext/intl/intl_convertcpp.lo] Error 1
-----------------------------------------
```


## 原因と対処
このサイトに書いてあるままに。
[PHPインストール時のerror: unknown type name 'UnicodeString'を解消する](https://tukaelu.hatenablog.jp/entry/2018/04/07/solve-unknown-type-name-UnicodeString)
ReactのcomponentDidCatchを使ってErrorハンドリングしたら開発者もユーザーも幸せになれそう

## 経緯
現在Reactのプロジェクトに携わっているわけですが、ユーザーからたまに下記のようなお問い合わせを受けることがあります。

「ページが真っ白で何もできない」

もちろん「500エラー」とかその辺はすでにハンドリングしているわけですが、たまにこういった問い合わせがあったります。んで、だいたいよくあるのが「ReferenceError: hoge is not defined」とかだったりするんですよね。
フロントのcomponentで起きたエラーある場合に起きるのですが、本番環境ではログは出ないようになっているので、何がundefinedなのかわからないんですよね。

その際に、どんなエラーでどこのページで起きたかわかればエラーの修正がしやすいのかなと。


## componentDidCatchを使う

ってか、ほぼほぼこれだけで解決です。こいつのすごいのは子コンポーネントにも孫コンポーネントにも、てか配下のコンポーネントのどこかにフロント側のエラーがあるとエラーを返してくれます。またAPIとの通信が必要なもののエラーはキャッチしないです。例えばsubmit時のエラーでは作動しないです。
なので、一番上のコンポーネントにこんな感じのコードを書きます。

``` javascript
componentDidCatch(error, info) {
    if (ENV !== 'DEV' && error) {
      const errorLog = {
        path: window.location.href,
        error: `${error}`,
        id: this.props.user.userId
      }

      this.props.history.push(`/is-error?error=${JSON.stringify(errorLog)}`)
    }
  }
```

開発中にこのエラーを受け取ってしまうといちいち`/is-error?error=`に遷移してしまうので、`ENV !== 'DEV'`としています。
`error`を受け取ったら`/is-error?error=`に遷移をしてurlにエラーログが入るようにしています。今回はエラーの内容とユーザーID、`is-error`の前にいたページをurlに入るようにしている感じです。

ちなみに、エラーページ何かしらメッセージを表示してではトップページへの遷移ができるようにしておけば良いかと。



## Google アナリティクスで検索しやすいかも

エラーが起きたらエラーページに遷移するので、Google アナリティクスさえ設定していれば「ページ」から`is-error`を検索すれば、起きているエラーもわかります。
しかも、どれくらいそのエラーができているかもわかるので、エラーの修正の優先度もつけやすいのではと思います。


## まとめ
このcomponentDidCatchを使ったErrorハンドリングも今後使いにくい部分も出てくると思うので、その辺は追記していきます！！
h2o web serverのmrubyを使ってみる

spa(single page application)のindex.htmlをh2oで配布する際どうすりゃいいのか。

vueとかのspaだと、vue-routerとかつかってルーティングするため、
`http://xxx.com/aaa/bbb/ccc`でアクセスしたときも、`index.html`を返却して、その中でjsを解釈してルーティングをする。

h2oでindex.htmlを配布するさい、どうすりゃいいのかわからなかった。
nginxだと`try_files`とかいうので対応できるみたい。

h2oはmrubyでフック処理をかけるので、それで簡単に対応できたけど、本番環境だと、他にいろいろ考慮しなければいけない感じがする。

runitで動かしてるのでファイル指定などは相対パスにしてる。

```conf
listen:
  port: 8000

hosts:
  "0.0.0.0":
    paths:
      /:
        mruby.handler-file: './forspa.rb'
        file.dir: /tmp/somewhere
```


./forspa.rbの内容。

```ruby
path = "/tmp/somewhere"
cont = File.open("#{path}/index.html").read()
lambda do |env|
  unless File.exist?("#{path}/" + env["PATH_INFO"])
    return [200, {'content-type' => 'text/html'}, [cont]]
  end
  return [399, {}, []]
end
```
AKS debug tips

[Hexadite/acs-keyvault-agent](https://github.com/Hexadite/acs-keyvault-agent)を試す必要があり、２時間を使ってしまったので、その過程で発生した AKS 関連のデバッグのためのコマンド等を自分のためにメモしておきたい。

# 代表的なデバッグコマンド

## Pod のログを見る

```
kubectl logs <Pod name>
```

## Pod の詳細を見る

ちなみに他のリソースを見たい場合も、Pod 部分を変えればよい

```
kubectl describe pod <PodName>
```

## k8s クラスターのイベントを見る

Podのログで分からないケースでもこちらで分かる場合もあり。

```
kubectl get events
```

## コンテナにログイン

```
kubectl exec -it <Pod Name> -c <Container Name> /bin/bash
```

# Initialize Container のログ

Pod にコンテナが二つあるケースと同じ

```
kubectl logs <Pod name> -c <Initialize Container name> 
```
# Service Principal の取得

AKS をデプロイすると、どの Service Principal だったか忘れる場合がある。 Service Principal は各nodeの`/ect/kubernetes/azure.json` の下に配置している。であるので、次のような、yamlを作ってデプロイして、ログインするとよい。

```yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  name: test-sp
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: keyvault
    spec:
      containers:
      - image: alpine:latest
        name: test-app
        command: ["/bin/sh", "-c", "--"]
        args: ["while true; do sleep 5; done;"]
        volumeMounts:
        - name: host-sp
          mountPath: /host/azure.json
          readOnly: true
      volumes:
      - name: host-sp
        hostPath:
          # this file contains the cluster service-principal, it exists on every node by default
          path: /etc/kubernetes/azure.json
          type: File
```

これを作って、下記のようにすれば、どの Service Principal だったかわかります。

```
kubectl create -f some.yaml
kubectl exec -it <podname> /bin/bash
# cat /host/azure.json
```
ちなみに、上記のリポジトリは、Azure keyVault にサービスプリンシパルを渡すことなく、KeyVault からSecretsを引っ張ってくれて、volume 経由でアクセスできるようにするものです。

```
$ kubectl exec -ti test-keyvault-f849dd45c-2bcgc -c test-app /bin/sh
/ # cat /secrets/secrets/hello
world
```
GAS＋Vue.jsでサーバレスなWebアプリ②

#はじめに
GASの[HtmlService](https://developers.google.com/apps-script/reference/html/html-service)を使ってSPAライクなWEBアプリケーションを書くことになったのでその時のメモです。
[こちらの記事](https://qiita.com/kyhei_0727/items/f409ab53bac931d4eb77)の続きとなります。

#今回のアウトライン
1. CSSファイルとJavascriptファイルを作成する。
2. `index.html`からCSSとJavascriptファイルを読み込む。
3. 終わりに

#それではさっそく書いてみるよ。

###1. CSSファイルとJavascriptファイルを作成する。
[前回の記事](https://qiita.com/kyhei_0727/items/f409ab53bac931d4eb77)で作成したGASプロジェクトに以下のファイルを作成していきます。
プロジェクト内には.gsファイルか.htmlファイルのどちらかしか作成できないので、どちらも.htmlファイルとして作成します。

```css.html
<style>
  p {
    color: #4aac00;
  }
</style>
```

```js.html
<script>
  var vm = new Vue({
    el: "#vm",
    data: {
      message: "Hello GAS and Vue!"
    }
  })
</script>
```

どちらもHTMLファイルとして扱うので`<style>`や`<script>`タグ内に実際のコードを書いていくのがミソです。
ここまでで現在のプロジェクトには、

- `server.gs`
- `index.html`
- `css.html`
- `js.html`

の４つのファイルが作成されました。

###2. `index.html`からCSSとJavascriptファイルを読み込む。
上の手順で作成した`css.html`と`js.html`を`index.html`から呼び出すために前回作成した２つのファイルも修正していきます。

```index.html
<!DOCTYPE html>
<html>
<head>
  <base target="_top">
  <meta charset="utf-8">
  <?!= include('css'); ?>
  <!-- vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue"></script>
</head>
<body>
  <div id="vm">
    <p>{{ message }}</p>
  </div>
  <?!= include('js'); ?>
</body>
</html>
```

見慣れないタグが出てきました！
`<?!= include('css') ?>`
[公式のドキュメント](https://developers.google.com/apps-script/guides/html/templates)によるとRubyのERB、Pythonのjinja2的なテンプレート構文のGAS版といったところでしょうか。
とにかくサーバサイドで定義した関数をこのタグ内では呼び出すことができます。

さて、これで次にすべきが見えてきました。
`server.gs`内に`css.html`や`js.html`の内容を返す関数`include(filename)`を早速書いていきましょう。

```js:server.gs
function doGet(request) {
  var template = 'index';
  return HtmlService.createTemplateFromFile(template).evaluate();
}

function include(filename) {
  return HtmlService.createHtmlOutputFromFile(filename)
      .getContent();
}
```

これでCSSやJavaScriptファイルを`index.html`から読み込む仕組みが整いました。
本記事のさらに詳しい内容は[公式のベストプラクティス](https://developers.google.com/apps-script/guides/html/best-practices)を参考いただければさらに理解が深まるかと思います。

お疲れ様でした！

###3. 終わりに
ここまでの内容でひとまずクライアントサイドのみで実装可能なVueアプリケーションは作成できるかと思います。
次回はクライアントサイドとサーバサイドの連携について書いていきます。
ActiveModel::Serializerでattributesを条件付きにしたい時の注意点

## 要約
- attributesを条件付きにすることは実はできない
- 諦めてattribute使うべき 

## 検証
```
class UserSerializer < ActiveModel::Serializer
  attributes :id, name

  # NOTE: NG ケース
  attributes :secrets, if: :signed_in?

  def signed_in?
    # 何らかの認証処理
  end
end
```

##### Error
```
TypeError ({:if=>:signed_in?} is not a symbol nor a string):
```

## 代替策としてどうするか
```
class UserSerializer < ActiveModel::Serializer
  attributes :id, name

  # NOTE: attributeに変更
  attribute :secrets, if: :signed_in?

  def signed_in?
    # 何らかの認証処理
  end
end
```

## 関連リンク
- Openしたままのissue
  - Conditional for attributes in plural not working #1885  
    https://github.com/rails-api/active_model_serializers/issues/1885

- マージされずにCloseしたプルリク
  - Allow options on multiple attributes at once #1714  
    https://github.com/rails-api/active_model_serializers/pull/1714

  - Serializer attributes options #2148  
    https://github.com/rails-api/active_model_serializers/pull/2148
FortigateのVLAN

Fortigateのネットワークインターフェイスには先人も散々苦労させられているようである。
特にVLAN関連はとてもややこしい。
私もハマってしまい、図を書いてうんうん悩んでいたのだが、シンプルな結論にやっとたどり着いた。

- Fortigateにはインターフェイスがたくさんついてて、スイッチとして動作するけど単機能！
- ポートVLAN「だけ」かタグVLAN「だけ」が利用可能
- まあ、組み合わせても使えるんだけど、みんながイメージする利用方法は実現できない！！！
    - タグVLANでインターフェイスを作ると、タグVLANでしか使えない
    - 同じくポートVLANでインターフェイスを作ると、ポートVLANでしか使えない
    - 本体のインターフェイスにサーバを1台つなげて（ポートVLAN）他はタグVLAN経由で別のスイッチに繋ぐ、みたいなことはできません！
- 必ず配下にスイッチをぶら下げて、そこにサーバやPCを接続しましょう
    - 構築するネットワークがWANとLAN 1セグメントだけならスイッチは不要
- スイッチとの接続をポートVLANにするかタグVLANにするかは、各セグメントのトラフィック量次第
- 特にセグメント間通信が多い場合はポートVLANにした方が良いと思う
    - 安価なモデルはリンクアグリゲーションが使えないからね

ということで、FG50Eや60Eを買う人は自分の利用目的にあったスイッチを一緒に買うようにしましょう。
Apple Watchでページベース画面に遷移するときの注意点

## ページベース画面とは

Apple Watchの画面遷移のひとつに、ページベースがあります。

![01.png](https://qiita-image-store.s3.amazonaws.com/0/38924/dea6a29a-66a4-43f9-ce15-9d166812f097.png)


ページベースは、iPhoneの天気アプリと同じように、スワイプでページを切り替える画面です。

## ページベース画面に遷移してるのにページベースにならない！？

開発中のアプリで、下の画面のようにストーリーボードのSegueを設定せずに、`presentController(withName:context:)` をつかって遷移しようとしました。

<img width="520" alt="presentを使う01.png" src="https://qiita-image-store.s3.amazonaws.com/0/38924/ecda70e2-6b1c-134f-4933-07ddf10c87e8.png">


`Modal Code` ボタンのIBActionを設定して、ボタンをタップしたときに下のコードを実行するようにしました。

```
    @IBAction func pushModalCodeButton() {
        presentController(withName: "FirstPageInterfaceController", context: nil)
    }
```

シミュレーターで実行して、Modal Codeボタンをタップすると……

![presentを使う03.png](https://qiita-image-store.s3.amazonaws.com/0/38924/cb9ff137-3282-f155-dbf6-a113e240d47d.png)


？？？
「あ……ありのままいま起こった事を話すぜ！　俺はページベース画面に遷移したと思ったら、いつのまにかページベースじゃなくなっていた。 な……何を言っているのかわからねーと思うが、俺も何をされたのかわからなかった」

遷移先の画面が、なぜかページベース画面ではなくなってしまいました（画面下に丸が表示されていないことに注目してください）。

### 追記　コメントで対応方法を教えていただきました。詳しくは、[追記](#追記)をご覧ください。

## ストーリーボードでボタンに直接Segueを設定しよう

ページベース画面に遷移したいときはどうすればいいのでしょうか？
いろいろ試してみると、どうやらストーリーボードのボタンに直接Segueを設定して、ページベース画面に遷移するようにしたら大丈夫なようです。

下の画面のように `Modal` ボタンからSegueを伸ばして、ページベース画面と接続します。

<img width="507" alt="ストーリーボードでボタンにSegueを設定01.png" src="https://qiita-image-store.s3.amazonaws.com/0/38924/5f223319-1239-028d-2fdd-6e5be02ee76e.png">



シミュレーターで実行して、Modalボタンをタップすると……

![ストーリーボードでボタンにSegueを設定02.png](https://qiita-image-store.s3.amazonaws.com/0/38924/d95c2b23-0604-25fe-ddf0-85ad09f3ef5a.png)


バンザーイ。
無事にページベース画面に遷移するとこができました。画面下にも丸が表示されて、スワイプで画面を切り替えることができます。

## 最後に

というわけで、なんだか釈然としませんが、ページベース画面に遷移したいときは、ストーリーボードのボタンにSegueを設定しましょう。

「こうやったら `presentController(withName:context:)` でもページベース画面に遷移できるよ！」という知見をお持ちのかたは、ぜひコメントお願いします🙇‍♂️

## 追記

[BlackCat](https://qiita.com/BlackCat)さんから、 `presentController(withNames:contexts:)` を使うとページベース画面に遷移できるよ、とコメントをいただきました。ありがとうございます！

あらためて、[WKInterfaceController - WatchKit | Apple Developer Documentation](https://developer.apple.com/documentation/watchkit/wkinterfacecontroller) を読んでみると、以下のように書いてありました。

> When presenting a modal interface, you can display a single interface controller (which is the most common use) or you can display multiple interface controllers in a page-based layout.
Use the presentController(withName:context:) and presentController(withNames:contexts:) methods to present your interface controllers modally. 

シングルインターフェース用には `presentController(withName:context:) ` 、ページベース用には `presentController(withNames:contexts:)` と、メソッドが別々に用意されているんですね。

これで無事にコードからでもページベース画面に遷移できます。よかったよかった。
SkypeとAppear.inの違い

こんにちは。
今回はオンライン勉強会で便利なアプリ「Skype」と「Appear.in」の簡単な紹介について触れます。

＊「Appear.in」の特徴
　　1.アカウント登録必要なし
　　2.一度にチャットできるのは4人まで
　　3.全員が画面共有ができる

＊「Skype」の特徴
　　1.アカウント登録必要
　　2.画面共有は一画面

Appear.inとSkype、
場にあったアプリを使用してみてください
分析環境の準備メモ

anacondaを入れるだけなんだけど，色々設定したのを忘れないように．

# anacondaを入れる

## pyenv

私の場合，pyenvを使う

```shell
git clone https://github.com/pyenv/pyenv.git ~/.pyenv
```

```conf:~/.zsh/.zshenv
# pyenv
if test -e ~/.pyenv; then
    export PYENV_ROOT=${HOME}/.pyenv
    export PATH=${PYENV_ROOT}/bin:${PATH}
    eval "$(pyenv init -)"
fi
```

## anaconda

```shell
pyenv install -l
# (一覧を表示して入れるバージョンを決める)
pyenv install anaconda3-X.X.X
cd /path/to/workspace
pyenv local anaconda3-X.X.X
# docoptとかxlrdとか
conda install PKGNAME
# conda-forgeで入れるのもある．jupyter_contrib_nbextensionsとか
conda install -c conda-forge PKGNAME
```

## pip

condaで出てこないのはpipで入れる．chainerとかpytest-ipynbとか

```shell
pip install PKGNAME
```

## 設定1 （jupyter notebookへのリモートアクセス）

jupyter notebookの設定を生成する．
tokenで毎回コピペする方法と2種類あるけど，色々なマシンからアクセスする場合はパスワード認証が楽．

```shell
jupyter notebook --generate-config
vi ~/.jupyter/jupyter_notebook_config.py
```

```python:jupyter_notebook_config.py
# 変更部のみ抜粋

c.NotebookApp.ip = '0.0.0.0'

c.NotebookApp.password = 'sha1:XXXXXXXXXXXXXXXXXXXXXX'
```

パスワード生成は

```shell
python -c 'from notebook.auth import passwd;print(passwd())'
# これで出てくる入力待ちコンソールに文字列を打ち込むと文字列が返ってくる
```

## 起動

私の環境では，ブラウザの自動起動は不要なことが多いので，オプションをつける

```shell
cd /path/to/workspace
jupyter notebook --no-browser
```

## 設定2 （拡張機能の追加）

``http://localhost:8888/nbextensions`` で有効にしたいものにチェックをつける．
今んところ追加したのはTable of Contents(2)くらい．

## 設定3 （gitでipynbを管理）

gitでipynbを管理しようとすると死ねる．
でも実行結果は保存しておきたい．
そんな時に．

[Jupyter Notebook\(ipynb\)の実質コードのみをgitリポジトリ管理するには \- どこでも見れるメモ帳](http://ni66ling.hatenadiary.jp/entry/2018/01/02/022905)
一応転記しておくと，

1. jqのインストール

    ```shell
sudo apt-get install jq
```

1. ワークスペース毎にフィルターをセット

    ```conf:.git/config
[filter "clean_ipynb"]
  clean = jq --indent 1 --monochrome-output '. + if .metadata.git.suppress_outputs | not then { cells: [.cells[] | . + if .cell_type == \"code\" then { outputs: [], 　execution_count: null } else {} end ] } else {} end'
  smudge = cat
```

    ```conf:.git/info/attributes
*.ipynb  filter=clean_ipynb
```
crenvでcrystalをインストール

[公式](https://crystal-lang.org/docs/installation/on_redhat_and_centos.html)
[crenv](https://github.com/pine/crenv)

rubyのスクリプトで処理が遅いと思うところでcrystalを取り入れてみようかな、程度のモチベーションで使ってみる。

crystalのDockerfileを示す。  
yumで必須はgcc,git

```bash:Dockerfile
FROM             centos:centos7.4.1708
MAINTAINER       TestUser
ENV              container docker

##### crystal environment var
ENV              crystal_ver=0.20.0 #最新は投稿時点で0.24.1
ENV              CRENV_ROOT=/usr/local/crenv

##### yum setting & install
RUN              yum update -y && yum clean all
RUN              yum swap -y fakesystemd systemd && yum clean all
#RUN              yum install -y httpd && yum clean all
#RUN              systemctl enable httpd
RUN              yum -y install git gcc-c++\
                     make tar wget openssl openssl-devel \
                     readline readline-devel gdbm-devel libffi-devel zlib-devel \
                     curl-devel procps autoconf sudo bzip2 bzip2-devel gcc postgresql-devel \
                     sqlite sqlite-devel

##### mkdir
# for data persistence on docker.
RUN              mkdir /root/work

##### crystal install
RUN              curl -L https://raw.github.com/pine/crenv/master/install.sh |bash
RUN              echo 'export PATH="${CRENV_ROOT}/bin:$PATH"' >> /etc/profile.d/crenv.sh
RUN              echo 'eval "$(crenv init -)"' >> /etc/profile.d/crenv.sh
RUN              source /etc/profile.d/crenv.sh
RUN              ${CRENV_ROOT}/bin/crenv install "${crystal_ver}"
RUN              ${CRENV_ROOT}/bin/crenv global "${crystal_ver}"

##### expose
EXPOSE           22
EXPOSE           80
EXPOSE           443
EXPOSE           5432
EXPOSE           8000
EXPOSE           8001

```

# 追加

docker-composeで`crystal play`を立ち上げるようにしておく。
ちな、0.24.1ではバグでplayが上記のインストール手順ではうまく動かない。

```
/usr/local/crenv/shims/crystal play
can't find file 'compiler/crystal/tools/playground/server.cr'
???
???
???
???
???

Error: you've found a bug in the Crystal compiler. Please open an issue, including source code that will allow us to reproduce the bug: https://github.com/crystal-lang/crystal/issues
```

```yml
version: '3'

services:
  crystal:
    build:
      context: .
    user: root
    volumes:
       - "./work:/root/work"
    privileged: true
    ports:
      #- "4444:4444"
      #- "18080:18080"
      - "8001:8001"
    restart: unless-stopped
    command: /usr/local/crenv/shims/crystal play -b 0.0.0.0 -p 8001
```

`docker-compose up -d`で立ち上げるとlocalhost:8001でplaygroundが使える。
【tutorial】AWSにEC2インスタンスを作成

2018/4/16に実施。

１．ログイン。AWSマネジメントコンソールで「仮想マシンの起動」をクリック。
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/7fe38328-253a-4a06-dd0d-c985cfa5e494.jpeg)

２．今回は適当に１番上で。「選択」をクリック。
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/3f5d0bb8-3e96-e5c9-4aac-55967905ad62.jpeg)

３．何も考えずに「確認と作成」をクリック。
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/620a540f-9c6c-ebb9-eb90-a29abd57e196.jpeg)

４．何も考えずに「作成」をクリック。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/e3e104c7-2931-4b70-1ea5-77c5ab829f33.jpeg)

５．「既存のキーペアの選択」を「新しいキーペアの作成」に変更。
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/0051b12a-5794-2f4f-96f7-f88d04716199.jpeg)

６．キーペア名を適当に入力して、「インスタンスの作成」をクリック。
![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/b6b0f395-493c-6d15-caa1-944d329d8296.jpeg)

終わり。
Android StudioのTemplatesの出力先をsrc/main/kotlinにする


# 環境

- macOS 10.13.4
- Android Studio 3.1

# どんな問題か

フルKotlinなプロジェクトで、ソースファイルディレクトリが`src/main/java`ってしっくりこないので（※個人の感想です）
`src/main/kotlin`にした。
![スクリーンショット 2018-04-16 14.00.35.png](https://qiita-image-store.s3.amazonaws.com/0/6290/d52152c8-6097-9bd6-c1ab-f27b0b19850c.png)

ディレクトリ名をjavaからkotlinにリネームしてbuild.gradleに下記sourceSetsを追加。

``` build.gradle
sourceSets {
    main.java.srcDirs += 'src/main/kotlin'
}
```

よし、Activityを追加するぞ、とメニューからEmpty Activity【何かしらのテンプレート】を選択してActivity名などを入力後Finishすると..
![スクリーンショット 2018-04-16 14.01.26.png](https://qiita-image-store.s3.amazonaws.com/0/6290/5f56ecf6-7524-9f3f-8ddb-7f4eb286821c.png)

`src/main/kotlin`の方に出力して欲しいのに`src/main/java`が作られてそちらにActivityが出力されてしまうという問題。
![スクリーンショット 2018-04-16 14.02.20.png](https://qiita-image-store.s3.amazonaws.com/0/6290/0a557b10-665c-2ba0-9fba-164d603a3ea4.png)

# 解決法を教えていただいた

java配下に出力されたファイルを移動させるという対処はやりたくなかったので、渋々`src/main/java`のままにしていた。

先日、shibuya.apkという勉強会で[『AndroidStudioのテンプレートを覗いてみよう』](https://speakerdeck.com/kiuchikeisuke/androidstudiofalsetenhuretowosi-itemiyou)という発表を見た時にふとこの件を思い出しつぶやいたところ
登壇者の@k_keisukeさんから解決法を教えて頂きました。ありがとうございます。

# 実際にやってみた

試しに`Empty Activity`テンプレートの出力先を変更してみる。
`/Applications/Android Studio.app/Contents/plugins/android/lib/templates/activities/EmptyActivity`配下にこのテンプレートに関するファイルが入っている。

## 作業前

Android Studio終了させとく。不安なら修正前にバックアップ取っておく。

## globals.xml.ftl修正

`/Applications/Android Studio.app/Contents/plugins/android/lib/templates/activities/EmptyActivity/globals.xml.ftl`に`srcOutKotlin`を追加する

``` globals.xml.ftl
<?xml version="1.0"?>
<globals>
    <global id="hasNoActionBar" type="boolean" value="false" />
    <global id="parentActivityClass" value="" />
    <global id="simpleLayoutName" value="${layoutName}" />
    <global id="excludeMenu" type="boolean" value="true" />
    <global id="generateActivityTitle" type="boolean" value="false" />
    <#include "../common/common_globals.xml.ftl" />
    <!-- 下記追加 -->
    <global id="srcOutKotlin" value="app/src/main/kotlin/${slashedPackageName(packageName)}"/>
</globals>
```

## recipe.xml.ftl修正

`/Applications/Android Studio.app/Contents/plugins/android/lib/templates/activities/EmptyActivity/recipe.xml.ftl`の`srcOut`を`srcOutKotlin`に変更する

``` recipe.xml.ftl(一部)
    <instantiate from="root/src/app_package/SimpleActivity.${ktOrJavaExt}.ftl"
                   to="${escapeXmlAttribute(srcOutKotlin)}/${activityClass}.${ktOrJavaExt}" />
    <open file="${escapeXmlAttribute(srcOutKotlin)}/${activityClass}.${ktOrJavaExt}" />
```

## 確認

Android Studioを起動する。
メニューから`Empty Activity`を使ってみると無事`src/main/kotlin`の方にActivityが生成された。


# 参考

[Android Studioのテンプレートを自作する方法](https://qiita.com/k_keisuke/items/bc8282e7bf68eebd643e)
Laravelを使って開発をするときに入れておきたいPhpStormのプラグイン

- Laravelにかかわらず必要だよね、ってのも入ってます。
- 一応URLを乗せましたが、PhpStormの設定を開いてPluginページで同名のプラグインを探してインストールするのが良いです。
- Laravel Plugin以外はインストールするだけで大丈夫です

# Laravel Plugin

https://plugins.jetbrains.com/plugin/7532-laravel-plugin
`Settings > Languages & Frameworks > PHP > Laravel` で

-  `Enable Plugin for this project` にチェックを入れる
- `Use AutoPopup for completion`にチェックを入れる


# Blade Support

https://plugins.jetbrains.com/plugin/7569-blade-support


# PHP composer.json support

https://plugins.jetbrains.com/plugin/7631-php-composer-json-support

# .env files support

https://plugins.jetbrains.com/plugin/9525--env-files-support

# .ignore

https://plugins.jetbrains.com/plugin/7495--ignore


# PHPUnit code coverage

https://plugins.jetbrains.com/plugin/6167-phpunit-code-coverage
【tutorial】Eclipseをダウンロード→JavaでWebアプリケーションを動かす（Pleiades）

2018/4/9に実施。面倒なのでPleiades。
 　Pleiades All in One は Windows、Mac 向けに Eclipse 本体と日本語化を行うための
 　Pleiades プラグインおよびプログラミング言語別に便利なプラグインをまとめたパッケージです。

１．ダウンロード。今回は「Eclipse 4.7 Oxygen」。
http://mergedoc.osdn.jp/
![1.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/d30f08e4-0212-6d48-1e85-98f060886ebf.jpeg)

２．Editionを選択。今回は「Java」「Full Edition」。
![2.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/449fbee2-466e-3116-8931-1fb76a5ac35e.jpeg)


３．ダウンロードしたファイルを解凍。
 　　解凍先のディレクトリが深いと「パスが長すぎます」とか言われて煩わしいので、Dドライブ直下に解凍。

４．「D:\pleiades\eclipse」のeclipse.exeを実行。

５．何も考えずに「起動」をクリック。
![3.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/2c0baf4d-e91d-bbb0-d799-1903471b660a.jpeg)

６．「ファイル」→「新規」→「その他」をクリック。
![4.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/f3c1ee38-b299-063a-7937-4219e985d9ab.jpeg)

７．「Web」→「動的Webプロジェクト」をクリック。
![5.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/66d70491-1797-62d4-bcf7-4b0b2a773de1.jpeg)

８．プロジェクト名を適当に入力して「完了」をクリック。今回は「webproject」。
![6.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/34d37fb4-6936-ca1b-9897-d7c6886f285f.jpeg)

９．パッケージエクスプローラーに「８．」で入力した名前でプロジェクトが出来ているので、
　　「WebContent」を右クリックして「新規」→「その他」をクリック。
![7.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/4875f3ab-af57-7b9d-5dc7-77dfd45fd48e.jpeg)

１０．「Web」→「JSPファイル」を選択して「次へ」をクリック。
![8.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/22d793ab-2a0c-5d70-4052-6b215b29213a.jpeg)

１１．何も考えずに「完了」をクリック。
![9.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/6b00fe5d-a527-0ed3-a845-56d616a0d1b3.jpeg)

１２．NewFile.jspというファイルが出来ているので、ダブルクリック。
![10.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/860305bf-13a0-bce4-cca1-b198dff66052.jpeg)

１３．ファイルの中身はこんな感じ。
![11.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/30cd8c8d-e4bc-3d10-5a6c-cee386c14206.jpeg)

１４．10行目に「hello world」を記載。
![12.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/ded92f8b-28e6-6781-89fc-8eaacc1c43a9.jpeg)

１５．NewFile.jspを右クリックして「実行」→「サーバーで実行」をクリック。
![13.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/db3ad7a1-0993-5e1f-5602-eb07810b2be1.jpeg)

１６．何も考えずに「完了」をクリック。
![14.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/4afb3934-44af-322a-b3ef-dbfce22a1639.jpeg)

１７．↓のURLにアクセスすると「hello world」が表示される。
http://localhost:8080/webproject/NewFile.jsp
![15.jpg](https://qiita-image-store.s3.amazonaws.com/0/247425/3647d724-c3e8-0d90-1345-8916f5096abc.jpeg)

終わり。