OmniAICreator/Qiita-1.07M huggingface dataset:
スプレッドシートにGmailの内容を自動で書き込む

この記事は移行しました！[最新の内容はこちら](https://naoqoo2.github.io/blog/%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E3%82%B7%E3%83%BC%E3%83%88%E3%81%ABGmail%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E8%87%AA%E5%8B%95%E3%81%A7%E6%9B%B8%E3%81%8D%E8%BE%BC%E3%82%80/)をご覧ください😀

## はじめに

定期的にくる問い合わせメールやシステムメールをシートで管理したいとき、あるよねー。
という人にオススメの記事です。

※既に同じ内容の記事は山ほどありますが、
カスタマイズしたい場合にどれを参考にしようか毎回悩むので今後はこれを基準にしていきます。

## 本プログラムの概要

* 日付、件名、from、to、本文がシートに出力されます
* 複数回実行しても同じメールは処理しません（日付、from、to、件名の一致で判断）

あとは状況に応じてカスタマイズしましょう。

## 設置手順

1. スプレッドシートを新規作成
2. メニュー→ツール→スクリプトエディタ
3. 下記コードを貼り付け
4. 実行

```js

// スプレッドシートにメール内容を書き込む
function mailToSheet () {
  
  // ----- ここから書き換え -----
  // 書き込むシートURL
  var sheet_url = 'https://docs.google.com/spreadsheets/d/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx/edit';
  // 書き込むシート名
  var sheet_name = 'シート1';
  // Gmailの抽出条件
  var mail_query = 'Gmailの抽出条件';
  // 存在チェック（既にシートに書き込み済のメールは処理しない（日付、from、to、件名の一致で判定））
  var existence_check = true;
  // ----- ここまで書き換え -----

  var ss = SpreadsheetApp.openByUrl(sheet_url);
  var sheet = ss.getSheetByName(sheet_name);
  var existence_keys = fetchExistenceKeys();
  var mail_data = fetchMailData();
  for (var i = 0; item = mail_data[i]; i++) {
    if (existence_check && existsData(item)) {
      continue;
    }
    sheet.appendRow(itemToRow(item));
  }  

  function fetchExistenceKeys () {
    var existence_keys = {};
    var sheet_data = sheet.getDataRange().getValues();
    for (var i = 0; row = sheet_data[i]; i++) {
      existence_keys[generateKey(rowToItem(row))] = true;
    }
    return existence_keys;
  }
  
  function existsData (item) {
    if (existence_keys[generateKey(item)]) {
      return true;
    }
    return false;
  }

  function generateKey (item) {
    var key = item['date'] + '_' + item['subject'] + '_' + item['from'] + '_' + item['to'];
    // Logger.log(key);
    return key;
  }

  function rowToItem (row) {
    var item = {};
    item['date'] = row[0];
    item['subject'] = row[1];
    item['from'] = row[2];
    item['to'] = row[3];
    return item;
  }

  function itemToRow (item) {
    var row = [];
    row[0] = item['date'];
    row[1] = item['subject'];
    row[2] = item['from'];
    row[3] = item['to'];
    row[4] = item['body'];
    return row;
  }
  
  function fetchMailData () {
    var result = [];
    var threads = GmailApp.search(mail_query);
    for (var i = 0; it = threads[i]; i++) {
      var messages = it.getMessages();
      for (var j = 0; message = messages[j]; j++) {
        var item = {};
        item['date'] = message.getDate();
        item['subject'] = message.getSubject();
        item['from'] = message.getFrom();
        item['to'] = message.getTo();
        item['body'] = message.getBody();
        result.push(item);
      }
    }
    return result;
  }  
}
```

## さいごに
毎日定期的に取り込みたい場合はトリガーを設定すると簡単にできます。
Gmailの抽出条件に「newer_than:1d」などを利用するのがオススメです。
初見でわかりにくいと思ったES2015

この記事は[Javascript Advent Calendar](http://qiita.com/advent-calendar/2016/javascript) 22日の記事です。

## はじめに

ES2015ではクラスを始め、これまでのJavascriptにないたくさんの便利な仕様がたくさん追加されました。

そのため、**ES2015使えばフレームワークなしでも管理しやすいアプリを作成できる** ようになったのではないかと思います。
(※もちろん、複雑なアプリや大規模なアプリならフレームワークの導入を検討した方がいいと思います。)

そんなES2015、これまでのJSではまず見ることがない文法が新しく追加されています。
「リファレンス読む前にまずはネット上のサンプルを動かす」派の私には、

* サンプル見て何をしているのかわからない orz
* ネットでどうググればいいかわからない(キーワードどう指定すればいいんだよ・・・)

ということが結構あり、勉強し始めた時は苦労しました。

という事で、この記事では、「**私がES2015勉強し始めの時よくわからなかった3つの文法**」を紹介します。
この記事が、これからES2015を勉強しようと考えている人の少しでも助けになれば幸いです。

## その１：スプレッド演算子 (```...values```)

```...values``` のように、ピリオドを3つ繋げたやつです。3点リーダーと呼んだりします。
これはスプレッド演算子と言います。複数の引数をとる関数や配列に値をセットする（または取り出す）時に使用します。

```js:関数にスプレッド演算子を使用する

// ３つの値を受け取り、その値をログに出力する
function spreadDemoFunc(value1, value2, value3) {
    console.log(value1, value2, value3);
}

// データ
let args = [2, 4, 6];

spreadDemoFunc(...args);  // 変数argsの値が展開され、spreadDemoFuncの引数にセットされる

// 実行結果: 2 4 6
```

```js:配列に値をセットする時に使用する
let value1 = [1, 2, 3, 4, 5];
let value2 = [6, 7, 8, 9, 10];

let joinValue = [...value1, ...value2]; // value1, value2がそれぞれ展開され、1つの配列になる

console.log(joinValue);

// 実行結果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
```

```js:配列から値を取り出す時に使用する
let value = [1, 2, 3, 4, 5, 6, 7, 8, 9];
[a, b, c, ...others] = value; // 先頭3件のデータをa, b, c それぞれ代入し、残りはothersに入れる
console.log(a, b, c, others);

// 実行結果: 3 1 2 3 [4, 5, 6, 7, 8, 9]
```

## その２アロー関数 (```() => {}```)

アロー関数関数は無名関数みたいなものですが、無名関数と違ってthisが宣言した場所のthisに束縛されます。
このアロー関数でわかりにくかったのは「書き方がいくつかある」ことです。
下記にアロー関数の書き方を３種類紹介します。下記はすべて同じ値を返します。

```js:アロー関数1
let helloWorld = (name) => {
    return('Hello '+ name + '!!!!');
};
console.log(helloWorld('Qiita'));

// 実行結果: Hello Qiita!!!!
```

```js:アロー関数2
let helloWorld = name => {
    return('Hello '+ name + '!!!!');
};
console.log(helloWorld('Qiita'));

// 実行結果: Hello Qiita!!!!
```

```js:アロー関数3
let helloWorld = name => 'Hello '+ name + '!!!!';
console.log(helloWorld('Qiita'));

// 実行結果: Hello Qiita!!!!
```

一番下のアロー関数はreturnを省略した書き方で「```'Hello '+ name + '!!!!'```」の部分が
returnされます。私は始めてこの記述を見た時に「何か代入でもするのか？？」とか思ってしまいました。

## その３ オブジェクトの省略記法／分割代入

オブジェクトの省略記法／分割代入は、割とすぐに調べることができましたが、ネット上にあるES2015のサンプルコードを見たときに、「コーディングミス？？」と誤解したためピックアップしました。

ES2015より、下記のように、オブジェクト作成時にオブジェクトのキーを省略して代入することができるようになりました。

```js:省略記法
let a = 1, b = 2, c = 3;
let object = {a, b, c};
console.log(object, a, b, c); 

// 実行結果: Object {a: 1, b: 2, c: 3} 1 2 3
```

逆に、次のように書くとオブジェクトの中身を分割して変数に代入することができます。

```js:分割代入
let object = {a: 1, b: 2, c: 3};
let {a, b, c} = object;
console.log(object, a, b, c); 

// 実行結果: Object {a: 1, b: 2, c: 3} 1 2 3
```

## まとめ

ES2015で追加された文法の中でも、ぱっと見で何をしているのかわかりにくいと感じた文法を3つ紹介しました。なお、今回掲載した記事は[MDN](https://developer.mozilla.org/ja/) を参考にして作成しました。

今回紹介したした３つの文法は、最新verのChromeであれば全てサポートされています。
なので、「Babelのようなトランスパイラを使ったことがない人」、「ES2015試すのにBabel使うのめんどくさい」と思っている人でも、Chromeのデベロッパーツールから手軽に実行できるので、ぜひ試してみてください！！
RESTfm で Create してみよう

# RESTfm で Create する
Update、Delete と続き、いよいよ最後の動作である Create（POST メソッド）です。

……とは言えですね、これまた Update および Delete とほぼ変わりません。[公式ドキュメント](http://restfm.com/manual)を見るとわかるように、「2.7.3 Create - POST」と「2.11.1 Create - POST」にのみ Create が存在します。これは Delete と同じです。

仕方ないんのでコピペ的を承知の上で Create の方法を記していきましょう。

# Create できるのはレコードだけ
Create という言葉は要は新たに生成できる（する）ということですから、レコードはもちろんのこと、レイアウトやデータベースを生成することを考える向きもあるでしょう。

しかし、レコード以外を API で生成したところで中身の本質的な生成は FileMaker 側で行う必要があることは自明です。したがって、API ではレコードの生成のみができることになります。

# 基礎となる URI と使用するデータベースおよびレイアウト
説明を分かりやすくするために、RESTfm を以下の場所に配置したと仮定します。

**http\://hogehoge/RESTfm/**

また、説明に使うデータベース名は`Member`とし、同じくレイアウト名は`categories`とします。

# レコードを Create する（URI を構成する）
レコードを Create しましょう。Update や Delete と違い、対象とするレコードというものはありませんから、レイアウトを指定するだけで API として叩く URI は確定します。すわなち、以下の URI を叩きます。

http\://hogehoge/RESTfm/Member/layout/categories

# レコードを Create する（レコード内の各フィールドのデータを入力する）
ただ単にレコードを Create しただけでは、レコード内のフィールドは空っぽになります。それはそれでいい場合もありますが、Create の際に特定のフィールドには特定の値を入れたい場合も多いでしょう。

その場合は POST を投げる時に以下のようなフォーマットでデータを投げてあげます。`foo`というフィールドを`bar`と設定し、`hoge`というフィールドに`fuga`と設定する場合です。

```
{
    "data": [
        {
            "foo": "bar",
            "hoge": "fuga"
        }
    ]
}
```

PHP で上記 JSON を作る場合は以下のようにすればいいでしょう。

```php
$data = array("data" => [
        array("foo" => "bar"),
        array("hoge" => "fuga")
        ]);
$post_json = json_encode($data);
```

# レコードを Create する（PHP の curl を用いる）
URI も定まり、送るべき JSON も作れました。あとは実際に POST するだけです。PHP でのコード例を以下に示します。

```php
$uri = "http\://hogehoge/RESTfm/Member/layout/categories";
$request = "POST";
$headers = array("Content-Type: application/json");
$data = array("data" => [
        array("foo" => "bar"),
        array("hoge" => "fuga")
        ]);
$post_json = json_encode($data);

$options = array(
    CURLOPT_URL => $uri, 
    CURLOPT_CUSTOMREQUEST => $request,
    CURLOPT_HTTPHEADER => $headers,
    CURLOPT_POSTFIELDS => $post_json,
    CURLOPT_RETURNTRANSFER => true
);

$curl = curl_init();
curl_setopt_array($curl, $options);
$response = curl_exec($curl);
curl_close($curl);
```

$post_json = json_encode($data);
```

# オプションパラメータ
ここまでで Create は完了しました。ただ、さらに Update を便利にするパラメータが用意されています。詳しくは[公式ドキュメント](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabaselayoutlayout/create-post)を参照してほしいのですが、1点紹介をします。

- **RFMscript**
    - このパラメータを指定すると、Update した後に指定のスクリプト（「=」でつないでスクリプト名を指定）を実行します
    - スクリプトに引数を用いる場合はさらに`RFMscriptParam`パラメータを付与します

# bulk も可能
GET や Update の記事で記載した bulk での Update も可能です。詳しくはやはり[公式ドキュメント](http://restfm.com/restfm-manual/web-api-reference-documentation/uri-restfmdatabasebulklayout-bulk-operations/create)をどうぞ。

# エラー処理を含めるとなおよし
GET メソッドは単に情報を取得するだけですので誤った URI を叩いたりしてしまってもエラーが出るくらいです。しかしながら POST メソッドの場合は新たにデータを追加することになり、場合によってはデータの整合性を失わせることになります。たとえば特定の検索結果のカウント数を処理に用いるとして、不用意な POST によりそのカウント数がズレてしまう、などの場合です。したがって、テストデータなどで十分に仕様を把握した上で実戦投入するといいでしょう。

また、エラーチェック（ログ出力）などを組み込むことで何かあった際の対応が楽になると思います。そこらへんも意識してコードを書くようにしてみてください。
保守について

# はじめに
社会人になって3年目
ずっと保守業務をやっています。
実務経験としては2年ちょっとになります。
まだまだペーペーですが、保守という仕事は性に合っている気がするので、
楽しい事とか大変な事とか書いてみます。

# 保守といっても色々
そうですね。
一口に「保守」と言っても、会社によって指すものは変わってきます。
自分は1社しか経験していないので聞いた話しになってしまいますが、プログラムを一切かかない保守業務もあるようです。
皆が皆プログラム書いてもねって感じですね。
設計とか仕様決めるとか、自社開発でなければ他社との営業的なお仕事もあるみたいです。

私はプログラムを書く保守をやっています。
自社開発なので営業的なことはほぼありません。
連携先の企業様と日程や仕様の調整をするくらいです。

# 普段やっていること
会社紹介ではないのであまりコアな話しをしても仕方ありませんが、少しだけ。
普段は問合せの調査や軽微な改修をすることが多いです。
バグとかちょっとした機能追加とか。
大きな事はしません。他の人がします。

# 大変な事
「保守」として大変な事。

「予測できない急な仕事」が発生しやすいです。
予測できるバグなんてありません。そんなもの分かっていたら事前に潰します。

やらなければいけないことが急に増えて、精神衛生上よくないです。
それが保守と言ってしまえばそうなります。
これ自体辛いと言ってしまうと、保守そのものが辛いことになってしまいます。

本当に大変だなと思うのは「何から対応するのが最善か」判断することです。
目の前の事だけをやっていても暫定対応にしかなりません。
遠くの事だけを考えていても、今やならきゃいけないことができません。

いい感じにどっちも取れる器用さが欲しいです。

# 楽しい事
そう言えば、保守ってあんまり人気無いですね。
就職活動していた頃だったかな・・・「保守は大変だからやめとけ」みたいな声も聞きました。
が、基本的には保守好きです。

プログラムは書く時間より読む時間の方が長いです。調査が多いので。
多分これが自分の性にあっていて、私は大学院まで数学をやっていたのですが、
ほとんどが論文を読む研究だったんですよね。
それとプログラムを読むのはとても近しいのです。

数学では「悪魔の証明」なるものをやっていました。
と言うか、数学は少しの例外も認めない 全て「悪魔の証明」です。
何かの証明が100番目まで大丈夫だとしても、101番目は？102番目だとダメなんじゃないの？？と言われます。

99.9%大丈夫な製品とか気持ち悪いです。100%であってほしいです。
ただし、その0.1%を詰めるのにどれだけの時間(コスト)がかかるのかってところですよね。
時間は有限です。

数学の証明には時間の概念なんて無いですからね。
無限というものをよく扱います。
CPUの仕様率とかサーバーの負荷とか、そういった有限的なものはありません。

数学をやっていた人がシステム屋になることは結構あるみたいですが、きっと数学の「無限」とか深い所のプライドを捨てて、
「有限」の人生やサーバーのスペックを理解してプログラムを書くのでしょう。(違ってたらごめんなさい)

否定的な話しになってしまいましたが、100%を求めるのとは逆に、間違いを見つけるのは簡単なのです。
これは数学の論文の証明の行間を埋める際に教授に指摘されるのに似ています。
ゼミで頑張って証明しても、判例を1個挙げられると、その証明は破綻します。

開発環境でバグの再現に成功した時は逆にスッキリします。
「間違っている」ということが分かれば、直す事ができるのですから。
間違いを見つけるのが結構楽しかったりします。
もちろん、他人の間違いを見つけたときは言い方とか考えましょう。

なんだかんだ数学に結びつけて毎日楽しく生きています。

# モチベ
保守のモチベ。
「保守のおかげで昨日と同じ事ができる」
当たり前の事ができる。現状維持。何も無いがそこにある。
平和なのはいいことです。田舎は好きです。

# 座右の銘
冗談半分ですが、もし自分がバグとか出した時に思う事。
「1にリカバリー 2に正座 3,4がなくて5に坊主」
誠意は大事ですが、仕事と法律は「ごめん」で済むものでもないので、正座して謝るより先にリカバリー。
やってしまった後どうするかが大事かと。
別に保守に限った事じゃないんですけどね。社会人として。。

# 最後に
結局3年やそこらで偉そうに「保守」を語るなんて恐れ多いです。
まだまだわからないことだらけです。

あと、なんだかんだ数学と結びつけようとするあたり、やっぱり自分は数学が好きなんだと思います。
ちなみにSQLは集合の概念なので、極めるならPHPとかプログラミング言語よりSQLがいいです。

最近プライベートでも色々あり新しい趣味を見つけたいので、SQLの資格とか目標にして勉強しようかな。。
VisualStudio for Mac やってみた

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

こんにちは。Windows大好きエンジニアの@Ntdoyです。
最近ちょっと浮気心が出まして会社からMacを買ってもらいました:relaxed:
私はこれまでずっとWindowsエンジニアだったので、実は人生初Macなんです。
なので主にWin版と比較して・・・という視点でレビューしていきたいと思います。

#VisualStudio for Mac とは
本家ブログより
>Visual Studio for Mac は、Xamarin と .NET によるモバイルおよびクラウド アプリ開発に最適化された開発環境で、Android、iOS、.NET Core テクノロジなど、Mac での .NET 開発を一手に引き受けます。ネイティブ ユーザー インターフェイスを備えた Visual Studio for Mac には、Android および iOS 向けの最新の API や UI デザイナーなど、モバイル アプリやサーバー アプリケーションを妥協することなく作成、デバッグ、テスト、発行するために必要なすべてのツールが統合されています。

ということみたいです。**VS for Macはクロスプラットフォームで動作するWindowsアプリケーションを作れるものではありません！**Windows使いの皆さんあまり期待しないように。
ぶっちゃけXamarin Studioの名前が変わっただけみたいですね。
ちなみにXamarinについては[ココ](http://qiita.com/amay077/items/38ee79b3e3e88cf751b9)が詳しいですね。
すごく簡単に言うと、C#で書いたライブラリをiOS/Android間で共有化できるよーって感じです。
それでは、冷静にインストールからやってみましょう。
#インストール
[ここ](https://www.visualstudio.com/vs/visual-studio-mac/)からダウンロードできます。
<img width="1358" alt="スクリーンショット 2016-12-08 19.18.48.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/d552fc97-b92e-04ee-c5eb-53287ee73e9f.png">
コマンドとかじゃなくてホッとしたのは内緒。
次へ次へで進めていきましょう。
<img width="912" alt="スクリーンショット 2016-12-08 19.31.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/91b9635b-bd4a-9326-4866-7363c31addc9.png">
無事にインストール出来ました。
<img width="1440" alt="スクリーンショット 2016-12-19 18.51.02.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/a5b44738-cb98-3c71-8b27-048187425e95.png">

#Hello, Mac World.
まあ、何はともあれこれでしょ。
言語はC#かF#だけって聞いてたけど色々ありますね。
まずはコンソールアプリでC#にチャレンジ！
<img width="711" alt="スクリーンショット 2016-12-19 21.05.47.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/64047fda-fd08-1c2c-a0b1-7d5abf2f9fdf.png">

なかなかの再現率ですね
<img width="1440" alt="スクリーンショット 2016-12-19 21.14.04.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/6d43ee80-55fe-3675-7386-501f2f22bae3.png">

nugetもイケました。使い方はWindows版と同じです。
<img width="1524" alt="スクリーンショット 2016-12-19 21.31.15.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/efd46d1d-8c8d-3e04-624b-c9c8c4bb4781.png">
有名なJSON.NETにC#の醍醐味であるLINQを添えて。
<img width="1552" alt="スクリーンショット 2016-12-19 21.49.37.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/d8d1c9ce-8513-46eb-503e-b2d03a3cbdc2.png">
<img width="682" alt="スクリーンショット 2016-12-19 21.54.20.png" src="https://qiita-image-store.s3.amazonaws.com/0/146648/db56bf51-55c8-d37d-0ce4-ca78618f4312.png">
#感想
~~何よりMacが難しい。~~
Consoleアプリでは何のメリットもありません←
Xamarin使ってナンボですかね・・・。
でもPreviewにしてはよく出来てました:clap:
リファクタリングについて

#リファクタリング
##きっかけ
仕事で機能追加や不具合修正をしていますが、綺麗に書かれてないソースを変更するの
めっちゃ大変です。何よりデグレが怖い！！
影響範囲はここまでだと思ってテストしても、思わぬところでバグが残ってたりすることもあります。
綺麗に書かれたプログラムなら修正範囲も明確になって、テストも簡単になって、リリースまでの
スピードも上がるんだろうな〜と夢みながらリファクタリングについて勉強しようと思いました。
リファクタリングについて勉強したこと感じたことを書いていきたいと思います。

##リファクタリングとは
ソフトウェアの外部の振る舞いを保ったままで、内部の構造を改善していく作業。
これがプログラムの読みやすさや機能回収のしやすさにつながっていきます。
また、リファクタリングによって、設計書作業が最初の工程で集中的に発生するのではなく、
全行程を通じて継続して行われるようになります。
実装しながら設計を常に意識しないといけないということですね。
設計者と実装者の境界がなくなっていくのかなとか思ったり。

##例えば一時変数の削除
計算結果とかを一時変数に入れて使いまわしてました。
計算を何度もさせるのは無駄なのかなぁと思ってたんです。
例えばこんな感じで。

```java:sample.java
double kingaku = shohizei * tanka;
if (kingaku > 1000) {
    return kingaku * 0.90;
} else {
    return kingaku * 0.95;
}
```

それがこう置き換えられます。
　　　　　　↓

```java:sample.java
if (kingaku() > 1000) {
    return kingaku() * 0.90;
} else {
    return kingaku() * 0.95;
}

double kingaku() {
    return shohizei * tanka;
}
```
メソッド作って何度も計算させます。
このメソッドは計算結果を返してるだけですが、ループする場合でもメソッド化して何度も呼びます。
その場合、処理速度が遅くなるのではと疑問が湧いてきますが、チューニングとリファクタリングの作業は分ける
という考え方が前提としてあります。
まず、リファクタリングでプログラム綺麗にしてから、チューニングのこと考えようということですね。

##最後に
ここで書いたのはほんの少しでしたが、リファクタリングの勉強は新しい発見の連続で楽しかったです。
これを仕事でも生かし、後から見た人が読みやすい！！って思ってくれるソースを書いていきたいと思います。
開発環境へのデプロイを誰でもできるようにしてみた

マイネット Advent Calender22日目の記事です。

# はじめに
現在私が所属している、会社のプロジェクトでは、Ruby on RailsのアプリケーションをCapistranoでdeployしています。
また、開発環境と本番環境問わずcapistranoでエンジニアがデプロイしていました。
しかし、アプリケーション内に企画やデザイナーの人が触るマスタデータやバイナリデータが含まれており、
エンジニアが行う開発環境へのdeploy作業が非常に多い上に、エンジニアがいない時に作業が止まってしまうため、
誰でもデプロイできるようにしようという背景で、
以下のようなデプロイ方式にすることでエンジニア以外もアプリケーションのデプロイを可能にしました。

# 概要

1. chatworkにデプロイに必要なパラメータを記述した下記のようなテンプレを貼り付ける。

```
deploy----------------------------
リポジトリ: hoge
デプロイ先環境: development
ブランチ: fuga
----------------------------yolped
```
　
2. botがテンプレを解析して、デプロイ用シェルスクリプトを走らせる。

- テンプレを受け取ったbotは入力チェックを行うスクリプトを走らせます。
- テンプレが問題なければ、デプロイを行う旨をchatworkに通知し、実際にデプロイを行うシェルスクリプトを走らせる。
 - デプロイ用シェルスクリプトはbotのサーバーでマスタやバイナリをリモートリポジトリにpushした後、2回のsshを行い、その先でsuを行い、capistranoを動かします。
- デプロイの成功/失敗のパラメータをbotに返します。

　
3. botがデプロイ結果をchatworkに通知する。

本記事では、このスクリプトについての詳細と、ハマったことと気をつけた点について紹介しようと思います。

# 用意したもの
- chatworkのAPI KEY
- GASでもhubotでもいいのでchatworkのログを拾えるbot

# デプロイ用シェルスクリプトでハマったところ
デプロイシェルスクリプト部分は、bot用のサーバーからデプロイを行う際、多段sshからのsuコマンドでユーザーを切り替えた先でcapコマンドを叩いています。
上記の操作に関しては、シェルスクリプトを書く際にかなりハマってしまったので、ハマったところをまとめておきます。

- 2段ssh

2段でsshを行う際には、expectコマンドとssh -tを使用します。下記のように書くことで実現可能です。
1回のsshはシェルスクリプトで書いたことあったので、expectを入れ子にすればなんとかなると思ってハマってしまいました。

```
expect -c "
set timeout 60
spawn ssh -t $HOST1 \"ssh $HOST2 'コマンド'\"
expect \"$HOST1's password:\";
send \"$PASSWORD1\n\"
expect \"'s password:\"
send \"$PASSWORD2\n\"
interact
"
```

- su - username

こちらも、シェルスクリプト内に単純に記述すれば動くと思っておりましたが、そのままだとスクリプトが止まってしまいました。
下記のように書くことで解決します。

```
su - username -c "コマンド"
```

- su - username -c内での変数の挙動

su - username -c "" を行っている際、シェルスクリプト実行側の変数を使いたい場合と、username側の変数を使いたい時がありました。
通常のように変数を使うと実行側の変数として扱われ、su内で実行しているコマンドの終了ステータスなどがとれずに苦労しました。
下記のような記述にすることで、変数を使い分けることができました。

上手くいかない例

```
$ sudo su -l root -c "aaaaa;echo $?"
-sh: aaaaa: command not found
0
```

上手くいく例

```
$ sudo su -l root -c "aaaaa;echo `echo '$?'`"
-sh: aaaaa: command not found
127
```

# 本機能を作る上で注意したこと

- テンプレの入力チェックをかなり厳しく行った
間違って本番環境へ上げてしまったり、テンプレが間違ってて意図しない動作にならないように、入力チェックは厳しく行いました。
コロンの右側以外の編集があった場合や、production指定などがあった場合、存在しないブランチや環境に指定があった場合にエラーを返すようにしています。
- 予期せぬ不具合を防止するため、異常系の動作チェックは念入りに行った
botが止まってしまってはエンジニア作業がなくならないので、ここは各コマンドについて異常系を考えました。

# 終わりに
弊社のカレンダーの記事に定時退社ネタが幾つかあったので、エンジニアがルーチンワークに縛られずに帰るためについ最近行ったアクションについて記事にしてみました。
ruby製のコマンドラインツールをmrubyに置き換える

私が管理しているサーバー上で動く、管理用のツールだったりバッチ処理だったりがいくつかあります。

# 課題
## Rubyで書きたい
Ruby on Rails で開発しているチームで運用しているサーバーなので、おのずとそういったツールも Ruby で作られる事が多いです。[^0]
処理にもよりますが、シェルスクリプトではなく慣れている Ruby で書きたいのです。

## Rubyのインストールが必要
Rubyで書きたいとなるとサーバーに Ruby のインストールが必要になります。
Ruby on Railsのアプリが稼働しているサーバーなら、当然 Ruby もインストールされているのですが、そうでないサーバーもあります。OS のパッケージマネージャーで入る Ruby は古いことも多いので rbenv など使ってインストールすることになります。[^1]
シェルスクリプトのツールを使う場合と比べるとインストール直後のサーバーで動く場合も多く、rubyスクリプトでツール運用はやはり手間が増えることになります。[^2]

# mruby-cli
mruby-cliとは、mrubyでワンバイナリなコマンドラインラインツールを作るために色々やってくれるツールです。
複数プラットフォーム向けにビルドが可能で、クロスコンパイル環境についてもDockerにて用意されています。Docker for MacをインストールしたMacとmruby-cliがあればMac上だけで、LinuxやWindowsのバイナリをビルド可能になります。
mruby-cli自体がmruby-cliで出来ているので、自分の環境用のバイナリを落としてくればすぐに動きます。
ここからダウンロードしましょう。https://github.com/hone/mruby-cli/releases

# 開発手順
* mruby-cliコマンドにてプロジェクトの雛形作成
* 利用するmgemや、ビルド対象プラットフォーム設定
* コーディング
* ローカルでビルド
* 完成したら対象プラットフォーム用にビルド
* 出来上がったバイナリを、対象サーバーに置く

# 実用してみた
上記の開発手順に従って、今回はファイルをS3へ転送するバッチ処理を移植しました。元のツールは ruby2.3.1 で書かれていたものです。
mgemも中々充実していて、ライブラリの機能を呼ぶだけで実装が可能でした。
ただ、ruby と mruby は完全な互換はありませんし、利用したライブラリも、rubyのgemと同じ訳ではないので移植にあたって書き換えは発生しました。

スクリプト自体は、業務で使っているものなので公開出来ませんが、利用した mgem は以下のものです。

* iij/mruby-io
* iij/mruby-dir
* iij/mruby-aws-s3
* iij/mruby-env
* mattn/mruby-onig-regexp
* gromnitsky/mruby-fileutils-simple

それぞれの mgem を見たいただければ分かるのですが、mrubyはファイルシステムが無いような環境も想定されているので、標準ではIOが無かったりします。
それらの機能について、rubyと互換が出るように mgem としてライブラリが作られています。結構な数のライブラリが作られているので、かなり便利にコードを書いていけます。

# まとめ
組み込み用という紹介のされ方が多い mruby ですが、mruby-cliのお陰でワンバイナリコマンドラインツールの作成にも使え、組み込み以外にも用途があることがわかりました。
私のように、普通のアプリケーションを書く人が増えて、ライブラリも増えていくといいなと思いますので、組み込み関連は触らない人でも mruby 試してみてはどうでしょうか。

----

[^0]: ここでいうサーバーは Linux です。うちでは Cent OS が多いのですが今回の記事ではあまり関係ありません。
[^1]: rbenvのお陰でインストールも楽ではありますが。
[^2]: そもそも構成管理ツールを使うなどするべきという話もあります。
過去の自分に伝えたい転職の技術

# 「転職できるように備えておこう」と思ったら

- 新しい技術に取り組むべし
    - 「優秀なエンジニアは新しい技術に飛びつく」と考える人が多い
- ひとつの分野を極めるべし
    - 川相昌弘や鈴木尚広のような一芸に秀でたエンジニアにはニーズがある
- GitHubで技術力をアピールすべし
    - 面接の受け答えのみで技術力をアピールするのは難しい
    - 資格はそんなに評価されない

# 転職を決めたら

- 夏と冬の転職活動は避けるべし
    - 夏は暑く、冬は寒い
- 転職エージェントを使うべし
    - 自力でがんばるより効率的
    - 書類選考を通過しやすい職務経歴書の書き方を教えてくれた（Forkwell Agent）
    - 元同僚エンジニア（超優秀）が使ったエージェントから非公開求人の連絡が来た（自分まで優秀だと思われた）

# 面接に臨んだら

- 給与の下限は明確に伝えるべし
    - 内定後に給与のミスマッチで御破算になるのは時間の無駄
- 給与振込口座が会社指定の金融機関になるかどうか確認すべし
    - メインバンクと異なる場合、毎月の振替が面倒だし手数料もかかる

# 不合格になったら

- 気にせず他の転職先候補を探すべし
    - 書類選考で不合格となった企業から、2年後に内定がもらえた
    - 企業の求める人材は時期によって変わる

# 転職先が決まったら

- 退職日に注意すべし
    - 以前、退職願に「退職日：12月31日」と書いたら「12月30日に直してほしい」と言われた
    - 影響を考えずに直した結果、会社で年末調整してくれず、自分で確定申告することになった
    - また、1日だけ国民年金に加入することになった。厚生年金の加入期間が1ヶ月減る可能性がある

# 筆者について

- 2001年（28歳）：5社目に転職（非エンジニアからWeb系エンジニアに転身）
- 2016年（43歳）：9社目に転職
- 2017年（44歳）：10社目に転職予定（内定済み）
capistranoからitamaeを実行する「capistrano-itamae」

# capistrano-itamaeとは?
capistranoに登録してるhostに対してitamae sshするためのgemです

* https://github.com/sue445/capistrano-itamae
* https://rubygems.org/gems/capistrano-itamae

# 使い方とか
基本的な使い方は以前Qiitaに書いたのでそっちを参照

[capistrano-itamaeというgemを作った - Qiita](http://qiita.com/sue445/items/5a74e6df4c4b513d1453) を参照

# 最近使ってる設定
capistrano-itamaeを3〜4つくらいのアプリに入れてみて自分の中のテンプレができたので書いておきます

## lib/capistrano/tasks/itamae.rake
```ruby:lib/capistrano/tasks/itamae.rake
require "yaml"

ROLES = %i(web db).freeze

namespace :itamae do
  ROLES.each do |role|
    namespace role do
      # nodes.ymlから特定のstageだけ取り出してtmp/stage.ymlに書き出す
      # （nodes.ymlにstageがなければdefaultを採用する）
      task :setup_stage_node do
        stage = fetch(:stage)
        data = YAML.load_file("cookbooks/nodes.yml")
        node = data[stage.to_s] || data["default"]
        File.open("tmp/#{stage}.yml", "wb") do |f|
          YAML.dump(node, f)
        end
      end

      desc "Run itamae to #{role}"
      task :apply => :setup_stage_node do
        on roles(role) do
          itamae_ssh "#{role}.rb", "--node-yaml=tmp/#{fetch(:stage)}.yml"
        end
      end

      desc "Run itamae to #{role} (dry run)"
      task :dry_run => :setup_stage_node do
        on roles(role) do
          itamae_ssh "#{role}.rb", "--node-yaml=tmp/#{fetch(:stage)}.yml --dry-run"
        end
      end
    end
  end

  namespace :all do
    desc "Run itamae to all roles"
    task :apply => ROLES.map { |role| "itamae:#{role}:apply" } do
    end

    desc "Run itamae to all roles (dry run)"
    task :dry_run => ROLES.map { |role| "itamae:#{role}:dry_run" } do
    end
  end
end
```

taskを動的生成しているので分かりづらいですが、 `cap -T` するとこんな感じです。

```shell-session
$ bundle exec cap -T | grep itamae
cap itamae:all:apply                                 # Run itamae to all roles
cap itamae:all:dry_run                               # Run itamae to all roles (dry run)
cap itamae:db:apply                                  # Run itamae to db
cap itamae:db:dry_run                                # Run itamae to db (dry run)
cap itamae:web:apply                                 # Run itamae to web
cap itamae:web:dry_run                               # Run itamae to web (dry run)
```

webロール、dbロールへのそれぞれのdry_runとapply（本実行）、ロールの個別指定を省略した全ロールへのdry_runとapplyが生成されます。

## cookbooks/nodes.yml
```yaml:cookbooks/nodes.yml
default: &default

staging:
  <<: *default
  db_name: "hoge_staging"

production:
  <<: *default
  db_name: "hoge_production"
```

stage毎に値を変えたいということがあったので [^stage]、Railsのdatabase.ymlみたいな形式にして実行時のstageの値でymlを出力して、`itamae ssh` に渡すようにしています

[^stage]: データベース名とか

## itamae実行時のエンドポイント
この中で `include_recipe` 書いたりしています。

```ruby:cookbooks/web.rb
# webロールで実行したいレシピ
```

```ruby:cookbooks/db.rb
# dbロールで実行したいレシピ
```
Ruby で Hello World!

# 概要
この記事は[螺旋祭り Advent Calendar 2016](http://qiita.com/advent-calendar/2016/spiral-s)の22日目の記事です。

そして、記念すべきQiita初投稿です。
何を書くか迷いましたが、最近始めたRubyで、慣習に従い"Hello World!"を出力します。

### 環境
- Microsoft Azure Virtual Machines上に構築したWindows Server2012
- ruby 2.3.1

# インストール
[こちら](http://www.buildinsider.net/language/rubytips/0004)を参考にRubyInstallerでインストールしてみました。
特に問題がなかったので詳細はすっ飛ばします。

# Hello World!

```helloworld.rb
puts 'Hello World!'
```

これで"Hello World!"を出力できるのですが、あんまりなので動かします。[^1]

```stream_helloworld.rb
target = 'Hello World!'

def interval(len)
  ' ' * len
end

def init_queue(size)
  (' ' * size).split('')
end

words = target + interval(10)
queue = init_queue(30)

while true
  words.each_char do |c|
    queue.shift
    queue.push(c)
    print queue.join + "\r"
    sleep(0.1)
  end
end
```

# 実行
![GIF.gif](https://qiita-image-store.s3.amazonaws.com/0/148859/a2440e53-638c-e41e-cd3b-f8e95560fbf4.gif)

# まとめ
Rubyって書いてて楽しい♪

[^1]: Rubyっぽくないとか、こう書いた方がイイとかありましたら教えてください(優しく)
GoでGitHubAPIを操作する〜Enterpriseから逃げるは恥だが役に立ったはず

[ディップ Advent Calendar 2016 - Qiita](http://qiita.com/advent-calendar/2016/dip-dev)にまたしてもやって参りました。

GoでGitHubAPIを操作するネタです。

## なぜやるか
とあるデータをGitHubEnterpriseに自動的にブランチを切ってぶっこんでプルリクまで出したい。　　
ʕ•ᴥ•ʔ＜とにかくGoでやりたい！

## やったこと

### APIを読んだ
https://developer.github.com/enterprise/2.8/v3/

### go-githubなるものの存在を知った
https://github.com/google/go-github

ʕ•ᴥ•ʔ＜go-github!使いたい！
とりあえず検証するためのリポジトリを作り、Tokenでも取得しよう。

ʕ•ᴥ•ʔ＜Tokenは[ココ](https://github.com/settings/tokens)で取得できるよ！

<img width="745" alt="githubでトークンを取得する" src="https://qiita-image-store.s3.amazonaws.com/0/41774/01bdce85-88aa-d49d-177c-204a39cfa440.png">

importはこんな感じ。

```main.go
import (
	"flag"

	"github.com/Sirupsen/logrus"
	"github.com/google/go-github/github"
	"golang.org/x/oauth2"

	config "path/to/config"
)
```

[go-github](https://github.com/google/go-github)を見るとGitHubのユーザと対象のリポジトリ、そして先ほどのTokenが必要そうなので用意しておく。

```environments.go
package github

import (
	"os"
)

type Environments struct {
	GitHubOwner      string
	GitHubRepository string
	GitHubToken      string
}

var (
	GetEnvironments = func() *Environments {
		return &Environments{
			GitHubOwner:      os.Getenv("GH_OWNER"),
			GitHubRepository: os.Getenv("GH_REPOSITORY"),
			GitHubToken:      os.Getenv("GH_TOKEN"),
		}
	}
)
```

サンプルはこんな感じ。
パラメータで渡したブランチを作成してくれる...はず。

```main.go
var (
	branchName = flag.String("branch", "", "create branch name")
	baseBranch = "master"
)

func init() {

	logrus.SetLevel(logrus.DebugLevel)
	logrus.SetFormatter(&logrus.JSONFormatter{})

	flag.Parse()
}

func main() {

	client := getGitClient()
	service := client.Git

	createBranch(service)
}

func getGitClient() *github.Client {

	ts := oauth2.StaticTokenSource(
		&oauth2.Token{AccessToken: config.GetEnvironments().GitHubToken},
	)
	tc := oauth2.NewClient(oauth2.NoContext, ts)
	return github.NewClient(tc)
}

func createBranch(service *github.GitService) error {

	base := baseBranch
	new := *branchName

	masterRef, _, _ := service.GetRef(
		config.GetEnvironments().GitHubOwner,
		config.GetEnvironments().GitHubRepository,
		"heads/" + base,
	)


	ref := &github.Reference{
		Ref: github.String("refs/heads/" + new),
		Object: &github.GitObject{
			SHA: masterRef.Object.SHA,
		},
	}
	_, _, err := service.CreateRef(
		config.GetEnvironments().GitHubOwner,
		config.GetEnvironments().GitHubRepository,
		ref,
	)

	return err
}
```

試しに走らせてみよう！

```
go run main.go --branch "feature/new_branch"
```

ʕ•ᴥ•ʔ＜Dream!

## そして...
お気づきだろうか。
わたしが懸命にテストしていたのは、GitHubなのであって、GitHubEnterpriseではないのでした。

ココの部分なんとかならないのかな。

```github.com/google/go-github/blob/master/github/github.go
defaultBaseURL = "https://api.github.com/"
```
[Issue](https://github.com/google/go-github/issues/179)も上がってるし！誰か...誰か...
どんなに僕の瞳が君を疑っても、君は要件で嘘をつく

ビュー数稼ぎのタイトルに釣られた皆様こんにちは

この記事はファーストサーバのAdvent Calenderの22日目用に書き下ろした記事です
http://qiita.com/advent-calendar/2016/firstserver

今年は真面目にサーバ使ってそれっぽい何かやろうと思いましたが、

相棒のラズパイさんが、**愚息との思い出動画サーバ** と成り下がってしまったので下手に触るにもいかず

ワイドショー見て浮かんだネタを基に、お仕事の話でもしようと思います。

# 私のお仕事

私は12年ほど前、ナウでヤングでデジタルな人種になるべくこの業界に足を踏み入れて、

**システムエンジニア**、通称 **SE** なんぞと呼ばれるお仕事を生業としてきました。

その名の通り、様々なものを「システム化」「IT化」することで、

作業の省力化、自動化を進めていくお仕事だと思いますが、

私の私生活と言えば、

* 自動運転という単語が飛び交う中、**MT車**を購入する

* iphoneのゲームではなく、**同人アナログカードゲーム**の制作にハマる

* ポケモンGOより**GO朱印**を集めるほうが楽しい

* 美少女を育成するゲームより、**実在青少年を2体ほど育てる**ほうがプレイ時間が長い

と、「デジタル」とは真逆の「アナログ」方向に進んでいます。きっと性に合わないんでしょう。

その影響か、仕事でもコーディング作業はめっきり疎遠となり、

最近では「SE」という肩書も烏滸がましいので、**「似非SE」**と名乗ることにしています。

ではそんな「似非SE」の人はどんな仕事をするのでしょうか。

その一つが**要件定義**です


# 要件定義とは

> 要件定義とは、システムやソフトウェアの開発において、実装すべき機能や満たすべき性能などのを明確にしていく作業のこと。
IT用語辞典 e-wordsより

簡単言うと「こんなの作って」に対して「こんなの作るよ」っていうのです。

「こんなの」をつらつらと書くだけの単純なお仕事です。

SEの仕事の中でも、一番アナログちっくな仕事なので私にはうってつけですね。

# 要件定義は難しい？

ただしこの「要件定義」ですが、非常に難しいと言われています。

「要件定義」だけについて書かれた書籍があったり、セミナーがあったりします。

みなさんも「欲しいものと作ってくれたけど・・・、なんか違う・・・」といった経験有りませんか？

そんなときは、「要件定義」に失敗したと思って良いでしょう。

この画像に共感できればそれは本物ですね。

![youkyu.jpg](https://qiita-image-store.s3.amazonaws.com/0/71261/d19ae088-dee7-6f0e-a6e0-6d62cad7eb5c.jpeg)

# なぜ難しいの？

これにはいくつか原因はあるかと思いますが、専門的な話はセミナーや書籍に任せます。

ただ「頼んだこと」が「解決になってない」「しっくりこない」といった点についてのみ限り、

なぜ難しいのかと問われれば、私は**依頼人は嘘をつく** からと答えます。

思ったより格好良かったのでフォントを弄ってもう一回

**<font color=red font-size: 10;>依頼人は嘘をつく</font>**からです。

# 実際にあったお話

「交番がどこにあるか教えてくれ」

私の妻が買い物からの帰り道、車椅子に乗ったおじいさんに声をかけられました。

一足先に子供と帰った私は妻が遅いので様子を見に行くと、彼女はスマホで1キロほど先の交番を案内していました。

事情を聞いた私は「車椅子で行くには遠いよ。交番でなにするの？」と聞いた所。

「道に迷ったので、おまわりさんに道を聞く。家に帰りたい。」といって100mも離れていない介護施設のカードを見せてくれました。

その後、私たちは100mほど寄り道をして帰りました。

# なぜ嘘をつくのか？

おじいさんの最初の依頼通りに「交番を案内」してもおそらく誰もハッピーになりません。

なのに、なぜおじいさんはこんな嘘の依頼をしたのでしょう？

依頼者は依頼を行う際に様々な事情を抱えています。

「立場」「時間的制約」「見栄」「驕り」「金銭的問題」「駆け引き」「引け目」

これら事情が、知らず知らずの内に「自分のやりたいこと」を隠し、

「相手のやってくれ**そう**なこと・でき**そう**なこと」という嘘をついてしまうではないでしょうか。

おじいさんも「家に帰りたいけど、こいつ道知らんやろうな、交番の場所ぐらいならわかるやろ」

という思考が働いたんじゃないかと思います。

# 明日からできること

人にものを頼む際は「困っていること・やりたいこと」を何よりも伝えましょう。

先の例で言えば「道に迷った」とか「家に帰りたい」ですね

これさえ伝えれば、対応者が「家まで送る」なり「道筋を教える」なり「交番を教える」から最適な回答を答えてくれます。

依頼者が答えを決めての質問、例えば「○○できますか？」「○○してほしい」はNGと心がけましょう。

逆に依頼を受ける側であれば「○○できますか？」「○○してほしい」という依頼は「嘘」が入っていること前提で聴きましょう。

根気強く話していればそのうち「真にやりたいこと」にたどり着くはずです。

# ちなみに

先の`実際にあったお話`ですが

* 私とおじいさんと会話したように見えますが、おじいさんはなぜか私と一切話をしようとしませんでした(私の人相の悪さのせいでしょうか)。
* 交番は実際には500Mぐらいでした。
* そして施設も同じぐらいでした。
* おじいさんを送ったのは妻一人で、私は施設が遠かったので帰りました。

...と大概私も嘘をついています
今さらのStylus

この記事は[CSS Advent Calendar 2016](http://qiita.com/advent-calendar/2016/css)の22日目の記事です。

僕はStylusが好きです。

StylusとはNode.js製のCSSプリプロセッサです。
SassやLESSよりも後発ですが、その分機能も充実しています。（ドキュメントはあまりないですが…）
Sassで使える機能は大体使えます。（たまに使えないのもありますが…）

　[Stylus](http://stylus-lang.com/)

僕の会社ではStylusを使っているのですが、この前勉強会でLTした時にそのこと喋ったら「Stylus知らない」とか「案件でつかってるとこ初めて見た」とか散々な言われようでした。悲しい。

ということで、今日はStylusの好きなところを書いていきます。
これを読んでStylus使いが増えたらうれしいです。

##`@include`とか`@if`とか書かなくて良い
僕が一番好きな部分です。Sassは`@include`とかやたら`@`を書かせる印象がありますが、Stylusはそんなことないので、コードがスッキリします。これは大きいですね。

**Sass**

```scss
@mixin $sp {
  @media (max-width: 320px){
    @content;
  }
}

.hoge {
  @include $sp {
    width: 100%;
  }
}

@if $num == 1 {
  //処理
}

```

**Stylus**

```
$clearfix() {
  zoom 1
  &:after {
    content ""
    display block
    clear both
  }
}


$sp() {
  @media (max-width: 320px) { {block} }
}

.hoge {
  $clearfix();
  +$sp {
    width: 100%;
  }
}

if $num == 1 {
  //処理
}
```

##CSSを直接読み込める

StylusはSass記法（セミコロンや括弧を省略する書き方）とscss記法（普通のCSSみたいな書き方）の両方が使えます。
なので、直接CSSを移植したり、 `@import` で読み込めたりするので既存のCSSを読み込まなきゃいけないときとか便利です。

Sassとかでもできるのかな？詳しい人教えてください。

##ディレクトリ単位で読み込みができる

`@import "../base/**/*"` みたいな感じで、指定したディレクトリ配下のファイルを一括で読み込むことができます。地味に便利ですね。

##プログラムちっくに書ける

僕はこの点が一番気に入ってます。
`@`を書かなくて良いことにくわえて、Styluでは変数を定義する特は `=` を使うので、プログラムっぽく書けます。

Stylusでfor文を書くとこんな感じになります。

```
types = apple grape pine peach

for type in types {
  .type-{type} {
    background-image: url('../img/img_'+type+'_.png');
  }
}
```

関数も作れます。

```
$aspectRatio(h = 4, w = 3) {
  position: relative;
  &:before {
    content: '';
    display: block;
    padding-bottom: unit(w / h * 100, '%');
  }
}
```

mixinにオブジェクトで設定を渡すことも出来ます。
プログラミング言語っぽくオブジェクト作れるのは結構便利で、よく使います。
(Sassではできるのかな…？)

```
$style($conf = {}) {
  $conf_default = {
    paddingLeft: 20px,
    fontSize: 14px,
    lineHeight: 24px,
  };
  $paddingLeft   = $conf.paddingLeft || $conf_default.paddingLeft;
  $fontSize      = $conf.fontSize || $conf_default.fontSize;
  $lineHeight    = $conf.lineHeight || $conf_default.lineHeight;

  padding-left: $paddingLeft;
  font-size: $fontSize;
  line-height: $lineHeight;
}

.hoge {
  $style($conf = {
    paddingLeft: 10px
  })
}
```

こう見るとかなりプログラムっぽく書けるのがわかると思います。

##まとめ
**Stylus**はいいぞ。みなさんもぜひStylus使いましょう！
FacebookAPIをgo言語から呼ぶ

この記事は[WACUL Advent Calendar](http://qiita.com/advent-calendar/2016/wacul) の22日目です。

## はじめに

FacebookのAPIをgo言語から扱いたいと思います。
FacebookのAPIはOauthの認証をする必要があります。ユーザの認証を経て、トークンを取得し、そのトークンを使用してAPIを呼びます。

## 下準備

適当にFacebookアプリを登録し、アプリIDとapp secret を控えておきます。
そして、Reidirect URL に `http://localhost:8080`を登録しておきます。

![test_―_Facebookログイン_-_開発者向けFacebook.png](https://qiita-image-store.s3.amazonaws.com/0/85771/6e37f5ee-0934-0251-893b-1904ab56d194.png)

## APIを呼ぶ

以下の手順を実装します。

1. 認証ページのURLを表示
2. コールバックされたときのために:8080でサーバを起動
3. ユーザはURLをコピーしてブラウザに貼り付け
4. 認証するとlocalhost:8080にコールバック
5. コールバックの実装では、パラメータで渡ってくるコードからトークンに変換し、トークンを使ってAPIを呼ぶ

ソースコードは以下です。

```go
package main

import (
	"fmt"
	"log"
	"net/http"

	fb "github.com/huandu/facebook"
	"golang.org/x/oauth2"
	fbauth "golang.org/x/oauth2/facebook"
)

var conf *oauth2.Config

func main() {
	conf = &oauth2.Config{
		ClientID:     "11111111111111",
		ClientSecret: "xxxxxxxxxxxxxxxxxxxxxxxxxx",
		Endpoint:     fbauth.Endpoint,
		RedirectURL:  "http://localhost:8080/",
	}
    //認証ページのURL
	url := conf.AuthCodeURL("")
	fmt.Println(url)
	fmt.Println("Please access the URL")
	//リダイレクトURLで指定したサーバを起動しておく
	http.HandleFunc("/", handler)
	http.ListenAndServe(":8080", nil)
}

func handler(w http.ResponseWriter, r *http.Request) {
	code := r.FormValue("code") //codeが返ってくるので取得
    //codeを使ってAccessTokenを取得する
	token, err := conf.Exchange(oauth2.NoContext, code)
	if err != nil {
		log.Fatal("exchange error", err.Error())
	}
	client := conf.Client(oauth2.NoContext, token)

	session := &fb.Session{
		Version:    "v2.8",
		HttpClient: client,
	}

	//APIを使って自身の情報を取得
	res, err := session.Get("/me?fields=id,name", nil)
	if err != nil {
		log.Fatal("api get error", err.Error())
	}
	fmt.Println(res["name"])  // your facebook name
}

```

以上で、facebook APIを呼ぶことができました。
組込系がWeb系に転職した経緯

この記事は転職アドベントカレンダーの２２日目の記事です

経験談をつらつらと書いていこうと思います。

# ざっくりな略歴
- 20歳で高専の機械科を卒業する
- 元からプログラムや電子工作が好きだったので東京の組込系の会社に入社
- Androidがちょうど出始めた頃でアプリを触りだす
- 会社の技術スタックと興味の方向性が違うから辞めようかと悩む
- 悩んでるタイミングで３年間ほど出向でロボット業界へ
- 出向から戻ってきて１年ほど居たけどもやっぱり辞めてWeb系の会社へ転職

転職は2016年春に始め、夏には転職しました。
気がついたら２８歳になっていました。


# 何故辞めたのか？
色々とふわふわとした理由ですが、大きくは以下かなと。

- ３０歳までなら失敗してもなんとかなるんじゃないかなという不確かな自信
- 会社にいても自分だけ技術スタックが違う
- プロダクトに関わってお金を稼げるような仕事をしてこなかった


# どうやって転職したのか
転職エージェントを利用して転職しました。

使ってみた感想としては、もし転職したい企業に個人的な繋がりがあるのであれば、
そこからまずは話を聞きに行くみたいなスタイルで行ったほうが色々な所へ話が聞きに行けるかなと。
ただ、それで失敗したら転職先だけでなく友人も失う可能性もありますが。

エージェント利用でよかったのは大手だったり比較的お固めの会社との接点が作りやすいのと、
職務経歴書とかの添削をしてくれることですかね。
特に職務経歴はふわっとした内容でもべた褒めしてくれるので
自分に自信が無くなったときに相談しに行くのがオススメです。

## エンジニアならではのアピール
面接行く前にやったことです

- Qiita、Wantedlyの充実化
- 複数社のAPIを組み合わせたモノを作る

１つめのQiita、Wantedlyの充実化ですが、これは人事などの非エンジニア向けの人へのアピールも兼ねて行いました
どうしてもGitHubなどのソースコードでの実力を見せる場の話は非エンジニアの人へのアピールとしては少し弱いかなと思い
日本語でかけて、なおかつ知名度もあるQiita、Wantedlyに投稿数を増やすようにしていました。

２つめの複数社のAPIを組み合わせたモノを作るですが、
こちらは単純にエンジニアとしての力を面接時に見せれるように動かせるモノを作りました。
ちょうど時期的にもLINE Botが出始めた頃だったので色々Botネタをやりました。
複数社組み合わせると何社か話をしに行ったときに使いまわしが効くからです笑


# どこへ行こうとしたのか
- スタートアップ系
- 大手組込系
- 外資系
- IT系メディア
- 大手Web系

と受けました。

## スタートアップ系
スタートアップ系は大体書類選考で落ちました。もともと職務経歴書には組込系な内容しか書いてなかったので求められる人材とは違ったのでしょう。
人がそんなに多くないし面接してる時間もとれないのかな？と思って諦めました。

## 大手組込系
エージェント経由でしたが応答すらありませんでした。
組込業界の闇を少し感じました。

## 外資系の組込
英語で職務経歴書を求められたので辞退しました。このときほど真面目に英語やっておけばよかったと思いました。
プログラミング言語ならマルチリンガルなのに・・・

## IT系メディア
２次面接まで行きました。が、落ちました。
１次面接で企画の概要を即興で作らさせられて、２次面接で実際の編集の人と企画の概要ベースで話をするといった感じでした。
求めている人材とは違ったので今回はお見送りでといった感じだったと思います。
あれからちょっと悔しいのでブログ記事の寄稿とか社内ブログとか書くようにしてます。

## 大手Web系
今の会社が決まってから、もう一社受けました。
今の会社へ行くことを決めていたのですが、流れ的に面接等が断れない状況だったのでもう一社の方もちゃんと受けました。
が、ライブコーディングがクソだったので落ちました。
ちゃんと手を動かさないとコーディングをすることができなくなりますね。もっと知見を広めよう。

# 今の会社にした理由
あるジャンルではかなりのデカいビックデータ()を持っているので、
データサイエンティスト的なことがモニョモニョとできそうだったたり、
基本的な体力がある会社ほどメイン業務以外での楽しいこともできそうかな？という期待からでした。

# 今は満足なのか
この記事を書いている時点では満足しています。
自社ブログの執筆や、技術系イベントへの参加の支援などのびのびと技術を謳歌できています。
自分がやりたかったことが今のところできる環境になったんじゃないかなと思います。
WP_UnitTestCaseのちょっと変わったテストを見てみる(knownWPBug編)



http://develop.svn.wordpress.org/trunk/tests/phpunit/includes/testcase.php を見ていると、「そんなテスト / ヘルパー関数もあるのか」というものを時より見かけるので、ピックアップしてみます。


## knownWPBug( $ticket_id )
`$ticket_id`に対応するチケットがオープンになっている場合、該当のテストをスキップします。


###テストコード

```php
class SampleTest extends WP_UnitTestCase {

	/**
	 * A single example test.
	 */
	function test_some_core_bug_opend() {
		// クローズされていないチケットの場合
		// https://core.trac.wordpress.org/ticket/38653
		$this->knownWPBug( 38653 );
	}
	function test_some_core_bug_closed() {
		// すでにクローズされているチケットの場合
		// https://core.trac.wordpress.org/ticket/100
		$this->knownWPBug( 100 );
	}
}
```

###テスト実行結果

```bash
$ phpunit
/tmp/wordpress-tests-libInstalling...
Running as single site... To run multisite, use -c tests/phpunit/multisite.xml
Not running ajax tests. To execute these, use --group ajax.
Not running ms-files tests. To execute these, use --group ms-files.
Not running external-http tests. To execute these, use --group external-http.
PHPUnit 5.7.3 by Sebastian Bergmann and contributors.

S.                                                                  2 / 2 (100%)

Time: 2.16 seconds, Memory: 26.00MB

OK, but incomplete, skipped, or risky tests!
Tests: 2, Assertions: 0, Skipped: 1.
```

１つ目のテスト`test_some_core_bug_opend()`がスキップされました。

クローズ済のテストはスキップされずに実行されています。

##使い所を想像してみた
コアのバグを拾ってしまった時に、そのコアのバグが影響するテストをスキップさせることで、テストをFailさせないようにするという使い方なのかなと思います。

でなければチケット番号指定で実行させるというやり方にはならないと思いますし。

該当チケットが解決されればテストはそのまま実行されますので、バグが修正されたらコードを消さないといけないというわけでもなさそうです。

##余談
サンプルで使った以下のチケットですが、`Good First Bugs`とよばれる「はじめてWordPressコアにバッチを送ってみよう」と思った人のための簡単なバグです。
https://core.trac.wordpress.org/ticket/38653

コア開発などに興味がある方は、ぜひ挑戦してみてください。
Nim 0.16.0がリリースされました

### 1/8にNimの新しいバージョン(0.16.0)がリリースされたようです。

[リリースノート](http://nim-lang.org/news/e029_version_0_16_0.html)を見ながら、Library Additionsを見ていると、
terminalというモジュールに何個かメソッドが追加されたとの事。

```
Added hideCursor, showCursor, terminalWidth, terminalWidthIoctl and terminalSize to the terminal (doc) module.
```

terminalモジュールってもしかして、ターミナルのカーソル位置や背景色や前景色なんかを設定できるのかなと思ったらアタリでした。[terminal.nim](https://github.com/nim-lang/Nim/blob/master/lib/pure/terminal.nim#L674)の末尾にあったテストコードをちょっといじってみました。

### サンプル

```nim
import os,terminal

# STDOUTに出力
write(stdout, "never mind")
# カーソルを消去
stdout.hideCursor()
# スクリーンクリア
stdout.eraseScreen()
# カーソル位置を１，１へ移動
stdout.setCursorPos(1,1)
# スタイル付き描画(ブリンクするはずですが、Linuxではただテキストが表示されているだけでした)
stdout.styledWriteLine("styled text ", {styleBright, styleBlink, styleUnderscore})
# 背景色をシアンに設定
stdout.setBackGroundColor(bgCyan, true)
# 前景色を青に設定
stdout.setForeGroundColor(fgBlue)
# カーソル位置を１０，１０へ移動
stdout.setCursorPos(10,10)
# テキスト出力
stdout.writeLine("ordinary text")
# ちょっと待つ
sleep(1000*10)
```

### 実行結果

![Screenshot from 2017-01-10 23-38-52.png](https://qiita-image-store.s3.amazonaws.com/0/58872/b7766ffc-d622-a424-19fc-d7136493ff3f.png)
CentOS7上でPython3をCGIとして動かすまで

タイトルの通り。wsgiではなく伝統的なCGIとして動かすまで。
# 1. 前提条件
1. Python3.xがインストールされていること
2. CentOS7.x系であること
3. SELinuxはdisabledであること

# 2. コマンド
## 2.1. Apacheインストール・起動

```text
$ sudo yum -y install httpd
$ sudo systemctl start httpd
$ sudo systemctl enable httpd
```

この時点で`http://[サーバのIPアドレス]/`を入力してApacheのデフォルトページが表示されることを確認
※ virtualboxでNATをしている場合は`http://[サーバのIPアドレス]:[指定したポート番号]/`

## 2.2. Apache設定

```text
$ sudo vim /etc/httpd/conf/httpd.conf
```

```xml:/etc/httpd/conf/httpd.conf
～
<IfModule alias_module>
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
</IfModule>
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options ExecCGI
    Require all granted
    AddHandler cgi-script .py .pyc
</Directory>
```

## 2.3. Pythonファイルの作成

```text
$ sudo vim /var/www/cgi-bin/sample.py
```

```py3:/var/www/cgi-bin/sample.py
#!/usr/bin/python3

print("Content-Type: text/html;")
print("")
print("<!DOCTYPE html>")
print("<html lang='ja'>")
print("<head>")
print("    <meta charset='utf-8'>")
print("    <title>hello world.</title>")
print("</head>")
print("<body>")
print("    <h1>hello world.</h1>")
print("</body>")
print("</html>")
```

シバン(1行目の`#!/usr/bin/python3`)は、**各々の環境に読み替えてください。Python3.xの実行ファイルが入っている場所を書く必要があります。
特にpyenvなどを使っている場合はここの指定は気を付けてあげてください。**
先に`which python`などとして場所を確認しておくとよいです。


**！日本語を表示したい場合は下記を2行目(シバンのすぐ下)に追加！**

```py3
import sys
import io

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
```

## 2.4. Pythonファイルのパーミッションの変更
755になってたら変更しなくていいですが、そうでない場合は変更。

```text
sudo chmod 755 /var/www/cgi-bin/sample.py
```

## 2.5. 表示確認

`http://[サーバのIPアドレス]/cgi-bin/sample.py`を入力して「`hello world.`」が表示されることを確認

# 3. トラブルシューティング
Internal Server Errorなどと表示されうまくいかない場合の対処法が下記。
とりあえず下記コマンドでApacheのログを確認。

```text
$ sudo tail /var/log/httpd/error_log
```

## 3.1. (13)Permission denied: exec of '/var/www/cgi-bin/sample.py' failedと書かれている
### 3.1.1. Apacheの設定ミス
もう一度正しく設定が行なわれているか確認してください。
### 3.1.2. ファイルのパーミッション
`ls -al /var/www/cgi-bin/sample.py`などでパーミッションを確認し、`-rwxr-xr-x`（755）になっているか確認してください。
### 3.1.3. SELinuxの設定ミス
`getenforce`を実行して結果が「Enforcing」の場合、SELinuxが効いている可能性があります。virtualbox上で動かしているなどの場合は必要ないかと思いますので、設定をオフにしましょう。何かの本番用であれば、それ相応の設定をしておきましょう。オフにする場合は下記です。

```text
$ sudo setenforce 0
$ sudo vim /etc/selinux/config
```

```properties:/etc/selinux/config
SELINUX=disabled
```

ちなみに設定をミスしてしまうと最悪**カーネルパニック**だそうなので気を付けましょう。
### 3.1.4. シバンで指定しているPythonのパーミッション
pyenvなど仮想環境を使っている場合、配置されているディレクトリによってはパーミッションが適切ではない場合があります。`ls -la [対象のPython実行ファイルまでのパス]`などとし、`-rwxr-xr-x`（755）であることを確認してください。
ちなみにpyenvを使っている場合のシバンは`#!/home/[username]/.pyenv/versions/3.5.2/bin/python`や`#!/home/[username]/.pyenv/shims/python`や`#!/usr/local/.pyenv/versions/3.5.2/bin/python`などとなると思いますので、自分の環境に読み替えたうえでパーミッションが適切か確認してください。
## 3.2. それ以外のエラー
単純に文法をミスしているか、Content-Type:text/htmlを忘れているか、**日本語を表示しようとしているのに上記の行を追加していない**などがあると思います。

# 4. 結びに
Python3＋CGIの組み合わせでの記事がほとんどなく、はまったときのトラブルシューティングなどもなかったため、書いてみました。何か誤り等あればコメントいただければ幸いです。
唐突にデータウェアハウス（DWH）の設計をすることになったので、DWHの設計周りを調べた

# 前提
## 筆者のスペック
+ SQLが書ける程度でデータベースに詳しいかと言われるとそうではない新卒1年目のエンジニア（の卵）。
+ DWHとかデータウェアハウスって聞いたことあるけど具体的に何かはわからない。
+ DWHに加えてデータマートとやらが必要らしいとは知っていたが、具体的にデータマートが何かわからない。
+ DWHの4特性を知らなかった。
+ もちろんDWHの3つのアーキテクチャを知らなかった。
+ データベースよりむしろフロントエンドの方が好き。

## 今回の取り組みの目的
### DWHの設計方法を理解し、要件に沿った最適な設計が可能になること。（2日で）
以上。

## 要件
### 複数のデータソースを元にBIツールでの分析がしたい。そのために必要なDWH・データマートを設計すること。
分析自体の要件は決まっているため、データソースを元にDWH・データマートをどのような設計にするか決定することがゴール。

# データウェアハウス(DWH)とは
1990年、インモンが提唱。
### 基幹系データベースと、意思決定支援システムに用いられる情報系データベースとの分離を説き、提唱したシステム環境[^1]
この定義じゃ難しいですね。。。
簡単に、「目的別に再構成した統合データベース」という理解で良いかと思います。

## DWHの4特性
### サブジェクト指向（subject oriented）
企業が必要とするテーマや目的、用途別のデータモデリング

### データの統合（integrated）
データ項目の命名規則、単位、コード体系、データ形式などを統一した基準の下で行う

### 時系列（time variant）
ある時点の値を持つデータ（スナップショット）を時間的な順序で集めたもので構成される

### 不変性（non-volatile）
時系列のスナップショットは、DWHに一度正しく蓄積されると更新されることはない

## DWHの3つのアーキテクチャ
色々と呼び名があるようですが、[こちらの連載](http://el.jibun.atmarkit.co.jp/dwbi/)にある名称に統一します。
DWHと言えばこれ、のようなデファクトスタンダードなアーキテクチャはないみたいです。
### コーポレートインフォメーションファクトリー
先ほども登場したインモンさんが提唱したアーキテクチャです。そのため、インモンモデルとも呼ばれます。

>エンタープライズデータウェアハウスという企業のすべてのデータを集めたセントラルデータベースを構築し、そこから各部署で分析に必要なデータをデータマートとして、抽出、構築して分析はそのデータマートに対して分析を行うというものです。[^2]

エンタープライズデータウェアハウスは第3正規形で構築、データマートは非正規化し、分析に適したスタースキーマを構築することでクエリパフォーマンスをアップするという思想のようです。

### キンボールディメンショナルデータウェアハウス
ラルフ・キンボールさんが提唱したアーキテクチャです。キンボールモデルとも呼ばれます。

>ディメンショナルデータウェアハウスアーキテクチャですが、これは簡単にいってしまえば、ディメンショナルモデリング、つまり、スタースキーマでデータウェアハウスを構築することです。[^3]

データウェアハウスはスタースキーマを持ったデータマートの集合だ、という思想のようです。

### データボルトモデリング
>すべてのオペレーションシステムから来たデータをそのまま保管するモデリング[^4]

・・・？
仕様変化に耐えうる、万が一のことに対応できるなどの利点があるようですが、今回目指すBIツールによる分析という要件からは大きく外れるため早々に却下しました。

## スタースキーマ
[第5回：ディメンショナルモデリング：スタースキーマ](http://el.jibun.atmarkit.co.jp/dwbi/2011/06/5-d4bd.html)や[スター スキーマによるデータ ウェアハウス設計](http://support.pb.com/help/spectrum/9.3/webhelp/ja/EnterpriseDataIntegrationGuide/EnterpriseDataIntegrationGuide/source/Introduction/StarSchemaConcept.html)などの良い解説記事があるため、詳しくは解説せず特徴を述べるだけにします。

### 特徴
#### ファクトテーブル
スタースキーマの中心となるテーブルで、特定のイベントを記述する情報が含まれ、主要なデータを持つ。
各ディメンションテーブルの外部キーとなるカラムを持つ。

#### ディメンションテーブル
ファクトテーブル内の情報を記述するデータを保存している。マスターデータのイメージ。
クエリの単純化のため、第2正規形に留めておくことが一般的。

### 注意点
ファクト同士、マスタ同士が結合してはいけない。
→クエリのパフォーマンス低下につながるため。

# 検討事項
DWHについて一通り調べたところで、要件を念頭に置きつつDWH&データマートの設計を考えています。
画面側のレスポンスを早くするために簡単なクエリで集計できるデータマートが必要になるので、主にそこについて考えています。
画面側の要件も読み解きつつやるしかないですねー。

# 参考書籍
[10年戦えるデータ分析入門](http://amzn.asia/5EBoKoc)
第11章のDWHに関する記述が役に立ちました。

# 脚注
[^1]: [データウェアハウスの基礎: RDBから一歩進んでデータ利用技術を学ぶ スキルズ・オン・デマンド研修プログラム](http://amzn.asia/3eFhB0A)より引用
[^2]: [第2回：データウェアハウスアーキテクチャ（1）：インモンのコーポレートインフォメーションファクトリー](http://el.jibun.atmarkit.co.jp/dwbi/2011/05/21-41bc.html)より引用
[^3]: [第3回：データウェアハウスアーキテクチャ(2)：キンボールディメンショナルデータウェアハウス](http://el.jibun.atmarkit.co.jp/dwbi/2011/05/32-5671.html)より引用
[^4]: [第4回：データウェアハウスアーキテクチャ(3)：データボルトモデリング](http://el.jibun.atmarkit.co.jp/dwbi/2011/06/43-fc48.html)より引用
SQLServerのViewにコメントを書いたらTextHeaderの構文エラーでスクリプトを生成してくれなくなった話

# はじめに
ある日、コメントを書き終えてスクリプトの生成をしようと思ったらエラーで取得できなくなってしまったのでメモ。

# 結論
結論を先に言えば**コメント内にSQL文の中に更に[スラッシュスターコメント](https://msdn.microsoft.com/ja-jp/library/ms178623.aspx)を記述するとTextHeaderで落ちる。**

# こんなエラーが出ます。
![Error.png](https://qiita-image-store.s3.amazonaws.com/0/119455/39d89c28-1753-2531-f12e-6cc7b2393329.png)

# 再現したバージョン
```sql:Sample.sql
SELECT @@VERSION
```
```text:Log
Microsoft SQL Server 2014 - 12.0.2269.0 (X64) 
	Jun 10 2015 03:35:45 
	Copyright (c) Microsoft Corporation
	Express Edition (64-bit) on Windows NT 6.3 <X64> (Build 14393: )
```

# テストデータを作る
CREATE VIEW用のテーブルを作る。
VIEWでなくてもスクリプトを生成するタイミングでコメントが書ければ何でもよい。

```sql:CreateHoge.sql
CREATE TABLE T_ほげ(
    ID int NULL,
    Name nvarchar(50) NULL
) ON PRIMARY
```

# 問題のCreateView

```sql:Sample.sql
/*--------------------------------------------------------------------
名称 ：hogehoge
説明 ：fugafuga
SELECT ID /**/, Name FROM T_ほげ
/* SELECT ID    , Name FROM T_ほげ */
--------------------------------------------------------------------*/
CREATE VIEW V_ほげげほ AS
SELECT
      ID
    , Name
FROM T_ほげ
```
上記CreateViewでSQL文と[スラッシュスターコメント](https://msdn.microsoft.com/ja-jp/library/ms178623.aspx)をコメントに混ぜるとスクリプト生成ができなくなってしまった。
**ただしViewとしては普通に動作する。**

# どんなコメントがダメなのか。

## アウトなコメント
**SQL文と[スラッシュスターコメント](https://msdn.microsoft.com/ja-jp/library/ms178623.aspx)をコメントに混ぜる**とスクリプトの生成ができなくなる。

```text:text
SELECT ID /**/, Name FROM T_ほげ
/* SELECT ID    , Name FROM T_ほげ */
```

## セーフなコメント
他にもスクリプト生成で落ちるのではないかと思ったものをまとめてみた。
SQL文と[スラッシュスターコメント](https://msdn.microsoft.com/ja-jp/library/ms178623.aspx)をコメントに混ぜると危険になるらしい。

- コメントの中にSQL文を記述する
- コメントの中に多重コメント 
- --コメント

```text:Sample
■ コメントの中にSQL文は問題ない
SELECT ID    , Name FROM T_ほげ
SELECT ID -- , Name FROM T_ほげ（SQL文中にある --コメント付きのものも大丈夫）
/*/*/*/*/*/*/*/*/*/*多重コメントは大丈夫！*/*/*/*/*/*/*/*/*/*/
```

# 追伸 2018年10月11日
SQLServer2017になってエラーにならず生成できるようになってた:relaxed:

```sql:Sample.sql
SELECT @@VERSION
```

```text:Log
Microsoft SQL Server 2017 (RTM-GDR) (KB4293803) - 14.0.2002.14 (X64)
Jul 21 2018 07:47:45
Copyright (C) 2017 Microsoft Corporation  Developer Edition (64-bit) on Windows 10 Home 10.0 <X64> (Build 17763: ) 
```

# 参考
1. [-- (コメント) (Transact-SQL)](https://msdn.microsoft.com/ja-jp/library/ms181627.aspx)
2. [スラッシュ スター コメント (TRANSACT-SQL)](https://msdn.microsoft.com/ja-jp/library/ms178623.aspx)
VS 2015 で std::codecvt_utf8 がリンクできない場合の対処法

C++ で `std::wstring` を UTF-8 の文字列に変換する際、以下のようにします。

```cpp
std::wstring wStr = L"日本語";
std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t> utf8Conv;
auto utf8Str = utf8Conv.to_bytes(wStr.c_str());
```

ただ、 `wchar_t` は環境によりサイズが異なるので、このままでは困ることがあります。
そこで、 `char16_t` 、 `char32_t` を使用してサイズを指定するようにします。

```cpp
std::u16string utf16Str = u"日本語";
std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> utf8Conv;
auto utf8Str = utf8Conv.to_bytes(utf16Str.c_str());
```

しかし、Visual Studio 2015 Update 3 でビルドすると、リンク時にエラーとなります。
(Mac や Linux 上の GCC 、Clang では問題ありません)

```
error LNK2001: 外部シンボル ""__declspec(dllimport) public: static class std::locale::id std::codecvt<char16_t,char,struct _Mbstatet>::id" (__imp_?id@?$codecvt@_SDU_Mbstatet@@@std@@2V0locale@2@A)" は未解決です。
```

すでにエラーとして報告されているようです。

https://social.msdn.microsoft.com/Forums/en-US/8f40dcd8-c67f-4eba-9134-a19b9178e481/vs-2015-rc-linker-stdcodecvt-error?forum=vcgeneral

# 対処方法

リンク先にも書かれていますが、 `char16_t` を使わずに `uint16_t` を使う、とのことです。

```cpp
std::u16string utf16Str = u"日本語";
std::wstring_convert<std::codecvt_utf8<uint16_t>, uint16_t> utf8Conv;
auto utf8Str = utf8Conv.to_bytes(reinterpret_cast<const uint16_t*>(utf16Str.c_str()));
```