OmniAICreator/Qiita-1.07M huggingface dataset:
TensorFlowをGCPで実行してみる

これは [日本情報クリエイト Engineers Advent Calendar 2016](http://qiita.com/advent-calendar/2016/njc) による13日目の記事になります。

今回は[前回](http://qiita.com/tk-shirasaka/items/bc3093eac41e4831e7a6)に引き続きTensorFlowネタですが、今話題のGCPで学習させてみることにしました。

## 説明

GCPの無料トライアルではなんと60日間$300分を無料で利用可能ですので今回はこの無料枠の中で触ってみることにしました。

無料トライアルについては[こちら](https://cloud.google.com/free-trial/?hl=ja)を御覧ください。

## 準備

GCPを初めて使用する場合は機械学習サービスのAPIが無効になっていますので、まずは機械学習のAPIを有効にしましょう。

APIを有効にするには
[メニュー] -> [API Manager] から API Managerのダッシュボードに移動し、『
Google Cloud Machine Learning』を選択し、有効にして下さい。

## Google Cloud Shell

GCPではGCPの各種SDKが付与され、各種APIにアクセス可能な環境を無料で利用することができます。
GCPの機械学習サービスでは学習をさせるためにAPIをコマンドラインから呼び出す必要があるため、この無料で利用可能なshellは非常に役立ちます。

しばらく利用しないとshellのインスタンスは消失してしまいますが、$HOMEディレクトリ以下のデータは永続的に保持され5GBまで利用できるので、利用開始の敷居が下がり軽く触ってみたい方も時間をかけずに開始することができてとてもいいですね。

## 学習・・・の前に

早速学習に入って行きたいところですが、前回紹介したソースのままではGCPで学習させることができないので学習できるように少しばかり手を加えていきます。

まず、とても重要なことはせっかくCSVとして準備した学習データですが、そのままでは使えません・・・orz
その為、学習を始める前に準備したデータセットを一度クラウドのストレージに保存し、学習開始前にこのデータセットをダウンロードするという手順をふむ必要があります。

ただ、機械学習を実行するインスタンスにもSDKがインストールされているらしく、データは以下のようなコードで取得できます。
ダウンロード先は書込み権限のある/tmp以下にするのが無難でしょう。

```task.py
import subprocess

subprocess.check_call(['gsutil', 'cp', 'gs://<バケット名>/image.csv', '/tmp/image.csv'])
```

ちなみに前回は学習結果を保存する方法を記載してませんでしたが、以下のようなコードで保存できます。
（保存先はやっぱり書込み権限のある/tmp以下にしましょう）

``` task.py
saver = tf.train.Saver()
sever.save(sess, '/tmp/output/export')
```

また、学習した結果もやっぱりどこにも保存されないので、学習が終わったデータは同じくクラウドのストレージにアウトプットしましょう！

``` task.py
subprocess.check_call(['gsutil', 'cp', '-r', '/tmp/output', 'gs://<バケット名>/output'])
```

最後に学習を実施するコードをmain関数の中に突っ込みましょう。
最終的にはこんな感じになります。

```task.py
import tensorflow as tf
import numpy as np
import httplib
import subprocess

def main(_) :
    '''
    学習コード
    .
    .
    .
    '''

if __name__ == '__main__' :
    tf.app.run()
```

tf.app.run()が実行されるとmain関数が呼び出され学習が実行されるような形ですね。
main関数の引数にはコマンドライン引数(後述)が入るのでなにかスクリプト内に渡したいデータがある場合はコマンドライン引数経由でデータの受け渡しができます。
大体、出力先や学習データセットの取得元などを指定する場合が多いように思います。

## 学習

それでは、ようやく準備が整ったのでGCPにjobを投げてみます。
jobはコマンドラインから登録するためGoogle Cloud Shellで以下のスクリプトを実行するだけです。
簡単ですね。

```run.sh
JOB_NAME=$(date "+i%Y%m%d_%H%M%S")
TRAIN_BUCKET=gs://<バケット名>
TRAIN_NAME=myproject

gsutil cp image.csv ${TRAIN_BUCKET}/image.csv
gcloud beta ml jobs submit training ${JOB_NAME} \
  --package-path="test" \
  --module-name="test/task" \
  --staging-bucket="${TRAIN_BUCKET}" \
  --region=asia-east1 \
  -- \
  --csv_file="${TRAIN_BUCKET}/image.csv" \
  --output="${TRAIN_BUCKET}/output"
```

これで『test/task.py』に配置されたソースがGCPに展開され実行してくれます。
『--package-path』、『--model-name』、『--staging-bucket』、『--region』は（ほぼ）必須パラメータなので適宜指定して下さい。
また、『--』以降のパラメータは実行するソース（この場合task.py）にコマンドライン引数として渡されますのでデータの受け渡しが必要な場合はこのように指定しましょう。

## まとめ

GCPというよりCloud Shellは非常に便利でした。
こういう物があるとクラウドを利用する際の検証の敷居が下がるので、とてもありがたかったです。
機械学習については無料枠がないので、無料トライアルの無料分を消費する形になりますが、40時間くらいリソースを使っても1,000円程度で済むので無料トライアルでも十分検証利用は可能なようです。
ただ、分散処理をしていないためか[256 x 256]の画像データを4000枚ほど学習させたところでOOMKillerが呼び出されてタスクが中断してしまい、学習を完了させることができませんでした。

とりあえずは学習データを1000枚にしてお茶を濁しましたが大量のデータでの学習は残念ながらできていないので、この問題が解決したら次回にでも書こうかな。
（全く違うことが書かれてたら察して下さい。。。）
LaTeXで1未満の10進小数を2進数へ変換

(0.1875)_10 = (0.0011)_2の変換の様子をLaTeXで実現する．

```latex:test.tex
\documentclass{article}

\usepackage{xstring}
\usepackage{xifthen}

\usepackage{amsmath}

\usepackage{fp}

\begin{document}


\newcounter{index}

\newcommand{\FtoB}[2][2]{%
   \edef\result{#2}%
   \FPsub{\result}{\result}{0}%
   \edef\resbin{0.}%
   \StrLen{#2}[\mystrlen]%
   \setcounter{index}{0}%
   \FPsub{\mylen}{\mystrlen}{2}%
   \FPtrunc{\result}{\result}{\mystrlen}%
   \whiledo{\value{index} < \mystrlen}{%
      \stepcounter{index}%
      $\result * 2 = {}$%
      \FPmul{\result}{\result}{2}%
      \FPtrunc{\resultint}{\result}{0}%
      \FPsub{\result}{\result}{\resultint}%
      \FPtrunc{\result}{\result}{\mystrlen}%
      \edef\resbin{\resbin\resultint}%
      $\result \rightarrow$ \ \resultint, \resbin
      \\
   }
}



\noindent
\FtoB{0.1875}

\noindent
\FtoB{0.5}

\noindent
\FtoB{0.125}

\noindent
\FtoB{0.25}

\noindent
\FtoB{0.200000000}


\end{document}
```

こうなります．

![スクリーンショット 2016-12-13 9.09.32.png](https://qiita-image-store.s3.amazonaws.com/0/44835/0050978a-d223-250d-c3ec-85365da262f3.png)
ajaxの設定方法

# ajax の利用方法

## submitボタンありの場合
大きな流れは、view(html) → controller → view(js)

form_for タグ内で、 remote: true を付加する。

```ruby:index.html.erb
<%= form_for @memo, remote: true do |f| %>
  <%= f.text_field :text %>
  <%= f.submit '投稿' %>
<% end %>
<ul>
  <%= render @memos %>
</ul>
```
- remote で呼ばれたcontroller内で、render されるファイルは jsファイル
以下の場合、create.js.erbが呼び出される
- `<%= render @memos %>`については、[Viewでのrenderの使い方-その4-](http://qiita.com/level52/items/553375a2462c9c987dbb#%E3%81%9D%E3%81%AE3)を参照

```ruby:memos_controller.rb
class MemosController < ApplicationController
  def create
    Memo.create(memo_params)
    @memos = Memo.all
  end
end
```

```ruby:create.js.erb
$("#memo_text").val(""); // 入力フォームを空欄にする処理
$("ul").html("<%= j(render @memos) %>");
```
- `<%= j(render @memos) %>` は、`<%= j(render :partial => 'memo', :collection => @memos) %>`と同じ意味

## submitボタンなしの場合
大きな流れは、view(html) → javascript → controller → view(html)

### その１
```ruby:search.html.erb
<!--- actionで指定しているresutlxx(controller) は、利用されない。 --->
<!--- url は、javascriptで指定 --->
<%= form_tag({ action: :resultxx }, remote: true) do %>
  <%= select_tag("test", options_from_collection_for_select(
    @books, :publish, :publish, ''), include_blank: true) %>
  <span id="progress0"></span>
<% end %>
<ul id="result0"></ul>
```

```ruby:cofeescript
  $('#test').change 'ajax:success', (e, data) ->
    $('#result0').empty()
    # urlは、controller の search_result0アクション
    $.ajax(
      type: 'GET'
      url: 'search_result00'
      data: {
        publish: $(this).val()
        }
      )
      # ajax通信が成功した場合、renderする
      .done (data) ->
        $('#result0').html(data)
```

```ruby:controller
  def search_result00
    sleep(2)
    @books = Book.where(publish: params[:publish]).order(:title)
    render action: "search_result0" # search_result0.html.erb の呼び出し
  end
```

```ruby:search_result0.html.erb
<ul>
<% @books.each do |book| %>
  <li><%= book.title %></li>
<% end %>
</ul>
```

### その2
```ruby:search.html.erb
<!--- action resutlx1 ・ controller は利用されない。 --->
<!--- url は、javascriptで指定 --->
<%= form_tag({ action: :resultx1 }, remote: true) do %>
  <%= select_tag("test1", options_from_collection_for_select(
    @books, :publish, :publish, ''), include_blank: true) %>

    <span id="result1">
      <%= select("test2", "", "", include_blank: "発行を選択してください") %>
    </span>
<% end %>
```

```ruby:cofeescript
  $('#test1').change 'ajax:success', (e, data) ->
    $.ajax(
      type: 'GET'
      url: 'search_result1'
      data: {
        publish: $(this).val()
        }
      )
      # ajax通信が成功した場合、renderする
      .done (data) ->
        $('#result1').html(data)
```

```ruby:controller
  def search_result1
    sleep(2)
    @books = Book.where(publish: params[:publish]).order(:title)
  end
```

```ruby:search_result1.html.erb
  <%= select_tag("test2", options_from_collection_for_select(
    @books, :title, :title, '')) %>
```
Travis CI への Heroku Deployment に失敗する場合の一例

# 問題

Travis CI での Heroku Deployment に失敗する。[Heroku Deployment - Travis CI](https://docs.travis-ci.com/user/deployment/heroku/) にある公式の手順どおりにやっても解決しない。

# 解決策

`travis` の対象 repository が間違っている可能性がある。

`travis show` で確認する。

次の例は bouzuya/mr-jums を期待していたのに bouzuya/bbn-cycle を対象 repository にされていたときのもの。

```
$ travis show
Build #30:  DEPRECATED
State:         passed
Type:          push
Branch:        master
Compare URL:   https://github.com/bouzuya/bbn-cycle/compare/33cba4ca5db8...3b97b612bfd5
Duration:      6 min 57 sec
Started:       2016-10-11 09:21:36
Finished:      2016-10-11 09:24:08

#30.1 passed:    2 min 27 sec   node_js: node, os: linux
#30.2 passed:    2 min 15 sec   node_js: 6, os: linux
#30.3 passed:    2 min 15 sec   node_js: 5, os: linux
```

対象 repository が間違っていると `travis encrypt` の対象も変わってしまう。`travis encrypt -r` オプションで指定するか、`git clone` し直すなどして、対象 repository を変更する。

次は `travis encrypt -r user/repo` での対応例。

```
travis encrypt -r bouzuya/mr-jums $(heroku auth:token) --add deploy.api_key
```
[1day1lang AdventCalender] day4 Ruby



# Rubyのインストール
今のところ複数のバージョンを切り替える必要がないので、rbenvやRVMを使わずサクッとインストール

```bash
$ sudo apt install ruby
```

```bash
$ ruby --version
ruby 2.3.1p112 (2016-04-26)
```
思ってたより新しいバージョンが入っていた


# Hello,World!

```bash
$ ruby -e "puts 'Hello, World'"
Hello, World
```
ちなみにこの状態で、最後尾にエクスクラメーションマークを書くと怒られる

```bash
$ ruby -e "puts 'Hello, World!'"
bash: !': event no found
```

シングルクォーテーションとダブルクォーテーションを入れ替えてみる

```bash
$ ruby -e 'puts "Hello, World!"'
Hello, World!
```
`!'` で怒られる理由については、調べて別記事を立てようかと。

# irbで書いてみる
irbの起動と終了

```bash
$ irb
irb(main):001:0> exit
```
irbでHello, World!

```irb
irb(main):001:0> puts "Hello, World!"
Hello, World!
=> nil
```

渡した文字列をキャピタライズして出力するhello関数定義

```irb
irb(main):002:0> def hello(name)
irb(main):003:1> puts "Hello, #{name.capitalize}!"
irb(main):004:1> end
=> :hello
irb(main):005:0> hello "world"
Hello, World!
=> nil
```
日本の西の天草、Tから始まるIoT

ほとんどのみなさん、はじめまして、野間です。

日本の西端の島、天草でもIoTで盛り上がってきてます。Tから始めるIoT、というよりbeyond edgeな話をいくつか紹介してみます。よかったら天草に足を運んでみてね。

#天草って何？
![天草の場所は日本の西のはずれ](https://qiita-image-store.s3.amazonaws.com/0/49042/29d2b61e-f946-b4b1-c954-e8d2fc84bc97.png "天草の場所")

1. 日本の西です。九州の西です。長崎県にちょっと似てて、鹿児島県とも近い、でも一応熊本県です。
すみません、地図に沖縄出てません。今話題の北方四島も出てません。
* 島です。天草諸島といって、12万人強住んでます。鹿児島県側の天草諸島長島町も含めると15万人くらいになります。（2016年現在）
* 有明海、八代海、東シナ海に囲まれ、水産資源が多様で本当においしい島です。
* 60年前までは離島だったので、何でも作ってしまう島生活が残ってます。
* 私、野間が住んでます。

##一応自己紹介
小学生からパソコンを触っていたIT屋さんです。プログラミングからコンサルまで幅広くこなしているつもりです。学生時代に起業しこれまで東京で仕事をしていた訳ですが、2013年くらいからグローバル化の次は**地方からの革命**だ！と思ってたところ天草とご縁ができ、昨年2015年から天草で生活をしてます。

天草、ほんとにいいとこですよー。魚介類は南のものから青物まで、ほんとに多種多様でおいしいです。そして野菜、果物も豊富、牛、豚、鳥もどれもおいしいものを取り揃えてます。皆さん、共同でサテライトオフィス兼保養所作りませんか？

#天草でIoT
ようやく本題です。
天草に来たのは、そもそも、ロボット、小型ワンボードマイコンが廉価になり、様々な現場で使えるフェ[ーズになったから、そして、シリコンバレーも一次産業に目を向け始めてたからというビッグウェーブが来てたからなんです。だからこそ「天草でIoT」なんです。

##地方IoTサミット2016 in 天草
11/11に開催しました。大都市以外でIoTサミットと名打つものは全国初です。ウフルの八子知札さんの話や県内のいろいろな取り組みに多くの人が刺激を受けました。そしてこの日をきっかけに、さらにこの動きを加速させましょうということになりました。
[インプレスさまによる報告記事](https://i.impressrd.jp/archives/1158)

##天草IoTイニシアティブ キックオフ！
サミットをきっかけに、天草でIoTに興味のある人で情報交換の場を作りました。勉強会、IoTLT、個別プロジェクトについての打ち合わせ、もくもく会などを少しずつ形にしていきます。
[天草IoTイニシアティブ](http://iot-initiative.com/)
[天草IoTイニシアティブFacebook Group](https://www.facebook.com/groups/iot.initiative/)

#どんなIoTプロジェクトがあるの？
##空のIoT
###天草Xアスロン大会
SAP・シーカヤック ⇒ トレイルランニング ⇒ マウンテンバイク ⇒ パラグライダー と4種の競技を一人の人がこなすというXアスロン大会が天草にはあるんです。（ちなみに年中すべて楽しめるようです）パラグライダー種目が天高く飛んでしまって様子がつかめないということで、さくらインターネットさんと連携して空飛ぶ選手をスマホから追っかけられるようにしてみました。
[さくらインターネットが「天草Xアスロン2016」でIoT実験！ その開発の舞台裏をレポート]https://thinkit.co.jp/article/10084

##地のIoT
###中山間地農業×IoT
天草には広い農地が少なく、消費地も遠い、そんな不利な条件の農業でも頑張ってる人たちがたくさんいます。
農商連携することでできるIoTを構想中です。細切れの田畑、多数の農業者、直売所がストレスなくつながることで、作付計画から変わってくる、そんな革命が起きそうです。

###生コン業者×IoT
人口の少ない天草では、生コン関連で事業者も垂直統合していたりします。製造から打設までを一つのシステムとして管理することでこの先予測される職人不足に対処することをもくろんでます。生コン製造工場、ミキサー車、工事現場がつながることで、よりきめ細かい品質管理ができるようになります。

##海のIoT
###遊漁船×IoT
釣りというと待ち時間が長かったり、釣れたり釣れなかったりするもの・・・
というのはもう過去の話かもしれません。潮・波・風の影響を強く受ける遊漁船をIoT化するとどうなるのか？
エンジン、帆、舵、衛星、風力計、魚群探知機などなど様々な要素が絡まりあう複雑系を制御できるか？大きな課題にチャレンジ中です。

###養殖業×IoT
養殖と一言で言ってもすごく多様です。沖にあるもの、陸上にあるものなど生け簀の作り方も多様、魚種も多様。そして天草はそんな多種多様な養殖場の博物館になってます。でも現場では、餌代の高騰、人手不足、高温、赤潮と課題がひっきりなしです。海水の状態、生き物の状態、餌の動態など未知かつ見えない要素が多いです。
海水（温度推移、溶存酸素量、微生物量、pH、塩濃度・・・）、生産物（生き物）の生態・生育状況、餌、各種機材、周辺海域の状況。新しいセンシング技術も求められる上、海中は電波が通らないなど技術的な課題が多数。

##観光のIoT
###あまたびプロジェクト
天草観光で課題になるのが、「足」
観光客に無償で電気自動車を利用してもらう社会実験が始まってます。車載の機器を通じ、「出会い」のある観光演出の方法を模索中です。車載器、各種観光拠点、天草人をつなげていくことは可能なのか？


#天草でIoTを考える
以前、IoT界隈で、ソフトよりハードよりの話を聞きながら、電子回路も確かにハードだけど、圧倒的にソフトに近い領域のハードじゃんと思ってました。天草に限らず地方には、ガチのハードの世界が広がってます。
![クラウド、エッジ、いやハードでしょ](https://qiita-image-store.s3.amazonaws.com/0/49042/2774e2ae-b0fe-f595-926e-90f223c63a1b.png)

世間では、プラットフォーム争いが激しく行われてますが、物事が変わるのはエッジの先、それも、今までコントロールが難しかった領域でこそ力を発揮すると確信してます。そしてリアルワールドから眺めている限り、プラットフォームはどこでもいいんです。そんなチャレンジできる場、そして一緒にチャレンジしてくれる現場が天草にはたくさんあります。

各取り組みについては、天草IoTイニシアティブでも少しずつ発信していきますのでよろしくお願いいたします。

1月14日にはドローンサミットも行いますし、12月13日からはIoTLTもスタートします。
[12/13 熊本版IoTLT天草](https://iotlt.connpass.com/event/45462/)

天草IoTイニシアティブ始まってます。
まだ可能性を語り合うフェーズの人が多い、けど、着実に次の時代に向かってます。
まずは観光がてら天草にいらしてください！
天草には来れないけど是非手伝いたいという方、FBグループへ！
ELB + nginx + php-fpm でHTTPS対応した

# はじめに

初老丸カレンダー 12/12分です。 UTCではまだ12日。

httpsにはhttps、httpにはhttpを返すというWebサイトを作りたいという要望がありました。
ELBが前段にあり、SSLターミネーションする環境のため、nginxにはhttpとしてリクエストが届きます。
railsなど、nginxをリバースプロキシとして動作させる場合の設定は検索によくでてきますが、php-fpmのようなfastcgi系の場合の設定がみつからなかったので試してみました。

# 設定

最初から答えになります。

https://www.nginx.com/resources/wiki/start/topics/examples/phpfcgi/
の設定をhttps化した例です

```

#X-FORWARDED-PROTOを使ってHTTPS判定する変数を作成
set $elb_https off;
if ($http_x_forwarded_proto = https) {
    set $elb_https on;
}

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    if (!-f $document_root$fastcgi_script_name) {
        return 404;
    }

    # Mitigate https://httpoxy.org/ vulnerabilities
    fastcgi_param HTTP_PROXY "";

    # HTTPSパラメータにX-FORWARDED-PROTOを判定した結果を設定
    fastcgi_param HTTPS $elb_https; 

    fastcgi_pass 127.0.0.1:9000;
    fastcgi_index index.php;
    include fastcgi_params;
}
```

組み込み変数 $http_x_forwarded_proto でロードバランサーでのSSL Terminationの有の場合にのみ、fastcgiのパラメータHTTPSをonにするという設定になっています。ELB用とかきましたが、他でもつかえるかとおもいます。

全部httpsとして返したいということであれば、 リダイレクト設定をいれる等の対応になるのですが、httpもつかうということでこの設定になっています。

いろいろ試していたのですが、fastcgi_paramをif文で括るとエラーになりました。また、直接$httpsを変更しようとしてもエラーとなりました。そういうものなのでしょうか。

おかしな点あれば是非ご指摘ください。

# 余談

FPMってFastCGI Process Managerの略だったんですね...
技術英語 > [Tough limits were set] on days at sea, and fish size, and net size. 

@ LOE > August 22, 2003
http://www.loe.org/shows/shows.html?programID=03-P13-00034

> By the earlier 1990s, codfish were growing scarce. Regulators closed many fishing grounds. **<font color=red>Tough limits were set</font>** on days at sea, and fish size, and net size. 

意訳「1990年代初頭までに、タラの生息数は激減した。規制を唱える人々は多くの漁場を閉鎖に追い込んだ。それらの日々において(?)海域、魚の大きさ、漁網の大きさに対して厳しい制限が課せられた。」

**(on daysの意味は取り違えている可能性がある)**

(追記 2016/12/14)
「on days at sea」に関して@knoguchiさんに[正しい訳を教えていただきました。](http://qiita.com/7of9/items/5f109b39ed41200ddd3e#comment-7aeafb9b7021dee5baa3)


https://github.com/gjamie/optout/blob/726003b1cbbdd348745ed2ddcfea9bc8f841f5f5/README
> It runs under Google App Engine, athough this does have some fairly **tough limits** on the emails that can be send.

<hr>
「制限」から関連して

[secureCoding > C11 > set_constraint_handler_s() / ignore_handler_s()](http://qiita.com/7of9/items/e5e58c16c63599fe4f88)
Go言語でExcel操作ライブラリを書いてみた

この記事は[Go (その3) Advent Calendar 2016](http://qiita.com/advent-calendar/2016/go3) 13日目の記事です。
# Go言語でExcel操作ライブラリを書いてみた

[excl](https://github.com/loadoff/excl) ライブラリ

## なぜそんなもの書いたのか

Go言語にはExcel作成用のライブラリ [xlsx](https://github.com/tealeg/xlsx) がすでに存在します。
xlsxライブラリは強力で、普通に使用する場合このライブラリが一番だと思います。
ただ、xlsxライブラリを調査していると今回作成するものの仕様に耐えられない部分がありました。

### xlsxライブラリの利点欠点

#### xlsxライブラリにできること
・Excelファイルの書き込み・読み込み・新規作成
・セルの書式設定
・Excelファイルを解凍せずに扱える
・OpenXMLの仕様に基づいた開発

#### xlsxライブラリの問題
・既存のExcelファイルを使用するといろいろなものが消える
　・チャートが消える
　・画像が消える
　・図形が消える
・マクロの存在するファイルの場合はマクロも消える
・メモリ使用量が異常に高くなる
　・数十メガバイトのデータでも使用メモリがギガを超える

## exclライブラリってなに？

既存のExcelファイルにデータを追加することを目的に作成されたライブラリ
可能な限りメモリに持たずにファイルに書き出す

### 使い方

```go:main.go
import(
  "github.com/loadoff/excl"
)

func main(){
  // Excelファイルを読み込み
  w, _ := excl.Open("path/to/read.xlsx")
  // シートを開く
  s, _ := w.OpenSheet("Sheet1")
  // 一行目を取得
  r := s.GetRow(1)
  // 1列目のセルを取得
  c := r.GetCell(1)
  // セルに10を出力
  c.SetNumber("10")
  // 2列目のセルにABCDEという文字列を出力
  c = r.SetString("ABCDE", 2)
  // シートを閉じる
  s.Close()
  // 保存
  w.Save("path/to/new.xlsx")
)
```

新規にファイルを作成する場合

```go
w, _ := excl.Create()
s, _ := w.OpenSheet("Sheet1")
s.Close()
w.Save("path/to/new.xlsx")
```

セルの書式を設定する場合

```go
w, _ := excl.Open("path/to/read.xlsx")
s, _ := w.OpenSheet("Sheet1")
r := s.GetRow(1)
c := r.GetCell(1)
c.SetNumber("10000.00")
// 数値のフォーマットを設定する
c.SetNumFmt("#,##0.0")
// フォントの設定
c.SetFont(excl.Font{Size: 12, Color: "FF00FFFF", Bold: true, Italic: false,Underline: false})
// 背景色の設定
c.SetBackgroundColor("FFFF00FF")
// 罫線の設定
c.SetBorder(excl.Border{
    Left:   &excl.BorderSetting{Style: "thin", Color: "FFFFFF00"},
    Right:  &excl.BorderSetting{Style: "hair"},
    Top:    &excl.BorderSetting{Style: "dashDotDot"},
    Bottom: nil,
})
s.Close()
w.Save("path/to/new.xlsx")
```

グリッド線の表示・非表示

```go
w, _ := excl.Open("path/to/read.xlsx")
s, _ := w.OpenSheet("Sheet1")
// シートのグリッド線を表示
s.ShowGridlines(true)
// シートのグリッド線を非表示
s.ShowGridlines(false)
s.Close()
w.Save("path/to/new.xlsx")
```

### exclライブラリの特徴

・既存のExcelファイルを使用する
　・もとの設定は消えないことを前提に開発を行った
・メモリ使用を抑える
・マクロファイルも使用できる

### 問題点

~~・新規作成(空のExcelファイルを用意する必要がある)~~
2017年01月のコミットで作成できるようになりました。
・Excelファイルが展開される

### TODO

・セルの書式を自由に設定する
・英語化

## 結論
新規にExcelファイルを作成し、データ量が多くない場合は [xlsx](https://github.com/tealeg/xlsx) ライブラリを使用するべきですが、テンプレート用のExcelファイルが存在する場合は[今回作成したライブラリ](https://github.com/loadoff/excl)が有用かと思います。

今更OpenXMLの仕様についてかなり調べましたが、OpenXMLは複雑だがよくできているなと感じました。
また、Go言語のxmlライブラリを使用してxmlns属性が存在するファイルをいじると
予想していない動作をします。
xmlns:_xmlns="xmlns" みたいな形になってしまい、まったく同じファイルを出力しなおすのに手間取りました。
[ここらへん](https://github.com/golang/go/issues/13400)で議論されていますが、1.8か1.9で修正予定みたいです。
[参考](https://play.golang.org/p/rxXydio31M)
Node.jsのFile System APIで同期処理と非同期処理の使いわけ

同期処理と非同期処理が混在している場合、予期しない動作として関数が通らなかったりする。
ポイントを抑えて、同期と非同期を使い分けなきゃいけませんね。

## 同期処理

```
fs.readFileSync（）
```
同期処理は<code>Sync</code>がついているようです。この処理が終わらないと次の処理に移らないようになります。例えば、非同期で<code>writeFile()</code>とかしていて、すぐ次に<code>readFileSync()</code>とかしていると「予期せぬエラーがおきました」的なエラーがでたりしました。考えてみれば当たり前ですが、午前3時くらいに遭遇するとハマりますね。

## 非同期処理

```
fs.readFile（）
```
逆に並行してどんどん処理を進めてよって時は非同期にしたほうがよいですね。ファイルの書き出しだけとかならできたところから出力してくれればいいので、非同期で進めてもらっちゃってかまわないということですね。

便利ですね。

Node.jsはやっぱり便利だなー。技術的革新て感じがする。これによって、かなりWebまわりとか可能性広がったと思う。まぁまぁ取り上げられているとはいえ、もっとインパクトのある技術革新だなーと改めて思う。

Electronでもっと気軽にアプリつくったら結構業務が便利になりそう。請求書発行したりとか。
JSON使ってローカルで完結すると別に変換するのも楽だし。
siema-railsというgemを作りました。

# Siema

とっても軽量で何にも依存していない、スライドのヘルパー（carousel）のgemです。

たったの1kbで依存なしというのがかっこいいのでお気に入りです。

[Siema Homepage](https://pawelgrzybek.com/siema/)

# Siema Rails

これのgemがなかったので、作ってみました。

https://github.com/Naggi-Goishi/siema-rails

http://naggi-blog.com/2016/12/programing/siema-rails/
XPathでソースコード検索する話 @ 第七回闇PHP勉強会


闇PHP勉強会は前から気になっていたイベントですが、たまたま弊社で開かれることになっていたので、どうにかして発表してみました。

スライドはこちら→https://speakerdeck.com/edvakf/xpathdesosukodojian-suo-1

コード→https://github.com/edvakf/php-ast-to-xml

例えば「in_arrayの第三引数が与えられていない箇所」みたいなのを探したい時に、便利なツールは無いんですよ。

前に会社の人がPHPのASTに対してjQuery風のクエリ言語で検索できるツールを作ってたのですが、そのDSLを覚えるのもなかなか面倒なのです。

PHP7になってASTを作るようになったのですが、これをPHP側から触れるようにするための[php-ast](https://github.com/nikic/php-ast)というツールを使って、ASTを機械的にXMLに変換することができます。下のようなXMLの形に落ち着いたのは僕の好みも大きく、ちょっと冗長ではあるのですが、大事なのは機械的に変換できるということです。

```
$ cat some.php
<?php

in_array(1, [1, 2]);

$ php-ast-to-xml some.php
<?xml version="1.0"?>
<ast>
  <AST_STMT_LIST lineno="1">
    <AST_CALL lineno="3">
      <expr>
        <AST_NAME lineno="3" NAME_NOT_FQ="NAME_NOT_FQ">
          <name>
            <scalar value="in_array" type="string"/>
          </name>
        </AST_NAME>
      </expr>
      <args>
        <AST_ARG_LIST lineno="3">
          <scalar value="1" type="int"/>
          <AST_ARRAY lineno="3">
            <AST_ARRAY_ELEM lineno="3">
              <value>
                <scalar value="1" type="int"/>
              </value>
              <key/>
            </AST_ARRAY_ELEM>
            <AST_ARRAY_ELEM lineno="3">
              <value>
                <scalar value="2" type="int"/>
              </value>
              <key/>
            </AST_ARRAY_ELEM>
          </AST_ARRAY>
        </AST_ARG_LIST>
      </args>
    </AST_CALL>
  </AST_STMT_LIST>
</ast>
```

すると、このXMLに対してクエリを書くことができて、「in_arrayの第三引数が与えられていない箇所」の場合はこうなります。

```
$ php-ast-xpath some.php '//AST_CALL[./expr/AST_NAME/name/scalar[@value="in_array"] and not(./args/AST_ARG_LIST/*[3])]'
some.php:3
```

最後に「妄想」として書いている、ASTからPHPのソースコードに復元することができれば…というところは、JavaScript界隈では数年前からそういうことが行われているので、不可能ではないはずです。

GoogleではClangのASTを使ってC++をリファクタリングしているそうです。

https://www.youtube.com/watch?v=mVbDzTM21BQ
【iOS】アプリ譲渡後の証明書関連について

13日目は、スマートテック・ベンチャーズの江本([@s_emoto](http://qiita.com/s_emoto))が担当いたします。

アプリを譲渡した後の証明書などに関しての記事が見当たらなかったので記事にしようと思います。アプリを譲渡する・される時の参考になれば幸いです。
譲渡の手順については下記の記事を参考にして下さい。
[App Storeに上がっているアプリを譲渡する方法](http://qiita.com/Sam/items/488f359093728d894b06)

# 譲渡により引き継がれるもの
・アプリの所有権 → App Store上の販売元が譲渡先に変わる
・App ID → 譲渡が完了した時点で自動的に追加されます

# 証明書 / プロビジョニング・プロファイル
譲渡先のアカウントで新規に作成する必要があります。
※ただし、アップデートをしないのであれば不要

# Bundle IDは変更できる？？
Bundle IDに企業名などが含まれている場合、譲渡が完了した後に譲渡先のBundle IDに変更したい、ということがあり得ると思いますが，**基本的には変更できません(別のアプリとしてApp Store上に２つ存在することになります…)**

しかし！
ある条件を満たす場合はBundle IDを変更できるようです。
以下、Appleサポートのメールからの引用です。
**アプリケーション譲渡後のアプリにおいて、Bundle ID を変更できるかのご質問をいただいておりましたが、わたくしの方で変更ができる場合の条件を確認させていただきました。その結果、Bundle ID を修正、変更できるのは、アプリケーションの最初のバージョンが「Prepare for Submission (提出準備中)」の状態のみとの事でした。**

将来譲渡する可能性のあるアプリを開発する時はこの条件に気をつけたいですね。

# 最後に
スマートテック・ベンチャーズでは、未経験だけどiOSの開発をやりたい！という人を募集しています。
Advent Calendarのスマートテック・ベンチャーズページに会社およびWantedlyのURLをのせていますので、興味のある方は是非ご覧ください。
http://qiita.com/advent-calendar/2016/stv

明日は@eKushidaさんです。
お楽しみに！
INNER JOINでエラーメッセージ「Column 'カラム名' in field list is ambiguous」が出た時


#原因
INNER JOINでテーブル結合する時に、テーブル内で同じカラムがあった場合、select等でそのカラムがどのテーブルに存在するものか指定していないとエラーメッセージ「Column 'カラム名' in field list is ambiguous」が表示される。

原因は単純にカラムが重複してしまい、どのテーブルを参照すればいいのか分からないから。

```
select id,status,
from テーブルA INNER JOIN テーブルB on テーブルA.カラム① = テーブルB.カラム①
where id is not null and status = 1
```
上記で実行すると→Column 'id' in field list is ambiguous

※カラム①のカラム名が同じ意味合いなのにテーブルで違う名前の場合もあるが、それはそれで、そのまま書けばOK

###テーブルA                                      
| id      | status | Category |
|:--------|-------:|:---------:|
| 1       |      1 |   A       |
| 2       |      1 |   A       |
| 3       |      3 |   B       |
| 4       |      4 |   C       |
| 5       |      1 |   C       |
| null    |      2 |   C       |

###テーブルB
| id      | status | type      |
|:--------|-------:|:---------:|
| 1       |      1 |   GJ      |
| 2       |      1 |   Go      |
| 3       |      0 |   Go      |
| 4       |      0 |   Go      |
| 5       |      0 |   GJ      |
| null    |      0 |   GJ      |

**テーブルAとテーブルBのidとstatusが重複してる**



#解決
SQL文内の重複するカラム全てにどのテーブルのカラムなのか追記する。

```
select id,status,
from テーブルA INNER JOIN テーブルB on テーブルA.カラム① = テーブルB.カラム①
where テーブルA.id is not null and テーブルB.status = 1
```

以上。
ツイキャスで自分のコメントを一括削除する方法


知り合いが似たような事をブックマークレットでやってたけど、自分でやってみたら意外と簡単だったのでメモ。

* Chromeブラウザで
* 放送のタブを開いたまま
* デベロッパーツールを開き
* コンソール部分に下記を入力してEnter

```
$('tr.you td.comment div a.comment-remove').click();
```

※ブラウザ上に表示されているコメントにしか適用されません。

[Chrome拡張機能版](https://chrome.google.com/webstore/detail/%E3%83%84%E3%82%A4%E3%82%AD%E3%83%A3%E3%82%B9%E3%82%B3%E3%83%A1%E3%83%B3%E3%83%88%E4%B8%80%E6%8B%AC%E5%89%8A%E9%99%A4/eeadjmebmbkfnhablhiedepfkkelcdef?hl=ja)作りました。

以上
gst-indent を使ってコード整形する

# gst-indent って?

[gnu indent](https://www.gnu.org/software/indent/)のラッパーで、GStreamerのコーディングスタイルにコードを整形してくれるというもの。

コードは [gstreamer/common](https://cgit.freedesktop.org/gstreamer/common/) にあります。

# gst-indent の使い方

引数にファイルを渡す。それだけ。

```shell-session
$ path/to/gst-indent hogehoge.c
$ ls
hogehoge.c hogehoge.C~
```

`~` チルダがついている方がもとのファイルです。

# gst-indent を vim から使う

また、vim の `equalprg` に gst-indent をセットしてあげれば、`gg=G` で整形することができます。

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.amazonaws.com/0/97187/f0bda603-2fb3-b3de-06e3-eb475f8b686e.gif)

setlocal を叩くのが面倒であれば `vimrc` や `init.vim` に以下を追記してもいいかもしれません。

```vim
au FileType c setlocal equalprg=~/src/gst/common/gst-indent\ 2>\ /dev/null
```
globalにgulp-cliをインストールしようとするとエラーが発生する

## 現象
gulp 4.x系に対応するべく、globalからgulp(3.9.0)をアンインストールし、改めてgulp-cliをインストールしようとしたろころ下記のようなエラーが発生する。
インストールは中断され、gulp-cliがインストールできない。

```
nayucolony:~ demo$ sudo npm install -g gulp-cli
/usr/local/bin/gulp -> /usr/local/lib/node_modules/gulp-cli/bin/gulp.js
npm ERR! Darwin 15.6.0
npm ERR! argv "/usr/local/bin/node" "/usr/local/bin/npm" "install" "-g" "gulp-cli"
npm ERR! node v6.9.2
npm ERR! npm  v3.10.9
npm ERR! path /usr/local/share/man/man1/gulp.1
npm ERR! code EEXIST

npm ERR! Refusing to delete /usr/local/share/man/man1/gulp.1: ../../../lib/node_modules/gulp/gulp.1 symlink target is not controlled by npm /usr/local
npm ERR! File exists: /usr/local/share/man/man1/gulp.1
npm ERR! Move it away, and try again.

npm ERR! Please include the following file with any support request:
npm ERR!     /Users/demo/npm-debug.log
nayucolony:~ demo$ gulp -v
-bash: /usr/local/bin/gulp: No such file or directory
nayucolony:~ demo$ 
```

## 原因

下記に注目

```
npm ERR! Refusing to delete /usr/local/share/man/man1/gulp.1: ../../../lib/node_modules/gulp/gulp.1 symlink target is not controlled by npm /usr/local
npm ERR! File exists: /usr/local/share/man/man1/gulp.1
npm ERR! Move it away, and try again.
```

npm側から操作できないゴミファイルが存在してインストールがうまくいってない様子


## 対応
下記のコマンドを叩いて、上記の２行目に表示されているゴミファイルを削除する

```
sudo rm /usr/local/share/man/man1/gulp.1
```

その後、改めて

```
sudo npm install -g gulp-cli
```
を叩くことでインストールが完了した。


## 備考
`sudo`は管理者権限で実行するためのコマンドで、パスワードを要求されることがあるので都度入力を行うこと。


また、本件とは関係しないが、gulp-cliをglobalにインストールすることについては公式の推奨事項ではあるものの、否定的な意見もあるのでよく考えて行うこと。
UIBezierPathで矩形のCornerRadiusを別々に指定するサンプルコード

<img width="264" alt="Screen Shot 2016-12-13 at 1.38.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/8358/04ef6ea5-6655-db13-3bdc-2e9c264f8bef.png">

Facebook Messengerの吹き出し(上のような画像)のように、それぞれ異なった角丸を持ったViewを作りたかったのですが、
UIBezierPathにはそのようなAPIはありませんでした。

角丸にする角を選択するAPIはあったんですけどね...
これのこと-> `init(roundedRect: CGRect, byRoundingCorners: UIRectCorner, cornerRadii: CGSize)`

なのでゴリゴリパスを書いて実現しました。

メモレベルですが、せっかくなのでここで共有させていただきます🌳

## サンプルコード

```swift
func roundedCorners(rect: CGRect, topLeft: CGFloat, topRight: CGFloat, bottomRight: CGFloat, bottomLeft: CGFloat) -> UIBezierPath {

  func radian(_ angle: CGFloat) -> CGFloat {
    return angle * CGFloat(M_PI) / 180
  }

  let path = UIBezierPath()
  path.move(to: CGPoint(x: topLeft, y: 0))

  path.addLine(to: CGPoint(x: rect.maxX - topRight, y: 0))
  path.addArc(withCenter: CGPoint(x: rect.maxX - topRight, y: topRight), radius: topRight, startAngle: radian(-90), endAngle: radian(0), clockwise: true)

  path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY - bottomRight))
  path.addArc(withCenter: CGPoint(x: rect.maxX - bottomRight, y: rect.maxY - bottomRight), radius: bottomRight, startAngle: radian(0), endAngle: radian(90), clockwise: true)

  path.addLine(to: CGPoint(x: bottomLeft, y: rect.maxY))
  path.addArc(withCenter: CGPoint(x: bottomLeft, y: rect.maxY - bottomLeft), radius: bottomLeft, startAngle: radian(90), endAngle: radian(180), clockwise: true)

  path.addLine(to: CGPoint(x: 0, y: topLeft))
  path.addArc(withCenter: CGPoint(x: topLeft, y: topLeft), radius: topLeft, startAngle: radian(180), endAngle: radian(270), clockwise: true)

  return path
}
```

## 使い方

```swift
let path = roundedCorners(
  rect: CGRect(x: 0, y: 0, width: 100, height: 36), 
  topLeft: 8,
  topRight: 8,
  bottomRight: 8,
  bottomLeft: 4
)
```
短縮URLサービスの作り方

これは [日本情報クリエイト  Engineers Advent Calendar 2016](http://qiita.com/advent-calendar/2016/njc) による10日目の記事になります。

#短縮URLサービスとは
長いURLを短いURLにしてリダイレクトさせるサービスです。
https://ja.wikipedia.org/wiki/%E7%9F%AD%E7%B8%AEURL

利用されだして随分経ちますが便利な反面いろいろと問題はあります。
1. 提供サービスの閉鎖により利用できなくなる。
2. 提供サービスの規約に抵触し利用できなくなる。
3. ウイルス感染源になりうる。

1,2は外部サービスを使う宿命ですが、できれば自分でコントロールしたいところです。
3は元のURLが隠しやすいためセキュリティ攻撃者にとっても便利なサービスとなってしまっています。

#自分で作れば安心
自分でつくれば閉鎖もないし制限も受けないし、利用者も制限できます。
そこで、できるだけ手間をかけず、コストをかけず、可用性を落とさないサービスとして、AWS のS3を利用しました。
ドメインを用意して、S3のバケットとドメインを紐づけて、htmlファイルにリダイレクトコードを書いた物をアップロードする。
って仕組みを作ったのが**2014年5月**でした。

そのうち時間ができたらAPI利用して生成ページ作ればアップロードの手間も不要になるなぁ
って放置していたらあっという間に2年が経過していました(^^;

#製作者現る!
弊社では毎年複数回インターン生を受け入れているのですが、1名だけのインターンが2回発生しました。
プログラム経験も少ない方だったので、社内向けで短期間で作成できるこの「短縮URL」を作成していただきました。

#ポイント
S3も2年の間に進化して、WEBリダイレクトオプションが利用できるようになっていました。
短縮URLっぽく最後に.htmlが不要なのでこちらのオプションを採用しました。

#主要コード(php)
    for ($i=0;$i<10;$i++){
    // オブジェクト名作成
      $s3_object = makeRandStr(6);
      // 同一オブジェクトがあるかの確認
      $check = $client->doesObjectExist($bucket_name,$s3_object);
      if (!$check){
        // 同一オブジェクトが存在していなかったら作成
        $result = $client->putObject(array(
          'Bucket' => $bucket_name,
          'Key' => $s3_object,
          'Body' => $s3_body,
          'ACL' => 'public-read',
          'ContentType' => 'text/html',
          'WebsiteRedirectLocation' => $target_url
         ));
         break;
       }
     }
社内系利用ってこともありきっちりしたエラー処理等も行っていません(^^;
コードの補足説明をすると以下の通りです。
`makRandStrはランダムな文字を生成する自作関数です。`
`$bucket_nameが短縮URLで作成されたバケット名です。`
`$s3_objectが6文字のランダムな文字で短縮URLの後半部分であり、ファイル名です。`
`$s3_bodyはファイルの中身です。`
`$target_urlはリダイレクト先のURLです。`

その他aws-apiへの接続部分や、登録フォーム結果表示ページ、本ページへのアクセス制限等を組み込んで完成です。

#謝辞
作成いただいたインターン生Aさん、php & AWS-API未経験でインターン補佐をご担当いただいた社員Sさん、手探りでの構築大変だったと思いますが作成いただきありがとうございました(^^
スプリントのタイムボックス 動かないチケット問題


カンバンで作業をチケット化しているときに本来はデイリースクラムで毎日進捗を確認しているときにチケットが１つも動かない日があるときには非常に問題です。
言うなれば進捗が０だという結果に見えるということです。

## 原因と対応

カンバンのチケット化は進捗が見えるようにするためにしているのに、１つもチケットが動かないということは、進捗が全くない非常に厳しい問題が起こっている可能性があります。
これの解決にはベテランなどをサポートに付けて一刻もはやく解消して下さい。


実はチケットが動かない問題としてもう１つの原因があります。
それはチケットの粒度が大きすぎることです。
チケットのサイズは２，３時間で１つ終わるくらいの作業にまで細かくするのが正しいです。
ストーリーは時間の掛かるものですが、エンジニアの作業する実装にはもっとブレイクダウンしたものにする必要があります。

## チケット分割の例

ストーリーが「ユーザ自身は自分のユーザ情報の編集、更新が出来る」とした場合に、このままチケット化しても良いですが、これはいくつかの作業に分割出来ます。
UIの実装、ユーザ情報を取り出すSQLの作成、ユーザ情報の更新SQLの作成。
HTMLからアプリケーションへのパラメータ連携、ユーザ更新ロジックの実装。
などです。
他にユーザ情報のテーブル作成やローカル環境を整えること、ユニットテストの実装など。

この例は抽象的なので、具体的な作業であればもっとチケットが現れるかもしれません。


## チケット分割のタイミング

本来であればスプリント計画のときにしっかり行えるのが良いです。
まだうまく分割できないメンバが居るときは、その人とマンツーマンで分割作業を進めることを数回行っても良いかもしれません。

一つ気をつけてほしいのは、これをメンバ全員がいるところで毎回やるのは避けて下さい。
まだ、全員が慣れてない数回は見えるとこでやっても良いですが、
以降は全員でやると全員の時間を使ってしまう上に深い話が出来ず、十分細かいチケットに出来ない事があります。
チケット分割が自分１人で出来ない場合、また、そのメンバがいる場合はマンツーマンで深く掘り下げてアイデアを出し合って分割して下さい。


## まとめ

もし、チケットが動かないときには２つの原因があります

- 大きな問題が起きていて調査で進捗がない時
- チケットが大きすぎて１日で終わらないサイズになっている時

それぞれに対してしっかり対処して、進捗を見えるようにしましょう！
モバイル開発におけるハイブリッドアプリという選択肢

swiftやkotlinを用いてiOS/Androidアプリを開発してきましたが、チーム事情でハイブリットアプリを使用する機会があったので、所感や環境の構築について記載します.

# ハイブリッドアプリの強み
やはりハイブリットアプリの強みといえばクロスプラットフォームであることだと思います. 私自身iOS, Androidでそれぞれ開発したサービスもありますが、開発はもちろん保守が大変です. その点統括してWeb周りのみ（html, css, javascript）で完結できてしまうのはやはり魅力です. 有名どころだと[wekipedia](https://itunes.apple.com/jp/app/wikipedia-mobile/id324715238?mt=8)や[cookipad](https://play.google.com/store/apps/details?id=com.cookpad.android.activities&hl=ja)などもハイブリッドアプリらしいです. 詳細に関しては[こちらの記事](http://qiita.com/okmttdhr/items/b0e2082432390af470fc)がわかりやすかったです.

# 実際に使ってみる
最もスタンダードとされる環境で作ってみました. また、開発エディタ(IDE)はローカルの慣れた環境で開発したかったので[monacaクラウドIDE](https://ja.monaca.io/register/start.html)ではなくWebStromを使用しました.
## 環境
* Mac OSX
* Cordova 
* AngularJS
* onsenUI
* node v6.9.2

# Cordova環境構築
nodeのインストールは済んでいるものとします.

* cordovaをグローバルでインストールします.  

```
npm install -g cordova
```

* バージョン確認  

```
cordova -v
```

* 新規プロジェクト作成

```
cordova create [プロジェクトのフォルダ名] [アプリ識別名] [プロジェクト名]
ex) cordova create cordovaSampler com.example.cordovaSampler cordovaSampler
```

* フォルダ構成
    * ```config.xml```
        * 設定ファイルです
    * ```hooks```
    * ```platforms```
        * iOSやAndroid etc..
    * ```plugins```
        * プラグインです
        * カメラやステータスバーのカスタマイズなどネイティブ機能を使用する際は基本的にプラグインを用いることが多いです.
    * ```www```
        * ```css```
        * ```js``` 
        * ```index.html```
            * 初期起動時ではこいつが表示されます.

# プラットフォームを追加する
今回はiOSとAndroidに対応するものとします.

* iOS / Androidを追加

```
cordova platform add ios
cordova platform add android
```

* 追加したプラットフォームの確認  

```
cordova platform ls
```

* 起動してみる  

```
cordova serve
```  

ブラウザで表示されればokです. → http://localhost:8000/ios/www/

# iOSシミュレータ（実機）でビルド
* AppStoreからXcodeをインストールしてください.
* ios環境に必要な諸々をインストール  

```
npm install -g cordova-ios ios-sim ios-deploy
```  

※ここらへんのインストール先はglobal推奨らしいです.  


* プロジェクトの実行 
* 下の```build```と```emulate```をまとめてのが```run```な模様 

```
cordova run ios
```
  
* build  

```
cordova build
```

* エミュレータの実行

```
cordova emulate ios
```

* 実機で実行  

```
cordova run ios -device
```

* ipaの作成
    * .xcworkspaceファイルを開くとXcodeが立ち上がります.
    * ネイティブ同様Archiveしてipaファイルを作成します.

# Android(エミュレータ)でビルド
* 環境変数を設定する  

```
export JAVA_HOME=`/usr/libexec/java_home`
```

* プロジェクトの実行  

```
cordova run android
```

* エミュレータの実行  

```
cordova emulate android
```

* デバイスを指定して実行  

```
cordova emulate --target=Nexus_6_API_23 android
```

* apkの発行
    * 通常のapkの場合はrunしたタイミングで作成されます.
    * ここにあります build > outputs > apk > android-debug.apk
    * 参考
        * <http://phiary.me/cordova-android-release-build-apk-for-google-play/>
       
# OnsenUIのインストール
* bowerでインストールできます.

```
bower init
bower install onsenui -S
```

ひとまずこれで準備は完了です.

# 所感
環境構築では特に難しいところはなく思ったよりスムーズに進行しました. 実機ビルドした際に変更が反映されないときがあったり、ステータスバーの下になぞの隙間ができてしまったりと不都合な部分もありましたが、一つ一つ解決していけばそれなりの開発スピードはでそうです.
ハイブリッドアプリで懸念される点としては動作スピードの遅さやファイルサイズの増大などありますが、近年かなり改善されているらしく普通に使っていてもあまり気になるレベルではないと感じました.
とはいえ、ゲームなどの処理速度を必要とするアプリに関しては不向きであると思います.
gulp環境構築 〜変更監視、トランスパイル中止抑制〜


[前回](http://qiita.com/takihiyoshi/items/525dbc05f090dba1393f)の設定だと、js以外の変更時にはトランスパイルされないし、トランスパイル時にエラーが出ると止まってしまうからそれらを設定する。


## 変更監視

監視は単純にpugとsassをgulpのwatchタスクに書いてないからなのでのでここに新たに書いてやれば良い。

```gulpfile.babel.js
〜 省略 〜
const paths = {
  allSrcJs: 'src/**/*.js',
  pug: 'src/pug/**/*.pug',
  sass: 'src/sass/**/*.sass',
  〜 省略 〜
};
〜 省略 〜
gulp.task('watch', () => {
  const watchList = [
    paths.allSrcJs,
    paths.sass,
    paths.pug,
  ];
  gulp.watch(watchList, ['main']);
});
〜 省略 〜
```

## トランスパイル中止抑制
この監視状態の時、このままだとトランスパイルに失敗してエラーが出るとそのたびに監視が止まってしまい、いちいち実行し直さなければならなくなってしまう。
これは流石にめんどくさすぎるので、監視が止まらないようにする。

```コマンドライン
yarn add gulp-plumber
```

こいつがエラーが出た時に感知して、こんなエラーが出てるよってコマンドラインには出してくれた上で止まらないように計らってくれる。
使い方としては、トランスパイル系の処理のpipe処理の前に書いておく。
例

```gulpfile.babel.js
〜 省略 〜
gulp.task('pug', () =>
  gulp.src(paths.pug)
    .pipe(plumber())　// ←ここに書く
    .pipe(pug({ pretty: true }))
    .pipe(gulp.dest(paths.html)),
);
〜 省略 〜
```

追記、この設定じゃだめだった。
plumber()だけだと、一度エラーを起こした後、動いてる様で動いてないというひどい状態になった
以下のやり方で回避できるみたい。
これ見る限り、plumberがエラーを吐いた後ゾンビるっぽい、エラーログ吐いた後に自身をendしてるし。
参考[gulp-sass, gulp-plumberを使うときの注意](http://qiita.com/Quramy/items/5491d8da29d1fe047464)

```gulpfile.babel.js
const plumberOption = {
  errorHandler(error) {
    console.log(error.message);
    this.emit('end');
  },
}
〜 省略 〜
gulp.task('pug', () =>
  gulp.src(paths.pug)
    .pipe(plumber(plumberOption))　// ←ここに書く
    .pipe(pug({ pretty: true }))
    .pipe(gulp.dest(paths.html)),
);
〜 省略 〜
```

##次回の予定
せっかくだからローカルサーバー建てて確認できるようにしたいよね。
D 言語で書かれた OS をいじっている

# ハック PowerNex

スウェーデンの兄ちゃんが目下開発中の OS がある。その名は [PowerNex](https://github.com/Vild/PowerNex)、もちろん D 言語製である。ユーザ空間のアプリケーションが書けるようになり、コマンドラインシェルを中心として、ちょっとしたデモが標準搭載されている。

OS があってコンソールがあるなら、[D 言語くん AA](https://gist.github.com/simdnyan/20e8fa2a2736c315e2c1) を降臨させようとするのが人情というもの。Advent Calendar だけに。

# Advent of D-man

ただコンソールに表示させるだけならば、ユーザ空間の Hello world プログラムを参考にすれば容易に可能だ。注意が必要なのは Phobos は移植されていないということだ。独自のユーティリティライブラリとシステムコールはそれなりに用意されているし、object.d もそれなりに移植されているようなので、ちょっとした遊びには困らない。

# PowerNex でも D 言語くんが通り過ぎる

さて、D 言語くんを降臨させたら、動かしたくなるのが世の常だ。そこで、[dl コマンド](https://github.com/ueshita/dl-cmd)を移植することにした。

このためには ANSI エスケープコードをコンソールが解釈する必要があり、それはカーネル側に実装する必要があったので、下のページを参考に、パーサを書いて使うことにした。

- [VT100.net: A parser for DEC’s ANSI-compatible video terminals](http://vt100.net/emu/dec_ansi_parser)


例によって Phobos はないもの、カーネル自体がクラスを多用しているため、クラスをゴリゴリ使えるような object.d が最低限用意されているのが強い。配列や連想配列でうぉりゃーとしようとするとリンカに怒られたりするが。そんなこんなで、それなりのエスケープコードを使えるようになったコンソールのデモがこれだ。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="en" dir="ltr">Does PowerNex dream of ANSI escape codes? Ya, I&#39;ve landed my parser partially on PowerNex&#39;s console! <a href="https://twitter.com/hashtag/dlang?src=hash">#dlang</a> <a href="https://t.co/zTrxbJ1Lgi">pic.twitter.com/zTrxbJ1Lgi</a></p>&mdash; えれ (@e10s) <a href="https://twitter.com/e10s/status/797483245679964160">2016年11月12日</a></blockquote>

これは最初期の状況で、今は各種エスケープコードに対応できるようにハックを続けている。GitHub に作業中のリポジトリがあるのである。この記事を書いている時点では D 言語くんプログラムをコミットしていないが。

- https://github.com/e10s/PowerNex/tree/ANSI

# 〆

普通の OS で動く普通の超高級な D 言語プログラムに飽きたときは、変な環境向けの処理を書くと新鮮な気持ちを D 言語くんが届けてくれる気がする。

どっちかっつーと、D 言語くん Advent Calendar 向きの記事になってしまった。
ubuntuのswap領域をinstall後に拡張

swapを広げたいHDD(SSD)にUbuntuが入っている場合、Gpartedでubuntuディスクを縮小できないため、USBでbootする。

usbでboot後、Gpartedをsudo権限で起動

``` shell:bash
sudo gparted
```

起動後、ubuntuが入っているパーティションを縮小
次にswapディスクを右クリックし、swapを解除
swapパーティションを囲っているパーティション？を拡張してから、swapを拡張する

最後にswapをONにしてubuntuを再起動
Spring Boot + Tomcat 8.5.8は使えないから注意してね！

現在リリースされている最新バージョン(2016/12/13時点)はSpring Boot 1.4.2.RELEASEで、デフォルトだとTomcatは8.5.6が使われわれます。Tomcatのバージョンは、[SPRING INITIALIZR](https://start.spring.io/)経由でプロジェクトを作ると簡単にバージョンを変えられます。

ビルドツールとしてMavenをつかっている場合は、以下のようにプロパティでバージョンを指定するだけです。

```xml
<properties>
    <!-- ... -->
    <tomcat.version>8.5.8</tomcat.version>
</properties>
```

# 8.5.8を使うとどうなるのか？

とりあえず・・・デフォルトのポート番号(8080)を使うとTomcatが起動しません :scream:

エラー内容は「Address already in use」です。ある意味よくみるエラーで、複数のSpring Bootアプリケーションを同時に触っていると起動しっぱなしにしていてこのエラーに遭遇することがあります。

```
...
2016-12-11 03:12:06.364 ERROR 20786 --- [           main] o.a.coyote.http11.Http11NioProtocol      : Failed to start end point associated with ProtocolHandler [http-nio-8080]

java.net.BindException: Address already in use
	at sun.nio.ch.Net.bind0(Native Method) ~[na:1.8.0_102]
	at sun.nio.ch.Net.bind(Net.java:433) ~[na:1.8.0_102]
...
```

でも今回は、別のアプリは起動してませんし、ゾンビプロセスもいません・・・。

# じゃあ、なぜAddress already in useなのか？

細かい話は省きますが、Spring Boot上で組み込みTomcat 8.5.8を使うと、Tomcatの`Connector`が意図せず2つできてしまうのが原因です。デフォだと両方とも8080ポートを使うため「Address already in use」がでてしまう・・・というわけです。

ためしに・・・Spring Bootのプロパティを使ってサーバのポート番号を18080に変更してみると・・・・

```properties
server.port=18080
```

以下のようなログが出てサーバーが起動します。

```
...
2016-12-11 03:15:39.717  INFO 20842 --- [           main] s.b.c.e.t.TomcatEmbeddedServletContainer : Tomcat started on port(s): 8080 (http) 18080 (http)
2016-12-11 03:15:39.721  INFO 20842 --- [           main] com.example.Tomcat858DemoApplication     : Started Tomcat858DemoApplication in 2.639 seconds (JVM running for 3.076)
```

起動はするけど・・・8080(TomcatがつくったConnector)と18080(Spring BootがつくったConnector)でリクエストを待ち受けるTomcatが起動しちゃいました :tired_face:


# 詳しい原因を知りたい方は・・・

Spring ProjectのProject Memberであり、Spring BootのCore Committerの [Andy Wilkinson](https://github.com/wilkinsona) さんがバグレポートしてくれてました！！

* https://bz.apache.org/bugzilla/show_bug.cgi?id=60368

内容は、ここで紹介したものと一緒ですがSpring Boot側にIssue作ってあるのでリンク貼っておきます。

* https://github.com/spring-projects/spring-boot/issues/7615


# どうすればいいの？

ま〜素直にTomcat 8.5.6を使うのがいいと思います。
何かしらの理由で8.5.6ではなく上位バージョンを使う必要があるなら・・・8.5.9を試してみてください。とりあえず、起動はしました:sweat_smile:
原因は見てないんですが・・・8.5.9にあげてPRしたらSpring Bootのテストでエラーがでているので、8.5.9でもSpring Bootと組み合わせると一部いまくいかないところがあるかもしれません。

# まとめ

特別な理由がない限り、使用しているSpring Bootが依存しているTomcatをそのまま使いましょう〜。
少なくても、過去のSpring Bootのリリースバージョンで使われた実績があるバージョンじゃないと・・・致命的な動作不良に遭遇する危険性が高まることを意識しておいた方がよいでしょう。

# 参考サイト

* https://bz.apache.org/bugzilla/show_bug.cgi?id=60368
* https://github.com/spring-projects/spring-boot/issues/7615
JavaのExceptionのStackTraceはnewした時に決まる


以下の様な 「例外を事前にnewしておいて使い回す」コードを書いていました。

```java
package exceptiontest;

public class ExceptionTest {
    
    // ここで例外を生成。
    private static final RuntimeException _e = new RuntimeException("hello"); // line: 6

    public static void main(String[] args) {
        // 実際に投げるのはここ。
        throw _e; // line: 10
    }
}
```

結果こうなる...

```
Exception in thread "main" java.lang.RuntimeException: hello
	at exceptiontest.ExceptionTest.<clinit>(ExceptionTest.java:6)
```

## なんでか？

JavaはExceptionのインスタンスを生成した時点でStackTraceが決まるようです。

> pythonとかだと ``raise`` (``throw``) した時のStackTraceが出るので、同じ感覚で書いてました。

例えば、コードを以下のように書き換えても...


```java
package exceptiontest;

public class ExceptionTest {
    
    // ここで例外を生成。
    private static final RuntimeException _e = new RuntimeException("hello"); // line: 6
    
    private static void f1() {
        f2();
    }
    
    private static void f2() {
        throw _e;
    }

    public static void main(String[] args) {
        // main() --> f1() --> f2() --> throw _e
        f1();
    }
}
```

常にExceptionをnewしている6行目のStackTraceが出ます。

```
Exception in thread "main" java.lang.RuntimeException: hello
	at exceptiontest.ExceptionTest.<clinit>(ExceptionTest.java:6)
```

> ``<clinit>`` とはクラスのstatic initializerのことです。
> 変数 ``_e`` はクラスの ``static`` 要素として宣言しているので、``ExceptionTest`` クラスのロード時にStackTraceが決まってしまいます。

## おまけ (Pythonだとこう)

期待した通りに(？)、動きます。

```py
_e = Exception('hello')

def f1():
    raise _e

if __name__ == '__main__':
    f1()
```

```
Traceback (most recent call last):
  File "/Users/username/Documents/workspace/raisetest/main.py", line 7, in <module>
    f1()
  File "/Users/username/Documents/workspace/raisetest/main.py", line 4, in f1
    raise _e
Exception: hello
```
Cocoa Study at Ikebukuro #6 (BUKURO.swift)

<p>12/5に開催された勉強会『Cocoa Study at Ikebukuro #6 (BUKURO.swift)』について報告する。</p>

<p>場所はいつもの<a href="http://co-forest.com/">池袋コワーキングスペース OpenOffice FOREST</a>。池袋駅から少し離れた場所だ。座席代は夜間ドロップインで一人1,000円。一時、渋谷でも開催していたが、会場の都合から池袋での開催となったが、利用しやすいので助かっている。</p>

<p>発表内容を簡単にまとめると以下の通り。</p>

# GNUstep用アプリ”MyWiki.app”をビルドする
<p>構想しているアプリケーションの参考として発表者が探してきたのが、GNUstepのサンプルコード"MyWiki.app"。GNUstepだというのが渋い。そして、手を加えないといけなかったが、最新のmacOSでも動作。見た目は、iWebを思い出させる、ちょっと懐かしい感じのUI。OPENSTEPの流儀で画像データをコードで記述する方法。なるほどねでした。</p>

# MacOSX用アプリ”CardBook.app”をビルドする
<p>こちらも先ほどの発表者が見つけてきたソースコード。素朴なメモ帳という感じだ。印刷に対応というのが、今の時代、懐かしい！</p>

# TouchBarDemoApp
<p>新型MacBook Proで話題のTouchBar。これを非対応のMacintoshで利用できるようにするのが、このソースコード。その感じから、OS9が動作してPowerBookの思い出していしまいました。</p>

# Swiftyを試す
<p>Try! Swift 2016での発表『文化を調和させる: 関数型プログラミング、プロトコル志向プログラミング、オブジェクト指向プログラミングの優れたテクニックを取り入れる』の手法を実際に試してみた事の発表。ボリュームがあり、最後に到達できなかったが、都築は、次回、勉強会で、出そうだ。</p>

<p>今回は、macOSのプログラミングが発表が多かったが、iOSの時代。新鮮に感じ、かつ、面白い！これからはmacOS向けAppStoreが熱いかな！？</p>

関連情報
<a href="https://cocoa-study.connpass.com/event/45262/">Cocoa Study at Ikebukuro #6 (BUKURO.swift)</a><br />
<a href="https://cocoa-study.connpass.com/">Cocoa Study</a><br />
<a href="https://connpass.com/series/499/">Cocoa勉強会 関東</a><br />
<a href="http://www.cocoa-study.com/">Cocoa勉強会</a><br />
<a href="http://wp.cocoa-study.com/">Cocoa勉強会（関東）</a><br />

【Cocoa練習帳】
<a href="http://www.bitz.co.jp/weblog/">http://www.bitz.co.jp/weblog/</a><br />
<a href="http://ameblo.jp/bitz/">http://ameblo.jp/bitz/</a>（ミラー・サイト）<br />
<a href="https://t.co/6P3h2jtbRk</a>note<br />
構造体のmutatingに関して


小ネタ。最初、原因がわからずイライラしたのはここだけの秘密だ。

```

struct Sample {
    let x : Int
    
    init(){
        self.x = 10
    }
    
    func zizyo() -> Int {
        return x * x
    }
}

let a = Sample()
a.zizyo()

```

これはOK


```

struct Sample2 {
    let x : Int
    
    init() {
        self.x = 5
    }
    
    mutating func zizyo() -> Int {
        return x * x
    }
}

let b = Sample2()
b.zizyo()

```

これはエラー。以下のメッセージが出る

```
Cannnot use mutating member on immutable value: 'b' is a 'let' constant

```

ここはbをletではなくvarで宣言しないといけない。
ややこしいのは変数にセットしないときもエラーになるという事でして。

```
var c = Sample2().zizyo() // <- これもエラーになる
```

以下のメッセージが出る。

```
Cannnot use mutating member on immutable value: function call returns immutable value

```

でも以下のようするのは良い。

```
var c = Sample2()
let d = c.zizyo()	
```


このなんとなく分かるような、分からないような現象について具体的かつ解りやすい説明は未だ出来ない。
とりあえず現象のみ


#### 参考リンク
[CWhen To Use Mutating Functions in Swift Structs](https://www.natashatherobot.com/when-to-use-mutating-functions-in-swift-structs/#)

この現象について解説してくれている・・・けど、まだしっくりこない
LightsailでWordPress（SSL化もする）

## Lightsailって何？

LightsailっていうのはAWSにあるサービスの一つでアプリケーションつきで起動するVPSみたいなもんです。（もちろんアプリケーションなしもあるよ）
https://amazonlightsail.com/

既存のAWSの資産も活用できるので、試しに何かを始めるならいいんじゃないかな。そこそこ安いよ。
月$5で下記のスペック。

- 512 MB Memory
- 1 Core Processor
- 20 GB SSD Disk
- 1 TB Transfer*

十分でしょ？

## LigthsailでWordPressって何が美味しいの？

何も美味しくないよ。ただLightsailやりたかったときにたまたま目の前にWordPressがあったんだよ。

## 作る

AWSのコンソールからLightsailへ移動して、ポチポチやるととりあえず起動しますので、やってみてください。
一瞬でグローバルIPが払い出されるので、とりあえず `http://IPアドレス/` へアクセスして、WordPress感を味わいましょう。
管理画面に入りたい場合は読み進めてください。

## 設定のためのチェックシート

とりあえず使い物になるまでのやることは下記になるよ。

- 固定IPをLightsailのWeb-UIから取得する
- 固定IPにAレコードを割り当てる（ドメイン持ってない人は飛ばしていいよ
- SSHのデフォルトキーをダウンロード(LightsailのWeb-UIから落とせるよ)してsshする。
    - `$ ssh -i LightsailDefaultPrivateKey.pem bitnami@固定IPアドレス`
- WordPressの認証情報を手に入れる
    - SSHでログイン後に `$ cat bitnami_application_password`
    - 上記のコマンドでパスワードが出るからメモっておきましょう。
    - ユーザ名は `user` です。
    - 管理画面が使えればいい人はここで手を止めてしまってOK
- Bitnamiのバナー（WordPressの右下についてるやつ）を削除する

```
$ sudo /opt/bitnami/apps/wordpress/bnconfig --disable_banner 1
$ sudo /opt/bitnami/ctlscript.sh restart apache
```

- SSL化（HTTPS）する。ドメインない人とかは飛ばしていい。

```
$ cd /tmp
$ git clone https://github.com/letsencrypt/letsencrypt
$ cd letsencrypt
$ ./letsencrypt-auto
$ ./letsencrypt-auto certonly --webroot -w /opt/bitnami/apps/wordpress/htdocs/ -d ドメイン名
$ sudo cp /etc/letsencrypt/live/ドメイン名/fullchain.pem /opt/bitnami/apache2/conf/server.crt
$ sudo cp /etc/letsencrypt/live/ドメイン名/privkey.pem /opt/bitnami/apache2/conf/server.key
$ sudo /opt/bitnami/ctlscript.sh restart apache
```

これで基本的な設定は完了なので、あとは好きなテーマを当てるなり何なりするといい。

## 証明書の自動更新

証明書の更新については、コメントに @jakephot さんがCrontabを書いてくれたので参考にしてみてください！

https://qiita.com/foursue/items/8e685b52cfddf05875ee#comment-06cf055e5188d03e4c1f


## 注意点

注意点はいろいろあるんだけど、書いてくれてる人の記事があるので、参考にしてくださいね。
http://qiita.com/morimori/items/27f7bfeeb5e508f5efa6

上流の制御がいまいちなんで割りと落とせますから、気楽な用途以外では使わないでね感強いですね。
passportでユーザオブジェクトのプロパティ名を変更する

## 概要
passportの認証ミドルウェアでコールバックに渡したユーザオブジェクトに，
他のconnectミドルウェアからアクセスしたい場合，
`req.user`という風に，リクエストオブジェクトを通してアクセスします．

デフォルトでは，リクエストオブジェクトの`user`というプロパティにユーザオブジェクトはセットされます．
この設定を変えたい場合どうするか，というお話です．

## 解説

passportのオプションに`assignProperty`を指定してやればOKです．

```javascript
app.post(
  '/protected-page',
  passport.authenticate('local', {
    successRedirect: '/',
    failureRedirect: '/login',
    assignProperty: 'account'
  }),
  (req, res, next) => res.render('protected-page', { account : req.account }) 
);
```
Componentに $props を生やすplugin(または型安全なVue Componentのはなし)

## ソース

こんだけ。

```js
const VuePropsPlugin = {
    install(vue, options) {
        vue.mixin({
            beforeCreate: function() { this.$props = this; }
        });
    }
}
```

## これは何？

vue.jsのコンポーネントに、 `$props` というインスタンスプロパティを生やすためのplugin

コンポーネントのprop(例えば `foo`)に `this.foo` だけでなく `this.$props.foo` という形でもアクセスできるようになる。

とりあえず、そういうプラグインがあった場合にどの程度うれしい試してみる目的のものなので、ウルトラ雑実装。(`$props` に `this` を突っ込んでいるだけなので、propどころかあらゆるインスタンスメンバに `$props` 経由でアクセスできる)
ちゃんと作るなら `$options.props` の内容をもとにラッパーオブジェクトを生成する的な実装になると思う。

**TypeScript >= 2.1と一緒に使うのを想定している。**

## それで何がうれしいの？

### 現状

現状、TypeScript でvueのコンポーネントを書くときには、クラススタイルで書いて、デコレータでコンポーネント化する方法が主流。

```ts
@component({
    props: { foo: { type: String }, bar: { type: String } }
})
class MyComponent extends Vue {
  foo: string;
  bar: string;
}
```

この時、propsの定義をデコレータの引数に渡しつつ、クラスのメンバとしても定義しなければならず、定義が分散してしまうのが悩みの種であり、それを解決するために、追加のデコレータを用意していたりする。 [^1]

```ts
@component({
  /* propsの定義は@propで指定した内容から自動的に構築されるので、ここではもう指定しなくていい */
})
class MyComponent extends Vue {
  @prop({ type: String }) foo: string;
  @prop({ type: String }) bar: string;
}
```

このコンポーネントを親コンポーネントの `render` 内で生成する場合などを考えると propsをインターフェイスにしておいた方が都合がよく、この方法はそのインターフェイスとの親和性が高いというメリットもある。

```ts
// MyComponentのProps
interface MyProps { foo: string, bar: string }

@component({ ... })
class MyComponent extends Vue implements MyProps {
  // MyPropsをimplementsすれば、foo, barの名前と型に間違いがないことは検証できる。
  @prop({ type: String }) foo: string;
  @prop({ type: String }) bar: string;
}
```

### TypeScript 2.1 以後

TypeScript 2.1で導入されたMapped Typeによって、安全に `props` の定義を書けるようになった。

```ts
// こういう型定義をあらかじめ用意しておく
type Props<T> = { [K in keyof T]: Vue.PropOptions | String | Number | ... };

interface MyProps { foo: string, bar: string }

@component({
  props: <Props<MyProps>> { // foo, barをtypoしてたり過不足があったらコンパイルエラーになる
    foo: { type: String },
    bar: { type: String }
  }
})
class MyComponent extends Vue { /* 略 */ }
```


ただ、`foo`, `bar` をクラスのメンバとして定義しないといけないようだと結局また二重定義になってしまってありがたみがない、というところで、ようやくこのプラグインの出番。
詳細(というほどでもないけど)は以下のコードを参照。

```ts
interface MyProps { foo: string, bar: string }

@component({
  props: <Props<MyProps>> { // foo, barをtypoしてたり過不足があったらコンパイルエラーになる
    foo: { type: String },
    bar: { type: String }
  }
})
class MyComponent extends Vue {
  // foo, barを個別に定義する代わりに、この１行で済む。(コード内では、$prop経由で各propにアクセスする)
  // 薄いVueのラッパーを用意してやればこの行も不要になるはず
  // (というか、ラッパー作るならコンストラクタでアレすればいいのでプラグイン自体不要な気がする)
  $props: MyProps;
}
```

`@prop` とかで頑張るよりも、こっちの方がいろいろとシンプルになるんじゃないかと思うんだけど、どうだろう、というようなことを考えている。
`$emit` 回りも似たような方法である程度型安全にできるんじゃないかという気がしていて、継続考慮中。

## 脚注

[^1]: 定番の [vue-class-component](https://github.com/vuejs/vue-class-component) に [vue-property-decorator](https://github.com/kaorun343/vue-property-decorator) を組み合わせると `@prop` が使えるようになるし、僕が作った[vueit](https://github.com/wonderful-panda/vueit) も同じような感じ。