OmniAICreator/Qiita-1.07M huggingface dataset:
Struts2+SpringFrameworkでJUnit4のテストケースを作る(Action編)

# Struts2+Springの構成でActionクラスの単体試験をする

今回はActionクラスの実行結果を判定するJUnitテストの作り方を紹介します。
Actionクラスのreturn値は、どの画面をレスポンスとして出力するかを決定します。

またActionクラスは入力チェック(Validation)の結果、エラーがあった場合は自動的にinput(ActionSupport.INPUT)になりますので、入力値の検証が想定通り行われているかもチェックできます。

まとめると、テストリクエストに対してActionクラスは何を返すか（どの画面を返すか）の試験ができます。

# Struts2+Spring専用のJUnit4ケースの作り方

以下の必須ルールがあります。

* テストクラスの宣言部に以下のアノテーションを付与します。
 * StrutsSpringJUnit4TestCase<テスト対象Action> を継承
 * @RunWith(SpringJUnit4ClassRunner.class)
 * @ContextConfiguration() にてSpringの設定を記載
* テストメソッドは以下のルールがあります。
 * @Testアノテーションを付与
 * メソッド名はtestから始める

この例を以下に示します。

```java:RegisterActionTest.java
package sample.action;

import static org.junit.Assert.*;

import org.apache.struts2.StrutsSpringJUnit4TestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.opensymphony.xwork2.ActionProxy;
import com.opensymphony.xwork2.ActionSupport;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
		  locations={"classpath:spring/applicationContext.xml",
		             "classpath:spring/applicationContext-*.xml" })
public class RegisterActionTest extends
		StrutsSpringJUnit4TestCase<RegisterAction> {

	@Test
	public void test登録失敗_タスク名なし() throws Exception {
		// リクエストパラメータを設定する
		request.addParameter("vo.name", "");
		request.addParameter("vo.task", "### タスクh3");
		request.addParameter("vo.userid", "user01");
		request.addParameter("vo.jobid", "sam");

		// Actionクラスのインスタンスを取得(=リクエスト情報をStruts2に読ませる)
		ActionProxy proxy = getActionProxy("/register");

		// Actionクラスを実行し、result値を取得
		String result = proxy.execute();

		// テスト結果の比較
		assertEquals(ActionSupport.INPUT, result);
	}
}
```
set -u してるときに変数が未定義または空文字かチェックする for RHEL/CentOS 6

次のようにすると変数が定義されているかどうかチェックできます。

