OmniAICreator/Qiita-1.07M huggingface dataset:
Androidの新しい力、指紋認証をアプリで使う！

#来た。Android M。
2015年10月に、ついにAndroid Mがリリースされました。Android Mにはいくつかの機能追加が入っていますが、その中で私が注目しているのは指紋認証です。

本投稿を読んでいただくと、Androidアプリへの指紋認証の組み込み方がわかります。
また、指紋認証と暗号を使った[サンプルコード](https://github.com/ukiuni/FingerprintManagerInspect)もご用意しました。暗号を使うのは少しくせがあるため、この投稿を覚えておいていただく価値はあると考えます。

# Android MでAndroid標準APIになった指紋認証
これまでも指紋認証を端末独自にサポートするAndroidはありましたが、Android MからはAndroid標準APIで指紋認証がサポートされるようになりました。これで端末のロック解除だけでなく、アプリに指紋認証を取り込むことができます。早速使ってみます。

やることは２つ。AndroidManifest.xmlへの権限追加とFingerprintManagerの利用です。

# Androidで指紋認証
さて、早速ソースコードを見てみましょう。

```xml:AndroidManifest.xml(抜粋)
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
```
AndroidManifest.xmlで指紋認証を使うUSE_FINGERPRINTを宣言します。

```java:FingerAuthActivity.java(抜粋)
FingerprintManager fingerprintManager = (FingerprintManager) getSystemService(FINGERPRINT_SERVICE);
if (fingerprintManager.isHardwareDetected() || fingerprintManager.hasEnrolledFingerprints()) {//指紋を取るハードウェアがあり、かつ、指紋が登録されていることをチェック。
    fingerprintManager.authenticate(null, null, 0, new FingerprintManager.AuthenticationCallback() {
        @Override
        public void onAuthenticationError(int errorCode, CharSequence errString) {
            Log.e("", "error " + errorCode + " " + errString);
        }

        @Override
        public void onAuthenticationFailed() {
            Log.e("", "failed");
        }

        @Override
        public void onAuthenticationSucceeded(FingerprintManager.AuthenticationResult result) {
            Log.i("", "auth success";
        }
    }, new Handler());
}
```

Context#getService()　にFINGERPRINT_SERVICEを指定することでfingerprintManagerが得られるので、そこにコールバックオブジェクトであるFingerprintManager.AuthenticationCallbackを設定します。
認証が成功・失敗・エラーになるに応じてFingerprintManager.AuthenticationCallbackの各メソッドが１度だけ呼びだされます。

認証する指紋は予め端末に設定されていなければなりません。
上記コードを実行して端末に設定された指紋で指紋センサーに触ると、onAuthenticationSucceededが呼びだされます。
設定されていない指紋で指紋センサーに触るとonAuthenticationFailedが呼びだされます。

# FingerprintManager#authenticateの解説
FingerprintManager#authenticateをもう少し詳しく見てみましょう。
第１引数にはCryptoObjectを指定します。これはAndroidの鍵ストアに指紋認証を行わないと利用できない鍵を設定するためのものです。詳しくは後述します。
第２引数には指紋認証をキャンセルするためのオブジェクトを設定します。
第３引数には指紋認証のコールバックオブジェクトを指定します。
第４引数は0じゃなきゃダメだそうです。
第５引数に、第３引数のコールバック時に利用されるハンドラを渡します。スレッドのコンテキストとでも言えばいいでしょうか。UIスレッドのハンドラを渡すことが多いです。

この中で重要なのが第一引数のCriptObjectです。
認証しないと利用できない鍵を設定することができ、この鍵を利用するための暗号機が、指紋認証成功時に得られるAuthenticationResultからgetCryptoObject取得することができます。これで指紋認証と署名用などの鍵情報を紐付けることができます。
この仕組を使うことで、例えば、鍵をサーバと端末で共有し、認証時にサーバからの求めに応じて端末で鍵を使って暗号化処理を行います。サーバは暗号化されたデータが共有された鍵を使ったものと一致するかを確認することで、端末で指紋認証が行われたことを確認することができます。
つまり、サーバへのログインに、パスワードの代わりにAndroidの指紋認証が使えるというわけですね。
暗号鍵を用いた指紋認証のコードは[こちら](https://github.com/ukiuni/FingerprintManagerInspect)にサンプルを置いておきました。ご覧ください。

Androidの標準APIで指紋認証が使えるようになったことで、ますます指紋認証の利用用途が広まっていくことが期待できます。
Android端末には複数の指紋が登録できるのですが、現段階では、どの指紋で認証されたかは得られないようです。どの指紋で認証されたかがわかるようになり、複数人の指紋を登録しておいて個人特定に使える用になると、更に楽しそうですね。今後に期待です。
[Java] Zipファイル内の日本語ファイル名


# 目的

Zipファイルは作られた環境によって日本語ファイル名の表現方法が異なるので整理する。
（主に、Javaでの扱い方）

# 環境ごとの違い

Zipファイルの日本語ファイル名は、一般的に以下のような文字コードで記載されている。

- Windows : MS932 
- Linux : UTF-8(NFC)
- Mac : UTF-8(NFD;一部独自)

# 文字コード

Java7 からは、java.util.zip.ZipFile で扱う際に文字コードを指定することができるようになった。
(Java6まではUTF-8固定だったので別のライブラリが必要だった。たとえばantとかcommonsとか)

```java
ZipFile zipFile = new ZipFile(file, charset);
```

ただし、MS932とUTF-8のどちらで開けば良いか事前に判断することは難しい。

# Unicode 正規化

NFC や NFD というのは、Unicodeの正規化方法の違いのこと。
ウムラウト記号や、濁点・半濁点をどのように表現するかが異なる。

- NFC : 合成した1文字で表す（例：「ガ」を１文字で表す）
- NFD : 結合文字で表す（例：「ガ」を「カ」＋「結合文字の濁点」で表す）

参考： [wikipedia:Unicode正規化](https://ja.wikipedia.org/wiki/Unicode%E6%AD%A3%E8%A6%8F%E5%8C%96)

ちなみに結合文字の濁点(U+3099)と、単独の濁点(U+309b)は別のコードポイントになっている。
半濁点も同様。

```java
int[] codePoints = { 0x3099, 0x309a, 0x309b, 0x309c };

for (int codePoint : codePoints) {
    System.out.printf("U+%04x : %s\n", codePoint, Character.getName(codePoint));
}
```

```
U+3099 : COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
U+309a : COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
U+309b : KATAKANA-HIRAGANA VOICED SOUND MARK
U+309c : KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
```

NFC/NFDの変換は、java.text.Noralizer#normalize(CharSequence, Form)でできます。

```java
/** NFDをNFCに変換 */
public String toNfc(String nfd) {
    return Normalizer.normalize(nfd, Normalizer.Form.NFC);
}
```

Javaからファイルを作る場合には、Mac環境であってもNFCで指定することができる（自動でNFDに変換して処理してくれる）。

逆にWindows上にNFDでファイルを作ると、見た目はNFCとほとんど同じだが別のファイルができてしまうので、注意が必要。

```java
String nfcName = "がぎぐげご.txt";
// NFDに変換
String nfdName = Normalizer.normalize(nfcName, Normalizer.Form.NFD);

new File(nfcName).createNewFile(); // -> true
new File(nfdName).createNewFile(); // -> true (Windowsの場合)
```

そのため特別な理由がなければ、 UTF-8 の ZipEntry 名については NFC に変換してから使うほうが良いと思われる。
Appcelerator CLIで [Error: Module did not self-register.] と出るようになった

今までTitaniumアプリの開発にはNode.js v0.10系を使っていたのですが、ふと [Titanium Compatibility Matrix](https://docs.appcelerator.com/platform/latest/#!/guide/Titanium_Compatibility_Matrix-section-29004837_TitaniumCompatibilityMatrix-Node.js) を見たら、MAXバージョンがv0.12.7になっていました。（さらにさっき見たら、さらにv4.1.xになっていました）

そこで、さっそくv0.12.7を入れて使ってみようとしたところ、 `appc` コマンドを叩くたびに `[Error: Module did not self-register.]` というメッセージが出力されるようになってしまいました。

[Issueはあがっている](https://jira.appcelerator.org/browse/CLI-827) ので、いずれAppcelerator CLI側で何かしら対策をしてくれると思いますが、現時点での対策方法があったので、メモっておきます。

※上記IssueにはNode.js v0.12.7とAppc CLI v5.0.2の組み合わせとのことでしたが、私の環境ではAppc CLI v5.0.1やv5.0.3でも発生したので、v0.10系からv0.12系に移行した場合に発生しやすいのではないかと思っています。


環境および発生手順
------------------

| 環境 | バージョン |
|---|---|
| OS | Mac OS X 10.10.5 |
| Xcode | 6.4 |
| Command Line Tools | 7.0 |
| Node | v0.10.40 → v0.12.7 |
| Appcelerator CLI (npm) | 4.2.0 |

さらに、Node.jsのバージョン管理には [ndenv](https://github.com/riywo/ndenv) を使っています。

もともとndenvでv0.10.40を入れて使っていた環境にv0.12.7を追加し、そこに改めてAppcelerator CLIをはじめ、必要なnpmパッケージをインストールして使ってみたところ、今回の問題が発生しました。


対処方法
--------

原因は、Node.jsのバージョンが切り替えた際に、ネイティブ拡張を含むnpmパッケージが壊れてしまうことにあるようです。

そこで、このエラーが発生するAppcelerator CLI Coreの *package* フォルダへ移動し、 `npm rebuild` を実行して、環境を再構築することで、修復することができました。

バージョン部分は、適宜使っている環境に合わせて読み替えてください。

```
$ cd ~/.appcelerator/install/5.0.2/package
$ npm rebuild
```

使用するNode.jsのバージョンを切り替えると、またエラーが発生するので、そのときは再度同じ手順を実行すればOKのようです。

また、実行時に `bufferutil` 関連のエラーで失敗する場合は、以下の記事も参考にしてみてください。

[Appcelerator CLI Coreのインストールでbufferutilのビルドがエラーになる - Qiita](http://qiita.com/umi_uyura/items/02e7e65f55f385a85a2c)


### 2016/04/08 追記

[Understanding the Unified Appcelerator CLI](http://www.appcelerator.com/blog/2016/03/understanding-the-unified-appcelerator-cli/)

この問題は、やはりndenvなどNode.jsのバージョンを切り替えるツールを使った場合に発生するものということで、Appcelerator CLI v4.2.2で対策され、自動的に修正するようになったようです。

もしそれでも同じ現象が発生する場合は、 `appc use 5.2.0 --force` というように　`--force` フラグを付けて実行することで、指定したバージョンを強制的に再インストールすれば良いようです。



参考
----

* [[CLI-827] Only CLI 5.0.2 & NodeJS 0.12.7 give: [Error: Module did not self-register.] - Appcelerator JIRA](https://jira.appcelerator.org/browse/CLI-827)
* [[CLI-836] Packages should be rebuild if NodeJS version has changed since last use - Appcelerator JIRA](https://jira.appcelerator.org/browse/CLI-836)
ブラウザのタブを閉じた時に BrowserSync を終了させる

<!--
title: ブラウザのタブを閉じた時に BrowserSync を終了させる
tags: Node.js BrowserSync
-->

BrowserSync を `open:true` で使っているとき、開いたブラウザのタブを閉じたら BrowserSync にも終了してほしいことがあります。

----

クライアントが `disconnect` したときに接続されているクライアントの数を調べて、ゼロならプロセスを終了します。

ただし、`disconnect` の後の即時だとリロードで閉じてしまうので、2秒のディレイをかけています。

```js
var util = require("util");
var bs = require("browser-sync").create();

bs.init({
    logLevel: "debug",
    files: ["web/*.html"],
    server: "./web",
    open: true,
    port: 16845,
    online: false,
    ui: false
}, function () {
    var logger = bs.instance.getLogger("autoexit");
    var sockets = bs.instance.io.sockets;
    var timer = null;

    sockets.on("connection", function(socket){
        logger.info(util.format("Socket connection (%s clients)", socket.client.conn.server.clientsCount));

        socket.on('disconnect', function () {
            logger.info(util.format("Socket disconnect (%s clients)", socket.client.conn.server.clientsCount));

            clearTimeout(timer);
            timer = setTimeout(function(){
                logger.info(util.format("Delay timeout (%s clients)", socket.client.conn.server.clientsCount));
                if (socket.client.conn.server.clientsCount == 0) {
                    logger.info("Exit process");
                    process.exit();
                }
            }, 2000);
        });
    });
});
```

----

次のようなモジュールを作成し、

*bs-autoexit.js*

```js
var util = require("util");

function plugin(opts, bs)
{
    var logger = bs.getLogger("autoexit");
    var sockets = bs.io.sockets;
    var timer = null;

    sockets.on("connection", function(socket){
        logger.info(util.format("Socket connection (%s clients)", socket.client.conn.server.clientsCount));

        socket.on('disconnect', function () {
            logger.info(util.format("Socket disconnect (%s clients)", socket.client.conn.server.clientsCount));

            clearTimeout(timer);
            timer = setTimeout(function(){
                logger.info(util.format("Delay timeout (%s clients)", socket.client.conn.server.clientsCount));
                if (socket.client.conn.server.clientsCount == 0) {
                    logger.info("Exit process");
                    process.exit();
                }
            }, 2000);
        });
    });
}

module.exports = {
    plugin: plugin
}
```

次のように use で使用することも可能です。

```js
var bs = require("browser-sync").create();
bs.use(require("./bs-autoexit"));
bs.init({
    logLevel: "debug",
    files: ["web/*.html"],
    server: "./web",
    open: true,
    port: 16845,
    online: false,
    ui: false
});
```

----

ブラウザを連続でリロードしまくると接続数がどんどん増えていって、タブを閉じても BrowserSync が死ななくなる・・・
Browsersync の起動を早くする

<!--
title: BrowserSync の起動を早くする
tags: BrowserSync
-->

BrowserSync の起動が遅くてイライラが半端無かったので、debug ログを表示してみたところ下記の3箇所で詰まっていました。

```
[BS] [debug] -> Starting Step: Finding an empty port
[BS] [debug] Found a free port: 3000
[BS] [debug] Setting Option: port - 3000
[BS] [debug] +  Step Complete: Finding an empty port
```

```
[BS] [debug] -> Starting Step: Checking online status
[BS] [debug] Resolved www.google.com, setting online: true
[BS] [debug] Setting Option: online - true
[BS] [debug] +  Step Complete: Checking online status
```

```
[BS] [UI] Starting Step: Finding a free port
[BS] [UI] Step Complete: Finding a free port
```

----

`[BS] [debug] -> Starting Step: Finding an empty port` は BrowserSync のサーバのための空きポートを探しています。

`port:8080` のようにポートを指定すれば消えるかと思ったのですが、消えませんでした。`port` の設定は使用するポートを固定するわけではなく、空きポートの検出をどこから行なうかの設定のようです。指定したポートが使用されているとその次のポート（例えば `8081`）がチェックされます。

とりあえず、なるべく空いてそうなポートを指定するのが良さそうです。

----

`[BS] [debug] -> Starting Step: Checking online status` はホストがオンラインかどうかを調べています。

`xio` や `tunnel` を使わないなら `online:false` で良いです。

----

`[BS] [UI] Starting Step: Finding a free port` は BrowserSync の UI のための空きポートを探しています。

UI が必要ないなら `ui:false` で良いです。

----

```js
var bs = require("browser-sync").create();
bs.init({
    logLevel: "debug",
    files: ["web/*.html"],
    server: "./web",
    open: true,
    port: 16845,
    online: false,
    ui: false
});
```
Groongaで学ぶ全文検索 2015-10-23


# 転置インデックスで日本語を検索する際の仕組み

## 転置インデックスとは
速く全文検索するための仕組み
文書全体を頭から検索していると時間がかかるため
事前にインデックスを作成して高速に検索できるようにする。

今回の例はネット上にある文書を全文検索の対象とする。
大まかな流れは以下のようになる

```
検索キーワードをパース→転置インデックスから文書を検索→文書を返す
```

##転置インデックスの作り方

文書に含まれる文字列をキー、キーが含まれる文書を登録したインデックスを作成する。
インデックス作成時のキーの分け方に形態素解析やN-gramがある

インデックスのイメージ

| キー| 文書 |
|:-----------|------------:|
| こんにちは  |       http://A,http://B|
| 全文     |      http://A,http://B |
| 検索     |      http://A |
| したい     |      http://A |


### 形態素解析とは
日本語を辞書を用いて良い感じにを分ける仕組み

```例
全文検索したい！
→全文　検索　したい　！
```

### N-gram
N文字ごとに文字列を区切る仕組み

1文字ごとに区切る：ユニグラム
2文字ごとに区切る：バイグラム
3文字ごとに区切る：トリグラム

```例
こんにちは

こん
んに
にち
など
```


* 形態素解析早いが漏れがある
* N-gramは遅いが漏れが無い

```例
京都を探したい時
東京都が出てほしくない：形態素解析使う
出て欲しい：N-gramを使う
```

 キワードをパースする際と転置インデックスを作成するときに同じロジックでを分ける必要がある、ロジックが違うと正しい物がヒットしなくなってしまう。

```例
「全文検索」をキーにしてインデックスを作成してもキーワードをパースする際に「全文」で分けてしまうと対象の文書を返却できない。
```

## その他メモ
* GroongaはMeCabも利用できる
* Groongaにはパトリシアトライというツリー構造にして絞込を行える仕組みもある。
→オートコンプリート機能などで
「と」を入力した際に「東京」を候補として出すような場合に使える。
* MySQL5.7日本語対応しているがバイグラムなので1文字を検索できない。
* Mroongaはパトリシアトライを利用して1文字検索も可能
* MariaDBにはデフォルトでMroongaがインストールされている

* 転置インデックスには要素が増えても検索スピードが落ちない仕組みがある。

```例
1.0〜9の配列を用意
2.キーをハッシュ化した数値を取得
3.数値を10で割ったあまりの配列にデータを格納
4.アクセスする際には2.,3.で取得した値をキーに格納されているデータから対象のデータを検索する

上記によって用意する配列の数を増やせば、各配列に格納されているデータの量が減るため高速に検索できる。
```

* 辞書を変えると転置インデックスを作る時もキーワードをパースする際も更新が必要だが更新作業は大変
→新しいキーワードを追加する場合などに更新作業が発生する。
→対応策として事前に切り替え用のインデックスを作成しておいてから切り替える事でダウンタイムを最小限に抑えられる。
CPUやディスクなどのリソースに余裕がある場合に実施できる。

* 日本語の場合、複数のキーワードで検索することも多く、検索の際に検索したキーワードは同じ文書にあって、隣り合っていなければならない。隣り合っている事を確認するための方法が完全転置インデックスとそれ以外の場合の２種類がある。

#### 完全転置インデックス
転置インデックスはキーと存在する文書を格納したもの

* キー、対象のURL、文書の中の位置を保存し
差が1だったら隣り合っているものと判定し検索結果を返す
* 下記のような例だと「全文」「検索」で検索した場合
*
「検索」の位置と「全文」の位置の差分が1(3-2=1)になっているので
http://Aがマッチした文書として返却される


| キー | 文書 | 位置 |
|:-----------|------------:|:------------:|
| こんにちは  |       http://A|     1     |
| 全文     |      http://A |    2    |
| 検索     |      http://A |    3    |
| したい     |      http://A |    4    |


#### 完全ではない転置インデックス

* 位置を保存しないで、対象の文書だけをしぼりこみその文書の中身を検索する
* PostgreSQLなどで採用されている。
入れる情報が少なくなるのでメモリ上に載りやすくなり、少ないリソースでも動きやすくなるが検索時に遅くなりがち

* タグ検索など位置情報が必要ないものにも使える
Swift エラー関連

#Swiftエラー一覧

```
forced cast of "it" to same type has no effect 

//Castされるitは同じ型でなんら効果がないよという警告
cast = データ型の変換を意味していている。

単純にBaseClassで設定していない型はCastしない、で解決。
```



```
frame for view will be different at run time

//アプリケーションの起動時に異なったViewになるよという警告。

解決したところ
http://discuss.codewithchris.com/t/frame-will-different-at-run-time/482/2
```

```
Main.storyboard: warning: Unsupported Configuration: Scene is unreachable due to lack of entry points and does not have an identifier for runtime access via -

適切にアクセスするための識別子がないですよ.
とのことなので、StroyboardIDに任意の文字列を入力すれば改善できます。
大抵は、新しく作ったControllerよりも前のControllerに識別子設定をすれば改善されます。
改善されなければ全てに適応させれば良いだけです。

参考URL
http://stackoverflow.com/questions/9746431/how-do-i-workaround-this-new-warning-in-xcode-4-3-1-scene-is-unreachable-due-t
```
.NETにおけるタプル

昨年はSwift、今年はElixirをつまみ食いしていますが、
これら２つの言語で「タプル」という概念を新しく学びました。

#タプルとは
[Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%83%97%E3%83%AB)

要は、値の組を作って関数の引数や戻り値に使えますよ、と理解しています。

使用を検討する状況としては、関数の戻り値として複数の値を返したいけど、
わざわざ戻り値用の構造体を作るのはちょっと手間だなーというときに、さくっと使えます。

#.NETにもタプル
ところで普段の業務ではVB.NETを使っているのですが、
実は.NET Framework 4.0からタプルが導入されていました。
（新しい言語を学ぶと、今使っているもので新たな発見があるのが嬉しいです。）

[Tuple クラス](https://msdn.microsoft.com/ja-jp/library/system.tuple(v=vs.110).aspx)

#使い方

例）エラーチェックを行う。エラーの場合、エラー理由も返す

```lang:VB.NET
Public Sub Main(args)
    Dim txt As String = "cccc"

    Dim result = ValidText(txt)

    '結果が不正の場合、エラーメッセージを表示する。
    If result.Item1 = False Then
        MsgBox(result.Item2)
    End If
	
End Sub

'文字列のチェック処理。戻り値.Item1がFalseであれば、不正。
Public Function ValidText(txt As String) As Tuple(Of Boolean, String)
    If String.IsNullOrEmpty(txt) Then
        Return Tuple.Create(False, "空文字です。")
    End If

    If Not txt.StartsWith("a") Then
        Return Tuple.Create(False, "aから始まっていません。")
    End If

    Return Tuple.Create(True, String.Empty)
End Function
```


#所感
複数戻り値を返したいケースはたまーにあるので、さっとできるのは便利だけれども、
タプルの各要素へのアクセス方法がItem1、Item2..という感じで
それが何を示しているのかソースコード上のその部分から読み取れない。
（読み解くにはタプルを作っている場所で何をしているか知る必要がある。）
Swiftみたいに[ラベルを付けられたり](http://qiita.com/keiskimu/items/3090a6c0a74bdfd285f9#%E5%80%A4%E3%81%AB%E5%90%8D%E5%89%8D%E3%82%92%E3%81%A4%E3%81%91%E3%81%A6%E5%AE%A3%E8%A8%80)、Elixirの[キーワードリスト](http://qiita.com/taku_oka/items/185bdecbc87f6a9c6f07#%E3%82%AD%E3%83%BC%E3%83%AF%E3%83%BC%E3%83%89%E3%83%AA%E3%82%B9%E3%83%88-hoge-foo-)みたいにできればいいのになーと思う
（キーワードリストに対し、ディクショナリの配列を返すようにするのはちょっとなぁ...と思う）
Railsで続きを読む、的な機能の実装メモ

 
よくブログとかで見かける「〜...」
のような本文が省略されたような表現をRuby On Railsで
自力に実装する際のメモ。

truncateメソッドが良さそう。


```ruby
# 5文字まで表示
truncate("今日は職場で飲み会がありました。", :length => 5)
```
accepts_nested_attributes_for で ["can't be blank"] と言われたら

**`inverse_of`で解決できる**
いや **(追記)rejet_ifの可能性の方が大きいかも**
[Rails - accepts_nested_attributes_for を使った入れ子のformが罠だらけな気がする - Qiita](http://qiita.com/shingo-nakanishi/items/229ae20bc1ddf7192dfb)

## 参考URLとその重要部分を引用する<br />（最も重要である回答のソースはSOを見てもらえばよいと思うので引用しない）
[ruby on rails - Trouble with accepts_nested_attributes_for on validating foreign key - Stack Overflow](http://stackoverflow.com/questions/13344059/trouble-with-accepts-nested-attributes-for-on-validating-foreign-key/16793929#16793929)

[<Child's Parent> can't be blank while using accepts_nested_attributes_for (Rails 4) - Stack Overflow](http://stackoverflow.com/questions/23463912/childs-parent-cant-be-blank-while-using-accepts-nested-attributes-for-rails/23467124#23467124)

> Try removing contact_id to test if it will accept or not. If it does accept, it means you're not passing the contact_id through your params to the model

[accepts_nested_attributes_for with Has-Many-Through Relations](https://robots.thoughtbot.com/accepts-nested-attributes-for-with-has-many-through)

> It seemed Rails was not setting the notice attribute on the EntityRole before attempting to save it, triggering the validation errors. This is a bit surprising as other has_many relations (omitted in this blog post) should have the same save mechanics and were working just fine.

<br />
> When you use collection= assignment with a has-many-through (as accepts_nested_attributes_for does), you have to specify inverse_of for Rails to save everything correctly.
[Android][Lollipop]マナーモード設定を取得する

（注意）現在Android 6.0 Marshmallowでの動作は確認できていません。
手元のNexus 5(MRA58K)で確認したところSettingNotFoundException(API23より追加)が出るため、塞がれている可能性が高いです。

# Lollipopで追加されたマナーモード設定を参照する

Lollipop以前ではマナーモードはVolumeオフでしかありませんでしたが、Lollipopになってマナーモードという、通知やAlarmをスリープさせるモードが追加されました。

そのモード中はアラームも鳴らないため(AlarmManagerがサスペンドされる？)、アラーム系のアプリや通知系のアプリでは設定を検知した時注意したいかもしれません。
そこで調べてみました。

# 取得方法

設定値は通常のSystem設定のProviderで公開されているため、特別な権限は必要ありません。

```java

int mode = Settings.Global.getInt(getContext().getContentResolver(),
                        "zen_mode");
```

"zen_mode"というフィールド名はSettings.Globalの中に@hideで定義されています。
Android 5.1以降で追加されています。

```java:Settings.java
        /**
         * Defines global zen mode.  ZEN_MODE_OFF, ZEN_MODE_IMPORTANT_INTERRUPTIONS,
         * or ZEN_MODE_NO_INTERRUPTIONS.
         *
         * @hide
         */
        public static final String ZEN_MODE = "zen_mode";

        /** @hide */ public static final int ZEN_MODE_OFF = 0;
        /** @hide */ public static final int ZEN_MODE_IMPORTANT_INTERRUPTIONS = 1;
        /** @hide */ public static final int ZEN_MODE_NO_INTERRUPTIONS = 2;
```

それぞれなんとなくわかりますが、通知領域に表示されている、すべて・重要・マナーモードに当てはまります。

他にもzenmodeの維持する時間を設定するzen_mode_config_etagもあります。

```java:Settings.java
        /**
         * Opaque value, changes when persisted zen mode configuration changes.
         *
         * @hide
         */
        public static final String ZEN_MODE_CONFIG_ETAG = "zen_mode_config_etag";
```

# 変更方法

変更も同様の方法で可能ですが、実行には `android.permission.WRITE_SECURE_SETTINGS` が要求されます。
そのため、自分でAndroidをBuildしたり、rootを取得して権限を適切に取得しない限りは使えません。

```java

boolean result = Settings.Global.putInt(getContext().getContentResolver(),
                        "zen_mode", (Integer) value);
```
Linux(CentOS7)でWebサーバーを構築する。 -php導入編-

# 概要
前回の[-Apache導入編-](http://qiita.com/sango/items/b045a1da17606eda6f82)に引き続き、今回はphpを使えるようにする方法を綴ります。

と言ったものの、今回も導入は1行で終わってしまいます。 (>ω<)b

# 導入するもの
- php

# 手順
## 1. phpの導入

`# yum -y install php`
これだけ。

とっても簡単ね！

## 2. 動作確認
### 下準備
`$ cd /var/www/html/`
ドキュメントルートに移動して、
`$ vim tekito.php`
適当なファイル名で.phpを作るん。

```php.tekito
<?php
    phpinfo();
?>
```
こんな感じに編集して、保存&終了！
`:wq`

一応補足すると、
`<?php` は、「ここからphpの文章が始まりますよ、という合図」
`phpinfo();` は、「インストールされているphpの情報を表示する関数」
`?>` は、「phpの文章はここまで！」
って感じです。
### 実行
ブラウザから先ほど作った.phpにアクセスしてみよう！

`http://???.???.???.???/tekito.php`

![phpinfo.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/97611/dd8b9b45-4a5a-04c9-8e03-7f5ee9e32c77.png)
↑みたいな表が表示されたら成功！

`<?php phpinfo(); ?>` っていう文章がそのまま表示されちゃったら失敗…。


## 0. トラブルシューティング
手順2で躓いてしまった場合はここを読んでみてね。

`<?php phpinfo(); ?>` がそのまま表示されてしまう場合、

- phpが正しくインストールされていない
- httpdが正常に動作していない

等が考えられます。

### phpのインストール状態確認
phpがインストールされているか否かは以下のコマンドで確認できるよ！
`# yum list installed | grep php`

実行結果の中に、

- php
- php-cli
- php-common

があるか確認してね。

なければ、手順1で失敗しているかも…。

### httpdの動作状態確認
httpdが正常に動作しているか否かは以下のコマンドで確認できるよ！
`# systemctl status httpd.service`

実行結果の中に赤字のメッセージがある場合、httpdで何かしらのエラーが起きているかも…。
下記コマンドでhttpdを再起動してみよう。
`# systemctl restart httpd.service`

statusから赤字は消えたかな？


## 3. php.iniについて
### php.iniとは
phpの挙動を設定するファイルだよ！(ざっくり)

`vim /etc/php.ini`

### 軽い解説
よく使いそうな項目について触れておきます。
(本当はもっといっぱいあるけど…！)
<table><tr><th style="text-align:center;">項目名</th><th style="text-align:center;">概要</th></tr><tr><td>post_max_size</td><td>POSTで転送できる最大データサイズ</td></tr><tr><td>memory_limit</td><td>php処理中にphoが確保しても良いメモリサイズ<br>制限しない場合は -1 を指定<br>※指定する場合post_max_sizeより大きい値にする(POSTデータもメモリ確保を行う為)</td></tr><tr><td>upload_max_filesize</td><td>転送可能なファイル最大サイズ(1ファイルあたり)</td></tr><tr><td>max_file_uploads</td><td>同時に転送可能なファイルの数</td></tr><tr><td>default_socket_timeout</td><td>ページ読み込み処理にこの値以上の時間が掛かってしまった場合は処理を中断(単位:秒)<br>いわゆる(?)タイムアウト</td></tr></table>
※うまく説明できた気がしない…。_ (:3」∠) _ <3
### 参考
[コア php.ini ディレクティブに関する説明](http://php.net/manual/ja/ini.core.php)


# 変更履歴
2015/10/29 : php.iniのパスを追記
nginxを利用する際に何度も確認するコマンド

環境
さくらのVPS 2GB
> Architecture:          x86_64
CPU op-mode(s):        32-bit, 64-bit
Byte Order:            Little Endian
CPU(s):                3
On-line CPU(s) list:   0-2
コアあたりのスレッド数:1
ソケットあたりのコア数:1
Socket(s):             3
NUMAノード:         1
ベンダーID:        GenuineIntel
CPUファミリー:    6
モデル:             45
ステッピング:    7
CPU MHz:               2499.998
BogoMIPS:              4999.99
ハイパーバイザーベンダー:KVM
仮想化タイプ:    完全仮想化
L1d キャッシュ:   32K
L1i キャッシュ:   32K
L2 キャッシュ:    4096K
NUMA node0 CPU(s):     0-2





# nginx設定ファイルの確認

nginx メインの設定ファイル nginx.conf
`cd /etc/nginx/`

その他設定ファイル
`cd /etc/nginx/conf.d/`


#nginx再起動
`sudo nginx -s reload`
動的な表示切り替えを可能とするVue.jsの使い方

## はじめに
前回、Vue.jsの基礎について記事を書きましたが、もう少し踏み込んだ動的な表示切り替えをする使い方をまとめました。
（今後も追加していくかも？）

[前回記事：軽量・シンプルな思想でデータバインディングができるVue.jsの基礎まとめ](http://qiita.com/kyota/items/0b41952c8abcd37e0aef)

### 追記（2016年12月1日）
この記事は公式日本語ドキュメントが無い時代に書いた記事です。
[公式の日本語ドキュメントができたので、今後はこちらをご覧ください。](https://jp.vuejs.org/)

## 要素の生成を分岐する`v-if`
値がtrueなら、DOMが生成されます。逆にfalseなら生成されない。

### 例

#### HTML

```html
<div id="vue">
    <div v-if="val">
	   ...
    </div>
</div>
```

変数だけじゃなくて、以下のように式も入れられます。

```html
<div id="vue">
    <div v-if="val + hoge || fuga">
	   ...
    </div>
</div>
```

#### JavaScript
```JavaScript
var vue = new Vue({
    el: '#vue',
    data:{
        val: false
    }
});
```

変数valを動的にtrue or falseを入れて、画面全体や一部エリアの表示を切り替えたりなどに使用。

## アニメーションさせる`v-transition`
バインドタイミングでアニメーションをつけられます。
アニメーション処理は、CSSを使用。

### 例
#### HTML
`v-transition="anime"`をつけます。
`anime`部分は任意文字。

```html
<div id="vue">
    <div transition="anime">hello</div>
</div>
```

#### CSS
HTMLの属性値が、`***-enter`, `***-leave`というクラス名の`***`部分に付与されます。
今回の場合は`anime`。

`***-enter`はバインドされた時、`***-leave`はバインドが外れた時（false時）にクラス名が付与されアニメーションされます。

```css
.anime-enter {
    animation: anime-in 1s ease-in;
}
.anime-leave {
    animation: anime-out 1s ease-out;
}
@keyframes anime-in {
    0% {
        transform: scale(0);
    }
    100% {
        transform: scale(1);
    }
}
@keyframes anime-out {
    0% {
        transform: scale(1);
    }
    100% {
        transform: scale(0);
    }
}
```

### おまけ
`stagger="100"`属性をつけると、複数要素にアニメーションつけた場合、間隔時間を調整できます。
値は変更可能。（1000 = 1秒）

例えば、データに合わせて数字やボックスを、順番にフェードインなどといったことが可能になります。

```html
<div id="vue">
    <div transition="anime" `stagger="100"`>hello</div>
</div>
```
iPhone 6s Plus Simulator iOS9.1 で iTunes Store の URL を踏むと invalid だと怒られる

# こうなりました

![スクリーンショット 2015-10-23 19.08.57.png](https://qiita-image-store.s3.amazonaws.com/0/30241/3b304f30-743d-5f5f-35b7-0e34cd3e3a15.png)

# 解説

シミュレータに入れた自作したアプリから `https://itunes.apple.com/app/apple-store/id〜` 遷移すると開けませんと表示される
（これは昔からこの挙動だったのかは知らないので誰か教えて下さい）
実機だと問題なく動きます
シミュレータに入ってる Safari が実機とはことなるものなんだろう

あと `http://〜` が開けなかったのは ATS とかの問題かな

# 感想

iPhone アプリ開発どんどん複雑化してしまってダメな気がする
昔のお手軽感はどこへ消えてしまったのだろうか（お手軽ではなかったが）
Change MySQL password policy level

**MySQL version: 5.7.9**

For development, using a MySQL server with strong password policy is dosing some matter.

If you set a simply password for someone, you will got an error like this:

```
ERROR 1819 (HY000): Your password does not satisfy the current policy requirements

```

To change the default password plugin level, we can change the settings at runtime or in config file.

```
mysql> SHOW VARIABLES LIKE 'validate_password%';
+--------------------------------------+--------+
| Variable_name                        | Value  |
+--------------------------------------+--------+
| validate_password_dictionary_file    |        |
| validate_password_length             | 8      |
| validate_password_mixed_case_count   | 1      |
| validate_password_number_count       | 1      |
| validate_password_policy             | MEDIUM |
| validate_password_special_char_count | 1      |
+--------------------------------------+--------+
6 rows in set (0.01 sec)

```

The default level is `MEDIUM`, we can change it to `LOW`, which will only check the password's length(min: 8 chars).

```

mysql> SET GLOBAL validate_password_policy=LOW;
Query OK, 0 rows affected (0.00 sec)


```


Or we can set it in `my.cnf` file

```
[mysqld]
validate_password_policy=LOW
```

Reference:

[6.1.2.5 The Password Validation Plugin](http://dev.mysql.com/doc/refman/5.7/en/validate-password-plugin.html)
起動している EC2 インスタンスの Name タグと PublicIpAddress から ssh の config を作るワンライナー

<!--
# [aws][aws-cli]起動している EC2 インスタンスの Name タグと PublicIpAddress から ssh の config を作るワンライナー
-->

```sh
aws ec2 describe-instances \
  --filters Name=instance-state-name,Values=running |
  jq -r '.Reservations[].Instances[] | .PublicIpAddress as $addr |
    .Tags[] | select(.Key=="Name").Value |
    "Host " + . + "\n    User centos\n    Hostname " + $addr' | tee ssh_config
```

こんな感じに作られます。

```
Host sv03
    User centos
    Hostname 54.1.2.3
Host sv02
    User centos
    Hostname 54.4.5.6
Host sv01
    User centos
    Hostname 54.7.8.9
```

最終行で出力内容を決めているので、次のようにすれば Ansible のインベントリファイルの形式も可能。

```sh
aws ec2 describe-instances \
  --filters Name=instance-state-name,Values=running |
  jq -r '.Reservations[].Instances[] | .PublicIpAddress as $addr |
    .Tags[] | select(.Key=="Name").Value |
    . + " ansible_ssh_host=" + $addr'
```

パイプで `while read addr name` に流すようにすればわかりやすいかもしれない。

```sh
aws ec2 describe-instances \
  --filters Name=instance-state-name,Values=running |
  jq -r '.Reservations[].Instances[] | .PublicIpAddress as $addr |
    .Tags[] | select(.Key=="Name").Value |
    . + " " + $addr' |
  while read addr name; do
  cat <<EOS
Host $name
    User centos
    Hostname $addr
EOS
  done
```
[Elixir] PhoenixでPlugの自作

# やりたいこと

Plugはとても便利。特にNode.jsからやってきた自分にとっては、Plug = Middlewareということで非常にとっつきやすい。こいつを使いこなすことで幸せになれるんじゃないかと本能的に感じた。

[（公式）Plug Guide](http://www.phoenixframework.org/docs/understanding-plug)

RackやConnectを触っていた人にはすぐとっつける内容だと思うが、今回は違ったバックグラウンドの方でもわかるように書く。

## Plugって何？

HTTP Request/Responseをまとめた"connection"をリレーする、プラグインのスタック。

## Phoenixが提供するPlug

Phoenix.Contoller配下にpluggableな実装がまとめられている。

[（公式）Phoenix.Controller](http://hexdocs.pm/phoenix/Phoenix.Controller.html)

必要なものは一通り揃っている印象。

## 今回作ってみるPlug

APIリクエストの送信元が、localhostか、ローカルネットワーク内からのものか、グローバルからのものかを判断し、必要なアクセス制限を加える、allow_accessというPlugを作ってみる。

# 実装

Plug本体は以下のような実装。

```web/plugs/allow_access.ex
defmodule Demo.Plug.AllowAccess do
  import Plug.Conn

  def init(default), do: default

  def call(conn, params) do
    case conn.peer do
      {{127, 0, 0, 1}, _} ->
        conn
      {{192, 168, _, _}, _} ->
        if params == [:localhost] do
          send400 conn
        else
          conn
        end
      _ ->
        if params == [:localhost] or params == [:internal] do
          send400 conn
        else
          conn
        end
    end
  end

  defp send400(conn) do
    conn
    |> put_resp_content_type("text/plain")
    |> send_resp(400, "Bad Request")
  end
end
```

init/1でPlugそのものへの初期化を行う。当然これは一回しか呼ばれない。今回は特に何も行わない。

call/2で実際の処理を行う。
paramsには`:localhost`、`:internal`、`:all`の3種類が渡される想定。

これを実際に利用するRouterは以下の様な感じ。

```web/router.ex
defmodule Demo.Router do
  use Demo.Web, :router

  pipeline :browser do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug Demo.Plug.AllowAccess, [:all]
  end

  pipeline :admin do
    plug :accepts, ["html"]
    plug :fetch_session
    plug :fetch_flash
    plug :protect_from_forgery
    plug :put_secure_browser_headers
    plug Demo.Plug.AllowAccess, [:internal]
  end

  pipeline :api do
    plug :accepts, ["json"]
    plug Demo.Plug.AllowAccess, [:all]
  end

  pipeline :api_restricted do
    plug :accepts, ["json"]
    plug Demo.Plug.AllowAccess, [:localhost]
  end

  scope "/", Demo do
    pipe_through :browser

    get  "/", PageController, :index
  end

  scope "/admin", Demo do
    pipe_through :admin

    get "/", AdminController, :index
    resources "/users", UserController
  end

  scope "/api", Demo do
    pipe_through :api

    resources "/users", UserController, only: [:index, :show]
  end

  scope "/api_restricted", Demo do
    pipe_through :api_restricted

    resources "/users", UserController, only: [:delete]
  end
end
```

ユーザー登録ができるアプリケーションを想定しており、`/`と、`/api`へのアクセスはIP制限を行わず、Adminページへのアクセスはローカルネットワーク内からのみアクセスを許可、ユーザーの削除だけはAPI経由でlocalhostから行うよう強制させた。

# あとがき

Plugはあらゆる局面で活用できる優れた仕組みだが、まだまだElixirのエコシステムが成熟していないため、細かいものも含めて自作する機会が多い。

Elixirが言語として成熟してきて、かゆいところに手が届くPlugがたくさん公開されるようになると良いのだが。
[AngularJS] コレクションに挿入した後にスクロール位置を保持する

# やりたいこと
コレクションを`ng-repeat`で描画しているときに、そのコレクションに対して`unshift`（先頭に挿入）した場合、DOM描画後にスクロール位置が先頭に移動してしまいます。これを回避したいという話です。

# 解決方法
厳密に言うと、「元のスクロール位置を保持」しているからこそ、先頭に移動してしまうわけで。。。つまり、もともとスクロール位置が画面トップだった場合は`scrollTop == 0`ですが、`unshift`による再描画後も`scrollTop == 0`のままなので、スクロール位置が先頭に来ているというわけです。

というわけで、再描画後にスクロールコンテナの高さが増えた分だけ下にスクロールさせてやればよい、ということになります。（ベストな方法かは分からないですが・・・）

# サンプル
初期状態では`items`というコレクションを100件表示します。画面上部の"Load Previous Items"というリンクをクリックすれば、その前にさらに100件の`item`を読み込みます。その際にスクロール位置を保持するというサンプルです。

```html:index.html
<!doctype html>
<html ng-app="app">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.min.js"></script>
    <script src="app.js"></script>
  </head>
  <body ng-controller="ItemsCtrl" keep-scroll-position>
    <a href="" ng-click="loadPreviousItems()" ng-if="!loaded">Load Previous Items</a>
    <div ng-repeat="item in items">
      <div>{{item}}</div>
    </div>
  </body>
</html>
```

```js:app.js
angular.module('app', [])

.controller('ItemsCtrl', function($scope) {
  $scope.items = [];

  for (var i=100; i < 200; i++) {
    $scope.items.push('item' + i);
  }

  $scope.loadPreviousItems = function() {
    var previousItems = [];
    for (var i=0; i < 100; i++) {
      previousItems.push('item' + i);
    }
    Array.prototype.unshift.apply($scope.items, previousItems);
    $scope.loaded = true;
  };
})

.directive('keepScrollPosition', function() {
  return function(scope, el, attrs) {
    scope.$watch(
      function() { return el[0].clientHeight; },
      function(newHeight, oldHeight) {
        console.debug('Height was changed', oldHeight, newHeight);
        el[0].scrollTop = newHeight - oldHeight;
      });
  };
});
```

[jsFiddleはこちら](http://jsfiddle.net/itmammoth/ymLaes7e/)

# ソース解説
`keepScrollPosition`というディレクティブにスクロールコンテナ（この場合はbody）の高さを監視してます。高さに変更があったら（＝`items`が追加された）スクロール位置を元の場所まで移動してやります。

_

できてみると、めちゃくちゃ単純なコードなんですが、「高さを監視する」という発想に至るまでかなり時間を要してしまいました・・・。

# 参考
* http://mizuki-r.hatenablog.com/entry/2014/04/22/225914
Scratchでテトリス(Tetris)を作ってみた

# スクラッチでのテトリス(tetris)の作り方

Scratch で テトリスの作り方についてまとました。
![c.jpg]
(https://qiita-image-store.s3.amazonaws.com/0/54192/a8b29f2a-920c-e188-5c21-23720a618af5.jpeg)

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/index.html

本文では、概要を紹介します。ここでは、工程のみですが、作り方がわかると思います。


## (1) プロジェクトを作る 

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_project/index.html

## (2) ネコを削除する

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/remove_neko/index.html

## (3) フィールドを作成する

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_board/index.html

<img width="200" alt="board.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/f135e91b-d6b3-49f5-07c0-4b85e47fba00.png">

## (4) フィールドに状態を持たせる。枠とか空とかテトロミノとか

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_board_state/index.html

![test.png](https://qiita-image-store.s3.amazonaws.com/0/54192/175d1767-baa6-7b80-3f57-4ea04d8e9029.png)

## (5) フィールドに枠を表示する

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_frame/index.html

<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/13c378d1-6ef2-a9be-715c-f871f0db7ef5.png">

## (6) テトリスを表示する

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_tetromino/index.html

<img width="135" alt="tetrimino.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/86e80fd9-1b9a-7834-05f0-6020420e18b5.png">


## (7) (6)以外のテトロミノを表示する
https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/create_tetriminos/index.html

<img width="135" alt="tetrimino.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/6e37df41-5959-860d-c7fc-c1d0487fa8e3.png">

## (8) テトロミノの衝突判定
https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/collision/index.html

<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/a4a759cf-cb81-d0fc-5ad5-0812ca179cf2.png">

## (9) 下に移動する

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/down/index.html
<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/0295b742-adc5-ddca-7d57-3c6c51983922.png">

## (10) 左右に移動する
https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/move_left/index.html

<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/f888f995-f2e1-f09a-087d-dac07070e88a.png">

## (11) 回転させる

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/rotate_right/index.html

<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/0113e266-bd3c-1070-d6cb-ec855084df02.png">

## (12) 揃った列をクリアする

https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/clear/index.html

<img width="81" alt="board_4.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/a9ff5f9f-5fa3-6d5e-3976-d1e4139e1907.png">

## (13) 落下させる
https://kyorohiro.gitbooks.io/doc_scratch/content/tetris/fall_tetromino/index.html
<img width="81" alt="board_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/54192/f76234d0-c7ec-0b17-3ee2-0547ad9da08f.png">

## (14) 完成です。

あとは、点数をつけたり、してみてください。

------
Kyorohiro Work

http://kyorohiro.strikingly.com/
node-configで詰まった

今回は、名前の命名によって問題が起きてしまったnode-configで詰まったことを紹介します。

## 内容

devとかstageとかprodでうまくconfigファイルが読まれない！
何故かlocalで上書きされる。。。

でもENVの値はちゃんと設定されている・・・。

## 原因

原因特定に1時間位かかってしまったが判明。
原因は命名にありました。

どうやら、node-configではlocal.拡張子というファイルを最後に読むらしく、短縮して管理しようとしてしまったのが仇となってしまいました。。。

## 対応

対応自体は単純で、ファイル名を変更しました。
localをlocalhostのように通常の単語へ変更。問題なく読んでくれるようになりました。
JS Board Shibuya #4 行ってきた

# イベントの概要
そもJS Boardとは、主催者のかわのさん([@bakuonboogie](https://twitter.com/bakuonboogie))によれば

>
- JavaScriptで触れる基板やデバイスの総称です。
- 有名な基板といえば、TesselやParticle
- フレームワークはjohnny-fiveやCylon.js
- これらを使うとArduinoやDroneをJavaScriptで動きます。

とのこと。
(https://esa-pages.io/p/sharing/409/posts/466/adca8e1033d38e91d5cc.html)

で、このイベントは
>
- JS Boardなどの基板やデバイスと触れ合うソフトウェアデベロッパー向けのイベントです。
- 基本はもくもく会
- 無料配布は基本無し
- スタッフはいませんが、みんながスタッフ

となっていて、みんなで助け合って盛り上げようみたいな感じ。
今回はRaspberry Piを持ち込んでもくもくしたり、現地購入して始めてみようという感じだった。会場はビズリーチさんでした。

# 参加者
思ってたより多かった。10人くらいで黙々とやってんのかなーと思ってたけど、25人くらいはいたかな？1室が満席でもう1室も使ってました。
Mac持ってる人が多かったのでWeb系の人多いのかな？
年齢層は30くらいの人が多かったのかな？中には高校生がいてみんなビックリしてました。

# 基本的な流れ
1. 開始のあいさつ
2. 物販
3. もくもく
4. LT

私はPCとお財布だけもって参加して、Raspberry Piとその周辺部品を会場で買い、わかる人に助けてもらいながらもくもくしてました。
物販が混沌の様相でしたね。でもあれで会場の雰囲気が作られた感あると思うのでよかったのかも。

# もくもくの流れ
ラズパイ初心者組の流れです。

1. Raspberry Piを開封
2. FTDIとRaspberry Piをつなぐ
3. Raspberry Piに無線LANドングルを差し込む
4. PCからFTDI経由でRaspberry Piの無線LANの設定を行う
5. PCから無線LAN経由でSSH ←うまくいかず

FTDIはラズパイとPCをUSBでつなぐ変換アダプタみたいなもんです。
たぶん会場の無線の設定で無線経由のSSHはうまくいかず。家でやってみたらうまくいきました。

# イベントの様子
こちらにまとまってます
http://togetter.com/li/890326

まとめにない部分としては、

- ラズパイ購入者がType-CのUSBケーブルがなくて参加者同士で融通した
- かわのさんが常に走り回ってた
- できる人が声かけて教えてくれるのありがたかった
- ちょいちょいmilkcocoaのステマ
- LTでかわのさんがLittleBitsをビービー鳴かせてた

こんなことが印象に残ってます。かわのさんお疲れ様です。

# 感想
あたりまえかもですが、こういうイベントは参加者もしっかり準備してくることが必要ですね。
データ通信できるUSBケーブルは、電源と合わせてハードの勉強会では必須の持ち物だなぁと思いました。ないものを融通しあうのもワイワイできていいなと思いますが。

あと今回[milkcocoaブログ](http://blog.mlkcca.com/)を結構参考にしました。IoTに関することがけっこうまとまってるのでとても参考になります。milkcocoa自体もすごく良いのでみんな使いましょう。
横スクロールをスクロールバーで実装するスライダーサンプル

以前下記のような記事を書いた。
http://qiita.com/blurblue/items/b06b5dace3e8e48a03e8

最近下記の記事を読んで、ちょうどスクロール部分が問題だったので、「はーなるほどー」となり、参考にしてちょっと改良してみた（関係ない部分のコードも見なおした）。
http://qiita.com/volkuwabara/items/412a2e48d813f2f52537

##サンプル
http://s.codepen.io/blurblue/debug/NGXOwa

参考記事ではスクロールバーのサイズはCSSによる固定値だったが、今回はJSで高さを調整できるように動的に書きだした。
いちおう、PCでもタブレット端末でも動くようにしている。

##コードはこちら
http://codepen.io/blurblue/pen/NGXOwa
processingのSimpleOpenNIについて

Kinectなどを制御するためのProcessing用ライブラリ「SimpleOpenNI」を使って
Mac用のアプリケーションにエクスポートしたところ、
実行すると何も画面に表示されないのでちょっと調べてみました。
どうも「SimpleOpenNI」ライブラリをそのままMacのルートディレクトリに
コピーすれば動くようです。
CentOS6上にredis clusterの環境を構築する



##環境
・Linuxサーバー2台(192.168.0.1,192.168.0.2)
・使用ポート(:6379,:6380,:6381)
・Master3インスタンス、SLAVE3インスタンス
・CentOS6.7
・redis-3.0.5

##redisをダウンロードする
wget http://download.redis.io/releases/redis-3.0.5.tar.gz
tar xzvf redis-3.0.5.tar.gz
cd redis-3.0.5

##redisをインストールする
cd /redis-3.0.5/utils/
./install_server.sh
**・redisの使用ポートを入力してEnter**
Please select the redis port for this instance: [6379]

**今回他の項目はEnter連打で進めてます**

##redis.confを修正する
/etc/6379.conf
/etc/6380.comf
/etc/6381.conf
を下記の様に修正する
```
cluster-enabled yes
appendonly yes
```
設定変更後は、各インスタンスを再起動する
/etc/init.d/redis_6379 stop
/etc/init.d/redis_6379 start

**※cluster-node-timeoutはデフォルトだと15秒とわりと長いので、
適宜調整する**

##rubyとかもろもろをインストールする
yum -y install ruby.x86_64
yum -y install rubygems.noarch
gem install redis

##クラスタを構築する

cd /redis-3.0.5/src/
./redis-trib.rb create --replicas 1 192.168.0.1:6379 192.168.0.1:6380 192.168.0.1:6381 192.168.0.2:6379 192.168.0.2:6380 192.168.0.2:6381

上記のスクリプトを実行すると、各インスタンスに自動的にMASTER,SLAVEが割り当てられるので、yesを入力してEnterを入力
これで1MASTERにつき1SLAVEが紐付いたクラスタ環境の構築が完了
【Windows】Docker Toolboxのチュートリアルを社内proxy下でやったときにはまったこととその回避方法【手順まとめ】

社内でDocker Toolboxのインストールからhello-worldまでを試そうとしたところ、スムーズに行かなかったので、詰まったところについてまとめました。
結論から言うと、無理にdefaultを使わないこと。

## チュートリアルのおおまかな流れ

1. Docker Toolboxのダウンロード・インストール
2. Quick start terminal起動（自動でdefault vm 作成）
3. sshログイン
4. hello-worldの実行

１番はここでは省略して、２番以降でつまったところを中心に書いていきます。

## つまったところ・回避策

1. Starting VM... が終わらない
2. docker run hello-worldが上手くいかない

### 1. Starting VM... が終わらない

流れの２番のところで、通常であれば、Quick start terminalを立ち上げると「default」という名前のVMが自動で作成・起動され、クジラのAAが表示されるはずですが、「Starting VM...」で止まってしまいました。

回避方法：Quick start terminalを一旦止める→再起動

止まっているときにVirtualBoxをみてみると、default VMは起動済みとなっていました。
そこでQuick start terminalを一旦止めて再起動したところ、とりあえずさっきまで止まっていたところを越えてクジラが出てきました。

### 2. docker run hello-worldが上手くいかない

起動が上手く？いったところで、下記のコマンドでVMにログイン→コンテナ起動を試したところ、hello-worldイメージの取得に失敗しました。

```

docker-machine ssh default
(ユーザ名：dockerでVMにログイン)
docker run hello-world
```

ちなみにエラーはこんな感じ。
ローカルにイメージがないので、pullしようとして失敗しているようです。

```

docker@default:~$ docker run hello-world
Unable to find image 'hello-world:latest' locally
Pulling repository docker.io/library/hello-world
Error while pulling image: Get https://index.docker.io/v1/repositories/library/hello-world/images: net/http: TLS handshake timeout
```

回避策：proxy設定込みで新しくホストを作成する

はじめはdefaultにproxy設定をしようとしましたが、OSがCent OSでもubuntuでもなくCore Linux？ということで、検索してもやりかたがよくわからない。
そこで、ホスト作成時にproxy設定するオプションを使って、新しくホストを作成してしまうことにしました。
コマンドは以下の通りです。（設定は各自の環境に合わせてください。testという名前のVMが作成されます。）

```

docker-machine create -d virtualbox \
    --engine-env HTTP_PROXY=http://your.proxy.co.jp:port \
    --engine-env HTTPS_PROXY=http://your.proxy.co.jp:port \
    --engine-env NO_PROXY=127.0.0.1 \
    test
```

ここで注意することは、最初のときと違って「Starting VM...」で止まっても中断しないこと。
今回はちゃんと終わるので、少し待機します。
（私は最初ここで中断してうまくいきませんでした。defaultで止まるのは内部でイメージの取得でも試みているのでしょう。）

完了したら、下記コマンドでホストに入って動作確認をしましょう。

```

docker-machine ssh test
(ユーザ名：dockerでVMにログイン)
docker run hello-world
```

こんなメッセージが出ていれば成功です。

```

Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

Share images, automate workflows, and more with a free Docker Hub account:
 https://hub.docker.com

For more examples and ideas, visit:
 https://docs.docker.com/userguide/
```

いらなくなったdefaultですが、消すと次回起動時に再生成されてまた処理が止まるという…。
仕方ないので放置です。

今回は以上です。
削除したブランチをSourceTreeを使って（？）復元する方法

Macのタイムマシーンで対象ディレクトリを引っ張ってきて、そのディレクトリで別にリポジトリ作って対応するという超アナログだけど簡単な方法。

コミットしていなかったブランチを消してしまったので。。。

要するに**バックアップはしっかり取っておこう**というお話でした。
Excelバッドノウハウメモ (+ Windows, Mac 向けショートカット)


Excel提出の事務書類は滅びろ。

## セルの内容を編集する

* Windows: F2
* Mac: Ctrl + U

## セル内改行文字の入力

* Windows: Alt + Enter
* Mac: Command + Option + Enter

## 改行文字の検索・置換

検索ダイアログ等のテキストボックスでは Alt + Enter が効かない。

* Windows: Ctrl + J
* Mac: 不明

## 半角文字で入力したいのに、勝手にIMEがオンになってイライラ

OSやIMEの制御周りが悪さをしているのかと感じるかもしれませんが、元凶はExcelです。

* メニューバーの「データ」→入力規則→「日本語入力」タブ→日本語入力：オフ（英語モード）


## 印刷で文字が切れないようにする

フォーマットにあわせてテクニックを組み合わせる必要あり。
バッドノウハウを蓄積しよう。

参考にした記事：[《文字が印刷されない》Excel文字切れの9割を解消してきた厳選技5つ！](http://incloop.com/excel%E5%8D%B0%E5%88%B7%E3%81%A7%E6%96%87%E5%AD%97%E5%88%87%E3%82%8C%E3%81%AE9%E5%89%B2%E3%82%92%E8%A7%A3%E6%B6%88%E3%81%97%E3%81%A6%E3%81%8D%E3%81%9F%E5%8E%B3%E9%81%B8%E6%8A%805%E3%81%A4%EF%BC%81/)

### セルの自動幅調整

* セル（列）境界線をダブルクリック
* リボンの「ホーム」タブ→セル→書式→列幅に自動調整

### セルの自動高さ調整

* セル（行）境界線をダブルクリック
* リボンの「ホーム」タブ→セル→書式→セルの高さの自動調整

### セルの折り返し表示

長い文字を折り返す設定。上記の、自動高さ調整と組み合わせることが多いと思う。

* リボンの「ホーム」タブ→配置→折り返し→折り返して全体を表示する

### セルの縮小表示

セルからちょっとだけ文字が溢れる、といった場合に、文字サイズを全体的に縮小してセルにフィットするようにすることができる。
大体文字の長さがある程度読めているけど、時々少しだけはみ出るような場合に有効。

* リボンの「ホーム」タブ→配置→折り返し→縮小して全体を表示する

### 結合したセルの高さ自動調整がきかない

結合したセルに関しては、高さの自動調節を直接適用することができません。仕様です。
対処方法としては、同じ行の空白のセルに改行文字のみを入力して高さを調整する、といった方法があります。


...

...

つらい
bitbucketでPermission denied（windows）

# sshキーを登録しないと......。

公開鍵を生成するにあたって手間取ったのでメモ。
cmdでは次のコマンドが認識されなかった。

```
ssh-keygen
```

なので、git bashから行うか、
[puttygen](http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html)を使用して、

```
~/.ssh/id_rsa.pub
```

ファイルを作る。
puttygenは、鍵を生成するにあたり、
「ウィンドウ内でマウスカーソルをぐるぐるする」
というわかりにくい操作が必要なので注意。
TypeScriptなMeteorプロジェクトをHerokuで動かす方法


# はじめに

最近、Meteor公式が[Galaxy](https://www.meteor.com/why-meteor/pricing)というMeteorプロジェクトのデプロイ＆運用サービスを始めました。
ただ、価格情報を見れば分かるんですが、お試し気分ではなかなか手が出ないお値段設定です。

そこで[Heroku](https://www.heroku.com)です。Herokuは１日のうち８時間スリープに目をつぶれば無料で使えます。
２４時間ずっと起動させておきたい場合は、hobby Planにすれば、その制約もなくなります（２０１５年１０月２３日現在で月額７ドル）。
さらにheroku標準では独自ドメインでSSL対応させる際に普通月額２０ドル（２０１５年１０月２３日現在）かかりますが、[CloudFlareなどのサービスを使えば実は実質無料でSSL対応](http://uzulla.hateblo.jp/entry/2015/02/25/033133)できます。
（このCloudFlareを使ったSSL対応についても、そのうち記事書きましょうかね？ ちなみにこの場合、SSLはherokuapp.comドメインでのデフォルトのものを使うことになります。閑話休題。）

すでに、	通常のMeteorプロジェクトをHerokuにデプロイする良記事がありましたので、リンクさせていただきます。<del>基本はこちらの記事のとおりにやればOKです</del>。

[herokuにMeteorで作成したアプリケーションをデプロイする](http://qiita.com/rubytomato@github/items/57b9f4102dd6bd29c86b)

（→2015/10/23時点で、この記事で紹介されているbuildpackではうまくいきませんでした。次に、私がいつも使っている `https://github.com/AdmitHub/meteor-buildpack-horse` を試したところ、イイ線いってたんですが、悲しいかな。現在のMeteor1.2.0.2では[ECMAScript2015のコードが混じっていると、開発時は問題ないがデプロイ時（つまり、Productionモード時）にminifyがエラーでコケるという問題](https://github.com/meteor/meteor/issues/5517)があり、デプロイ途中で失敗。じゃあminifyさせなきゃいいじゃん！　ということで、`https://github.com/AdmitHub/meteor-buildpack-horse` をフォークしてminifyしないバージョン [https://github.com/emadurandal/meteor-buildpack-horse](https://github.com/emadurandal/meteor-buildpack-horse) を一時しのぎとして作りました。とりあえず、2015/10/23時点では私のこのbuildpackをお使いください。）

しかし、TypeScriptを使ったMeteorプロジェクトの場合は、この手順だけだとデプロイに失敗します。Herokuがtscコンパイラを見つけられないためです。

# 解決策

まず、前述で紹介した記事の通りに作業を進めます。（ただし、buildpackだけは私の[https://github.com/emadurandal/meteor-buildpack-horse](https://github.com/emadurandal/meteor-buildpack-horse) を使うように読み替えてください）

この時点ではまだ、デプロイに失敗してしまうのですが、さらに以下の手順を行えば、TypeScriptを使ったMeteorプロジェクトも動くようになります。

1) meteorhacks:npmをインストールします。

```bash
$ meteor add meteorhacks:npm
```

2) Meteorプロジェクトフォルダ直下に、以下の内容の`packages.json`を配置します（TypeScriptのバージョンはお好みで）。

```json
{
  "typescript": "1.6.2"
}
```

3) 一度、ローカルでMeteorプロジェクトを実行します（この時に自動生成されるファイルが、Herokuにデプロイするときに必要なため）。

```bash
$ meteor
```

4) gitリポジトリに、本件で作られた全てのファイルをコミットします。

5) herokuにデプロイを行います。

```bash
$ git push heroku master
```

通常のMeteorプロジェクトより、若干時間がかかりますが、デプロイに成功するはずです。

# さいごに

いかがでしょうか。Meteor 1.2から標準でECMAScript2015に対応し、クラスなども使えるようになったため、TypeScriptを使うまでもない、というケースもあるかもしれません。
しかし、だんだんプロジェクトが大規模になってくると、TypeScriptの必要性は増してきます。
ちなみに私は、Meteor & TypeScript & Riot.jsという組み合わせで開発しています。Riot.jsもイイヨーｗ

まぁそれはともかく、みなさまも良いMeteor & TypeScriptライフをお過ごしください^^/

※2015/10/23現在、すでに述べたとおり、minifyの問題がありますが、そのうちMeteor本家がこの問題を解決してくれるでしょう。将来のアップデートを待ちましょう。「待ってらんねぇ！」という方、minifyしないという回避策を許容できる方のみ、私のbuildpackをお試しください。
サーバ証明書が無料で手に入る時代がもうすぐ(2015/11/16週に)くる Let's Encrypt

# Let's Encrypt is Trusted!!
ついにLet's Encryptで作ったサーバ証明書が信用できる証明書と言うことになった。
すでにLet's Encryptのページに用意されている [Hello Worldページ](https://helloworld.letsencrypt.org/)は証明書のエラーになることもなく表示されます。
これは、とても記念すべき日ではないかと個人的には考えています :tada: 

最近では、「Webサービスはすべてhttps化するべし。」と言う流れですがサーバ証明書に大金を使えない場合もある・・・
そんな中、まさに救世主と個人的には感じています。

* 最近https必須だなと感じた点
 * iOS 9やEl Capitanで導入されたApp Transport Security(ATS)問題
 * 各キャリアの「通信の最適化」問題
 * google様のhttps優先問題 などなど。。。

Let's Encryptで発行されるサーバ証明書は、「ドメイン認証」なので企業認証やEVの代わりにはならないと思いますが、積極的に利用したいと考えています。
これで二度と「オレオレサーバ証明書」は使わなくてもよくなると期待しています！

## Let's Encrypt
Let's Encryptのページです、ぜひご覧ください！

 * https://letsencrypt.org/

# リリース日(予定)
2015/11/16週にリリースされる模様
[Updated Let's Encrypt Launch Schedule](https://letsencrypt.org/2015/08/07/updated-lets-encrypt-launch-schedule.html)
> General availability: Week of November 16, 2015

# 参考サイト

* Let's Encrypt is Trusted
 * https://letsencrypt.org/2015/10/19/lets-encrypt-is-trusted.html
* Hello World, Let's Encrypt. 
 * https://helloworld.letsencrypt.org/
bashで正規表現 ある文字列を含んである文字列を含まない

## やりたかったこと
"hoge"という文字列を含んで、"fuga"という文字列を含まないものを正規表現でマッチさせたかった。

## ハマった点
以下で実行してみると「NG」となり、ハマって同僚に相談。

```
NAME="hoge"
if [[ ${NAME} =~ ^(?!.*fuga).*(?=hoge).* ]]; then
    echo "OK"
else
    echo "NG"
fi
```

どうやらbashの正規表現がEREなのでこれではうまくマッチしなかったのが原因。

## 対処

```
NAME="hoge"
MATCH_PATTERN="^.*hoge.*$"
MISMATCH_PATTERN="^.*fuga.*$"
if [[ ${NAME} =~ ${MATCH_PATTERN} && ! ${NAME} =~ ${MISMATCH_PATTERN} ]];then
    echo "OK"
else
    echo "NG"
fi
```

普通に一つずつ判断してAかつBって感じで判断してもらうようにしました。
UIViewController＋UITableViewの組み合わせでstatusbarをタップして最上部までスクロールした時にUIRefreshControlが動作しないようにする方法

タイトル長すぎですね。。。

UIViewController＋UITableView＋UIRefreshControlの組み合わせでstatusbarをタップして最上部までスクロールすると、UIRefreshControlが動作もしくは表示されることがあります。


そんな時は以下のコードを書いておくと回避できます。

```swift
func scrollViewShouldScrollToTop(scrollView: UIScrollView) -> Bool {
	self.tableView.scrollToRowAtIndexPath(NSIndexPath(forRow: 0, inSection: 0), atScrollPosition: UITableViewScrollPosition.Top, animated: true)
	return true
}
```

これは魔法ですので、理由は聞かないでください。。。