OmniAICreator/Qiita-1.07M huggingface dataset:
Rails Better Errorsでデバックする (Ajaxでのエラーも)

# 概要
「Better Errors」というgemを使ってデバック作業をすると捗ります。
見やすいUIで、ブラウザ上でのデバックも簡単に行うことが出来ます。

また、ajaxのエラーもデバック出来るのでとても便利です。

導入も使い方も非常に簡単なのでとりあえず、自分のプロジェクトに入れてしまいましょう。

# 準備
```rb:Gemfile
gem 'better_errors'
```
上記を、Gemfileに記述して、Bundle installをするだけ。development環境にだけ設定しましょう。

# 使い方

##画面確認

Better Errors導入前は以下のようなエラー画面のはずです。

![スクリーンショット 2015-09-05 12.32.42.png](https://qiita-image-store.s3.amazonaws.com/0/40796/aaf7dc32-7917-8055-f678-ba0bbe90b4c6.png)

導入後は以下のような画面に変わります。

![スクリーンショット 2015-09-05 12.33.49.png](https://qiita-image-store.s3.amazonaws.com/0/40796/caa3bc3b-e15b-a2ea-e667-55e7dc53f530.png)

## 画面説明

![スクリーンショット_2015-09-05_12_33_49.png](https://qiita-image-store.s3.amazonaws.com/0/40796/0c9497b6-dcd1-be25-c2e9-42305caf71be.png)

### エラーメッセージ
エラーメッセージの確認が出来ます。どんなエラーが出ているか示してくれているので注目部分です。

###デバック画面
「irb」や「rails c」と同じように使うことが出来ます。エラーとして動作が止まった部分までの変数も確認することが出来るので便利です。

他、「トレース情報」や「リクエスト情報」、「ローカル変数」も表示してくれるのでこちらも必要なときはチェックです。

## ajax時にエラーを確認する
ajaxでエラーが起きているときも「Better Errors」なら確認出来ます。
ajaxでエラーが出た直後に以下にアクセスすると、起こっているエラーの画面が表示されます。後は通常と同じようにデバック出来ます。（ポート番号は適宜)
[http://localhost:3000/__better_errors](http://localhost:3000/__better_errors)

## おまけ
基本的なことはBetter Errorsでこと足りると思いますが、[pry-rails](http://qiita.com/icb54615/items/374f76b38f673fab7744#pry-rails)も便利なのでこちらもチェックすると完璧でしょう。

また、単純な変数チェックをするときはコード中に「raise」と入れてあげると動作が止まってそこまでの変数をチェック出来るので使っています。pry-railsでいう「binding.pry」と同じように使っています。
（正しい使い方かは知りませんが、とりあえず出来る）
powershell は意外とgawk的なワンライナーに向いてた

とあるツールをバッチファイル + gawk で書いてたけど、いざ他人に渡そうとすると gawk がないだろうから、Windows 標準コマンド固めにしたかったー

# ipconfig の結果から最初の IPv4 のアドレスをゲットする

```
ipconfig | gawk "/IPv4/{ print $NF ; exit}"
```

IPv4 を含む行を抽出するのと、最後の項目を抜き出すのは `for /F` と `findstr` で代用できるが、意外と最初のものだけを出すというのが厳しい。まじめに JScript あたりでスクリプト書く必要あるかと思ったが、PowerShell ならワンライナーで済ませられた。

```
powershell -Command "ipconfig | ?{ $_ -match '^ *IPv4'} | Select-Object -first 1 | %{ $_.Split()[-1] }"
```

* PowerShell はシングルクォートを文字列を囲む記号に使えるのでワンライナーにも適していた

# あらかじめ、ファイルに落としておいた ipconfig の結果を同様に扱う

```
powershell -Command "Get-Content $env:userprofile'\Share\etc\Hayama-pc.txt' | ?{ $_ -match '^ *IPv4'} | Select-Object -first 1 | %%{ $_.Split()[-1] }"
```

* `%USERPROFILE%\Share\Etc\Hayama-PC.txt` に、あらかじめ ipconfig の結果が入っている。目的としては他の PC の(DHCPで割り当てられた）IP アドレスを OneDrive 経由でゲットしたかった
* 環境変数をゲットするのは `$env:userprofile`で、文字列連結は`+`のはずだが、なぜか `+` を書くと、結果の文字列に `+` が入ってしまうので、そのまま横にならべた。なんでじゃろね
* バッチファイル中のものを引用したので「`%`」が「`%%`」になってます

# ゲットした IP アドレスを環境変数に格納しなおす

```
for /F "usebackq" %%I in (`powershell -Command "Get-Content $env:userprofile'\Share\etc\Hayama-pc.txt' | ?{ $_ -match '^ *IPv4'} | Select-Object -first 1 | %%{ $_.Split()[-1] }"`) do set "REMOTEIP=%%I"
```

* `for /F` でコマンド出力を取り込めるが、二重引用符も一重引用符も powershell で使ってしまっている。そんな時、`for /F "usebackq"` を使えば、in 句内で逆引用符が使える
* 結果の IP アドレスは `%REMOTEIP%` という環境変数に取り込む

この IP　アドレスを `ttermpro.exe` (TeraTerm) の ssh フォワーディングのためのパラメータに渡してだね…あ、だれか来たようだ。

もっと簡単にやる方法もありそうな気がするが、それはコメントを待つことにしよう
JavaMailの罠


Javaでメールを扱うライブラリとして[JavaMail](https://java.net/projects/javamail/pages/Home)が有名ですが、設計が古いため、使いにくかったり、いろいろと罠が潜んでいます。その中で自分が痛い目にあったこと、痛い目にあいそうなことを書いておきます(つД`)ノ

# はじめに

- この記事を書いた時のJavaMailの最新版は1.5.4です。
- **必ず[API documentation](https://javamail.java.net/nonav/docs/api/)を読みましょう**。動くからとメソッドの意味も分からずに使ってると後で泣きます。

# Sessionを取得する方法

javax.mail.Session#getDefaultInstance()を使う例がよく載っていますが、これは避けたほうがいいです。

- [javax.mail.Session#getDefaultInstance(Property props)](https://javamail.java.net/nonav/docs/api/javax/mail/Session.html#getDefaultInstance-java.util.Properties-)
- [javax.mail.Session#getDefaultInstance(Property props, Authenticator authenticator)](https://javamail.java.net/nonav/docs/api/javax/mail/Session.html#getDefaultInstance-java.util.Properties-javax.mail.Authenticator-)

このprops引数には以下のように書かれています。つまり、同じメソッドを違うプロパティを引数として呼ぶと、2度目は無視され、意図しない挙動になります。

> props - Properties object. **Used only if a new Session object is created.**

対処方法としては、getDefaultInstanceの代わりにgetInstanceを使いましょう。こちらは新しいオブジェクトを返すので安全です。

- [javax.mail.Session#getInstance(Property props)](https://javamail.java.net/nonav/docs/api/javax/mail/Session.html#getInstance-java.util.Properties-)
- [javax.mail.Session#getInstance(Property props, Authenticator authenticator)](https://javamail.java.net/nonav/docs/api/javax/mail/Session.html#getInstance-java.util.Properties-javax.mail.Authenticator-)

> Returns:
> a new Session object

# デバッグ情報を出力する方法

デバッグ情報を出力する方法は以下の2種類です。mail.debugの設定はSession作成時のデフォルト、setDebugはSessionごとに設定するメソッドです。

- プロパティの"mail.debug"を"true"にする([javax.mailパッケージの説明](https://javamail.java.net/nonav/docs/api/javax/mail/package-summary.html)より)
- [javax.mail.Session#setDebug(boolean debug)](https://javamail.java.net/nonav/docs/api/javax/mail/Session.html#setDebug-boolean-)

ネットを検索すると「"mail.smtp.debug"を"true"にする」という情報が見つかりますが、[com.sun.mail.smtpパッケージの説明](https://javamail.java.net/nonav/docs/api/com/sun/mail/smtp/package-summary.html)にはありません。以前はあったのか、そもそも間違いなのか分かりませんが、設定しても何も起きません(´･ω･`)

# 送信時のエラー取得

JavaMailでは多数の例外が定義されていますが、全てMessagingExceptionのサブクラスとして定義されています。そのため、以下のようにMessagingExceptionをcatchするだけで、通常は事足ります。

```java
try {
    Transport.send(msg);
} catch(MessagingException e) {
    ...
}
```

しかし、メールを送信する場合は別です。[javax.mail.Transport#send(Message msg)](https://javamail.java.net/nonav/docs/api/javax/mail/Transport.html#send-javax.mail.Message-)などでメールを送信しますが、このメソッドはSendFailedExceptionという例外も発生します。

> Throws:
> **SendFailedException - if the message could not be sent to some or any of the recipients.**
> MessagingException - for other failures

このSendFailedExceptionは、送信に成功したアドレス、失敗したアドレスの情報が取得できます。以下のように書くことで、複数人に同時に送ったときに、一部だけ失敗した場合の対処が可能です。ただし、**nullを返す場合があるので注意してください**。

```java
try {
    Transport.send(msg);
} catch(SendFailedException e) {
    // 現在なら当然List<Address>を返すべき
    Address[] sentAddresses = e.getValidSentAddresses();
    Address[] invalidAddresses = e.getInvalidAddresses();
    Address[] unsentAddresses = e.getValidUnsentAddresses();

    ...

    // FIXME: nullチェックしないとダメ!
    for(Address : unsentAddresses)
    {
        ...
    }
} catch(MessagingException e) {
    ...
}
```
unity > 調査 > RS-232Cの使用


Unityを使って、RS-232Cの通信キャプチャをできないだろうか。

その場合、端末は何がいいかわからない。


Intel Edisonの場合は以下のものがある。
これを2枚重ねできるのだろうか?
https://learn.sparkfun.com/tutorials/sparkfun-blocks-for-intel-edison---uart-block

24.95ドル
https://www.sparkfun.com/products/13040?_ga=1.9336565.1396376735.1435299001

Unity側では System.IO.Ports を使うようだ。
http://forum.unity3d.com/threads/rs-232-comm-support.6689/

EdisonでUnityを実行するのはすでに以下にされている方がおられる。
http://qiita.com/dsedb/items/bd11a10167accfcbe70e

I/OピンでソフトUART作るほうが簡単だろうか?
Appleが、WebサイトがSearch APIの要件を満たしているか判別してくれるツールを公開したので試してみた


Appleが[App Search API Validation Tool](https://search.developer.apple.com/appsearch-validation-tool/)を公開しました。

AppleBotのクロール結果を表示してくれます。

Search API周りは、もう大体ドキュメントも揃ってきて、そちらへのリンクなども下部にあるので、便利です(　´･‿･｀)

# [今開発中のPlayer!](https://itunes.apple.com/jp/app/player!-minnadetsukurusupotsunyusu/id897872395?mt=8)

http://web.playerapp.tokyo/news/279371?tag=24 を入力してみました。

![Screen Shot 2015-09-05 at 11.32.47 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/b1f454c4-6dfb-3b0d-2f66-82941a12bab7.png "Screen Shot 2015-09-05 at 11.32.47 AM.png")



うーんあまり良くない結果ですね(´・︵・｀)

[Smart App Banner](https://developer.apple.com/library/ios/documentation/AppleApplications/Reference/SafariWebContent/PromotingAppswithAppBanners/PromotingAppswithAppBanners.html)は、もうすぐ対応予定ですが。

Search APIは、クライアントは対応予定ですが、Webはちょっと遅れそう(　´･‿･｀)

# Gunosy

https://gunosy.com/articles/RyjHW を入力してみました。

さすがʕ ·ᴥ·ʔ

![Screen Shot 2015-09-05 at 11.33.33 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/8539046c-1f2b-10c4-1e77-93373dd6cdc6.png "Screen Shot 2015-09-05 at 11.33.33 AM.png")


# NewsPicks

https://newspicks.com/news/1142780?ref=index を入力してみました。
まあまあ(　´･‿･｀)

![Screen Shot 2015-09-05 at 11.35.48 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/977d7c26-ad0b-accc-9912-2ec09bf1beb7.png "Screen Shot 2015-09-05 at 11.35.48 AM.png")


# Qiita

http://qiita.com/mono0926/items/df03c61adc56934e2e7a を入力してみました。
Player!と似た感じ。Qiitaは、公式スマフォアプリ無いから、この結果でもまあ良いですね。

![Screen Shot 2015-09-05 at 11.37.12 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/e74d1079-493b-3342-4b07-9cf329c51fa8.png "Screen Shot 2015-09-05 at 11.37.12 AM.png")

# Twitter

https://twitter.com/_mono/status/639990933388292097 を入力してみました。
良くないですね(　´･‿･｀)

![Screen Shot 2015-09-05 at 11.59.27 AM.png](https://qiita-image-store.s3.amazonaws.com/0/19398/2b6a5fc6-67f4-9db2-aceb-4dbd560d4df8.png)


---

Universal Linksは、大手も非対応な状態なので、チャンスかもしれませんねʕ ·ᴥ·ʔ
(Gunosy・Twitterは古い形式という警告が出ているので、導入中ぽいですが)

参考: [URLスキーム・独自ディープリンク実装に代わる、Universal Links(iOS 9で導入)でより良いUXを実現 - Qiita](http://qiita.com/mono0926/items/2bf651246714f20df626)
2015年からじわじわと来ているJavaScriptのライブラリ記事でも書いておくかな！ 【壱】

# 記事
[JavaScriptのライブラリメモ記事・ブログ](http://pollseed.hatenablog.jp/entry/2015/09/05/2015%E5%B9%B4%E3%81%8B%E3%82%89%E3%81%98%E3%82%8F%E3%81%98%E3%82%8F%E3%81%A8%E6%9D%A5%E3%81%A6%E3%81%84%E3%82%8BJavaScript%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E8%A8%98%E4%BA%8B)
[JavaScriptのライブラリメモ記事・はてブページ](http://b.hatena.ne.jp/entry/pollseed.hatenablog.jp/entry/2015/09/05/2015%E5%B9%B4%E3%81%8B%E3%82%89%E3%81%98%E3%82%8F%E3%81%98%E3%82%8F%E3%81%A8%E6%9D%A5%E3%81%A6%E3%81%84%E3%82%8BJavaScript%E3%81%AE%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E8%A8%98%E4%BA%8B)

2015年から続々と毎日のように更新されているライブラリを使っては捨て、使っては忘れを繰り返してます。
その中でも変わったものやちょっとおもしろそうなものは是非広めたいので、5個に絞って記事にしました。Hatenaの方に投稿してしまったので、こちらにはライブラリのタイトルだけを書きます。お暇な方がいたら見て下さい。ちょっと参考までに使ってみるといいでしょう。

**とはいいながら、載せ忘れの物があったため6個に増えました。**

# 内容
1. limitCharacts・・・カウント系
2. pixi.js・・・2D系
3. Window-manager.js・・・ポップアップウィンドウ管理
4. heimcontrol.js・・・温度管理
5. algebra.js・・・代数式系
6. **randexp.js・・・正規表現によるランダム文字列生成**

今探しているものは、WebGL系、グラフ生成用の良さ気なライブラリですね。たくさんあるので、全部使ってるとキリがなくて中々これってものが見つかりませんが。
あるいは、FBの開発しているReactが流行っているので、それ系のは別途調査してます。特に[デベロッパーツール](http://facebook.github.io/react/blog/2015/09/02/new-react-developer-tools.html)みたいに公式から出ているニュースは押さえたいです。
[Objective-C] GLSLなどのテキストを普通のコードのように埋め込めるマクロ


[GPUImage](https://github.com/BradLarson/GPUImage)のソースコードを見ていて見つけた方法。別言語のコードを埋め込む際に使えそう。

以下、抜粋。

```objc
#define STRINGIZE(x) #x
#define STRINGIZE2(x) STRINGIZE(x)
#define SHADER_STRING(text) @ STRINGIZE2(text)
```

### 使い方

```objc
NSString *const kGPUImageVertexShaderString = SHADER_STRING
(
attribute vec4 position;
...

void main() {
	//
}
);
```

わりと最近、Metalのコードを埋め込むことがあって結構めんどくさかったのでメモ。
MacのGo開発環境を1.4→1.5にした際の設定メモ

# 概要
- MacのGo開発環境を1.4→1.5にした際の設定メモです
- homebrewを使用

# go1.5をインストール

```
# brew install go

==> Downloading https://homebrew.bintray.com/bottles/go-1.5.yosemite.bottle.tar.
Already downloaded: /Library/Caches/Homebrew/go-1.5.yosemite.bottle.tar.gz
==> Pouring go-1.5.yosemite.bottle.tar.gz
==> Caveats
As of go 1.2, a valid GOPATH is required to use the `go get` command:
  https://golang.org/doc/code.html#GOPATH

You may wish to add the GOROOT-based install location to your PATH:
  export PATH=$PATH:/usr/local/opt/go/libexec/bin
==> Summary
🍺  /usr/local/Cellar/go/1.5: 5328 files, 273M
```

- `/usr/local/Cellar/go/1.5`がインストールされた

# GOROOTを確認

```
# go env | grep GOROOT
GOROOT="/usr/local/opt/go/libexec"
```
- GOROOTのデフォルトはここ

# go1.5のシンボリックリンクを作成

```
# ln -s /usr/local/Cellar/go/1.5 /usr/local/Cellar/go/current
# ll /usr/local/Cellar/go/current
drwxr-xr-x   8 502           admin  272 Sep  5 11:03 1.5
lrwxr-xr-x   1 root          admin    3 Sep  5 09:53 current -> 1.5
```

# (自分ユーザの)GOROOTをbrewでダウンロードしたgoのパスに変更

```
$ vi ~/.bash_profile
$ export GOROOT=/usr/local/Cellar/go/current
$ export GOPATH=xxx(プロジェクトパス。どこでも良い)
```
unity > maskでの設定画面のshow / hide > .localScaleを使う

http://qiita.com/ayumegu/items/cc8171573b289238978c
に記載されているウィンドウの表示/非表示が素晴らしいと思った。

でも自分にはまだ技術がないので、とりあえずMaskの使い方を覚える。

```txt:動作確認
Unity 5.1.2-f1 on MacOS X 10.8.5
```

##準備

以下のようにUIの部品を用意する。

- PanelSetting: Panel
  - IF_ipdar1 : Input Field 
  - IF_ipdar2 : Input Field 
  - IF_port : Input Field 
- B_showHide : Button

PanelSettingに Add Component で Maskを追加する。

PanelSettingの Rect Transform にて stretch/stretchをやめて left/topにする.

![Main_unity_-_150905-showHideSettingWithMask_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/d70d8721-4422-6dd8-8142-fc77bac3a9c4.jpeg)


![Main_unity_-_150905-showHideSettingWithMask_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/a269a06b-f2f8-5183-6c46-95322c1fa61a.jpeg)

B_showHideに Add Component にて NewScriptと追加して ButtonControl という名前にする。 スクリプトは以下の通り

```csharp:ButtonControl.cs
using UnityEngine;
using System.Collections;

public class ButtonControl : MonoBehaviour {
	private bool doShow = false;
	
	public void ShowSettingClick() {
		GameObject panel = GameObject.Find ("PanelSetting");
		if (panel == null) {
			return;
		}
		
		// size change
		RectTransform rect = panel.GetComponent (typeof(RectTransform)) as RectTransform;
		Vector2 size = rect.sizeDelta;
		if (doShow) {
			size.y = 250;
		} else {
			size.y = 5;
		}
		doShow = !doShow;
		rect.sizeDelta = size;
	}
}
```

B_showHideの Button(Script) の On Click()に 以下を関連付ける。

- B_showHide
- ButtonControl.ShowSettingClick()

以上でボタンを押すたびに右側の設定の表示/非表示が切り替えられる。

![Main_unity_-_150905-showHideSettingWithMask_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/d67b4f05-8426-1bca-03c0-a2e51714b804.jpeg)

![Main_unity_-_150905-showHideSettingWithMask_-_PC__Mac___Linux_Standalone__Personal_.jpg](https://qiita-image-store.s3.amazonaws.com/0/32870/74398f4a-6ebc-0135-85ea-df51e707d3e4.jpeg)

用途としては、設定項目を必要な時にshowして入力してもらい、通常はhideで隠しておく。そうすると画面を占領しなくて、他の用途（ウィンドウ）の表示に使えるようになる。

上記のコードは[github](https://github.com/yasokada/unity-150905-showHideSettingWithMask/commits/master)に置いた。

---

PanelSettingのPivotを
- x: 0
- y: 1
とした場合、sizeを縮小時に左上に折り畳まられる。


## localScaleを使った方がよい

.sizeDeltaを使うと具体的なwidth, heightを保持しないといけない。
.localScaleを使えばそれがいらなくなる。

.localScaleはexpand時は(1.0, 1.0)をセットすればいい。

```csharp
			RectTransform rect = panel.GetComponent (typeof(RectTransform)) as RectTransform;
			Vector2 size = rect.localScale;
			if (doShow) {
				size.x = 1.0f;
				size.y = 1.0f;
			} else {
				size.x = 0;
				size.y = 0;
			}
			rect.localScale = size;

```
Androidアプリに+1ボタンを設置したらストアのランキングは上がるのか？

初めまして。
[bowyer-app](https://github.com/bowyer-app)です。

今回の記事は技術的とゆうよりは、実際にその技術を導入した時の数値的な結果検証となります。
導入する際の参考数値としてご活用下さい。

それでは、本題に入ります。

[アプリに+1ボタンを設置する](http://qiita.com/gari_jp/items/1e5a63910ba7900f8945)

以前、こちらの記事を読み、+1ボタンの重要性を知り、個人的にストアに出しているアプリに設置してみました。

[gari_jp](http://qiita.com/gari_jp)さん、ありがとうございます。

# なぜ+1ボタンが重要なのか？
上記リンク先より引用。
>・+1の数が検索結果の順位やランキングに影響する
・Google+上の友達が+1してるとアプリ詳細ページで強調される
・導入が比較的簡単

ストアのランキングを上げるには、レビューやダウンロード数と同じくらい、+1ボタンも影響しているらしいです。
企業のアプリであれば、ある程度拡散する手段がありますが、個人のアプリやあまり有名でないアプリだと少しでもそういった努力が必要になってきます。
私のように無名なディベロッパーなら尚更その努力が必要です。

# どんなアプリに導入したか？
■ アプリ名　： [弓道のアプリ 採点簿 for Android](https://play.google.com/store/apps/details?id=com.bowyer.KyudoScoreBookSecond&hl=ja&utm_source=Qiita&utm_medium=link&utm_campaign=%2B1button)
■ 対象ユーザー　：　弓道をやっている高校生
■ 競技人口　：　約6万人

かなりニッチな市場かつ、Androidを持っている人となるとパイがかなり少ないです。

### アプリのDAUとMAU
■ DAU : 約500 
■ MAU : 約2000
一般的な個人開発のアプリに比べてかなり少ないと思います。
ご自身のアプリへの導入の際の参考数値として比較してみてください。

### 訴求場所と頻度
■ 立ち追加ボタン、もしくは占いボタンのイベント
→これらはアプリ内のKPIとして見ている指標になります。
→出現頻度は毎日使ってくれていたとしたら約1週間後くらいに出る想定
しっかりと定着してくれたタイミングで訴求しています。

# 導入日と結果
【導入日】
■ 2015/02/20 
■ +1数 : 20くらい
■ スポーツで200位前後
【結果】
■ 2015/09/04
■ +1数 : 72
■ スポーツで100位前後

+1が約50くらい増えました。
ランキングも100位くらいまでアップしました。

実際には+1だけに限らずレビューも関係していると思いますが、ランキングはアップしました。
また、ASOへの効果もあり、「弓道」と検索すると１番目に表示されるようになりました。

次回は、レビュー訴求の対策について書きたいと思います。

実装方法は以下を参考にしてみてください。
[Recommend content with the +1 button](https://developers.google.com/+/mobile/android/recommend?hl=en)

合わせてこちらの記事も読んでみてください
[Androidアプリでレビュー訴求の実装とレビュー荒れ防止の対策について](http://qiita.com/bowyer-app/items/5877eae40b1d0d7926fd)

[GooglePlayStoreのASO対策でランキングアップする方法（一部仮説あり）](http://qiita.com/bowyer-app/items/04aef416d7f708afde90)
Vagrant から digitalocean のインスタンスを立ち上げて ansible で provisioning する (Mac OS X)

# 目的
タイトル通り

# インストール

1. vagrant は最新版をインストール

2. digitalocean のプラグインを入れる
   `vagrant plugin install vagrant-digitalocean`

nokogiri が無いと言われた時
1. sudo gem install nokogiri 
2. vagrant が最新版か確認する

# Vagrantfile を作る
YOUR_TOKEN は、DigitalOcean から取ってくる。

```
Vagrant.configure('2') do |config|

  config.vm.hostname = "digitalOcean"

  config.vm.provider :digital_ocean do |provider, override|
    override.ssh.private_key_path = 'vagrant'
    override.vm.box = 'digital_ocean'
    override.vm.box_url = "https://github.com/smdahlen/vagrant-digitalocean/raw/master/box/digital_ocean.box"

    provider.token = 'YOUR_TOKEN'
    provider.image = 'ubuntu-14-04-x64'
    provider.region = 'sgp1'
    provider.size = '512mb'
  end
  config.vm.provision :ansible do |ansible|
    ansible.playbook = "playbook.yml"
    ansible.host_key_checking = false
  end
end
```


# playbook.yml を作る

```
- hosts: all
  sudo: yes
  tasks:
    - name: upgrade
      apt: upgrade=dist update_cache=yes
    - name: install
      apt: name={{ item }} state=present
      with_items:
        - nginx
    - service: name=nginx state=started
```


# ファイルを置く

* mkdir vagrant
* vagrant ディレクトリに Vagrantfile, playbook.yml を置く
* vagrant up
* vagrant ssh
教科書に載っていないけど、よい設計。

文献やネットを調べれば、どこかにあるのかもしれない。
入社3年目の頃、目から鱗が落ちるというか、ちょっとした感動、感銘を受けた良い設計の話。

# とあるバッチ処理で感銘を受けた良い設計
## I.感銘を受けた良い設計
![image](https://qiita-image-store.s3.amazonaws.com/0/76786/00928710-3e18-ea75-b3cb-54aa076d0024.png)

## II.業務要件通りの設計なのだが、今一歩足りていない設計
![image](https://qiita-image-store.s3.amazonaws.com/0/76786/ea67ef3e-25e3-a931-187e-1bc8e019f6e2.png)

## 何故感銘を受けたか？
業務要件では、「○○に合致したトランザクションレコードを削除のこと」というものでした。
そのまま写像すれば、II.の設計になると思いますが、I.の方が多少手間はかかっていますが、色々良いことがあり、それで感銘を受けました。

### 感銘を受けたこと(1)：テストがしやすい
①.削除対象リストを作るまでで、JOBを止めることができるので、要件通りに削除対象が抽出されているかテストしやすい。
(脱線：この「テストしやすい」については、他にも思うことがり、別記事を書きたいことです)。

上記II.の設計だとトランザクションレコードが一気に削除されるので、再度テストしようとすると、トランザクションデータの戻しが必要になってしまいます。数件のデータなら良いですが、稼働中の本番データをテスト用に持ってきていたりすると、まぁ大量データになり、戻すのも面倒です。

②．削除対象リストがあるので、顧客側含め皆が検証しやすい。
削除対象がリストになっているので、顧客側の受け入れテストの検証がしやすいです。
よく考えると、最初の業務要件にはなかったですが、結局受け入れテストで何らかの形でリスト化するなどが必要であり、結果的には、顧客の合意を得た設計なので、業務要件通りに作っていることになるのですが・・・。

### 感銘を受けたこと(2)：業務要件を分析(分けて明確にすること)し設計する
業務要件の「○○に合致したトランザクションレコードを削除のこと」の「○○」の部分はこんなに簡単ではなく、非常に複雑なものでした。これを設計した人は、業務要件を複雑な領域と単純な領域に明確に分け、複雑な領域は何度もテストできるようにしていました。
(あぁ、「何度もテストできる」、なんと素敵なことだろう)

当初の業務要件を一旦ちゃんと受け止めて、さらに一工夫しているところが、いかにもエンジニアっぽくて、良い設計だと感銘しました。

### 感銘を受けたこと(3):リリース後の初回稼働確認もしやすい
何よりよかったんは、リリース後の初回稼働の前日に「削除対象リスト」を作るJOBだけを動かして、本当にリストの内容が正しいか、顧客側含め確認できたことです。

# 応用編：リランしやすいバッチ処理の設計
教科書的にはバッチ処理では障害発生時の再実行(リラン)を考慮して設計しなさいなのですが、具体的にどうすればよいのかと思っていました。
この設計に出会ってから、実はリランを考慮したバッチ処理の設計にも使えると考え実践し、今では定石としてよく使っています。

また、さっきの今一歩の設計の登場ですが、
![image](https://qiita-image-store.s3.amazonaws.com/0/76786/e0718d05-a329-a2a1-2f16-5952b07ccd54.png)
「何らかの処理」からすると、「トランザクションデータ」に不都合なデータがあって、異常終了したとします。

不都合なデータが簡単に取り除けない場合、例えば、外部システムの持ち物であったり、正しいデータであるため、「何らかの処理」の都合では削除できない等の時どうるすか？
「何らかの処理」を何とか修正して、リランするでしょう。時間的な余裕がなかったらどうする？・・・とかいろいろ面倒です。

こんな時、よい設計の方は、
![image](https://qiita-image-store.s3.amazonaws.com/0/76786/892d51a4-0f48-211f-75b7-e73e2fd0f7e8.png)

「対象リスト」のファイルから不都合なデータを削除してしまえばリランができます。
※もちろん万能ではなく、最初の対象リストを作るところで異常終了してしまうとダメですが。ただ、ここは何回もテストしているところなので、かなり安定稼働しているところでもあります。
ファイル/フォルダをzipファイルに圧縮

Scripting.FileSystemObject、Shell.Applicationを使っての実装。

実装内容は、空のzipファイルを作って、この空のzipファイルを書庫としてCopyHere関数を使って、圧縮対象のファイル/フォルダをコピーする。

#コード

```vb
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)

Public Function zip(pthary() As String, zippth As String) As Boolean
    zip = False
    On Error GoTo Err
    Dim sfo As Object, app As Object
    Set sfo = CreateObject("Scripting.FileSystemObject")
    Set app = CreateObject("Shell.Application")
    If sfo.FileExists(zippth) = True Then
        sfo.DeleteFile zippth
    End If
    With sfo.CreateTextFile(zippth, True)
        .Write "PK" & Chr(5) & Chr(6) & String(18, 0)
        .Close
    End With
    Dim zipfld As Object
    Set zipfld = app.Namespace(sfo.GetAbsolutePathName(zippth))
    Dim idx As Long, maxidx As Long: maxidx = UBound(pthary, 1)
    Dim n As Long: n = 0
    Dim f As Variant
    Dim start_tim As Date, cpyflg As Boolean
    For idx = 0 To maxidx
        cpyflg = False
        f = sfo.GetAbsolutePathName(pthary(idx))
        If is_folder(pthary(idx)) = True Then
            If app.Namespace(f).items().Count > 0 Then  '空フォルダでない？
                                                        '⇒空フォルダは圧縮できない
                cpyflg = True
            End If
        ElseIf Dir(pthary(idx)) <> "" Then
            cpyflg = True
        End If
        If cpyflg = True Then
            zipfld.CopyHere f, &H4 Or &H10
            n = n + 1
            'コピーが終わるのを待つ
            start_tim = Now
            Do Until zipfld.items().Count = n
                If DateDiff("s", start_tim, Now) > 5 Then    'タイムオーバー
                    Exit Function
                End If
                Debug.Print CStr(n) & "/" & CStr(zipfld.items().Count)
                Sleep 10
            Loop
        End If
    Next
    zip = True
Err:
    If Err.Number <> 0 Then
        Debug.Print "zip(): " & Err.Description
    End If
    Set sfo = Nothing
    Set app = Nothing
End Function

Public Function is_folder(pth As String) As Boolean
    is_folder = CreateObject("Scripting.FileSystemObject").FolderExists(pth)
End Function
```

上記関数の引数は、ptharyが圧縮対象のファイル/フォルダを配列で指定するのと、zippthでzipファイル名を指定。

空のzipファイルはマジック№とかを書いているだけ。
この空のzipファイルに、圧縮対象のファイルをコピーするのにはCopyHereを使用。
CopyHereは非同期で動いて、実行結果(エラーコードとか)も取れないみたいなので、
コピーできたかをカウンタを見て調べている。
途中でエラーになった場合は、カウンタが上がらないので、経過時間もチェックして、タイムオーバーになったら、
エラー終了すると言う実装。
あと、空フォルダを圧縮する(書庫に入れる)ことはできないので、空フォルダはスキップしている。
レスポンシブサイトでSP表示の時に:hoverを打ち消す

レスポンシブサイトではPC版の時にhoverでボタンのスイッチがへこんだり、色が変わったりします。
ですが、SP版の場合触れた部分がhover状態になり、それが指を離しても戻ってきません（hoverが解除されません）
例えば、ページをスクロールしようとしてページ内にあるボタンを触ってしまったら凹んだままになってしまいます。これでは不格好です。その解決方法を3つほど紹介します。

## 上書きして消す
これは既にhoverを設定してしまっていた場合にhoverを消す方法はないので上書きして元のスタイルを当てる必要が有ります。

```css
.btn {
	background: blue;
}
.btn:hover {
	background: skyblue;
}

@media screen and max-width(480px) {
	.btn:hover {
	/* hoverが付いていない時と同じスタイルを当てる */
		background: blue;
	}
}
```

### 問題点
ただし、今は`background`のみの変更ですんでいますが、ボーダーの色や、幅、高さなどhover時に変更した箇所が増えれば増えるほど、またhoverした要素が多ければ多いほど打ち消しの記述が増えていきます。

## hover用のクラスを使う
bodyにhover用のクラスをつけて、javascriptでスマホサイズの時にhoverを外す指定をする。

```css
.btn {
	background: blue;
}
.hover.btn:hover {
	background: skyblue;
}
```

```jquery

var hover = function() {
	$(window).on('load resize orientationchange', function() {
		if($(window).width() <= 480) {
			$('body').removeClass('hover');
		} else {
			$('body').addClass('hover');
		}
	});
}

$(function(){
	hover();
});

```
このやり方では、javascriptの記述が多少増えますが、hover打ち消しのための記述が必要ありません。

## SP版から作成する
```css
.btn {
    background: blue;
}
@media screen and min-width(480px) {
	.btn:hover {
    	background: skyblue;
	}
}
```
min-widthでは指定したサイズ以上で適用されるのでおおよそスマートフォン以上の大きさの時のみhoverがつきます。

## まとめ
レスポンシブサイトを作成するならsp版から作成するのがコードも短くスッキリすると思います。
＊ただし、あくまで今回はhoverについてのみの話です。
[Rails] ActiveRecordの範囲指定に2点ドット(..)と3点ドット(...)を適切に使う

## 2点ドットの場合

```
Post.where(id: 1..3)
=> "SELECT "posts".* FROM "posts" WHERE "posts"."id" BETWEEN 1 AND 3"
```

between句になります。これは1と3の両端を含みます。

## 3点ドットの場合

```
Post.where(id: 1...3)
=> "SELECT "posts".* FROM "posts" WHERE "posts"."id" >= 1 AND "posts"."id" < 3)
```

1を含み3を含まないSQLが生成されます。あら便利。

## どう使う?

問題になるのはcreated_atなどの連続値における範囲指定で、2点ドットの両端を含むデータ取得だと思わぬところでダブルカウントしてしまう可能性があります。
離散値を使う時には2点ドット(..)、連続値を使う時には3点ドット(...)で範囲指定をするのが便利ですね。
Ruby on RailsをCloud9からHerokuへデプロイするセットアップ覚書


#はじめに
RailsをCloud9からHerokuをデプロイした際にいろいろ詰まったので、成功した際の諸条件を覚書で残しておきます。

#Cloud9でRailsのインストール

Cloud9のBashターミナルで以下をタイプ。

```bash
~/workspace $ gem install rails -v 4.2.2
```
バージョンは好きなやつで。

#Cloud9上で新しいRailsプロジェクトの作成

Bashターミナルで以下をタイプ。

```bash
~/workspace $ rails _4.2.2_ new sample_app
~/workspace $ cd sample_app
~/workspace $ bundle install --without production
```

*先にインストールしたRailsと同じバージョンで。

#Cloud9のサーバ上でアプリが動いていることの確認

まずコントローラにHello Worldファンクションを追加。

```ruby:sample_app/app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
  
  def hello
  	render text: "Hello World"
  end
end

```

あとRouteの設定をする。

```ruby:sample_app/config/routes.rb
  # You can have the root of your site routed with "root"
  root 'application#hello'
```

保存したら、Bashのターミナルで以下をタイプしてサーバを立ち上げる。

```bash
~/workspace/sample_app $ rails server -b $IP -p $PORT
```

Cloud9ページの右上の方にShareというボタンがあるのでそれを押すと、ApplicationへのURLリンクがある。それをコピーして、ブラウザで確認してみる。

画面に無事 Hello Worldと出ればまずはOK。

#Gitの設定
以下のコマンドをBashターミナルでタイプ。Gitの設定をする。
名前とEmailアドレスは自分のものを入力する。

```bash
~/workspace/sample_app $ git config --global user.name "My Name"
~/workspace/sample_app $ git config --global user.email sample@sample.com
~/workspace/sample_app $ git config --global push.default matching
~/workspace/sample_app $ git config --global alias.co checkout
```

Gitをイニシャライズして、ファイルをコミットする。

```bash
~/workspace/sample_app $ git init
~/workspace/sample_app (master) $ git add -A
~/workspace/sample_app (master) $ git commit -m "Initialize"
```

#Bitbucketでリモートレポジトリの作成

BitbucketでGitリポジトリを作成。今回はsample_appという名前で作成。するとRepository setupというページに飛び、下のほうにI have an existing projectというボタンがあるので押す。

以下のようなターミナル用のコードが書かれているので、それをそのまま一行ずつCloud9のBashターミナルにコピペする（Bitbucketのユーザ名によってコードは異なる）

```bash
git remote add origin git@bitbucket.org:XXX/sample_app.git
git push -u origin --all # pushes up the repo and its refs for the first time
git push -u origin --tags # pushes up any tags
```

#Herokuにデプロイする

まずはherokuにログインする。Herokuで登録したEmailアドレスとパスワードを聞いてくるので、それを入力する。

```bash
~/workspace/sample_app (master) $ heroku login
```

次にHerokuプロジェクトを新しく作り、GitデータをHerokuにプッシュする。

```bash
~/workspace/sample_app (master) $ heroku create
~/workspace/sample_app (master) $ git push heroku master
```

無事プッシュが終わったら、ターミナル上に書いてあるURLに飛んで、無事 Hello Worldが表示されれば成功。

#起こりうるエラーと対処法
Rails 4.2.2をインストールするとsqliteのバージョンが1.3.10であったが、これはHerokuではまだサポートされていないらしくプッシュできなかった。なのでその場合、Gemfileでsqliteのバージョンを1.3.9にし、以下のコマンドをタイプしてBundleのアップデート及びGitを更新することで無事Herokuにデプロイできた。

```bash
~/workspace/sample_app (master) $ bundle install
~/workspace/sample_app (master) $ git add -A
~/workspace/sample_app (master) $ git commit -m "Updated Gemfile"
~/workspace/sample_app (master) $ git push heroku master
```
CoffeeScript で引数の未使用を明示する

コールバック関数などで使わない引数を明示できると、使う引数がわかりやすくなります。

しかし、アンダースコアを使うやり方は Underscore.js などを使っているとだめで、複数の引数の未使用も明示できません。

```coffeescript
callback = (_, _, c) -> console.log(c)
```

変数名が重複しているため構文エラー。

そこで分割代入を使ってこう書きます。

```coffeescript
console.log(1) for [] in children

callback = ([], [], c) -> console.log(c)
```

分割代入はオブジェクトや配列の一部を効率的に取りだすものですが、空の分割代入を使うことで変数を締めだしています。

ちなみに ES6(Babel) では null を分割代入するとエラーになるためこのやり方は使えないです。
技術英語 > when tests [are run through] XXX

https://github.com/JakeGinnivan/VSTest.TeamCityLogger

> to display output when tests <font color=red>are run through</font> VSTest.console.exe

<hr>
http://eow.alc.co.jp/search?q=%E4%B8%80%E9%80%9A%E3%82%8A

run throughで「一通り」の意味

<hr>
https://github.com/github/training-kit/blob/46dcbf9f7a6baee3ca4851264f9d39efe72eec48/slides/_posts/pages/jekyll/0004-01-01-jekyll-processing.md

> All files with front matter <font color=red>are run through </font> Jekyll by default.

Jekyllを通して処理される、というニュアンスなのだろう。

<hr>
マイクロソフトアカウントと紐付けしないでAzure Webサイトを作成する

# マイクロソフトアカウントと紐付けしないでAzure Webサイトを作成する

## とりあえず2015/09/05時点の情報です
クラウドに関する情報の陳腐化が激しいので...

Azure Webサイトをささっと作成してみたいって時ありますよね
でもマイクロソフトアカウントと紐付けしたくない(マイクロソフトアカウントを作成したくない)
たとえば
- 無料試用枠を使いきっていたり
- 個人のクレジットカード番号を紐付けたくなかったり
- まだMicrosoftに魂を売りたくなかったり(笑)
- じっちゃんの遺言だったり(嘘)
理由はいろいろありますよ

## そういう時は「Azure App Service」を使ってみると良いです
### 何が違うか？
通常Azureをおはじめするときは
- マイクロソフトアカウントを作成して
- 無料試用版を使う
のが一般的です

しかしAzureポータルサイト [https://azure.microsoft.com/ja-jp/](https://azure.microsoft.com/ja-jp/)で、
####「製品」をクリック→「WebとMobile」をクリック
すると状況は変わります

1. 「製品」をクリック
![「製品」をクリックした状態](https://qiita-image-store.s3.amazonaws.com/0/89027/c7881447-beb3-3c5d-6a3b-42c4060f0582.jpeg)

2. 「WebとMobile」をクリック
![「WebとMobile」をクリックした状態](https://qiita-image-store.s3.amazonaws.com/0/89027/7c635d47-6214-a332-b880-3a6453af3adc.jpeg)
そこには「App Service アプリの作成」があるのでクリックします

3. アプリケーションの種類を選択できるので、「Web App」を選択します
![azure03.jpeg](https://qiita-image-store.s3.amazonaws.com/0/89027/6ee083b2-65ee-e9d3-d6d9-37416ddc2249.jpeg)

4. テンプレートが選択できるので適宜選択します
![azure04.jpeg](https://qiita-image-store.s3.amazonaws.com/0/89027/6baf2739-6290-dbb2-73ad-2acd24df346b.jpeg)

5. 「作成」ボタンを押すとユーザー認証が求められるのでGoogleアカウントでもFacebookアカウントでもお好みで選択します
![azure05.jpeg](https://qiita-image-store.s3.amazonaws.com/0/89027/88205b16-2c0c-b57c-e352-6385456446d7.jpeg)

6. 認証されるとAzure Webサイトが作成されて使えるようになります
![azure06.jpeg](https://qiita-image-store.s3.amazonaws.com/0/89027/2ddf935a-79e9-1bcc-21e1-d76e0586f39b.jpeg)


この方法で作成できるAzure Webサイトは
- 1アカウントにつき１つだけ
- 有効な期間は1時間だけ
です


## 作成したAzure Webサイトを削除するには
- 放置しておく→1時間経過すると削除される
- ポータル画面で「前へ」をクリックすると「削除」ボタンが表示される
![azure07.jpeg](https://qiita-image-store.s3.amazonaws.com/0/89027/5697f52d-8b59-5118-7844-b44cda6eb23a.jpeg)

Let's Deploy!!
AWS Certified Solutions Architect - Associate 頑張る記２

# まずはベストプラクティスを読むよー

https://media.amazonwebservices.com/AWS_Cloud_Best_Practices.pdf

こちらを読んでいきます。万が一現地でAWSの仕事をするようになった時に困らないように、ドキュメントは日本語ではなく英語を読んでいます。英語ドキュメント読むとくたびれるなあ。

自分なりの理解を買いていきます。間違っているかもしれないけどアウトプット大事。

## マインドを変える

まずは前半を読みました。その中で、オンプレとは違うから、まずはマインドを変えよう！と書いてあった。クラウドの世界では、必要なリソースは必要な時に入手できて、不要な時には捨てることができる。オンプレでは一度買い切ってしまうと、それっきり（増やしたり減らしたりは基本ない）。

### オンプレの場合

要件に対して過剰見積もりにならないように、機器の剪定を慎重に行う。といっても、次のreplaceまでの年数を５年とかに見積もり、顧客企業の成長予測に伴って「これだけの性能であればx年間は問題なく利用可能です」というような見積もりをする。

例えば、５年間の利用を想定するのであれば、５年後の予測される事業規模に基づいて性能を決める。

### クラウドの場合

必要な性能は必要な時に手に入れればいいので、必要になった時にどうやってスケールするかの戦略を立てる必要がある。

## 取りこぼし

オンプレミスの場合、性能は導入した時から変わらないので、予測を超えたリクエストに対応できないことがある。この時は50xエラーになったり、ソーリーソーリーって言ったりする。一方で、クラウドは柔軟に性能を変えられるから、きちんと対応できていれば、問題ない。

## オンプレのリスクとか

利用料は時間課金なので、場合によってはオンプレの方がやすいこともあるかもしれないけど、オンプレの場合、ハードウェアのメンテナンス、場所代、電気代、その他もろもろがあったり、データセンターがすっ飛べばすべておじゃんというリスクがある。

クラウドの場合は、世界中にあるリージョン、アベイラビリティゾーン、エッジサーバーに散らされるから、災害時の事業継続もしやすい。

## とはいえ

ものすごい重要な情報はやっぱオンプレになるんだろうなとか言ってみる。例えば、特定秘密情報とか、講座の勘定系データとか。

## ここまでの理解を図にしてみた

![ganbaru001.jpg](https://qiita-image-store.s3.amazonaws.com/0/9711/ffba7926-9e39-ecdf-905e-2735ff60fc4a.jpeg)

昔高校で習った積分みたいな図になったけど、スケールできる、柔軟であるというのは、つまりこういうことであろうと理解した。
SpringFrameworkユーザにやさしい Node.js + Express のディレクトリ構成

## SpringFrameworkユーザにやさしい Node.js + Express のディレクトリ構成
Node.js + Expressのディレクトリ構成で最初悩んだので、テンプレプロジェクトと一緒にメモ。

こんな感じ
![スクリーンショット 2015-09-05 4.24.33.png](https://qiita-image-store.s3.amazonaws.com/0/85138/37b3a074-7d2a-487c-b8f8-5e1e2fcc8314.png)
以下は各ファイル解説。

***
applicationContext.xml的なもの。

```app.js
var express = require('express');
var app = express();

// root-require
global.rootRequire = function(name) {
    return require(__dirname + '/' + name);
}

// static
app.use(express.static('public'));

// view
app.set('views', __dirname + '/views');
app.set('view engine', 'jade');

// controller
var controller = {};
controller.hello = rootRequire('lib/controller/hello-controller.js');
require('./router.js')(app, controller);

// run
app.listen(3000);
```
***

web.xml的なもの。

```router.js
module.exports = function(app, controller) {
  app.get('/hello', controller.hello.hello);
  app.get('/helloUser', controller.hello.helloUser);
}
```
***

コントローラクラス。
`Hello World`を返すものと、`Hello ${name}`を返すもの。
`${name}`はパラメータから取った値そのまんま。

hello-service.jsの読み込みに、requireの代替手段としてapp.jsで作ったrootRequireを使ってるるのがキモ。（Node.jsでは相対パス指定しかできない）
気に食わない人は[Better local require() paths for Node.js](https://gist.github.com/branneman/8048520)を参考に別の手段をどうぞ。

```hello-controller.js
var helloService = rootRequire('lib/service/hello-service.js');

exports.hello = function(req, res) {
  res.render('hello.jade', {
    hello : 'Hello World'
  })
}

exports.helloUser = function(req, res) {
  var name = req.query.name;
  helloService.getHello(name, function(hello) {
    res.render('hello.jade', {
      hello : hello
    })
  });
}
```
***

サービスクラス。
パラメータに`Hello`をくっつけて、非同期っぽくコールバックに渡すだけ。

```hello-service.js
exports.getHello = function(name, callback) {
  callback('Hello ' + name);
}
```
***

テンプレートエンジン。
`hello`って名前で渡された値を表示するだけ。jadeは趣味。

```hello.jade
html
  head
    title Hello World
    link(rel='stylesheet', href='./css/style.css')
    script(src='./js/client.js')
  body
    p= hello
```
***

最後にパッケージ管理。pom.xml的なもの。

```package.json
{
  "name": "template",
  "version": "0.0.1",
  "dependencies": {
    "express": "*",
    "jade": "*"
  }
}
```
***
Dockerの中でPlay Frameworkのプロジェクトをビルドしてzipを取り出す


sbtが取得するjarをキャッシュさせる部分で頭を捻らないといけなくて、ベストプラクティスが無い状態だけど、やってみたら意外と簡単だった。

以下の内容はCIサーバーで動かす用途を想定していて、手元のマシンで動かすことは考えてない。

Dockerfileをプロジェクトのルートに置く。

```
FROM java:8-jdk
COPY . /myapp
WORKDIR /myapp
```

Dockerfileではファイルのコピーだけやって、ビルドスクリプトでビルドする。

ビルドスクリプトはこんな感じ。

```bash
#!/bin/bash -eux

CONTAINER=myapp-build
IMAGE=myapp-build

docker build -t $CONTAINER .

# キャッシュするディレクトリをあらかじめ作っておく
mkdir -p $PWD/.ivy2 $PWD/.sbt

# 既に同名のイメージがあるとエラーになるので消しておく
docker rm $IMAGE || true

# キャッシュを使いつつビルド
 docker run --name=$IMAGE -v $PWD/.ivy2:/root/.ivy2 -v $PWD/.sbt:/root/.sbt $CONTAINER ./activator dist

# イメージからzipを抜き出す
docker cp $IMAGE:/myapp/target/universal/myapp-1.0-SNAPSHOT.zip ./

# イメージを削除
docker rm $IMAGE || true
```

これだけで myapp-1.0-SNAPSHOT.zip が手に入る。

`$PWD/.ivy2` と `$PWD/.sbt` はDockerfileで `COPY . /myapp` したときにコピーされると困るので .dockerignore に追加すると良い。

## ついでにテストも走らせる

テストにMySQLとmemcachedを使いたかったのでDockerfileでインストール。

```
FROM java:8-jdk

# MySQLのインストールにrootパスワード入力を求めない
ENV DEBIAN_FRONTEND noninteractive

RUN apt-get update && apt-get install -y mysql-server memcached --no-install-recommends && rm -rf /var/lib/apt/lists/*

COPY . /myapp
WORKDIR /myapp
```

ビルドスクリプトの `./activator dist` のところを

```
bash -c 'service memcached start && service mysql start && mysql -uroot < ./init.sql && ./activator test dist'
```

に変更。init.sqlにはデータベース作成とかユーザー作成が書いてある。

## ついでにデプロイ用Dockerコンテナも作る

ビルドにはJDKが必要だけどデプロイ用にはJREだけでいい。なので上のとは別にDockerfileを作った。

Dockerfile-release

```
FROM java:8-jre

EXPOSE 9000

# tgzをADDすると展開されてディレクトリになる
ADD ./myapp-1.0-SNAPSHOT.tgz /

WORKDIR /myapp-1.0-SNAPSHOT
RUN ["chown", "-R", "daemon", "."]
USER daemon
ENTRYPOINT ["bin/myapp"]
```

zipじゃなくてtgzで出力するために、ビルドスクリプトの `activator dist` のところを `activator universal:packageZipTarball` に変更しなければいけない。

1.0-SNAPSHOTって付くのがキモい場合はbuild.sbtに `name in Universal := moduleName.value` と書けば `myapp.tgz` という名前になってくれて嬉しい。

## 最終的なビルドスクリプト

上に書いた要素をすべて盛り込むとこういう感じになる。

```bash
#!/bin/bash -eux

CONTAINER=myapp-build
IMAGE=myapp-build

docker build -t $CONTAINER .

# キャッシュするディレクトリをあらかじめ作っておく
mkdir -p $PWD/.ivy2 $PWD/.sbt

# 既に同名のイメージがあるとエラーになるので消しておく
docker rm $IMAGE || true

# キャッシュを使いつつテストしてからビルド
 docker run --name=$IMAGE -v $PWD/.ivy2:/root/.ivy2 -v $PWD/.sbt:/root/.sbt $CONTAINER \
  bash -c 'service memcached start && service mysql start && mysql -uroot < ./init.sql && ./activator test universal:packageZipTarball'

# イメージからtgzを抜き出す
docker cp $IMAGE:/myapp/target/universal/myapp.tgz ./

# イメージを削除
docker rm $IMAGE || true

# デプロイ用コンテナを作成
docker build -t quay.io/example/myapp -f Dockerfile-release .

# quay.ioにpushする
docker push quay.io/example/myapp
```
Macにtmuxを導入する

# インストール

```
$ brew install tmux
```

# 設定
使いやすいように設定ファイルを作成する。
ひとまずこんな感じに。

```
$ cat ~/.tmux.conf
# prefixをCtrl-qに変更（デフォルトはC-b）
set-option -g prefix C-q
unbind-key C-b
bind-key C-q send-prefix

# UTF-8対応
setw -g utf8 on
set -g status-utf8 on

# Esc入力時の待ち時間をキャンセル
set-option -s escape-time 0

# アクティブウィンドウを目立たせる
setw -g window-status-current-fg white
setw -g window-status-current-bg red
setw -g window-status-current-attr bright

# アクティブペインを目立たせる
set -g pane-active-border-fg white
set -g pane-active-border-bg yellow

# rで設定読み込み
bind r source-file ~/.tmux.conf \; display "Config reloaded."

## ステータスバーを下部に表示する
set -g status-position bottom

# マウス操作を有効にする
setw -g mode-mouse on
set -g mouse-select-pane on
set -g mouse-resize-pane on
set -g mouse-select-window on

## viのキーバインドを使用
setw -g mode-keys vi

# クリップボード対応
set-window-option -g mode-keys vi
```

# コマンド
とりあえず最低限覚えていたほうがいいコマンドだけを記載。
慣れたら他も徐々に覚えたい。

セッション

|項目|コマンド|
|:-----------|:------------|
|セッション開始|tmux|
|セッション開始（名前指定）|tmux new-session -s (name)|
|前回のセッションにアタッチ|tmux a|
|セッション終了|prefix + d|
|指定したセッション削除|tmux kill-session -t (session-name)|
|セッション全削除|tmux kill-server|

ウィンドウ

|項目|コマンド|
|:-----------|:------------|
|ウィンドウ開始|prefix + c|
|ウィンドウ移動|prefix + n(next), prefix + p(pre)|

ペイン

|項目|コマンド|
|:-----------|:------------|
|ペイン分割|prefix + "（横）, prefix + %（縦）|
|ペイン移動|prefix + o(next)|
|ペイン削除|prefix + x|

確認

|項目|コマンド|
|:-----------|:------------|
|セッション確認|tmux ls|
|クライアント確認|tmux lsc|
|ウィンドウ確認|prefix + w|
|ペインのインジケータ確認|prefix + q（続けて番号押下でペイン移動）|

# その他
## マウス操作
今までターミナルを使って開発していたが、
ターミナルからtmuxを使うとマウス操作がうまくできないらしい。
（mode-mouseを設定しても効かない）
ということで、iTerm2を使うことにした。
[iTerm2 - Mac OS Terminal Replacement](https://www.iterm2.com/)

## コピー
デフォルトだとクリップボードへコピーができなかったので、以下の方法で対応。

設定追加

```
$ echo 'set-window-option -g mode-keys vi' >> ~/.tmux.conf
```

コピー方法
・コピーモードにするために、prefix + [ を入力
・コピー開始地点でSpace、完了地点でEnterをクリック
・貼付け時に、prefix + ] を入力

# 参考資料
[tmuxを使い始めたので基本的な機能の使い方とかを整理してみた - 完熟トマト](http://kanjuku-tomato.blogspot.jp/2014/02/tmux.html)
[tmuxに慣れてみる: tmuxとGNU screenの違いなど](http://rcmdnk.github.io/blog/2015/01/02/computer-tmux-screen/)
[tmuxの基本的な使い方とコマンドのまとめ - TASK NOTES](http://www.task-notes.com/entry/20150711/1436583600)
[tmuxのコピーモードを試してみる - ymkoの日記](http://d.hatena.ne.jp/ymko/20120302/p2)
Qtの循環参照でハマった話

# Qtの循環参照でハマった話

仕事でQtを使うことがあった。
しかも参加者は全員QtもC++も初めてだった。
さらにやっつけで既に変な設計で書かれたコードが出来上がっていた。

「Qtってすごいらしいぜ。QObjectの継承クラスで親子関係を登録したら、あとは親をdeleteするだけで子も全部deleteするんだってよ」
「マジで！メモリ管理めちゃ楽じゃん。やったね」

なんて思ったのもつかの間。

「おい、なんか変なエラーでて落ちるんだけど。なにコレ」
「んー、ページングってことはメモリ関連じゃね？freeとtopでメモリ見てみ。あとsysteminfoで随時出力しといて」
「リークしてんじゃん。newとdeleteくらいチェックしとけや」

newで確保されるのはヒープ領域だ。
この領域に確保されたメモリは自動では開放されない。
deleteが必要なのだ。
そんなことは当然みんなわかっているので、deleteのし忘れなどない。

「チェックしたけどちゃんと対になってるぞ。何が原因だ？」
「継承元のデストラクタはvirtualついてる？」
「そこもチェック済み。」
「じゃあcppcheckっていう静的解析ソフトあるからつかってみたら」
「やってみた。けど駄目だった。ちょろっとwarningはでるけど、リークは見当たらないぞ」
「PThredとか別プロセスはどうだ？デタッチ忘れとか」
「いや、それも大丈夫だわ。問題なかった」

ちなみにQtCreatorのデバッグ機能や高機能なメモリリーク検出ソフトは使えない状況だった。
そんなわけで原因がわからないまま時は流れた。
そしてみんなQtにも少し詳しくなってきた。

「Qtってリファレンスカウンタがあって、それでdeleteを監視してるみたいだぞ。リークの原因これじゃね？」
「でもデストラクタ呼ばれてるからdeleteはされてるだろ」
「でもメモリは戻ってないからQtが内部的に領域を保持してる可能性もあるんじゃ」
「コピーオンライトで参照カウンタが減ってない可能性もあるかも」
「じゃあ試しにこのクラスの継承してるQObject切ってみたら？」
「あ、リークなくなった」
「「コレが原因か！？」

QObjectでの親子関係の参照と、子から親へthisの自己参照を渡して処理を委譲している部分があった。
これは親と子が互いの参照を持つ相互参照または循環参照と呼ばれる。
メモリが開放されなくなる最悪なパターンの一つだった。
普通は循環参照はコンパイルエラーになるはずだが、サブクラスとしてQObjectがあるので、キャストして参照の受け渡しをやっていたのだ。

アプリの設計が悪いのだが、プロトタイプを最初に作った人を責めても仕方がない。
いい勉強になったし、次はこのような設計にはしないだろう。



ちょっとだけ愚痴。
オライリーのQtの参考書には循環参照とかその辺りのことは一切載っていなかった。
結構陥りやすいミスだと思うので一言くらい解説があってもいいと思う。
QWeakPointerとかも載ってなかった。トラブルシューティングこそ載せるべきだと思う。

それからdelete thisはやめてほしいと思う。危険過ぎる。スコープを抜けるときにスタック領域の開放とかがあったら落ちるだろうし。
あとコードのコピペもやめてほしい。3回同じコードを書いたらリファクタリングしろと言いたい。

追記:
デストラクタのvirtualの記述を追加。
下記記事は参考になった。
[C++の落とし穴](http://shnya.jp/moin/C%2B%2B%E3%81%AE%E8%90%BD%E3%81%A8%E3%81%97%E7%A9%B4)
JavaFXでバックグラウンドスレッドの実行

JavaFXで重い処理（時間がかかる処理）を実施する場合、
バックグラウンドスレッドで処理をしないと処理が終わるまで画面が更新されない。
（画面の操作もできない）

バックグラウンドスレッドで処理をするにはServiceクラスとTaskクラスを使用する。

以下がServiceクラスとTaskクラスを使用したバックグラウンドスレッドの処理の
サンプルになる。内容としては、ボタン押下して１秒後にテキストフィールドに
メッセージを出力する。

```ServiceMain.java
public class ServiceMain extends Application{
	final private static XService service = new XService();

	public static void main(String[] args){
		Application.launch(args);
	}

	@Override
	public void start(Stage stage) throws Exception {
		Group root = new Group();
		stage.setScene(new Scene(root));

		//テキストエリア
		TextField field = new TextField("");
		field.textProperty().bind(service.messageProperty());

		//ボタン
		Button btn = new Button("ボタンです。");
		btn.setOnMouseClicked(new EventHandler(){
			@Override
			public void handle(Event event) {
				service.restart();
			}
		});

		//レイアウト
		VBox vBox = new VBox();
		vBox.getChildren().addAll(btn, field);

		root.getChildren().add(vBox);
		stage.show();
	}
}
```

・サービスを生成し、ボタン押下でサービスをスタート（リスタート）する。

```XService.java
public class XService extends Service<Void>{

	@Override
	protected Task<Void> createTask() {
		return new XTask();
	}

}
```

・Serviceクラスをextendsする。
・createTaskメソッドをOverrideし、Taskクラスを生成してリターンする。


```XTask.java
public class XTask extends Task<Void>{
	@Override
	protected Void call() throws Exception {
		Thread.sleep(1000);

		updateMessage("OK");

		return null;
	}

}
```

・Taskクラスをextendsする。
・callメソッドをOverrideし、このメソッド内に重い処理（時間がかかる処理）を
　実装する。サンプルでは、１秒間スリープした後に文字列"OK"を設定。
Rhinoceros / Grasshopperでコーディングしたい人のためのレファレンス参照先


##はじめに

RhinocerosでVBScript、あるいはGrasshopperでC#, VB.NETあるいはPythonでコーディングしたい場合に、レファレンスやサンプルファイルの場所が色々な場所に散乱していたので、まとめておきます。

##RhinoScript(VBScript)

###Wiki

[RhinoScript Wiki](http://wiki.mcneel.com/developer/rhinoscript)
RhinoScriptのWikiページ。RhinoScriptに関するほとんどの情報はここから手に入る。

###Primer

[RhinoScript 101 Primer](http://www.rhino3d.com/download/rhino/5.0/rhinoscript101)
はじめてRhinoScriptを触る人にとっての初心者用マニュアル。

###Online Reference

[Rhinoscript Online Reference](http://4.rhino3d.com/5/rhinoscript/index.html)
Rhinoscriptのオンラインレファレンス。

[VBScript Online Reference](https://msdn.microsoft.com/en-us/library/t0aew7h6(VS.85).aspx)
VBScriptのオンラインレファレンス。

###Forum

[RhinoScript.org Forum](http://www.rhinoscript.org/forum)
RhinoScript等に関するフォーラム。

###Samples

[RhinoScript Samples in Github](https://github.com/mcneel/rhinoscript)
GitHubにあがっているRhinoScriptのサンプル集。

[RhinoScript.org RhinoScript Examples](http://www.rhinoscript.org/rhinoscript)
ユーザが投稿したRhinoScriptサンプル集。

##RhinoCommon

###Wiki

[RhinoCommon Wiki](http://wiki.mcneel.com/developer/rhinocommon)
RhinoCommonに関するWiki。概要を知るには良い。

[Using RhinoCommon from Python](http://wiki.mcneel.com/developer/pythonandrhinocommon)
PythonでRhinoCommonを使う方法。

###Online Reference

[RhinoCommon Online Reference](http://4.rhino3d.com/5/rhinocommon/)
RhinoCommonに関するオンラインレファレンス。

###Template

[RhinoCommon templates for v5](https://visualstudiogallery.msdn.microsoft.com/16053049-7db2-4c9f-961a-53274ac92ace)
RhinoCommonのプラグインを作るためのVisual Studio用テンプレートファイル。

##Python Scripting

###Wiki

[Python scripting for Rhino and Grasshopper](http://wiki.mcneel.com/developer/python)
Python Scriptingに関するWiki。

###Online Reference

[Rhino.Python Programmer's Reference](http://4.rhino3d.com/5/ironpython/)
Rhino Pythonのオンラインレファレンス。

###Samples

[RhinoScript.org Python Samples](http://www.rhinoscript.org/python)
ユーザが投稿したPython Scriptingのサンプル集。

##Grasshopper

###Download

[Grasshopper Download Page](http://www.grasshopper3d.com/page/download-1)
Grasshopperのダウンロード場所。

[GhPython](http://www.food4rhino.com/project/ghpython?ufh)
GrasshopperでPythonを使いたい人はこのプラグインをインストールする必要がある。

###Template

[Grasshopper Assembly](https://visualstudiogallery.msdn.microsoft.com/9e389515-0719-47b4-a466-04436b491cd6)
Grasshopperのプラグインを作るためのVisual Stuido用テンプレートファイル。

###Reference 

[Grasshopper SDK Download](http://www.grasshopper3d.com/video/grasshopper-sdk-download)
GrasshopperのSDKをダウンロードする方法。

###Forum

[Grasshopper Forum](http://www.grasshopper3d.com/forum)
Grasshopperに関するフォーラム。主に技術的な質問に関して。

###Samples

[RhinoScript.org Grasshopper Examples](http://www.rhinoscript.org/grasshopper)
ユーザが投稿したGrasshopperのサンプル集。
RubyMineでconsole.logが補完されないので作る

## console.log()を補完させる
ついでに補完した後は`()`の間にカーソルが来て気持ちよく入力できるようにする。

## 参考
http://stackoverflow.com/questions/9919385/code-snippets-in-phpstorm
https://www.jetbrains.com/ruby/help/creating-and-editing-live-templates.html

## こうする
![Screen Shot 2015-09-05 at 00.42.01.png](https://qiita-image-store.s3.amazonaws.com/0/27895/77aef6f1-4448-6efe-82c8-463cfc40de93.png)

## 使い方
`con`と打って`tab`で補完される

## 思ったこと
`Live Templates`に項目を足したかったのだが、できなさそうなので、
既存の使わなそうなやつを上書きした。
raspbianのヘッドレスインストール


raspberry piのOSのheadless(キーボード、ディスプレイ無し)のインストールについて今さらまとめる。なぜなら昨日再インストールするハメになったからだ。

## 通常コース(有線LANかつdhcp有効な環境)

<dl>
<dt>raspi使いの常識</dt>
<dd>raspbianは初期状態で、有線LANのdhcpとsshdが有効になっている。<dd>
</dl>

なのでヘッドレスインストールに必要な手順は
1. SDカードにraspbianを書き込み[^1]、ブートして、
2. 割り当てられたアドレスを探して(```arp -a```やdhcpのログ)
3. sshする。``` pi@192.168.1.xxx ``` (パスワードは raspberry )
4. 初期設定ツール起動 ``` sudo raspi-config ```

以上。
実に簡単だ。___通常は。___
私は上記常識を知らなかった(忘れていた)ので、わざわざ余計な手間をかけた。

[^1]: 書き込みには[win32diskimager](https://osdn.jp/projects/sfnet_win32diskimager/)が使える。

## イレギュラーコース(wifi, あるいはなぜかdhcpがない環境)

タイトル通り、wifiを有効にしたり、dhcpがなかったり、常識がなかったりするならこちらのコース。

raspbianのイメージファイルをマウントしネットワークの設定を行い、sshできるところまでもっていく。

```shell-session
 sudo kpartx -av raspbian.img
 ```
 とすると/devにブロックデバイスが作成されるのでそれを
 ```
 mount /dev/loopX  /mnt/raspbian # loopXはkpartxの出力による  
 ```
 でマウントする。
 
 ```shell-session
 vim /mnt/raspbian/etc/network/interfaces
 ```
 でネットワークの設定をする。
 
 後は上記通常コースの3から。

raspi-configが終わったら、必要なツールのインストールや設定は、ansibleとかchefとかでした方がいい。
**ほとんどの場合、セットアップ方法が記憶の彼方に消え去った頃に、またセットアップする日がくる**
FabricでTwitterのタイムラインを表示する

# FabricでTwitterのタイムラインを表示する

[[iOS]FabricでTwitterクライアントを作った](http://qiita.com/mokumoku/items/bf0460f420acac3c04fc)を参考にしたところ，
Fabricのバージョンが問題でコピペができなかったから，そこを修正してみる．

2015年9月4日現在，[TwitterKit Reference](https://docs.fabric.io/appledocs/Twitter/index.html)を元に修正．


# 基本的にはそのまま

`AppDelegate.swift`，`LoginViewController.swift`はそのまま使って問題がなかった．


# HomeTimelineを取得するためのクラス

基本的には[元のコード](http://qiita.com/mokumoku/items/bf0460f420acac3c04fc#hometimeline-%E3%82%92%E5%8F%96%E5%BE%97)．
ただ，微妙に仕様変更？のせいでエラーを吐いていたので修正．


```diff:TwitterAPI.swift

import Foundation
import TwitterKit

class TwitterAPI {
    let baseURL = "https://api.twitter.com"
    let version = "/1.1"

    init() {

    }

    class func getHomeTimeline(tweets: [TWTRTweet]->(), error: (NSError)->()) {
        let api = TwitterAPI()
        var clientError: NSError?
        let path = "/statuses/home_timeline.json"
+        let params = Dictionary<NSObject, AnyObject>()
        let endpoint = api.baseURL + api.version + path
// URLRequestWithMethodのparametersがnilを許容しなくなった + 返り値がNSURLRequestをアンラップしてくれない
-        let request = Twitter.sharedInstance().APIClient.URLRequestWithMethod("GET", URL: endpoint, parameters: nil, error: &clientError)
        let request: NSURLRequest! = Twitter.sharedInstance().APIClient.URLRequestWithMethod("GET", URL: endpoint, parameters: params, error: &clientError)
        if request != nil {
            Twitter.sharedInstance().APIClient.sendTwitterRequest(request) {(response, data, err) in
                if err == nil {
                    var jsonError: NSError?
-                    let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: &jsonError)
+                    let json: AnyObject? = NSJSONSerialization.JSONObjectWithData(data!, options: nil, error: &jsonError)
                    if let jsonArray = json as? NSArray {
-                        tweets(TWTRTweet.tweetsWithJSONArray(jsonArray) as [TWTRTweet])
+                        tweets(TWTRTweet.tweetsWithJSONArray(jsonArray as! [AnyObject]) as! [TWTRTweet])
                    }
                } else {
-                    error(err)
+                    error(err!)
                }
            }
        }
    }

}
```

# TimelineをTableViewで表示

基本的にはそのままで大丈夫．1箇所だけエラーを吐く場所があるから修正．
ただ，修正の仕方が正しいのかは微妙．とりあえず動くからいいかな的な感じです．


```diff:TimelineViewController.swift

func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
-        let tweet = tweets[indexPath.row]
+        let tweet = tweets[indexPath.row] as TWTRTweet!

        prototypeCell?.configureWithTweet(tweet)

-        if let height = prototypeCell?.calculatedHeightForWidth(self.view.bounds.width) {
+        let height = TWTRTweetTableViewCell.heightForTweet(tweet, width: self.view.bounds.width)
+        if !height.isNaN {
            return height
        } else {
            return tableView.estimatedRowHeight
        }
    }
```

いろいろな記事とかを読んでもどうもOptional型とDelegateがピンと来ない，，，
ユースケースがわからないのが決定打だなー．
どうにかしないと．
PostgreSQLで連続した3文字のアルファベットの一覧を作成する方法

```psql
SELECT
  string_agg(chr(num), '') OVER (ROWS BETWEEN 0 PRECEDING AND 2 FOLLOWING) 
FROM generate_series(65, 90) num
LIMIT 24;

 string_agg 
------------
 ABC
 BCD
 CDE
 DEF
 EFG
 FGH
 GHI
 HIJ
 IJK
 JKL
 KLM
 LMN
 MNO
 NOP
 OPQ
 PQR
 QRS
 RST
 STU
 TUV
 UVW
 VWX
 WXY
 XYZ
(24 rows)
```