- [Bash - set -uしてるときに変数が定義されてるかチェックする - Qiita](http://qiita.com/tadsan/items/0109d651780844acce09 "Bash - set -uしてるときに変数が定義されてるかチェックする - Qiita")

がしかし、この方法は RHEL/CentOS 6 では使えません、Bash のバージョン的な意味で。

RHEL/CentOS 6 では下記の記事のコメントにあるような方法で可能です。

- [ALL about Linux: bash でシェル変数が定義されているかを判定する方法は？](http://luna2-linux.blogspot.jp/2014/05/bash.html "ALL about Linux: bash でシェル変数が定義されているかを判定する方法は？")

がしかし、大抵の場合「変数が未定義」よりも「変数が未定義または空文字」で条件分岐することの方が多いでしょう。

その場合は次のようにします。

```bash
[ -n "${VAL-}" ]
```

`${VAL-}` は変数 VAL が未定義なら、`-` 以降の文字を展開したものに置換されます。

`-` 以降になにもないので、要するに空文字に置換されます。

変数 VAL が空文字なら空文字のままなので、「変数が未定義、または、空文字」でチェックできます。

---

確認用（`-v` 使っているのでCentOS 7 とかで実行）

```bash
cat <<'EOS'|bash
set +u
set -v

unset VAL
[ -v VAL ]; echo $?        # 1
[ -n "${VAL+x}" ]; echo $? # 1
[ -n "${VAL-}" ]; echo $?  # 1
[ -n "$VAL" ]; echo $?     # 1

VAL=
[ -v VAL ]; echo $?        # 0
[ -n "${VAL+x}" ]; echo $? # 0
[ -n "${VAL-}" ]; echo $?  # 1
[ -n "$VAL" ]; echo $?     # 1

VAL=123
[ -v VAL ]; echo $?        # 0
[ -n "${VAL+x}" ]; echo $? # 0
[ -n "${VAL-}" ]; echo $?  # 0
[ -n "$VAL" ]; echo $?     # 0
EOS
```
phpbrewでphp.iniを設定する


https://github.com/phpbrew/phpbrew

これを使ってphpのバージョンを変えている。


`php.ini`の設定を変更したくなった。
`/etc/php.ini`が使われるかと思ったがそうではなかった。

どのフォルダで設定されるかとかは、以下のような感じで見てみるのが早い。

```sh
$ php -i | grep php.ini
Configuration File (php.ini) Path => /Users/mapyo/.phpbrew/php/php-5.4.35/etc
Loaded Configuration File => /Users/mapyo/.phpbrew/php/php-5.4.35/etc/php.ini
```

以下のコマンドで調べた方がわかりやすそうです。(@koriym さんにコメントで教えて頂きました。ありがとうございます！！）

```sh
$ php --ini
Configuration File (php.ini) Path: /Users/mapyo/.phpbrew/php/php-5.4.35/etc
Loaded Configuration File:         /Users/mapyo/.phpbrew/php/php-5.4.35/etc/php.ini
Scan for additional .ini files in: /Users/mapyo/.phpbrew/php/php-5.4.35/var/db
Additional .ini files parsed:      /Users/mapyo/.phpbrew/php/php-5.4.35/var/db/memcache.ini
```


まぁ、大体は

```sh
~/.phpbrew/php/php-5.4.35/etc/php.ini
```

この辺にあります。（バージョンごとにフォルダは変更してください）

やっぱりちゃんとバージョンに対応した管理が出来るようになってるんだなぁー。
brew installでError: No available formulaが返るとき

Macの**Homebrew**のお話。

```shell-session
$ brew install <package name>
```

で

```
Error: No available formula for <package name>
```

というエラーが返ってくるときは、

```shell-session
$ brew search <package name>
```

とやる。たとえば**opencv**なら、

```
homebrew/science/opencv
```

と返ってくるので、以下のように`homebrew/science`のパッケージ情報を更新する。

```shell-session
brew tap homebrew/science
```

するとこんな情報が表示され・・・

```
Cloning into '/usr/local/Library/Taps/homebrew/homebrew-science'...
remote: Counting objects: 8057, done.
remote: Compressing objects: 100% (27/27), done.
remote: Total 8057 (delta 11), reused 1 (delta 0)
Receiving objects: 100% (8057/8057), 1.99 MiB | 768.00 KiB/s, done.
Resolving deltas: 100% (4463/4463), done.
Checking connectivity... done.
Warning: Could not tap homebrew/science/itsol over Homebrew/homebrew/itsol
Warning: Could not tap homebrew/science/newick-utils over Homebrew/homebrew/newick-utils
Warning: Could not tap homebrew/science/openfst over Homebrew/homebrew/openfst
Warning: Could not tap homebrew/science/opengrm-ngram over Homebrew/homebrew/opengrm-ngram
Warning: Could not tap homebrew/science/salt over Homebrew/homebrew/salt
Tapped 410 formulae
```

これで晴れて`$ brew install opencv`できるようになる。

---
ブログ書いています：[Weed software](http://weed.cocolog-nifty.com/wzero3es/)
Linux:シェルスクリプト: ファイル xxx が消えるまで待つ

もう出かける時間なのに、Firefox のダウンロードが終わらない。。。。
そんな場合のスクリプトです。

---
コマンドライン例。

```shell-session
:
: while_exist で「xxx.part」が消えるまで待って、それから warm_halt でシャットダウンします
:
$ while_exist xxx.part ; warm_halt
:
: 上のコマンドは返って来ません。このまま出かけましょう。
:
```

スクリプト。(パスの通っているディレクトリに置きます)

```bash:while_exsit.sh
#!/bin/bash
PATH=/usr/bin:/bin

file=${1:?"usage: $0 file [interval]"}
interval=${2:-60}

while [ -f "$file" ]
do
    sleep $interval
done
```
(※2015/01/09 追記) このスクリプトを使わない代替方法があります。詳しくはコメント欄を参照ください。

```bash:warm_halt.sh
#!/bin/bash
PATH=/usr/bin:/bin:/sbin

#
# root 以外で実行する場合、
# `sudo sync` と `sudo shutdown` は NOPASSWD で実行できる必要があります
#
[ "$LOGNAME" = "root" ] && sudo="" || sudo=sudo

$sudo sync               # 「sync は 2回」派、「sync は 4回」派の人は要調整
$sudo sync
$sudo sync
$sudo shutdown -h now
```

スクリプトの名前を変えたい場合は、シンボリックリンクを張るなどで対処してください。
以下は例です。

```shell-session
$ ln -s while_exist.sh while_exist   # 拡張子なしの名前でシンボリックリンクを張る
$ ln -s warm_halt.sh warm_halt       #             〃
```

---
参考。sudo の NOPASSWD の設定。

visudo コマンドで sudo の設定ファイル(/etc/sudoers)を開いて編集します。
/etc/sudoers は root 権限が必要なので sudo をつけます。

```shell-session
$ sudo visudo

: or

$ sudo EDITOR=vim visudo   # その場だけ vim を使って編集したい場合
```

例えば、lnznt アカウントに NOPASSWD で sudo を許可する場合、以下のような行を /etc/sudoers に追加して保存(エディタは終了)します。

```text
lnznt       ALL=(ALL:ALL) NOPASSWD: ALL
```

上の書式の意味は以下ですので、セキュリティポリシなどに合わせて適宜変更してください。

      lnznt        ALL=(ALL:ALL)            NOPASSWD:     ALL

    # アカウント名  ホスト=(ユーザ名:グループ名)  NOPASSWD:     コマンド名
    # [誰が]       [どこで]  [誰になって]    (パスワードなしで) [何を]     する

    # ※ホスト、ユーザ名、グループ名、コマンド名には ALL (全てを意味する) が指定可

もっと詳しいことは sudo(1)、sudoers(5) を参照してください。
homestead up で couldn't find HOME environment -- expanding `~' (ArgumentError)と言われる解決方法

Macにhomesteadの環境を作ろうとしていたらエラーがでました。

# homestead upでエラー
homesteadでvagrantをあげようとしました。

```bash:homesteadでupできない
homestead up

/Applications/Vagrant/embedded/gems/gems/vagrant-1.6.3/lib/vagrant/shared_helpers.rb:94:in `expand_path': couldn't find HOME environment -- expanding `~' (ArgumentError)
	from /Applications/Vagrant/embedded/gems/gems/vagrant-1.6.3/lib/vagrant/shared_helpers.rb:94:in `expand_path'
	from /Applications/Vagrant/embedded/gems/gems/vagrant-1.6.3/lib/vagrant/shared_helpers.rb:94:in `user_data_path'
	from /Applications/Vagrant/embedded/gems/gems/vagrant-1.6.3/lib/vagrant/plugin/manager.rb:16:in `user_plugins_file'
	from /Applications/Vagrant/embedded/gems/gems/vagrant-1.6.3/lib/vagrant/plugin/manager.rb:27:in `instance'
	from /Applications/Vagrant/bin/../embedded/gems/gems/vagrant-1.6.3/lib/vagrant/pre-rubygems.rb:22:in `<main>'
```

ここでhomesteadのバージョンを確認します。

```bash:homesteadのバージョンを確認
homestead -v
Laravel Homestead version 2.0.8
```
2.0.8だとダメらしいのです。。

# homeseteadを入れなおす
2.0.8を削除し

```bash:homesteadを削除
rm -rf ~/.composer/vendor/laravel/homestead
```
homesteadのv2.0.7をインストールします。

```bash:composerでv2.0.7をインストール
composer global require laravel/homestead:v2.0.7
```

# 再度homestead up
再度homestead upを試します。

```bash:homesteadをup
homestead up
```
今度はエラーがでませんでした。

# 参考
http://stackoverflow.com/questions/27285627/laravel-homestead-unable-to-run-homestead-up
メモ：どこかにあるであろうまともなライブラリを探す手間を惜しんで自分で書く、自分が個人的に使いやすい正規表現処理 javascript 編

***オレオレメモです。***

GAS ですが、正規表現での抽出が多用されるプログラムを書いていると named capture group に対応した正規表現ライブラリが欲しくなってきて、
オレオレライブラリがわりといいところまでできているんですが、まだ完成はしていません。
なので、今回はこんなので代用します。

```js
Mugime.match = (function(specs){
  var ps = matome.map('mkhash', specs, function(key,spec){
    var r = { p: spec.p, idx: {} };
    if (spec.s) {
      matome.map(spec.s.split(','), function(i,name){
        if (name.length > 0 && name.charAt(0) != '#') {
          r.idx[name] = 1 + Number(i);
        }
      });
    }
    return r;
  });
  return function(key, str) {
    var p = ps[key];
    if (! p) throw new Error('unknown key "' + key + '"');
    var m = str.match(p.p);
    if (! m) return false;
    return matome.map('mkhash2', p.idx, function(name,i) { return { key: name, value: m[i] }; });
  };
})({
  date0: { p: /^\s*(\d+)年(\d+)月(\d+)日/, s: 'year,month,day' },
  jan0: { p: /^\s*(\S+)\s*JAN/, s: 'jan' },
  caption0:  { p: /^\s*(\d+)\s+(.+)$/, s: '#sectioncode,val' },
  tax0:  { p: /^\s*外税([^\d]*)(\d+)\s*$/, s: ',val' },
  discount0:  { p: /^\s*((.割)|(割.+))\s+(\d+)%\d(-(\d+))?\s*$/, s: ',,,percent,val,absval' },
  unit:  { p: /^\s*(\d+)(.+)単(\d+)/, s: 'unitprice,unit,count' },
  price:  { p: /^\s*((￥\s*(\S.*))|([\d\.\,]+))\s*$/, s: 'val,valwithyen,valwithoutyen' }
});
```

これで、

```js
  var m = Mugime.match('date0', '2015年1月15日');
  if (m) { Logger.log({year: m.year}); }
```
とかできるようになります。

あと、"`/x`" modifier 相当のものは欲しいですね。

あと、

```js
  date0: { p: /^\s*(\d+)年(\d+)月(\d+)日/, s: 'year,month,day',
           ex: function(m) { m.datestr = m.year + '/' + m.month + '/' + m.day;
                               m.getDate = function() { return new Date(m.datestr) }; } },
```

とかやって、追加のプロパティを指定できたりすると嬉しいかも。
こんな感じですかね。

```js
Mugime.match = (function(specs){
  var ps = matome.map('mkhash', specs, function(key,spec){
    var r = { p: spec.p, idx: {} };
    if (spec.ex) r.ex = spec.ex;
    if (spec.s) {
      matome.map(spec.s.split(','), function(i,name){
        if (name.length > 0 && name.charAt(0) != '#') {
          r.idx[name] = 1 + Number(i);
        }
      });
    }
    return r;
  });
  return function(key, str) {
    var p = ps[key];
    if (! p) throw new Error('unknown key "' + key + '"');
    var m = str.match(p.p);
    if (! m) return false;
    var retval = matome.map('mkhash2', p.idx, function(name,i) { return { key: name, value: m[i] }; });
    if (p.ex) p.ex(retval);
    return retval;
  };
})({
 ...
});
```

あ、matome.map というの使ってましたね。これはオレオレライブラリの提供する関数でした。list like なものの要素に繰り返し関数を適用するような。
Chromeでセッション復元できるエクステンションSession Buddyが真っさらになった時の復旧方法


[Session Buddy](http://www.sessionbuddy.com)はChromeのセッションを保存して後から復元できるエクステンション。
Chromeのログインユーザーを削除してしまいSession Buddyが真っさらになった時の復旧の手順。

##経緯
![peopledel.png](https://qiita-image-store.s3.amazonaws.com/0/7500/0f85ff12-d1db-ce96-9cd9-00692388a39f.png "peopledel.png")

＿人人人人人人人人人人人人人人人＿
＞　この操作は元に戻せません。　＜
￣Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y￣

![スクリーンショット 2015-01-09 4.51.37 AM.png](https://qiita-image-store.s3.amazonaws.com/0/7500/d457295e-6904-3e57-c7d6-7ce4fcb276ae.png "スクリーンショット 2015-01-09 4.51.37 AM.png")

##手順
1. Chromeを終了する。
2. 消してしまったログインユーザーのSession Buddyのデータを探す。  
[How to Locate Session Buddy Data on Your Computer](http://sessionbuddy.com/datafileLocation.htm)
3. 新しいログインユーザーのSession Buddyのデータフォルダに探しだしたデータを入れる。  
[How to Back Up and Restore Session Buddy Data (Advanced Procedure)](http://www.sessionbuddy.com/processForPortingSessionBuddyData.htm)
4. Chromeを起動する。

##結果
![スクリーンショット 2015-01-09 4.56.41 AM.png](https://qiita-image-store.s3.amazonaws.com/0/7500/f69cb8e1-95b5-4833-c753-7ef8c32c14f8.png "スクリーンショット 2015-01-09 4.56.41 AM.png")

深夜のネットサーフィン、危険...
テンプレートな型をマクロの引数に

```
#define Eval(T) typename T::type
```

とかやっておいて

```
template <typename A, typename B>
struct Foo {
  using type = std::map<A, B>;
};
Eval(Foo<string, int>) foo;
```

とかやりたいですよね. でも怒られますよね. `ABS(f(x, y))` とかは許されるのに...

そんなときは

```
#define Eval(...) typename __VA_ARGS__::type
```

で幸せになれるかも. やったね.
SwipeRefreshLayoutの中にListViewを入れる際のEmpty View

## 問題

リストビューをswipe to refreshさせたい場合、empty viewをこうやって書いてたんだけどうまく表示されなかった

```xml
<android.support.v4.widget.SwipeRefreshLayout ...>
  <ListView
    android:id="@android:id/list" ... />
  <TextView
    android:id="@android:id/empty" ...
    android:text="@string/empty_list"/>
</android.support.v4.widget.SwipeRefreshLayout>
```

## 解決策

Empty ViewをSwipeRefreshLayoutと同じレベルに置けばいい

```xml
<android.support.v4.widget.SwipeRefreshLayout ...>
  <ListView
    android:id="@android:id/list" ... />
</android.support.v4.widget.SwipeRefreshLayout>
  
<TextView
  android:id="@android:id/empty" ...
  android:text="@string/empty_list"/>
```

あとはプログラムでempty viewをセットしてあげる

```java
listView.setEmptyView(findViewById(android.R.id.empty));
```

## 一個だけ問題が...

それは、empty viewが表示されてる状態ではswipe to refreshできないということ
もう一個SwipeRefreshLayoutを作ってTextViewを入れ子にすればいいのかな？（要検証）
T-Codeかな表

T-Codeのかな練習用に(自分用)。

## ひらがな

|       |     あ|     い|     う|     え|     お|
|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|
| **あ**| あ yf | い hd | う yd | え lt | お oa |
| **か**| か je | き hr | く jt | け nf | こ uf |
| **さ**| さ ug | し js | す ,f | せ uw | そ ;b |
| **た**| た ks | ち /a | つ .d | て la | と ja |
| **な**| な lg | に kg | ぬ a. | ね fd | の kd |
| **は**| は jg | ひ m. | ふ rs | へ ;; | ほ pz |
| **ま**| ま md | み /g | む yh | め lc | も ia |
| **や**| や ye |       | ゆ cc |       | よ jw |
| **ら**| ら ig | り jc | る ;a | れ ;e | ろ ps |
| **わ**| わ ys | ゐ s1 |       | ゑ d1 | を ;g |
| **ん**| ん nd |       |       |       |       |
| **ぁ**| ぁ 1z | ぃ 1x | ぅ 1c | ぇ 1v | ぉ 1b |
| **ゃ**| ゃ tt |       | ゅ q. |       | ょ ,. |
| **が**| が ;s | ぎ qf | ぐ dt | げ /z | ご /k |
| **ざ**| ざ fo | じ ux | ず ,z | ぜ ;3 | ぞ .u |
| **だ**| だ hc | ぢ 8v | づ ek | で hg | ど kq |
| **ば**| ば ,w | び jo | ぶ sb | べ yl | ぼ cm |
| **ぱ**| ぱ 1a | ぴ 1s | ぷ 1d | ぺ 1f | ぽ 1g |


## カタカナ
|       |     ア|     イ|     ウ|     エ|     オ|
|:-----:|:-----:|:-----:|:-----:|:-----:|:-----:|
| **ア**| ア ;w | イ mf | ウ .x | エ kk | オ /c |
| **カ**| カ jx | キ yw | ク ms | ケ yj | コ yr |
| **サ**| サ nt | シ pg | ス ua | セ hi | ソ il |
| **タ**| タ ie | チ /r | ツ ki | テ .e | ト le |
| **ナ**| ナ yt | ニ ov | ヌ k/ | ネ mm | ノ nl |
| **ハ**| ハ lm | ヒ za | フ /s | ヘ m3 | ホ nh |
| **マ**| マ it | ミ ;, | ム ub | メ ,x | モ yo |
| **ヤ**| ヤ nn |       | ユ o. |       | ヨ zz |
| **ラ**| ラ us | リ pd | ル kw | レ ;q | ロ ns |
| **ワ**| ワ oi | ヰ w1 |       | ヱ e1 | ヲ 1q |
| **ン**| ン ,d |       |       |       |       |
| **ァ**| ァ zi | ィ po | ゥ 1w | ェ td | ォ mu |
| **ャ**| ャ ;o |       | ュ .w |       | ョ .; |
| **ガ**| ガ mk | ギ bx | グ /x | ゲ tn | ゴ mj |
| **ザ**| ザ g, | ジ ;z | ズ // | ゼ vn | ゾ u; |
| **ダ**| ダ ok | ヂ 1r | ヅ 1t | デ hk | ド jz |
| **バ**| バ yc | ビ ,v | ブ ,h | ベ ;j | ボ sg |
| **パ**| パ ,t | ピ m/ | プ mw | ペ rt | ポ k, |
バッテリーゼロの Android 端末が充電・起動できない時

数年前に発売された Android では、端末によって、バッテリーがゼロになってしまうと PC の USB 給電からでは充電されないことがあります。
PC と USB ケーブルを挿しても、充電のランプが点かず、いつまでたっても充電されません。

そんな時は以下を試すと、給電されます。

- データ通信に対応して "いない" ケーブルでつないでみる
- コンセントに繋ぐタイプの USB 給電を試してみる

充電中のランプが着いて、起動できたら、PC からでも給電できるようになります。
Google Maps API v3 の Marker を作るときにオレオレプロパティを渡したらイベントハンドラで使えたよ、という話

#概要
タイトルのまんまですが、Google Maps API v3 の Marker を作るときに公式リファレンスに載っていないオレオレプロパティを含むオプションを渡したらイベントハンドラでそのプロパティが使えて便利だったよ、という話です。

##はじめに注意事項
[2013-07-23 にはてなダイアリーに書いた記事](/http://d.hatena.ne.jp/unau/20130728/1375029972) と同じものです。一応、この技を使ったページは今でも正常に動作していますが、非公式の技なのでその点、ご注意ください。正確に言うと、公式のドキュメントを精読していないので、非公式かどうかも定かではありません。

#詳細
Google マップに配置するマーカのコンストラクタには position や icon や title などのさまざまなプロパティをオプションとして渡せます。どんなプロパティがサポートされているかは、[公式リファレンス](https://developers.google.com/maps/documentation/javascript/3.exp/reference?hl=ja#MapOptions)に載っていますが、ここに載っていない独自のプロパティを渡してみたら、生成されたマーカのイベントハンドラ内でそのプロパティが拾えて便利でした。

具体的なコードを示す方が早いので。

とある農家が自分のところの畑ごとの地図情報を Google マップで表示したいと考えているケースを想定します。`fields` という連想配列に各畑の緯度経度、ポリゴン座標、アイコン画像などが入っているとします。
そして、指定された畑を地図の中心に持ってきて適切なサイズでズームする、という次のような関数 `pahTo()` が定義してあるとします。

```js
  function panTo(key) {
    if (! key in fields) return;
    var field = fields[key];
    map.panTo(field.latlng);
    map.setZoom(field.zoom);
  }
```

畑ごとのマーカを次のコードで生成します。

```js
    for (var key in fields) {
      var field = fields[key];
      if (field['poly']) {
        field.poly.setMap(map);
        var image = new google.maps.MarkerImage(field.mark.image,
                                                new google.maps.Size(64, 64),
                                                new google.maps.Point(0,0),
                                                new google.maps.Point(0, 32));
        var shadow = new google.maps.MarkerImage(field.mark.shadow,
                                                 new google.maps.Size(64, 64),
                                                 new google.maps.Point(0,0),
                                                 new google.maps.Point(0, 32));
        var opts = {
          position : field.latlng,
          title : field.name,
          icon : image,
          shadow : shadow,
          map : map,
          key : field.key
        };
        var marker = new google.maps.Marker(opts);
        google.maps.event.addListener(marker, 'click', function(e) {
          panTo(this.key);
        });
```

Marker のコンストラクタに渡している opts オブジェクトに key プロパティがありますが、これは Marker のコンストラクタで使われるプロパティとして定められているものではなくて、勝手に付け加えたものです。イベントハンドラのクロージャ内で this はイベントを登録した marker オブジェクトになるわけですが、ここで先ほど勝手に付け加えた key プロパティが拾えています。

####実運用している例
秘密情報ですが、この技は[ここ](http://mato.me/farm/access)で実際に使っていますので、全コードを見たり、動きを見ていただくことが可能です。いつまでこの仕組みを使い続けるか不明ですが。
MySQLで、my.cnfを更新しようとした時にハマった話

※20201211追記

今見ると全然情報量のない記事で申し訳なくなってきますね…。

下に書いたコマンドはRHEL6系でのもので、RHEL7系（今のUbuntuとかでも多分同じ）ではsystemdの`systemctl`コマンドを使って下記のようにします。
```bash
sudo systemctl stop mysqld
sudo systemctl start mysqld
```

さらに言うと、`mysql`じゃなくて大抵は`mysqld`ですね…。(修正済み。`mysql`でもいいかもしれませんが未確認)

reloadやrestartでも問題ないことはあるでしょうけど、うまく行かなかったら一度明示的に止めて、立ち上げる、というのをしてみましょうというだけですね。
これはMySQLでなくても同じことです。
my.cnfが反映されないみたいなのは調べるといろんなケースが出てくるので、あくまで一つのケースとして残しておきます。

---
すごく単純だけど、忘れるとめんどくさいので覚書。  

my.cnfを更新して、mysqlを再起動しようとしたところ、うまく行かなくてハマってしまった。
http.confとかその辺みたいな感覚で再起動時に反映するのかな、と思ったのに。  

と、いうわけで、手順として
1. mysqlを止める
2. my.cnfを更新する
3. mysqlを起動し、エラーが無いことを確認する。

という感じで行うようにする必要あり。

```bash
sudo service mysqld stop
```
↓
my.conf修正
↓

```bash
sudo service mysqld start
```

これだけですが、忘れないようにしないと…。
２つのファイルの共通行を抽出する方法

# はじめに
2つのリストから共通した行を抽出する方法

# grepコマンドを使う方法
文字の大小・ソートしていないファイルに対してイッパツで対応出来ます。
## コマンド
```shell-session
grep -x -i -f  file1 file2
```
## 説明
+ オプションx
> 行全体を検索対象にする

+ オプションi
> 検索条件に大文字と小文字の区別をなくす

+ オプションf
>　検索パターンとしてfileの内容を使用する

## 実行例
```shell-session
$ cat test1.txt
eee12345
AAA12345
$ cat test2.txt
aaa12345
bbb12345
ccc12345
ddd12345
eee12345
$
$ grep -x -i -f  test1.txt test2.txt
aaa12345
eee12345
```
# commコマンドを使う方法
なじみのないcommコマンドを使う方法。
commコマンドのオプション1とオプション2をあわせて使うと確かに共通行が出る！！
※inputファイルはソート済みであること。
※文字の大小もそろえてあること。
## コマンド
```shell-session
comm -1 -2 file1 file2
```
## 説明
+ オプション1
>　FILE1で指定したファイルの内容のみに存在する行を出力しない。

+ オプション2
>　FILE2で指定したファイルの内容のみに存在する行を出力しない。


## 実行例
+ ソート済み・大小もそろえたファイルを対象とした場合

```shell-session
$ cat test1.txt
aaa12345
eee12345
$ cat test2.txt
aaa12345
bbb12345
ccc12345
ddd12345
eee12345
$ comm -1 -2 test1.txt test2.txt
aaa12345
eee12345
```
+ ソートを行わないファイルを対象としたとき

```shell-session
$ cat test1.txt
eee12345
AAA12345
bbb12345
[vagrant@localhost tmp]$ comm -1 -2 test1.txt test2.txt
eee12345
comm: file 1 is not in sorted order
```

# 参考にしたサイト
http://codezine.jp/unixdic/w/comm
[MySql] Some notes when install mysql with homebrew

#### Start Errors
When use `mysql.server start` has the following error:

```bash
Starting MySQL
ERROR! The server quit without updating PID file (/usr/local/var/mysql/<PC-NAME>.local.pid).
```

Solution:

```bash

sudo chown <USER-NAME> <PC-NAME>.local.err
```

#### Start mysql from startup in OS X

```bash
ln -sfv /usr/local/opt/mysql/*.plist ~/Library/LaunchAgents
launchctl load ~/Library/LaunchAgents/homebrew.mxcl.mysql.plist
```
マテリアルデザイン#2 Subheaders, Switches, Snackbars & toasts


マテリアルデザインのコンポーネントのうち、

* Subheaders
* Switches
* Snackbars & toasts
の３つについて簡単にまとめる。

各コンポーネントがどういう目的で使われ、利用するときに気をつけるべきことはなにかを理解するためのメモ。
デザイナーさんが上げてきたデザインがマテリアルデザイン的に正しいかをチェックできるくらいの基礎知識を身につけることが目的。


# Subheaders
サブヘッダー（Subheaders）は、リストやグリッドで表示されているコンテンツをいくつかのセクションに分けるために利用される特別なタイルである。

主にリスト、グリッド、メニューの３パターンに分類される。

また、スクロールした時にサブヘッダーは画面の上側に固定される。
さらにスクロールして次のサブヘッダーが上部に来た時に、以前のサブヘッダーは消えて次のサブヘッダーが上部に固定される。

![components_subheaders4.png](https://qiita-image-store.s3.amazonaws.com/0/58726/4d43e48a-e322-88ac-402d-324adfdc0f6d.png "components_subheaders4.png")
Fig 1. リストのSubheadersの例。ここではFolders,FilesがSubheadersである。

## 仕様
リスト、グリッド、メニューそれぞれのサブヘッダーのレイアウトの規約などは[こちら](http://www.google.com/design/spec/components/subheaders.html#subheaders-list-subheaders)を参照。

# Switches
ユーザーがオプションを選択するために用いられるコンポーネントで、以下の３つがある。

* チェックボックス  
複数の選択肢を選択する場合に利用
* ラジオボタン  
１つの選択肢を選択する場合に利用
* On/Offスイッチ　　
on/offの状態を切り替えるだけの場合に利用

![components_switches_check3.png](https://qiita-image-store.s3.amazonaws.com/0/58726/40b6a67e-f5d7-ff39-1e4a-7b904bf4cc28.png "components_switches_check3.png")
Fig 2. チェックボックスの例


![components_switches_radio3.png](https://qiita-image-store.s3.amazonaws.com/0/58726/cb76990b-26d8-ca38-30db-3c36a373904e.png "components_switches_radio3.png")
Fig 3. ラジオボタンの例


![components_switches_switch3.png](https://qiita-image-store.s3.amazonaws.com/0/58726/41c734bc-3a33-ee6e-144e-8cfa34efd3c9.png "components_switches_switch3.png")
Fig 4. スイッチの例


# Snackbars & Toast
スナックバー(Snackbars)は、何らかの操作に対する簡易なフィードバックを提供するためのコンポーネントである。
モバイル端末では画面下部に、デスクトップでは左下に簡単なメッセージを表示する。
スナックバーは画面上のUI要素の上に表示し、アクションを含むこともできる。
その他の特徴を以下にまとめる。

* 時間により自動で消える。
* 画面のどこかをタッチしても消える。
* スワイプで消す事もできる。
* 入力を邪魔しない。
* 一度に表示されるのは１つだけ。
* Toastはスワイプできない、アクションを持たない点でスナックバーと異なる。

![components_toasts_mobile1.png](https://qiita-image-store.s3.amazonaws.com/0/58726/2fa2ceea-6256-a2cf-8e1f-bbbe427b510e.png "components_toasts_mobile1.png")
Fig 5. スナックバーのサンプル。 Archivedというテキストで下部に通知されており、UNDOというボタンで処理の取り消し（アクション）を行える。


## 使い方

* 操作の実行に直接関係する、わかりやすいテキストを表示する。
* アイコンは使わない。
* あくまで一時的なコンポーネントなので、アクションに対する核となる使用例としては用いず、他の方法で同じアクションができるように配慮する。
* 1つのスナックバーに対してアクションは多くても１つ。  
キャンセルボタンなどはつけない。もし重要なアクションであり、キャンセルが必要な場合などはダイアログの使用を検討する。

![components_toasts_usage6.png](https://qiita-image-store.s3.amazonaws.com/0/58726/15826448-16c3-2b44-afd6-e003ad6b5dd2.png "components_toasts_usage6.png")
fig 6. ダメな例。Dismiss（閉じる）ボタンは必要ない

* Floating Action Buttonの上には被せない。


## 仕様
レイアウトの規約などは[こちら](http://www.google.com/design/spec/components/snackbars-toasts.html#snackbars-toasts-specs)を参照。
表示の際の動きのサンプルもここで見ることができる。
Express 4.xでファイルがアップロード出来なくてはまった問題

```
npm install multer
```

そして

```
var multer = require('multer');
app.use(multer({dest: './tmp/'}));
```

良し.

----

### おまけ

* express@4.10.7
* multer@0.1.6

で

```
TypeError: Cannot read property 'image' of undefined
```

と怒られた, っていう話.
pip search に自分好みの表示機能を加える

こんにちは。
python のライブラリモジュールを（pypi 内で）検索するには下記のように pip コマンドを利用して検索結果を得ますが、加えて下記のような結果表示も加えたくなりました。

```console
$ pip search cvxopt
cvxopt                    - Convex optimization package
  INSTALLED: 1.1.7 (latest)
  https://pypi.python.org/pypi/cvxopt   <== この表示を加えたい

$ pip search pandas
pandas                    - Powerful data structures for data analysis, time series,and statistics
  LATEST:    0.15.2 (not installed)     <== この表示を加えたい
  https://pypi.python.org/pypi/pandas   <== この表示を加えたい
```

そこで、pip (v.6.0.x) の search に少し手を加えて実現してみました。

```console
$ ./mypatch.rb search.py.patch
```

```mypatch.rb
#!/usr/bin/ruby
# coding: utf-8
cmd = "patch -b -p0 < "
ARGV.each {|file|
    `#{cmd + file + " 2>&1"}`  # for sh/bash
}
```
```search.py.patch
--- /usr/local/lib/python2.7/site-packages/pip/commands/search.py
+++ search.py.orig
@@ -47,7 +47,7 @@
         if sys.stdout.isatty():
             terminal_width = get_terminal_size()[0]
 
-        print_results(hits, terminal_width=terminal_width)
+        print_results(hits, query, terminal_width=terminal_width)
         if pypi_hits:
             return SUCCESS
         return NO_MATCHES_FOUND
@@ -101,7 +101,7 @@
     return package_list
 
 
-def print_results(hits, name_column_width=25, terminal_width=None):
+def print_results(hits, query, name_column_width=25, terminal_width=None):
     installed_packages = [p.project_name for p in pkg_resources.working_set]
     for hit in hits:
         name = hit['name']
@@ -125,6 +125,11 @@
                     else:
                         logger.info('INSTALLED: %s', dist.version)
                         logger.info('LATEST:    %s', latest)
+            elif in_case_insensitive(name, query):
+                latest = highest_version(hit['versions'])
+                logger.info('  LATEST:    %s (not installed)' % latest)
+            if in_case_insensitive(name, query):
+                logger.info('  %s/%s' % (PyPI.pypi_url, name))
         except UnicodeEncodeError:
             pass
 
@@ -133,3 +138,7 @@
     return next(iter(
         sorted(versions, key=pkg_resources.parse_version, reverse=True)
     ))
+
+def in_case_insensitive(x, list):
+    return x.lower() in [y.lower() for y in list]
+
```
カレントディレクトリのサブディレクトリを含んだファイルの文字列を一括置換

こんな感じで、'置換する文字列'を'置換したい文字列'に置換します。

```find . -type f | xargs grep -l '置換する文字列' | xargs sed -i.bk -e 's/置換する文字列/置換したい文字列/g'```

```find . -type f```
カレントディレクトリ及びそのサブディレクトリからファイル名を取得。

```xargs grep -l '置換する文字列'```
'置換する文字列'を含んだファイル名を抽出。

```xargs sed -i.bk -e 's/置換する文字列/置換したい文字列/g'```
抽出したファイルに含まれている'置換する文字列'を'置換したい文字列'に置換。
```-i.bk```このオプションで、置換するときにバックアップファイルを作成します。
バックアップが必要ない場合は```-i```だけでOK。
名前空間を取り除いたクラス名を取得する


Classクラスの`class_name`メソッドを使用すると取得できる。
と思ったら、`class_name`はPryでしか使用できなかった。

どこで定義されているのかを調べてみたら、
`yard`モジュールで定義されていたようだった。

```ruby:pry
[1] pry(main)> show-source Class.class_name

From: /Users/uchiko/.rbenv/versions/2.1.3/lib/ruby/gems/2.1.0/gems/yard-0.8.7.6/lib/yard/core_ext/module.rb @ line 7:
Owner: Module
Visibility: public
Number of lines: 3

def class_name
  name.split("::").last
end
[2] pry(main)>
```

ということで同じことをしたかったら、以下のようにすれば良さそう。

```ruby:sample.rb
module Hoge
  class Fuga
    def name
      self.fullname.split('::').last
    end

    def fullname
      self.class.to_s
    end
  end
end

m = Hoge::Fuga.new
p m.name     #=> "Fuga"
p m.fullname #=> "Hoge::Fuga"
```
peer認証の関係でpsqlログインできない時の対処法

出つくしていくるんだろうけど、メモ

環境： ubuntu14ぐらい　postgres9.3
現象：postgresでない自分のUNIXユーザーでログインしたシェルから、psqlを実行する際、postgresql上のユーザーの正しいパスワードを入力してもログインできない
こんな感じ

```bash:psqlログイン
hoge@ubuntu:~$ psql -U postgres -h localhost -W
Password for user postgres: 
psql: FATAL:  password authentication failed for user "postgres"
```

hogeがUNIXグループpostgresには参加済みでもこうなる。

問題はLinuxの仕組みではなくpostgresの認証の仕組みが関係していた。
postgresユーザー名とパスワードを指定してもローカルからのアクセスはUNIXユーザー名とパスワードがpostgresのものと同じでないとログインできないPeer認証というのがあった。
pg_hba.confに設定は
(ubuntuなら/etc/postgres/postgresのバージョン/main/pg_hba.confにあった)


いくつかのハマりパターンがあるんだろうけど、自分の場合
http://stackoverflow.com/questions/7695962/postgresql-password-authentication-failed-for-user-postgres
を参考にして以下の手順を行ったら自分のUNIXユーザーからpsqlログインに成功した

リンク先にまったく同じことは書いているけど、、、

* postgresユーザー"postgres"のパスワードをもう一度設定。
このときmd5で保存した。

`sudo su postgres -c 'psql --username=postgres'`

psqlに入った後、

`ALTER USER postgres with encrypted password 'your_password';`

* pg_hba.confを修正。

`local   all         postgres                          md5`

* postgresを再起動

これで個人のUNIXユーザーからposgresユーザー'postgres'としてpsqlログインできる

`hoge@ubuntu:~$ psql -U postgres -h localhost -W`
MySQL 5.5系で slow queryを見張る設定


とにもかくにも、何はともかく、slow query退治は大事である。ほっとくと、DBサーバがあっという間にアップアップしてしまう。

作ってしまった後に、手を入れると絶対に大変だし、MySQL慣れしてない人が書いたクエリなんかもちゃんと指摘しないといけないし、いろいろとあるので、プロジェクト開始直後から厳しく、綿密にチェックする必要がある。


## 確認

`mysql -u root`で入り

```
show variables like 'slow%';
show variables like 'long%';
```


## 設定

`mysql -u root`で入り

```
set global log_output = 'TABLE';
set global long_query_time = 0.3;
set global slow_query_log = ON;
```

私は出力先がTABLEのほうがいろいろツブシがきいて好きなのだが、ファイルにする場合にはパスなどもあわせて設定すること。

`long_query_time`を`0`に指定すると全部slow query扱いになる。`0.3`という指定もここでは独断と偏見でしているが、プロジェクトの要求仕様に応じても最初から厳しい値にしておいたほうがいい。`0.1`とか。


## 見る

`select * from mysql.slow_log order by start_time desc limit 10` などすれば、どんなクエリが遅かったのかを確認できる。


## muninで見張る

mysqlのプラグインがあるので見張る。とても便利。サンプルとして2枚ばかり貼る。

前述した見る、だと、どうしても手間がかかるので、本番が近くなってくると、こういうので確認し、つぶしていくとよい。

運用が始まったら始まったで、DBが原因で遅いのか？など確認できて非常に便利。

![mysql_innodb_rows-day.png](https://qiita-image-store.s3.amazonaws.com/0/50220/ef46c5fd-d84d-1d08-38b0-03f2c4bfea09.png "mysql_innodb_rows-day.png")


![mysql_slow-day-2.png](https://qiita-image-store.s3.amazonaws.com/0/50220/bd5dfbce-d85c-2cab-ee5e-4c2f92f9dd08.png "mysql_slow-day-2.png")



## 解決方法

- ほとんどindexチューンで問題無いことが多い。
	- 次はメモリが足りない、とか、insertが遅い、とかになるが、これはスケールアップするか、マルチマスタを検討する。(筆者はマルチマスタは経験がない)
- lock_timeが大きくなる場合には、read replicationを増やすことをやらないと解決できないことが多い。
	- 例えば、DBをケチって集計cron参照先と運用が同じDBの場合など、こうなることが多い。
PyYAMLで順序を保持して読み込む

PyYAMLについてメモ

PyYAMLでYamlファイルを読み込んだ場合、デフォルトだと通常のDictionaryとして読み込むため、
ファイルの順序が保証されない。

例えばこんな感じのYamlファイルがあったとして、

```yaml:data.yml
aaa:
  a1: 1
  a2: 2
  a3: 3
bbb:
  b1: 1
  b2: 2
  b3: 3
ccc:
  c1: 1
  c2: 2
  b3: 3
```

普通に`yaml.load`して出力すると

```py:yaml_load.py
import yaml

data = yaml.load(file("data.yml"))

for k1, v1 in data.items():
    for k2, v2 in v1.items():
        print("%s - %s - %s" % (k1, k2, v2))
```

こんな感じになる。

```:実行結果
aaa - a1 - 1
aaa - a3 - 3
aaa - a2 - 2
bbb - b1 - 1
bbb - b2 - 2
bbb - b3 - 3
ccc - c2 - 2
ccc - c1 - 1
ccc - b3 - 3
```

ファイルに記載されている通りの順序で読み込みたい場合は、OrderedDictとして読み込むようにしてやる

```py:yaml_load.py
import yaml
from collections import OrderedDict

# これを追加する
yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
    lambda loader, node: OrderedDict(loader.construct_pairs(node)))

data = yaml.load(file("data.yml"))

for k1, v1 in data.items():
    for k2, v2 in v1.items():
        print("%s - %s - %s" % (k1, k2, v2))
```

これで順序を保持して読み込める。

```:実行結果
aaa - a1 - 1
aaa - a2 - 2
aaa - a3 - 3
bbb - b1 - 1
bbb - b2 - 2
bbb - b3 - 3
ccc - c1 - 1
ccc - c2 - 2
ccc - b3 - 3
```

[この辺](http://stackoverflow.com/questions/5121931/in-python-how-can-you-load-yaml-mappings-as-ordereddicts
)を参考にした

以上
WordPressで任意の$postオブジェクトを現在の$postとしてセットして、the_content()等の出力内容をテスト


以下のようなテストをしたいときに便利。

* ショートコードが期待通りに発火する？
* the_contentなどのフィルターフックが発火してる？

テストの流れ。

1. テスト用の投稿を保存
2. `get_post()`で$postオブジェクトを取得する。
3. `setup_postdata()`で現在のカレントの`$post`にセットする。
4. `the_content()`などのテンプレートタグの出力をテストする。

```php
<?php

class Sample_Test extends WP_UnitTestCase
{
	/**
	 * @test
	 */
	function sample_test()
	{
		$args = array(
			'post_title' => 'Hello',
			'post_author' => 1,
			'post_content' => 'Hello World!',
			'post_status' => 'publish',
			'post_date' => '2014-01-01 00:00:00',
		);

		$this->setup_postdata( $args );

		/*
		 * the_content()の結果に対してテスト
		 */
		$this->expectOutputString( "<p>Hello World!</p>\n" );
		the_content();
	}

	/**
	 * Add post and post be set to current.
	 * 
	 * @param  array $args A hash array of the post object.
	 * @return none
	 */ 
	public function setup_postdata( $args )
	{
		global $post;
		global $wp_query;

		$wp_query->is_singular = true;

		$post_id = $this->factory->post->create( $args );
		$post = get_post( $post_id );
		setup_postdata( $post );
	}
}
```
CentOS7へのJenkinsのインストール手順

## Javaインストール
```
# yum install java-1.7.0-openjdk
```

## Jenkinsのyumリポジトリ追加

```
# cd /etc/yum.repos.d
# curl -O http://pkg.jenkins-ci.org/redhat/jenkins.repo
# rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
```

## Jenkinsのインストール

```
# yum install --enablerepo=jenkins jenkins
```

## HTTPS用の証明書の作成

とりあえず自己署名証明書にしておく。

```
# cd /var/lib/jenkins
# mkdir .ssl
# keytool -genkey -alias jenkins-ssl-cert -keyalg RSA -keystore .ssl/.keystore -validity 365
# // パスワード以外はすべてデフォルト。最後は「はい」
# chown -R jenkins.jenkins .ssl
```

## Jenkins設定ファイルを更新

HTTPではなく、HTTPSで、なおかつポート番号(XXXXX)を使用する場合。

```lang:/etc/sysconfig/jenkins
JENKINS_PORT="-1"
JENKINS_HTTPS_PORT="XXXXX"
JENKINS_HTTPS_KEYSTORE="/var/lib/jenkins/.ssl/.keystore"
JENKINS_HTTPS_KEYSTORE_PASSWORD="password" # .keystoreのパスワードを設定
```


## ファイアウォールの設定
```
# firewall-cmd --zone=public --permanent --add-port=XXXXX/tcp
# firewall-cmd --reload
```

## サービスの自動起動設定
systemctlでenableにできなかった。

```
# chkconfig jenkins on
```

## サービスの再起動
```
# systemctl start jenkins
```

## 終わり

とりあえずこれでブラウザからアクセスできる。
iOSアプリのプロビジョニング周りを図にしてみる

# きっかけ
iOSアプリ公開の壁となっているプロビジョニング周りですが、ハマりまくったので覚えている内に図にしました。

## 難しくしてる理由
難しくしているのは、この辺が理由ではないかと思います。

1. iOS Developerサイトでの画面・操作手順がしょっちゅう変わる
2. Xcodeも、バージョンによって画面・操作手順が変わる

ということで、書籍やWebでのノウハウがすぐに古くなってしまいます。ググるといろんな情報が出てきてしまい、かえって混乱します。

また、開発時のiOSデバイスはXcode側である程度自動的にやってくれるのですが、それがかえって分からなくしているような気がします。


# 概念図
ということで、結局、概念を理解してしまうのがいいのではないかと思い、図にしてみました。
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/53823/c57f9a68-953f-87b9-4055-ce38976ea9fc.png)
（より厳密に実行端末が判断されるAd Hoc配布をベースに記述）

## ざっくり手順（※個別の操作は省略）
1. 鍵ペア（秘密鍵／公開鍵）を作成
    ※秘密鍵は端末内から外へ出ません

2. 公開鍵をCSR（証明書署名要求）として認証局（Apple）に送付

3. 証明書発行
    ※受け取った公開鍵から証明書を作成し、認証局の秘密鍵で署名

4. 発行された証明書をDLしてキーチェーンに登録

5. App IDを登録

6. 実行を許可する端末を登録
    ※端末のUDID（複数）

7. プロビジョニングファイルを作成
    ※証明書、App ID、実行許可端末を関連付け

8. プロビジョニングファイルをDLして端末内に登録

9. 配布したいアプリケーションにBundleID、コードサイニング（署名）の設定を行う

10. アプリケーションをビルド、アーカイブし、パッケージファイル（ipaファイル）を作成
    ※ipaファイルはZIP形式でまとめられており、プロビジョニングファイルを含む
    ※パッケージファイル全体に署名を施す

# あらためて、動作条件
配布アプリが端末内で動作する条件は、以下の通りです。
・ アプリのBundleIDが、AppIDと一致
・ コードサイニング（署名）が正しい
・ 実行が許可された端末である

ということで、様々発生する可能性のある問題は、上記条件に合致しないケースとなります。

## アプリのBundleIDが、AppIDと一致していない
・ Xcodeで設定したアプリのBundleIDと、プロビジョニングファイル内のApp IDが合っていない

Prefix,Suffix,ワイルドカードを含めて合致するかどうかなので注意

## アプリの署名が正しくない
・ コードサイニング（署名）から発行元の正当性が確認できない
・ プロビジョニングファイル内の証明書内の公開鍵と、ビルド時に署名に使った秘密鍵がペアになっていない

合致する秘密鍵をインポートしないまま違う端末でビルドした、コードサイニングに用いる署名を間違った、など。

・ ipaファイルを手動でZIP展開し、一部を改変した

ファイルの一部が変わるとハッシュ値が変わるため、署名と一致しない（＝不正）と判断されます。

[コードサイニング証明書の仕組み](https://jp.globalsign.com/service/codesign/knowledge/scheme.html)
[Digital Signature diagram ja - 電子署名 - Wikipedia](http://ja.wikipedia.org/wiki/%E9%9B%BB%E5%AD%90%E7%BD%B2%E5%90%8D#mediaviewer/File:Digital_Signature_diagram_ja.svg)

## 実行が許可された端末ではない

・ （アドホックの場合）プロビジョニングファイルに含まれる実行許可端末以外の端末で実行しようとしている

プロビジョニングファイルには実行許可端末のUDID（一意キー）が含まれているので、ipaファイルは実行許可端末を知っていることになります。


## その他
・ ビルドやアーカイブ時など、Xcode上で表示されるプロビジョニングファイルがサーバの一覧を見ているのか、ローカル内の一覧を表示しているのかよく分かんないケースがあります。不要と思っても一応リフレッシュしてみるといいかもしれません。

・上図の通り、鍵ペア（秘密鍵・公開鍵）がポイントになります。鍵ペアを作った後に端末が壊れたりすると鍵ペアの秘密鍵のほうが無くなってしまい、公開鍵を含む証明書・プロビジョニングファイルが使えなくなります。秘密鍵はパスワードエクスポートして影響のない場所にバックアップしておくのが良いと思います。（キーチェーンアクセスにエクスポート機能があります）

# さいごに
動作しない理由が分からないとイライラするものですが、上の条件がOKかどうか、一つずつ確認していくといいかと思います。（私のことですね）

お役に立てば幸いです。
jekyllのローカル開発サーバーを立ち上げました

jekyllのローカル開発サーバーを立ち上げようとしたらコマンドを忘れていました。

```bash:jekyllのビルトインサーバーを立ち上げる
bundle exec jekyll serve

略

Server address: http://0.0.0.0:4000/
Server running... press ctrl-c to stop.
```
jekyllのサーバーが立ち上がりました。
http://0.0.0.0:4000/ にアクセスすると表示が出来ました。ポートは4000番なんですね(☝ ՞ਊ ՞)
Firefoxでの動画再生

私が作っているWebGLアプリ作成フレームワーク[enforce3D](https://github.com/digitarhythm/enforce3d)で、ポリゴンに動画を貼れるようにしているのだが、Safari、Chrome、Firefoxだと何故かFirefoxだけ動画が再生出来ない。ぐぐってみると、MozillaがH264の莫大なライセンス料を払わないことにしているかららしい。

それならばと、オープンライセンスなOgg Theoraフォーマットの動画に変換して再生してみたが………画質は悪いしカクカクになるし…さらに同じ動画でもChromeのほうが再生画質がいい。

今のところ、「WebGL」「vr.js」「GamepadAPI」の全てに対応してるのがFirefoxだけなので、私がWebでVRをやろうと思った場合はFirefoxしか選択肢が無いので、なんとかしてFirefoxでH264再生が出来るようにならないだろうか。

有料のプラグインでもいいのだが。
久々にログインしたサーバでyumしたらepel接続でsslエラーが出たので対応


久々にログインしたテスト用のcentosでyumしたところ、epelリポジトリへのsslコネクションが失敗している様子。。

```
$ sudo yum install java-1.8*
Loaded plugins: fastestmirror, priorities
Loading mirror speeds from cached hostfile
Could not get metalink https://mirrors.fedoraproject.org/metalink?repo=epel-6&arch=x86_64 error was
14: problem making ssl connection
Could not get metalink https://mirrors.fedoraproject.org/metalink?repo=epel-debug-6&arch=x86_64 error was
14: problem making ssl connection
Could not get metalink https://mirrors.fedoraproject.org/metalink?repo=epel-source-6&arch=x86_64 error was
14: problem making ssl connection

```

[ネットワーク・セキュリティサービス(nss)](http://www.mozilla-japan.org/projects/security/pki/nss/)をアップデートする必要があるらしい 

※epelをdisableにして使うときだけ指定すればいいという話ではあるが。。

```
$ sudo yum install -y nss
```
これでエラー解消。

簡単ですが、結構はまった。。
admin_enqueue_scriptsフックで期待通りにjsやcssがロードされるかのテスト


## プラグイン側の処理

テストしたいコードは以下のような感じ。

`wp-admin/post.php`または`wp-admin/post-new.php`で、プラグイン独自のCSSやJavaScriptを読み込ませる。

`wp-admin/post.php`や`wp-admin/post-new.php`以外では読み込んでほしくない。


```php
	/**
	 * Fires on plugins_loaded hook.
	 *
	 * @param  none
	 * @return none
	 */
	public function plugins_loaded()
	{
		add_action( 'admin_enqueue_scripts', array( $this, 'admin_enqueue_scripts' ) );
	}

	/**
	 * Fires on admin_enqueue_scripts hook
	 *
	 * @param  none
	 * @return none
	 */
	public function admin_enqueue_scripts( $hook_suffix )
	{
		/*
		 * 管理画面のpost.phpまたはpost-new.phpでのみjavascript及びcssを追加
		 */
		if ( 'post-new.php' === $hook_suffix || 'post.php' === $hook_suffix ) {
			wp_enqueue_script(
				'tinymce-templates',
				plugins_url( 'js/tinymce-templates.js', __FILE__ ),
				array( 'jquery' ),
				filemtime( dirname( __FILE__ ) . '/js/tinymce-templates.js' ),
				true
			);

			wp_enqueue_style(
				'tinymce-templates',
				plugins_url( 'css/tinymce-templates.css', __FILE__ ),
				array(),
				filemtime( dirname( __FILE__ ) . '/css/tinymce-templates.css' )
			);
		}
	}
```


## PHPUnit用のテストコード

`admin_enqueue_scripts`フックのコールバック関数を実行して、`wp_style_is()`や`wp_script_is`でキューに保存されているかどうかをチェックする。

```php
/**
 * @test
 */
function admin_enqueue_scripts()
{
	$tinymce_templates = new TinyMCE_Templates();

	/**
	 * $hook_suffixがpost.phpでもpost-new.phpでもない
	 * wp_style_is(), wp_script_is()ともにfalseであるべき
	 */
	$tinymce_templates->admin_enqueue_scripts( '' );
	$this->assertFalse( wp_style_is( 'tinymce-templates' ) );
	$this->assertFalse( wp_script_is( 'tinymce-templates' ) );

	/**
	 * $hook_suffixがpost.php
	 * wp_style_is(), wp_script_is()ともにtrueであるべき
	 */
	$tinymce_templates->admin_enqueue_scripts( 'post.php' );
	$this->assertTrue( wp_style_is( 'tinymce-templates' ) );
	$this->assertTrue( wp_script_is( 'tinymce-templates' ) );

	/**
	 * $hook_suffixがpost-new.php
	 * wp_style_is(), wp_script_is()ともにtrueであるべき
	 */
	$tinymce_templates->admin_enqueue_scripts( 'post-new.php' );
	$this->assertTrue( wp_style_is( 'tinymce-templates' ) );
	$this->assertTrue( wp_script_is( 'tinymce-templates' ) );
}
```
ansible の条件判定でホストグループ別に実行を分けたいとき

メールサーバでは、localhost 以外のサーバからの smpt を受付け
アプリケーションサーバでは、自サーバでエラーが起こった時だけログをメールで送信したいとします。

その時に、postfix の設定ファイルを入れ分けたいので ansible でどうやってやるのか調べました。

参考にさせてもらったサイト①
http://d.hatena.ne.jp/akishin999/20130820/1377013914

```
- name: mailserver setting copy /etc/postfix/main.cf
  copy: src={{ item }} dest=/etc/postfix/ owner=root group=root mode=0644
  with_items:
  - mailserver_setting/main.cf
  when: hosts == “mailservergroup”　×

- name: default setting copy /etc/postfix/main.cf
  copy: src={{ item }} dest=/etc/postfix/ owner=root group=root mode=0644
  with_items:
  - default_setting/main.cf
  when: hosts == “apservergroup”　×
```

これだと hosts には実行対象のホスト名が入ってくるのでダメです。

今度は、”inventory” というキーワードで調べて見つけたのが inventory_hostname ですが結果は同じ。。。

参考にさせてもらったサイト②
http://ameblo.jp/pioho07/entry-11954301615.html

`  when: inventory_hostname == “mailservergroup”　×`

そっかホスト名しかダメなのか〜と思って

参考にさせてもらったサイト③：
https://groups.google.com/forum/#!topic/ansible-project/lr7nXyGw0UY

`　when: inventory_hostname in groups['mailservergroup']　×`

これだと上記のように相対する処理を入れていた時に、該当しない方がエラーとなってしまいました。。。

```
TASK: [postfix | mailserver setting copy /etc/postfix/main.cf] ****************
ok: [test-mailserver] => (item=mailserver_setting/main.cf)

TASK: [postfix | default setting copy /etc/postfix/main.cf] *******************
fatal: [test-mailserver] => error while evaluating conditional: inventory_hostname in groups['apservergroup']

FATAL: apservergroup hosts have already failed -- aborting
```

でも、近づいてきた気がする！！！

ここで “inventory_hostname” を忘れて、②のサイトをよくよく見てみると下の方に “グループ分け” って書いてある！！

`  when: "'mailservergroup' in group_names"`

表記はこんな感じです。

```
- name: mailserver setting copy /etc/postfix/main.cf
  copy: src={{ item }} dest=/etc/postfix/ owner=root group=root mode=0644
  with_items:
  - mailserver_setting/main.cf
  when: “’mailservergroup’ in group_names"

- name: default setting copy /etc/postfix/main.cf
  copy: src={{ item }} dest=/etc/postfix/ owner=root group=root mode=0644
  with_items:
  - default_setting/main.cf
  when: “’appservergroup’ in group_names"
```

`$ansible-playbook mailservergroup` のホストゆけー！

```
TASK: [postfix | mailserver setting copy /etc/postfix/main.cf] ****************
ok: [test-mailserver] => (item=mailserver_setting/main.cf)

TASK: [postfix | default setting copy /etc/postfix/main.cf] *******************
skipping: [test-mailserver] => (item=default_setting/main.cf)
```

行った！
Pure Python 版オンライン形態素解析ツール Rakuten MA

Pure PythonなRakuten MAを書いたのでその紹介記事です。

## Rakuten MAとは
[Rakuten MA](https://github.com/rakuten-nlp/rakutenma)は、楽天NLPプロジェクトさんによるJavaScriptの形態素解析器です。逐次でオンライン学習して手軽にモデルを更新できる点やブラウザを介してクライアント側から形態素解析ができる点などが特長だと思います。

詳しくは、以下の記事の説明がわかりやすいです。

- [本家 Rakuten MA 日本語ドキュメント](https://github.com/rakuten-nlp/rakutenma/blob/master/README-ja.md)
- [パソコン工房のPCで遊ぼう第2弾！ あんちべさんと一緒に Rakuten MA で形態素解析 - はてなニュース](http://hatenanews.com/articles/201501/22980)
- [RakutenMAによる形態素解析入門 - あんちべ！](http://antibayesian.hateblo.jp/entry/2015/01/08/085741)

## Python版 Rakuten MA
そんなRakuten MAをPythonで使いたいと思ったので、Python版を書きました！

`$ pip install rakutenma` でインストールできます。

https://pypi.python.org/pypi/rakutenma

```py3
from rakutenma import RakutenMA

rma = RakutenMA(phi=1024, c=0.007812)
rma.load("model_ja.json")
rma.hash_func = rma.create_hash_func(15)

print(rma.tokenize("うらにわにはにわにわとりがいる"))
print(rma.train_one(
       [["うらにわ","N-nc"],
        ["に","P-k"],
        ["は","P-rj"],
        ["にわ","N-n"],
        ["にわとり","N-nc"],
        ["が","P-k"],
        ["いる","V-c"]]))
```

こんな感じで本家JS版と同じようにAPIを使えるようになってます。
詳しくは上記PyPIを参照してください。

### <del>Python3系しか対応してないよ</del>
<del>本当はPython 2.7にも対応したかったのですが、気力が尽きたのでひとまずPython 3系のみ対応してます。</del>

<ins>バージョン0.2からPython 3.3, 3.4に加えてPython 2.6, 2.7でも動くようになりました。</ins>

### モデルの互換性あるよ
Rakuten MAのモデルは文字列をハッシュ関数によって数値化した値を扱います。このハッシュ関数の挙動をJS版と同じになるようにしたので、JS版と同じモデルファイルをPython版でも使い回すことができます。

このパッケージにはモデルファイルを含んでいないので、別途[本家Rakuten MAのリポジトリ](https://github.com/rakuten-nlp/rakutenma)から入手してください。

### 処理時間の比較
トークナイズと学習を1000回ずつ回して本家JS版と処理時間を比較してみました。

#### 実行環境

- CPU: Core i7 2GHz
- Memory: 8GB
- OS: Mac OSX 10.8.5

- Python: 3.4.2
- Node.js: 0.10.33
- Pypy: 2.4.0 (Python 3.2.5)

- Rakuten MA Python: 0.2
- Rakuten MA (JS): 1.0.0

#### 比較用コード
```python:rakutenma_benchmark.py
# -*- coding: utf-8 -*-
from rakutenma import RakutenMA

rma = RakutenMA()
for i in range(1000):
    rma.tokenize("もう何も怖くない")
    rma.train_one(
        [["もう","F"],
         ["何","D"],
         ["も","P-rj"],
         ["怖く","A-c"],
         ["ない","X"]])
```

```javascript:rakutenma_benchmark.js
var RakutenMA = require('./rakutenma');

var rma = new RakutenMA();
rma.featset = RakutenMA.default_featset_ja;

for (var i = 0; i < 1000; i++) {
    rma.tokenize("もう何も怖くない");
    rma.train_one(
        [["もう","F"],
         ["何","D"],
         ["も","P-rj"],
         ["怖く","A-c"],
         ["ない","X"]]);
}
```

#### 結果

<ins>計算機に余裕がある状態で計り直しました。(2015/01/15)</ins>

```
$ time python rakutenma_benchmark.py 

real	0m3.583s
user	0m3.573s
sys	0m0.009s

$ time node rakutenma_benchmark.js

real	0m1.852s
user	0m1.831s
sys	0m0.027s
```

本家JS版と比べて2倍近く時間がかかってます(;´Д`)

ついでにPypyでも試してみました。

```
$ time pypy3 test.py 

real	0m1.908s
user	0m1.859s
sys	0m0.042s
```

本家と並ぶ性能が出ました。

## さいごに
Python版Rakuten MAを書きました。本家と比べて2倍近く遅いし、ブラウザから使えるという大きなメリットを失っているのでいまいちですが、グルーコードを書かずにPythonからRakuten MAを使える、この一点だけが存在意義です。
(Djangoメモ)ImageFieldを使う


PIL（PythonImagingLibrary）が必要。
インストールは[easy_install](http://qiita.com/juniskw/items/10a4155dbd0864fa40e4)で出来る。
参考：http://memo.yomukaku.net/entries/BWTTNPl

インストールできたらまずは画像のアップロード先になるディレクトリ **MEDIA_ROOT** を設定。

```py:settings.py
#...
MEDIA_ROOT = os.path.join(BASE_DIR,'media')  # デフォルトでは定義されていないので手書き追加
#...
```

あとは好きなように作って・・・

###### 例

```py:models.py
class Face(models.Model):
	image = models.ImageField(upload_to='images/')  # upload_toは指定必須で、MEDIA_ROOT以下の同名ディレクトリにファイルがアップロードされる
	is_ok = models.BooleanField()
```

**アップロード先のパーミッション**をいじればOK。
サムスン GALAXY S III α SC-03E docomo の標準ブラウザと Chrome 間を行き来がしたい

# 標準ブラウザと Chrome の行き来がしたい

## 理由

### Chrome を使うようになった理由

- ソフトウェアアップデートが原因で標準ブラウザがクラッシュするようになった
- Chromecast を使うようになった

### 標準ブラウザに戻りたい理由

- Chrome のダウンローダは途中で失敗する率が高い
- ブックマーク・保存したページの利用
- Adobe Flash が必要なページがある（無理やり使える）

## 方法

- 共有からインテントを使う

## 問題点

- インテントの種類
- ブラウザの判別方法
- 他のアプリからの動作
- URL の抽出

### インテントの種類

共有から出ているのは `Intent.ACTION_SEND` で、
ブラウザを開くのが `Intent.ACTION_VIEW` なので、
Inten を新規作成するのが一番手っ取り早い.

### ブラウザの判別

#### Intent の flags を使う

一番手っ取り早い方法です.
自分の端末では以下の値が格納されていました.

```java

int 標準ブラウザ = 5033164;
int Chrome      = 50855937;
```

```java

Intent intent = mActivity.getIntent();
String action = intent.getAction();
if (Intent.ACTION_SEND.equals(action)) {
  int flags = intent.getFlags();
  
  // ...
  // TODO: Intent.EXTRA_TEXT から URL を取得
  // TODO: Intent.EXTRA_SUBJECT から URL を取得
  // ...

  Intent newIntent = new Intent(Intent.ACTION_VIEW, uri);
  switch(flags) {
    case 5033164: // 標準ブラウザだったら Chrome で開く
      newIntent.setPackage("com.android.chrome");
      mActivity.finish();
      break;
    case 50855937: // Chrome だったら標準ブラウザで開く
      newIntent.setPackage("com.android.browser");
      mActivity.finish();
      break;
  }
  mActivity.startActivity(newIntent);
}
```

`mActivity.finish()` をすると戻るボタンで元のブラウザに戻れるようになったりするよ.

### 共有からURLを抽出

共有からURLを取得するためには判別するしかない.

```java

private static final String HTTP_URL_PATTERN =
  "(http://|https://){1}[\\w\\.\\-/:\\#\\?\\=\\&\\;\\%\\~\\+]+";

private String getUrl(String text) {
  if (text == null) {
    return null;
  }
  Pattern urlPattern = 
    Pattern.compile(HTTP_URL_PATTERN, Pattern.CASE_INSENSITIVE);
  Matcher matcher = urlPattern.matcher(text);
  if (matcher.find()) {
    return matcher.group();
  }
  return null;
}
```

これさえわかればあとは煮るなり焼くなり好きにできる.

### 他のアプリからの動作

`setPackage` を行わず単純に URL を開く

## 結論

標準ブラウザの保存ページのエクスポートと Chrome のダウンローダが正常に動作すればこんなことしなくて済むのでサムスンと Google はなんとかしてください.
最新のソフトウェアアップデートを適用させると 最新バージョの Youtube が再生できない不具合があるので、アプリで検索してブラウザで再生することもできるので "共有" からブラウザで開く機能は非常に便利です.

### 作った

Github - [tanjo/http-intenter](https://github.com/tanjo/http-intenter)

キャッシュを保存しているのは後々履歴表示やらなんやらしたり.
インテントのカスタマイズもできるようにしたいなぁという願望の元保存されている.
いらないなら消せばいい.
Re-install guest additions when Vagrant can't mount host folders

I'm running a CentOS 7 box, once after a `yum update`, I got these errors when restart by `vagrant reload`:

```
Failed to mount folders in Linux guest. This is usually because
the "vboxsf" file system is not available. Please verify that
the guest additions are properly installed in the guest and
can work properly. The command attempted was:

mount -t vboxsf -o uid=`id -u vagrant`,gid=`getent group vagrant | cut -d: -f3`
vagrant /vagrant
mount -t vboxsf -o uid=`id -u vagrant`,gid=`id -g vagrant` vagrant /vagrant

The error output from the last command was:

/sbin/mount.vboxsf: mounting failed with the error: No such device


```

![vagrant_error_1.png](https://qiita-image-store.s3.amazonaws.com/0/2179/454fc1f0-b9c3-8d28-094b-af8b37169d41.png)


So I recognized that I should re-install the guest addition tools. In the console I have tried:

```
# /etc/init.d/vboxadd setup
Removing existing VirtualBox non-DKMS kernel modules       [  OK  ]
Building the VirtualBox Guest Additions kernel modules
The headers for the current running kernel were not found. If the following
module compilation fails then this could be the reason.
The missing package can be probably installed with
yum install kernel-devel-3.10.0-123.13.2.el7.x86_64

Building the main Guest Additions module                   [FAILED]
(Look at /var/log/vboxadd-install.log to find out what went wrong)
Doing non-kernel setup of the Guest Additions              [  OK  ]
```

![vagrant_error_2.png](https://qiita-image-store.s3.amazonaws.com/0/2179/518203d2-8815-aeed-d80e-10d77dfdfd2f.png)

Something got wrong in building the guest additions. And also it told me that I should also update the `kernel-devel` package. Off course I tried it:

```
yum install kernel-devel-3.10.0-123.13.2.el7.x86_64
```

Rerun the `/etc/init.d/vboxadd setup` command after installed the `kernel-devel` package, this time all were ok.

![vagrant_error_3.png](https://qiita-image-store.s3.amazonaws.com/0/2179/163de6a1-dacf-eeb1-039f-897888f400af.png)