OmniAICreator/Qiita-1.07M huggingface dataset:
minimongoでIsomorphic Storage

https://github.com/mWater/minimongo

```
npm install minimongo --save
```

minimongoは元々isomorphicフレームワーク(サーバーとクライアントのコードを同時に記述するパラダイム)のmeteorの中で使われてた使われた、コアとも言えるDB層であり、ブラウザでもサーバーでも動くように作られている。meteor触る時に一番特徴的な機能だと思う。

これがmeteorから単体で切りだされてForkされていた。meteorで使うのと多少APIが違うが、使える感じだった。(meteorは黒魔術的に非同期処理を隠蔽する機能があり、これをオミットしている)

## 良さ

- 元々meteorの中で使われたので、比較的実績がある
- mongo shell風のAPIがAPIがクライアントでも使える

僕はmongodb慣れてるのであのAPIでさっくりストレージを使いたい。
後者が目的でlokijs使ってたんだけど動作が不安定すぎて捨てた。


## Isomorphic!

purejsで書かれていて、環境ごとにバックエンドを任意に切り替えられるのが最大の特徴。
高速なインメモリモード、クライアントでIndexedDbかWebSQLをバックエンドにしたモード、MongoのREST API に透過するモード、インメモリDBとリモートDBを組み合わせるハイブリットモードがある。(ハイブリッドDBがあるってのはREADMEにあるんだけど、どんな動きに異なるかは把握してない)

学習コストの都合上、インメモリでもなんらかのストレージがバックエンドでも同じようなAPIで叩けるのは強い。要求速度によってバックエンドを変更すればスケールもしなくもなさそう。

こういう、Meteor使わなくてもいいのでMeteorの資産がこういう風に使えるようになるのは嬉しい。

ちなみに今のChromeだとIndexedDbで5MB使える。最近はAtomShell使ってるんだけど、AtomShellだと130MBまで許可されてて強い。


## サンプルコード

IndexedDb使う。

```js
var minimongo = require('minimongo');
var test = new minimongo.IndexedDb('test');
test.addCollection('col');
test.col.upsert({a: 1}, function(){console.log('item 1 save done')});
test.col.upsert({a: 2}, function(){console.log('item 2 save done')});

// 取り出す
test.col.find().fetch(function(data){
  console.log(data); // [{a:1, _id: 'a2e4ebeac1c540e19f2a71628dacf88d'}, {a:2, _id: "afd3841ce6c7477e9092087012a826e9"}]
})
```

IndexedDbを使えばちゃんと永続化されてる。
揮発して良いなら`new minimongo.MemoryDb('test')`でやればよい。

## クライアントでインメモリDBというアプローチの嬉しさ

- サーバーサイドっぽい開発アプローチがクライアントでも適用できる
- ReactがIsomorphicっぽいので相性が良い

やっとクライアントサイドの開発ノウハウが揃ってサーバーの開発ノウハウを応用できるようになってきた感。
APIデザインについてはあとで自分とこのブログに書きたい。
2台構成のElasticsearchでは1台停止中にindexを削除してはならない

elasticsearchを2台構成で組んでいるとき、1台が停止中にindexを削除すると、停止中の1台が復活した際に削除したindexが復活することに多少困っている。

Indexの削除を含む作業は、ちゃんと2台とも立ち上がっている時にやった方がいい。

実験していないが、削除の目的がMappingを変更して同じ名前のIndexを作るとかだったらどうなるのか不安で日中もう眠りたい。
iOSの提出アプリのバージョンはこうしろ！



下記の記事はobsoludedとなりました。あしからず。

はい、たまにはこっちにも書かないと。taです。よそよそしくしてね。
バージョンと言っても、GitとかSvnの話ではないのであしからず。結論から言っておくが、
**iOSの場合、ビルド番号と、バージョン番号は、分けておくべきだ。**

たとえば、iOSのアプリって、バージョンは、1.2.3とか、数字３つで管理してるよね。どのアプリもだいたいそうなってるから、だいたいみんなやってると思う。

でもビルド番号は、バージョン番号よりひとつ数字を多くしよう。1.2.3.15とか、４つの数字にするのが良い。

ああ、面倒だから、ここではひとまず「桁」と言っておこう。（通じるよね）
つまり、バージョンを２桁で管理してるなら、３桁のビルド番号にすればいい。３桁バージョンなら4桁のビルド番号。

なぜなら、そうしないと、アップロード用ビルドを作る毎にバージョンを上げないと、提出できないからだ。どこに？　とか聞くな。

つまり、ビルド番号のほうの桁を多くしておくと、アップロード済みのバージョン番号は前回と同じまま、新ビルドをITCにアップロードできる。

で、アップロード済みといっても、公開済みとはまた状態が異なるので、テストフライトなどでバグが見つかっても、再修正版はビルド番号だけ変えて再度アップロードしちゃえばいい。

そうすれば、いきなりバージョンの数値が飛んだ状態で公開したりしなくてすむ。

ちょっとしたミスで、公開バージョンがぽんぽん上がっちゃうのを避けたいなら、ビルドは1桁多くしておけば良いってことです。

いかんせん、ミスってのは起こるものだ。

以上。
接続されている全デバイスに同じインテントをBroadcastするシェルスクリプト

```bash:adb_all.sh
adb devices | sed '1d' | sed -e "s/device//" | sed '/^$/d' | while read i; do adb -s ${i} $@; done;
```

これに実行権限つけたうえで（`chmod a+x ~/bin/adb_all.sh`），たとえば
```
$ adb_all.sh shell am start -a android.intent.action.VIEW -d http://qiita.com/
```
とやると，接続されている全デバイスにQiitaサイト表示のインテントが飛ぶ．
（adbを代替しているので `adb shell am XXX` なコマンドはぜんぶ同様に扱える．）

`$@` は全引数を展開して渡すので便利だ．`adb devices`の結果のsed処理は，なんか1行目が空行無視処理をすりぬけるのであきらめて`sed '1d'`で消した．
dockerでslackにHubotを住まわせる

## 概要
CentOS7にHubotを立ててslackに住まわせるまでの記録。始めはherokuに立てる予定だったがやはり無料だと色々制限されるので、持て余しているさくらVPS上に構築した。

## dockerを使わない場合
「docker言うたやん」と思うかもしれないが、まずdockerを使わない場合でディレクトリ構成を説明する。
最近は何でもかんでもyeomanで雛形を作るのが流行らしい。

```bash
% npm install -g yeoman generator-hubot
% mkdir hubotdir
% cd hubotdir
#adapterがデフォルトではcampfireになっているのでslackにする。それ以外は任意。
% yo hubot
                     _____________________________  
                    /                             \ 
   //\              |      Extracting input for    |
  ////\    _____    |   self-replication process   |
 //////\  /_____\   \                             / 
 ======= |[^_/\_]|   /----------------------------  
  |   | _|___@@__|__                                
  +===+/  ///     \_\                               
   | |_\ /// HUBOT/\\                             
   |___/\//      /  \\                            
         \      /   +---+                            
          \____/    |   |                            
           | //|    +===+                            
            \//      |xx|                            

? Owner: [作成者名]
? Bot name: [ボット名]
? Description: [説明]
? Bot adapter: slack

~~ (省略) ~~

% npm install
% tree -L 2
.
|-- Procfile #heroku用、気にしなくて良い
|-- README.md
|-- bin #起動スクリプト格納場所
|   |-- hubot
|   `-- hubot.cmd
|-- external-scripts.json #利用するモジュールのリスト
|-- hubot-scripts.json #node_modules/hubot-scripts/src/scriptsの中で利用するスクリプトのリスト
|-- node_modules
|   |-- coffee-script
|   |-- hubot
|   |-- hubot-diagnostics
|   |-- hubot-google-images
|   |-- hubot-google-translate
|   |-- hubot-help
|   |-- hubot-heroku-keepalive
|   |-- hubot-maps
|   |-- hubot-pugme
|   |-- hubot-redis-brain
|   |-- hubot-rules
|   |-- hubot-scripts
|   |-- hubot-shipit
|   |-- hubot-slack
|   `-- hubot-youtube
|-- package.json
`-- scripts #自作スクリプト格納場所(格納したものは全て有効化される)
    `-- example.coffee

18 directories, 8 files

```

これであとはscriptsディレクトリ内に自作のスクリプトを置けばよい。
起動前に環境変数をexportしておく。

```bash
export HUBOT_SLACK_TOKEN=your_slack_token
export HUBOT_SLACK_TEAM=your_slack_teamname
export HUBOT_SLACK_BOTNAME=any_botname
```

* your_slack_token : slack連携画面から取得したアクセストークン
* your_slack_teamname : slackのチーム名
* any_botname : 任意のボット名(slack内での表示名)

起動コマンド

```bash
% ./bin/hubot -a slack
```

バックグラウンドで実行させたい場合はscreenやforeverなどを使うといい。

## dockerを使う場合
上で作った雛形をもとにDockerfileを書いてイメージをビルドした。

- https://github.com/almat64/hubot
- https://github.com/almat64/dockerfile-hubot

DockerHubにイメージをプッシュして置いたので次の起動コマンドでダウンロードと起動を一挙に行うことができる。

```bash
% docker run -d --name hubot -p 8080:8080 \
-e "HUBOT_SLACK_TOKEN=your_slack_token" \
-e "HUBOT_SLACK_TEAM=your_slack_teamname" \
-e "HUBOT_SLACK_BOTNAME=any_botname" \
almat64/hubot:slack
```

-eオプションでコンテナ内に環境変数を取り込んでいる。
この例では8080番ポートを割り当てているが、もちろんホスト側の割り当てポートは何でもいい。
私の場合はnginxをリバースプロキシとして```bot.[ドメイン]```というバーチャルホストに80番でlistenさせている。

slack側の設定はインテグレーションの管理画面に従えば、すぐにトークンを発行してくれる。

## 課題
コンテナのサイズ大き過ぎる...(500MB越え)
そもそもベースにしているnode.jsのイメージがデカいので仕方ないのかもしれないが。
Swift で録画したビデオ(mov)を MP4 に変換する


# iOS におけるビデオ変換

AVAssetExportSession を使用します。

## 変換時に指定できるフォーマット

たくさんありますがここでは AVFileTypeMPEG4 を使います。設定できるフォーマットはオフィシャルドキュメント参照。([File Format UTIs](https://developer.apple.com/library/ios/documentation/avfoundation/reference/
AVFoundation_Constants/index.html#//apple_ref/doc/constant_group/File_Format_UTIs ""))

# 処理の流れ

だいたい以下のようになります。

1. AVAsset の生成
1. 出力(変換)フォーマットなど変換の設定
1. 変換実行(必要であればライブラリに登録)

# サンプルコード

下記のコードで iPhone のカメラで録画したビデオを MP4 に変換できました。

環境：iOS 8.1.1, XCode 6.1

```
let avAsset = AVURLAsset(URL: self.fileMovPathUrl(), options: nil)
let exportSession = AVAssetExportSession(asset: avAsset, presetName: AVAssetExportPresetPassthrough)
exportSession.outputFileType = AVFileTypeMPEG4
exportSession.outputURL = self.fileMp4PathUrl()

exportSession.exportAsynchronouslyWithCompletionHandler { () -> Void in
    NSFileManager.defaultManager().removeItemAtPath(self.filePath(self.mov_extenstion), error: nil)
    switch exportSession.status {
    case AVAssetExportSessionStatus.Completed:
        let assetsLib = ALAssetsLibrary()
        assetsLib.writeVideoAtPathToSavedPhotosAlbum(self.filePathUrl(self.mp4_extenstion), completionBlock: {
             (nsurl, error) -> Void in
        })
        break
    case AVAssetExportSessionStatus.Failed:
        break
    case AVAssetExportSessionStatus.Cancelled:
      　break
    default:
        break
    }
}
```
非同期プログラミングのベスト プラクティス まとめ1

http://msdn.microsoft.com/ja-jp/magazine/jj991977.aspx の前半部分まとめ。


## 戻り値がvoidのメソッドを非同期呼び出ししない

### 理由

1. 戻り値が無い為、呼び出し側でタスクの終了を検出することができない為。

1. 戻り値が無い為、タスクで発生した例外を呼び出し側で補足することができない為。

### 例外

+ イベントハンドラーはOK。→ 前項の理由のような挙動でも問題ない。


## すべて非同期にする

同期処理と非同期処理、具体例を挙げると await と Task.Waite() を同一処理パスに混在させてはいけない。アプリケーション形態(WindowsFormアプリ、WPFアプリ、SilverLightアプリ、ASP.NETアプリ)によってはデッドロックが発生する。

※なんとなくデッドロック発生のイメージが浮かぶ程度の理解しかできていませんが、下記コードのコメントを見てもらえれば私のイメージが伝わるかと思います。

```csharp
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace AsyncExample
{
    public partial class Form2 : Form
    {
        public Form2()
        {
            InitializeComponent();
        }

        private static async Task DelayAsync()
        {
            //1. 非同期タスク実行
            await Task.Delay(1000);

            //3. 後続処理をUIスレッドで処理したいがロックされているので、ロック解除待ちする。
            MessageBox.Show("完了"); 
        }

        private void button1_Click(object sender, EventArgs e)
        {
            var task = DelayAsync();

            //2. タスク完了を同期的に待つ。UIスレッドをロックする。
            task.Wait();  
        }
    }
}
```
Qiita::Markdownを使う on Yosemite


# TL;DR

* `gem 'qiita-markdown'`
* `brew install icu4c`
* `brew install cmake`
* http://qiita.com/kwappa/items/20eecde98c81cc08cba8
* https://github.com/github/gemoji.git

# install

```Gemfile
gem 'qiita-markdown'
```

```
% budle install
```

Native Extensionsのbuildに失敗したら、各種依存ライブラリを準備する必要がある。

## `charlock_holmes`

build失敗メッセージに従い、Homebrewで `icu4c` をインストールする。

```
% brew install icu4c
```

## `rugged`

Homebrewで `cmake` をインストールする。

```
% brew install cmake
```

* https://github.com/libgit2/rugged
* http://stackoverflow.com/questions/21490051/bundle-install-fails-on-rugged-but-gem-install-rugged-works

## `nokogiri`

* [Ruby - nokogiri を bundle install する on Mavericks - Qiita](http://qiita.com/kwappa/items/20eecde98c81cc08cba8)

## emojiを準備する

* https://github.com/github/gemoji.git をcloneする
* `bundle install`

```Rakefile
diff --git a/Rakefile b/Rakefile
index 2cea5c9..64965dc 100644
--- a/Rakefile
+++ b/Rakefile
@@ -1,4 +1,5 @@
 require 'rake/testtask'
+load 'lib/tasks/emoji.rake'
 
 task :default => :test
```
* `bundle exec rake emoji`
* `public/images/emoji` 以下に画像ができる
* Rails Appの `public/images` 以下に移動

`qiita-markdown` は `gemoji` に依存しているので、gemのディレクトリに移動して作業してもよい。

# usage

* https://github.com/increments/qiita-markdown/
* https://github.com/jch/html-pipeline

```ruby
# processorを準備（このとき必要ならオプションを渡す）
processor = Qiita::Markdown::Processor.new
# markdown : renderしたいmarkdown文字列
result = processor.call(markdown)
# html-pipelineのHTMLツリーをHTMLに
output = result[:output].to_s
# viewに出力
output.html_safe
```
Vimを使い始めたいのでCentOS 7.0に最新版のVimをインスコする


ひよっこなりに「テキストエディタ？やっぱVimっしょ」みたいな雰囲気を出していきたいと思ったので今日からVimを使い始めようと思った。

で、ちょっと調べたらどうやら`yum`でyumyumしてくれるvimはバージョンがちょっと古いらしい。

なのでどうせなら、と最新版Vim(書いてる時点では7.4)を入れることにした。

##導入先環境
ちなみにVagrant上で走らせてマス

```
$ cat /etc/redhat-release
CentOS Linux release 7.0.1406 (Core) 
```

##とりあえず公式みる
[公式](http://www.vim.org/download.php)より

>Unix:	See the [Mercurial](http://www.vim.org/mercurial.php) page.

Mercurialとやらを使えとのお達し。
(Mercurialはバージョン管理システムらしい。ためになった。)

##おとなしくMercurialを導入

```
$ yum install mercurial
```

##そしてVimをいれる

```
$ cd /usr/src
$ hg clone https://vim.googlecode.com/hg/ vim
$ cd vim
$ sudo make
```

ら、なんかエラーが出た

```
checking for tgetent()... configure: error: NOT FOUND!
      You need to install a terminal library; for example ncurses.
      Or specify the name of the library with --with-tlib.
```

どうやらTerminal Libraryがたりないみたい。

##Nucursesを入れろとな！

```
$ sudo yum install ncurses ncurses-devel
```

導入後再度`make`したら怒られなかった。

##インストール。

```
$ sudo make install
```

##たぶんできてる

```
$ vim --version
VIM - Vi IMproved 7.4 (2013 Aug 10, compiled Nov 27 2014 04:30:58)
```

できてると思うんだけど。

これでぼくも今日からドヤ顔でVimが使えるようになりました。やった。
GitlabでGoogle Apps認証

===========================

## Installation

[Google Developers Console](https://console.developers.google.com/)から

- Contacts API
- Google+ API

を有効にする。

API & auth -> Credentialsより「Create new Client ID」 -> Web Applicationを選び必要項目を入力。
REDIRECT URISは

```
http://gitlab.example.com/users/auth/google_oauth2/callback
```

のように入力。

Gitlabの`config/gitlab.yml`にて

```
# 
signup_enabled: false

omniauth:
    enabled: true
    allow_single_sign_on: true
    block_auto_created_users: false
    providers:
      - {"name":"google_oauth2","app_id":"32183193207-piqbogilllsi7u21ujjqk7bpuh325fnk.apps.googleusercontent.com","app_secret":"N92-4QlPgKu2X9akEnUwpteE","args":{"access_type":"offline","approval_prompt":"force","hd":"example.com"}}
```

ログインを許可するドメインを制限したい場合はパラメータに`hd`をドメイン名として渡す。
`allow_single_sign_on: true`でGitlabデータベース内にユーザが存在しない場合でもユーザを作成、`    block_auto_created_users: false`で管理者の許可を得なくてもユーザを作成出来るようにする。

また既にGitlabに登録済みのアカウントをGoogle Appsアカウントと紐付けたい場合、omniauthを有効にすると「Profile」->「Account」ページ下部にGoogle Appsアイコンが出現するのでクリックし認証することで紐付け出来る。

## Trouble Shooting

- マルチバイト文字のユーザ名がDBエラーになる

usersテーブル等のcharacter-setをutf8に修正する
参照: [Encoding error in Gitlab 5.2 · Issue #4120 · gitlabhq/gitlabhq](https://github.com/gitlabhq/gitlabhq/issues/4120)

```
ALTER TABLE broadcast_messages CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE deploy_keys_projects CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE emails CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE events CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE forked_project_links CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE issues CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE keys CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE merge_request_diffs CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE merge_requests CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE milestones CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE namespaces CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE notes CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE projects CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE protected_branches CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE schema_migrations CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE services CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE snippets CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE taggings CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE tags CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE users CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE users_groups CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE users_projects CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
ALTER TABLE web_hooks CONVERT TO CHARACTER SET utf8 COLLATE utf8_unicode_ci;
```
iPhone6 Plus ( iOS8 ) で、ベーシック認証下で動画（videoタグ）が再生されない

Android端末でvideoタグがベーシック認証下で再生されないのは
なんとなく知っていたんですが、
iOS8からなのか検証はしていませんが、
iPhone6 + iOS8 の組み合わせでも同じく、
ベーシック認証下で動画が再生されなくなってました。

「三角」の再生矢印マークが出るんですが、
タップすると、斜線が表示されて何も表示されない・・・。

他のiPhone達では表示されるので謎な現象でした。

解決方法としては、htaccessにて動画形式を認証対象がにするか、
ベーシック認証がかからないところで確認するぐらいしかなさそうですかね。

[参考]
http://case-mobile-design.com/iphone-android-movie/
Ubuntu 14.04にPPAからffmpegを導入する

Ubuntu 14.04の標準パッケージにはなぜかffmpegが入っていないので、非公式リポジトリのPPAから導入します。

```bash
sudo add-apt-repository ppa:mc3man/trusty-media
sudo apt update
sudo apt install ffmpeg
```

音声コーデックのlibfdk_aacも入ります。

jon-severinsson/ffmpegリポジトリを勧めている記事が多いのですが、バージョンが古いです。
pre-commitでコミットをチェックする


git hooksのpre-commitを用いるとコミット時、jshintやテストを通してコミットを自動でチェックすることができます。

## .git/hooks/pre-commitに処理を書く
pre-commit.sampleというファイルがあるので参考にして下さい。
今回書いたのは`grunt jshint`でjshintエラーが出た場合にコミットを取りやめるというものです。

```sh
# !/bin/sh

grunt jshint
if ["$?" -ne 0]; then
	exit 1
fi
```

## 実行権限を付与
pre-commitに実行権限がないので付与しておきます。

```bash
% ls -ll .git/hooks/pre-commit
-rw-r--r--  1 ■■■  ■■■  67 11 18 12:30 .git/hooks/pre-commit
```

```bash
chmod a+x .git/hooks/pre-commit
```

```bash
% ls -ll .git/hooks/pre-commit
-rwx-r--r--  1 ■■■  ■■■  67 11 18 12:30 .git/hooks/pre-commit
```

実行権限が付与されました。これで準備OK。
Googleの正規表現ライブラリre2のGoラッパー

[GitHubで公開しました](https://github.com/wordijp/golang-re2)

基本的な使い方はregexpパッケージとほぼ同じです。
ただ、こちらはCompile系の関数呼び出し時に終了処理用のCloserを返したり、一部メソッドにRE2というprefixを付けています(理由はREADME.mdに記載しています)。

```Go:main.go
package main

import (
	"fmt"
	"github.com/wordijp/golang-re2"
)

func main() {
	re, closer := re2.MustCompile("fo.?")
	defer closer.Close(re)

	fmt.Printf("%q\n", re.FindString("seafood"))
	fmt.Printf("%q\n", re.FindString("meat"))
}
```
--------------------------
```
"foo"
""
```
Gitlabアップデート 7.2 -> 7.5

===========================

[Gitlab 5.0のインストール (CentOS 6.5)](http://qiita.com/shufo/items/6fb1bd067ec7e5d47902)
[Gitlabアップデート 5.0 -> 6.0](http://qiita.com/shufo/items/f27e62e23b048a5721c0)
[Gitlabアップデート 6.0 -> 7.2](http://qiita.com/shufo/items/77dae2474f153c2c8c03)

の後に行った作業です。


## Requirements

- CentOS (Tested on 6.5)
- ruby (Tested on 2.1.2)

## Upgrade

- gitlab停止

```
service gitlab stop
```

- バックアップ

```
su - git
cd /home/git/gitlab
bundle exec rake gitlab:backup:create RAILS_ENV=production
```

- アップグレードスクリプトでGitlab本体をアップグレード

```
su - git
cd /home/git/gitlab
if [ -f bin/upgrade.rb ]; then ruby bin/upgrade.rb; else ruby script/upgrade.rb; fi
```

- unicornのtimeoutを60秒に修正する（既に設定してあればそのまま）

```
vim config/unicorn.rb
```

```diff
-timeout 30
+timeout 60
```

- mysqlの接続設定を変更する

```diff
production:

-pool: 5
+pool: 10
+collation: utf8_general_ci
```

poolを増やしている。

- gitlab-shellをアップグレード

```
su - git
cd /home/git/gitlab-shell
git checkout v2.2.0
```

- gitlab-shellが利用するgitlabのURLを修正

```
cd /home/git/gitlab-shell
vim config.yml
```

```diff
-gitlab_url: "http://localhost:3000/"
+gitlab_url: "https://gitlab.example.com/"
```

```
vim lib/gitlab_config.rb
```

```diff
-@config['gitlab_url'] ||= "http://localhost:3000/"
+@config['gitlab_url'] ||= "https://gitlab.example.com/"
```



- 起動

```
service gitlab start
```

## Trouble shooting

- ログを見てみる

```
cd /home/git/gitlab/log
tail -f *.log
```

- `ActionView::Template::Error`のようなエラーが出て500になる

`config/gitlab.yml`内のgitのpathが合ってるか確認しましょう。

- submoduleを含むフォルダで500になる

submoduleを削除で解決します。もう一度追加すれば戻るかも。

- 日本語を含むタグ・ブランチ

消しましょう。
apacheでhttpへのアクセスをhttpsへ自動リダイレクトする


sslの設定などの説明は省略します。

## /etc/httpd/conf/conf.d/rewrite.confを設定
今回は`/etc/httpd/conf/conf.d`以下にリダイレクト処理だけを書く設定ファイルを用意しました。`/etc/httpd/conf/httpd.conf`に直接書いても構いません (ただしモジュールのロードの後に書く必要があります。)

## mod_rewriteの設定

```
<ifModule mod_rewrite.c>
      RewriteEngine On
      LogLevel alert rewrite:trace3
      RewriteCond %{HTTPS} off
      RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R,L]
</ifModule>
```

`RewriteRule`は書き換えのルール、
`RewriteCond`は`RewriteRule`を適用するかを判断するための条件です。今回はHTTPSがOffの場合、つまりhttp通信の場合にルールを適用させます。


※注意
RewriteLog, RewriteLogLevelの設定はapache2.4から削除されました。古い記事を参考にするとSyntaxErrorになりますので気をつけましょう。
centos7でキーボードレイアウト変更


毎回忘れてしまうので覚書。

## 設定ファイルから

・/etc/vconsole.conf

```
KEYMAP="jp106"
```

※ systemdの採用により、キーボードの設定ファイルが/etc/sysconfig/keyboardから/etc/vconsole.confに変更になりました。

## コマンドから

- キーボード設定の表示

```bash
$ localectl status
  
System Locale: Lang=ja_JP.UTF-8
VC Keymap: jp106
X11 Layout: n/a
```


- キーボードマッピングのリストを表示

```bash
$ localectl list-keymaps
ANSI-dvorak
amiga-de
amiga-us
applkey
```

- キーマップを指定

```bash
$ localectl set-keymap jp106
```
Gitlabアップデート 5.0 -> 6.0


[Gitlab 5.0のインストール (CentOS 6.5)](http://qiita.com/shufo/items/6fb1bd067ec7e5d47902)

の後に行った作業です。

## Requirements

- CentOS (Tested on 6.5)
- ruby (Tested on 1.9.3)

## Upgrade

- gitlabサーバ停止

```
sudo service gitlab stop
```

- バックアップ

```
su - git
cd /home/git/gitlab
mkdir /home/git/gitlab/public/uploads
chown git:git /home/git/gitlab/public/uploads
bundle exec rake gitlab:backup:create RAILS_ENV=production
```

- 6.0のコードをチェックアウト

```
cd /home/git/gitlab
sudo -u git -H git fetch
sudo -u git -H git checkout 6-0-stable
```

- gitlab-shellをアップデート

```
cd /home/git/gitlab-shell
sudo -u git -H git fetch
sudo -u git -H git checkout v1.7.0
```

- 追加パッケージをインストール

```
sudo yum install -y python-docutils
# ubuntuの場合
# apt-get install python-docutils
```

- GemfileとGemfile.lockを書き換え

```diff
Gemfile:136   
-     gem "modernizr",        "2.6.2"
+     gem "modernizr-rails",        "2.7.1"
```

```diff
Gemfile.lock:286
-     modernizr (2.6.2)
+     modernizr-rails (2.7.1)

Gemfile.lock:600
-     modernizr (= 2.6.2)
+     modernizr-rails (= 2.7.1)
```

- 依存gemインストール。


```bash
su - git
cd /home/git/gitlab
bundle install --deployment --without development test postgres
```

- DBのマイグレーション

```
bundle exec rake db:migrate RAILS_ENV=production
```

- グループのマイグレーション

```
bundle exec rake migrate_groups RAILS_ENV=production
```

6.0よりグローバル名前空間が非互換になったのでグローバルのプロジェクトをグループ以下の名前空間に移動する
プロジェクト所有者が既に存在しない場合移動は失敗するので手動でどこかの名前空間以下に移動しておくとよさそう

```
bundle exec rake migrate_global_projects RAILS_ENV=production
```

- フィンガープリントをDB内のssh鍵に追加するマイグレーション(鍵の重複を防ぐため？)。とりあえずnoにしたけど動いた。

```
bundle exec rake migrate_keys RAILS_ENV=production
```

- noteのマイグレーション

```
bundle exec rake migrate_inline_notes RAILS_ENV=production
``` 

- gitlab-satellitesを生成しなおす。サーバ移動時などまだ生成されていない場合実行。

```
bundle exec rake gitlab:satellites:create RAILS_ENV=production
```

- redisのキャッシュを削除

```
bundle exec rake cache:clear RAILS_ENV=production
```

- その他

```
bundle exec rake assets:clean RAILS_ENV=production
bundle exec rake assets:precompile RAILS_ENV=production
```

- configファイルのアップデート

```
cd /home/git/gitlab/config
cp gitlab.yml{,.bak} # バックアップ
rm gitlab.yml.example
wget https://raw.github.com/gitlabhq/gitlabhq/6-0-stable/config/gitlab.yml.example
cp gitlab.yml.example gitlab.yml
vim gitlab.yml 
 
 16   gitlab:
 17     ## Web server settings
 18     host: gitlab.local.com //変更
 19     port: 80
 20     https: false //httpsが必要な場合は変更
```

- unicorn.rbの変更

```
cd /home/git/gitlab/config
cp unicorn.rb{,.bak}
rm unicorn.rb.example
wget https://raw.github.com/gitlabhq/gitlabhq/6-0-stable/config/unicorn.rb.example
cp unicorn.rb.example unicorn.rb
```

- 6.0用のinitスクリプトをDL

```
curl --output /etc/init.d/gitlab https://raw.githubusercontent.com/gitlabhq/gitlabhq/6-0-stable/lib/support/init.d/gitlab
chmod +x /etc/init.d/gitlab
```

- 起動

```
service gitlab start
```

- ログ確認

```
cd /home/git/gitlab/log
tail -f *.log
```

- gitlab環境の確認

```
bundle exec rake gitlab:env:info RAILS_ENV=production
```

- 動作確認

```
bundle exec rake gitlab:check RAILS_ENV=production
```
LANを抜いてもHSRPが切り替わらない時に確認する点

Port-channelのtrunkにvlanが登録されていることを確認する。
本体の電源を抜き差しだと切り替わることは確認済み。

## 確認コマンド

* show config
* show standby brief

```bash:
#show standby brief
                     P indicates configured to preempt.
                     |
Interface   Grp  Pri P State  Active   Standby       Virtual IP
Vl21       0    200 P Active  local    5.5.5.21     5.5.5.19
Vl31       0    200 P Active  local    5.5.100.195  5.5.100.193
```

* Standby側のIPアドレスが`Unknown`の場合、trunk追加忘れている。1時間ハマった。
* 切り替わりは500ms x10回 = 5秒くらいかかる(slaが関係か？)
自分の家からインターネットにつなぐ時に必要になる機器類まとめ

ネットワーク関連についてちんぷんかんぷんすぎて、インターネットに接続する際に使っている機器がなんなのか全く分かっていなかったため、どんな機器がなんの役割を担っているのか調べてみました。

# モデム

> アナログ信号（ADSLなどの電話回線）とデジタル信号（パソコンから送られるデータ形式）を相互に変換する機械

> 光回線の場合はモデムを必要としません。モデムに相当するものとして光回線終端装置（ONU)が必要となります。やっていることは大体同じで光信号と電気信号間の変換をします。

# ルーター

* モデムだけだと一台しかネットと接続できない。

> そこで登場するのがルーター【router】です。ルーターは、コンピュータネットワークにおいて、2つ以上の異なるネットワークへ相互接続するための通信機器です。モデム、あるいは回線終端装置からLANケーブルを使ってこのルーターに接続すると複数の端末が同時にネットと接続することができます。また、ルーターに接続されている端末同士も通信できるようになります。
端末の接続方法は、LANケーブルで接続する方法と、無線によって接続する方法の2種類あります。
最近普及している無線LANルーターは名前の通り無線で複数の端末をネットに接続する機器です。ほとんどの無線LANルーターは、後ろにLANポートもあるので有線LANによる接続も可能となっています。
また、ルーター機能付きモデムというものも売られていて、この場合は設置するべき機器がひとつ減ります。

* モデムとルーターを利用したインターネット接続を図式化したものが下記
http://komakusa.net/internet/provider-setuzoku.html
* 家庭用で使うルーターは、いわゆるルーティング目的というよりは、家庭で必要な機能に特化しているルーター。いわゆるルーターと区別して、ブロードバンドルーターなどと呼ばれたりする。

> LAN側のパソコンから利用できるDHCPサーバ機能やNAT機能(プライベートアドレス・グローバルアドレス相互の変換機能)を備えているものが多い。
http://e-words.jp/w/E38396E383ADE383BCE38389E38390E383B3E38389E383ABE383BCE382BF.html

# 二台以上接続する場合になぜルーターが必要になるのか

ルーターの代わりにハブを使うことで複数の機器をネットにつなぐことはできないのか？（モデムにルーター機能がない場合）

答えは、機器を入れ替えるだけではできない。なぜなら、ルーター（レイヤ3レベルでの機器）がない限り、同じネットワーク内の機器にしかデータは転送できないから。

ルーターがルートを決定することにより、ネットワークは相互にデータ転送が可能になる。ルーターがなければ、異なるネットワーク間はデータ転送できない。
手持ちのPCをインターネットに接続するには、ローカルネットワークとインターネットネットワークという二つのネットワークをまたぐため、ルーターが必要となる。

※ハブは、レイヤ1レベルでの機器。ハブに接続されている機器から送られた信号は、ハブに接続されている他の機器全てに送信される。

# 引用元

* http://michisugara.jp/archives/2011/modem_router.html
ChEMBLから全化合物データをダウンロードして分割したsdfファイルをつくる

#概要
ChEMBLはEMBL-EBIが運営する化合物／薬物のデータベースです．
ケモインフォマティクスや創薬支援計算に非常によく使われています．

ChEMBLの化合物データはsdfファイルという形式で配布されています．
sdfは1つのファイルの中に複数の化合物データを記述するフォーマットになっています．
>参考：SDFって何？～化合物の表記法～ | Chem-Station
>http://www.chem-station.com/blog/2012/04/sdf.html

この記事ではChEMBLから全化合物データのsdfをダウンロードして，
１個１個分割したsdfファイルをつくる方法を紹介します．

#ChEMBLからsdfをダウンロード
ChEMBLのsdfは以下からダウンロードできます．
https://www.ebi.ac.uk/chembl/downloads
今回はchembl_19.sdf.gz (version 19, 2014年7月更新版) を使います．
 
```shell-session:chemblのsdfをwget
wget ftp://ftp.ebi.ac.uk/pub/databases/chembl/ChEMBLdb/releases/chembl_19/chembl_19.sdf.gz
gunzip chembl_19.sdf.gz
```

<code>chembl_19.sdf</code>ができました．

#sdfを分割する
sdfファイルの分割をする以下のpythonスクリプトを使います．

```py:sdf_sep.py
#!/usr/bin/python

import re
import sys

if (len(sys.argv) != 2):
    print 'Usage: # python %s chemblsdf' % sys.argv[0]
    quit()

sdffile = sys.argv[1]
fi = open(sdffile, 'r')

mol = []
while 1:
    line = fi.readline()
    if not line:
        break
    if line[:4] == "$$$$":
        mol.append(line)
        title = mol[0][:-1]
        fo = open(title+".sdf", 'w')
        for m in mol:
            fo.write(m)
        fo.close()
        mol = []
    else:
        mol.append(line)

fi.close()
```
これを使って，<code>chembl_19.sdf</code>に対し

```shell-session:sdf_sep.pyの実行
python sdf_sep.py chembl_19.sdf
```
とすると，実行したディレクトリに分割されたsdfファイルが生成されます．

```lang:できたsdfファイルの一部
CHEMBL2227709.sdf  CHEMBL375034.sdf   CHEMBL99804.sdf    CHEMBL1447940.sdf
CHEMBL1778883.sdf  CHEMBL222771.sdf   CHEMBL375035.sdf   CHEMBL99806.sdf
CHEMBL1447941.sdf  CHEMBL1778884.sdf  CHEMBL2227710.sdf  CHEMBL375036.sdf 
CHEMBL99808.sdf    CHEMBL1447942.sdf  CHEMBL1778885.sdf  CHEMBL2227711.sdf
````

ちなみにversion 19では1,404,752個のsdfファイル（化合物）がつくられました．

\#が，公式には1,638,394個あるはずなので，何かおかしい？

##追記
これによると，1,404,752個で合ってるようです．
>ChEMBL_19 Released - Now with Crop Protection Data! < Service news < News < About us < EMBL-EBI
>http://www.ebi.ac.uk/about/news/service-news/ChEMBL-19-released

@32nmさんありがとうございます！
>@32nm: @tonets You can see the number 1,404,752 at the release note http://www.ebi.ac.uk/about/news/service-news/ChEMBL-19-released
>[http://twitter.com/32nm/status/537820242496344064]
少し抽象度を上げた実装

# はじめに

　前回投稿した「letとlet*の括弧の数を減らす」という投稿の中で下のような関数が出てきました。

```cl:before.lisp
(defun create-param (list)
  (labels ((rec (list result)
             (if (null list)
                 (nreverse result)
                 (rec (nthcdr 2 list)
                          (push (list (first list) (second list)) result)))))
    (if (evenp (length list))
        (rec list nil)
        (error "wrong number of parameters"))))

(create-param '(a 1 b 2 c 3))
;=> ((A 1) (B 2) (C 3))
```

　今回はこのコードを題材に少し抽象度を上げた実装をしてみたいと思います。

# 少し抽象度を上げる

　create-param関数の、処理の内容はリストの第0要素と第1要素に対して、list関数を適用し、その結果をresultというリストに追加していってます。つまりリストの第0要素と第1要素に対して、関数を適用するということがメインの処理です。
　標準関数を使うと、リストの要素を2つずつ使用するmapcar関数と表現できると思います。

# 実装

　先程のmap関数の名前はmappairとします。
　コードの内容はcreate-param関数の内容とほぼ同じです。

```cl:mappair.lisp
(defun mappair (fn list)
  (labels ((rec (fn list acc)
			 (if (null list)
				 (nreverse acc)
				 (rec fn
					  (nthcdr 2 list)
					  (push (funcall fn (first list) (second list)) acc)))))
	(if (evenp (length list))
		(rec fn list nil)
		(error "wrong number of parameters."))))
```

　次にcreate-paramの中をmappairで置き換えます。

```cl:after.lisp
(defun create-param (list)
  (mappair #'list list))

(create-param '(a 1 b 2 c 3))
;=> ((A 1) (B 2) (C 3))
```

　このmappairを使うとリストから連想リストへの変換関数も簡単に書けます。

```cl:make_alist.lisp
(defun list->alist (list)
  (mappair #'cons list))

(list->alist '(a 1 b 2 c 3))
;=> ((A . 1) (B . 2) (C . 3))
```

# もう少し抽象度を上げる

　ここまで来るとリストの任意の数に関数を適用することができるmap関数が欲しくなります。
　ということで実装してみました。名前はmapnとします。

```cl:mapn.lisp
(defun mapn (n fn list)
  (labels ((rec (n fn list acc)
			 (if (null list)
				 (nreverse acc)
				 (let ((input nil))
				   (dotimes (i n)
					 (push (pop list) input))
				   (rec n fn list
						(push (apply fn (nreverse input)) acc))))))
	(rec n fn (copy-list list) nil)))

(mapn 2 #'list '(1 2 3 4 5 6))
;=> ((1 2) (3 4) (5 6))
(mapn 2 #'cons '(a 1 b 2 c 3))
;=> ((A . 1) (B . 2) (C . 3))
(mapn 3 #'append '((1 2) (3 4) (5 6) (7 8) (9 10) (11 12)))
;=> ((1 2 3 4 5 6) (7 8 9 10 11 12))
```

# おわりに
　少し抽象化すると様々な場面で使える汎用関数を定義することができます。
　また簡単な抽象化を行うことで基礎体力をつけることも大事だと思います。
　他の人が書いた高度に抽象化されたコードを読み解くためにも、抽象的に考える思考力を養っていきたいと思います。
html.erbファイルでjs直書きでその中にrubyのコードを埋め込んでいる状態のものをslimに置き換えるときの書き方


##jsをslimで書く場合
htmlファイル内にjsを書いちゃっている場合（それって良くないんじゃね？って議論は置いといて）、
slimで書くと以下のようになります。

```sample.html.erb
<script>
  $(function(){
    ・・・
  });
</script>
```

　　　　↓

```sample.slim
javascript:
  $(function(){
    ・・・
  });
```

##js内にrubyのコード書いちゃってる場合

###データが数字の場合

```sample.html.erb
<script>
  $(function(){
    var user_id = <%= @user.id %>;
  });
</script>
```

　　　　↓

```sample.slim
javascript:
  $(function(){
    var user_id = #{@user.id};
  });
```

###データが文字列の場合
文字列の場合は `.to_json` しないとなぜかsyntax errorになる。
エスケープ文字が含まれている可能性があるので `raw` をつけておくと良い。

```sample.html.erb
<script>
  $(function(){
    var user_name = <%= @user.name %>;
  });
</script>
```

　　　　↓

```sample.slim
javascript:
  $(function(){
    var user_name = #{raw @user.name.to_json};
  });
```

##変数名にrubyのコード使っちゃってる場合
`eval` で実行する。

```sample.html.erb
<script>
  $(function(){
    var user_info_<%= @user.id %> = new userInfo();
  });
</script>
```

　　　　↓

```sample.slim
javascript:
  $(function(){
    var user_id = #{@user.id};
    eval("var user_info_" + user_id + "= new userInfo();");
  });
```

##`each do`で繰り返しちゃってる場合
一回データを変数に入れてから `for` で繰り返す。

```sample.html.erb
<script>
  $(function(){
    <% @users.each do |user| %>
      var user_info_<%= user.id %> = new userInfo();
      user_info_<%= user.id %>.openMoreInfo();
      user_info_<%= user.id %>.closeMoreInfo();
    <% end %>
  });
</script>
```

　　　　↓

```sample.slim
javascript:
  $(function(){
    var users = #{raw @users.to_json};
    for(var i = 0; i < users.length; ++i) {
      eval("var user_info_" + users[i].id + " = new userInfo();");
      eval("var user_info_" + users[i].id + ".openMoreInfo();");
      eval("var user_info_" + users[i].id + ".closeMoreInfo();");
    }
  });
```

##途中で条件分岐しちゃってる場合

```sample.html.erb
<% if @user.logined? %>
  <script>
    $(function(){
      <% if @user.gender == "female" %>
        console.log("I love you!");
      <% else %>
        console.log("I hate you!");
      <% end %>
    });
  </script>
<% end %>
```

　　　　↓

```sample.slim
- if @user.logined?
  javascript:
    $(function(){
      var message = "#{@user.gender == 'female' ? 'I love you!' : 'I hate you!'}";
      console.log(message);
    });
    }
  });
```
任意の文字列を含むファイルのみsed置換するワンライナー


ag(silver_searcher)で検索してヒットしたファイルのみを対象にsedで置換

`````bash
$ ag -l HogeClass | xargs sed -i 's/group_result: true/group_by: :result/'
`````

`ag -l`はヒットしたファイル名のみを出力する.

``````bash:man
AG(1)
NAME
       ag - The Silver Searcher. Like ack, but faster.
# ...
       -l --files-with-matches:
           Only print filenames containing matches, not matching lines. An empty query will print all files that would be searched.
```````

`sed -i`は編集結果をファイルに反映する.

````bash:man
SED(1)
NAME
       sed - stream editor for filtering and transforming text
# ....
      -i[SUFFIX], --in-place[=SUFFIX]
             edit files in place (makes backup if extension supplied)
````````
docker-api でコンテナ作成時にコンテナ名を指定する方法

[swipely/docker-api](https://github.com/swipely/docker-api) でコンテナを作成する際、コンテナ名を指定する方法です。

```rb:sample.rb
container = Docker::Container.create('name' => 'my_ubuntu', 'Image' => 'ubuntu:14.04')
```

上記のように、「name」で指定してやるだけです。
「Name」ではだめでした。

[Docker Remote API (v1.12) の公式ドキュメント](https://docs.docker.com/reference/api/docker_remote_api_v1.12/#create-a-container)では 、

> Create a container
　Query Parameters:
　name – Assign the specified name to the container. Mus match /?[a-zA-Z0-9_-]+.

とあるように、Query Parameter としてコンテナ名を指定できるとありましたが、
swipely/docker-api ではどう指定すればいいのかわからなかったので、それを調べた結果でした。
PHPUnitの主なAssertメソッド一覧

#mixed is ...
|メソッド|意味|
|:-----|:---|
|`assertNull($var)`|`$varがNULLである`|
|`assertEquals($val1, $val2)`|`$val1が$val2と等しい`|
|`assertSame($val1, $val2)`|`$val1と$val2が型も含めて等しい`|
|`assertInternalType($type, $val)`|`$valの型名が$typeである`|
※InternalTypeで一致する可能性のある型名
http://apigen.juzna.cz/doc/sebastianbergmann/phpunit/class-PHPUnit_Framework_Constraint_IsType.html

#number is ...
|メソッド|意味|
|:-----|:---|
|`assertGreaterThan($expect, $var)`|`$expect < $var が成立する`|
|`assertGreaterThanOrEqual($expect, $var)`|`$expect <= $var が成立する`|
|`assertLessThan($expect, $var)`|`$expect > $var が成立する`|
|`assertLessThanOrEqual($expect, $var)`|`$expect >= $var が成立する`|

#string is ...
|メソッド|意味|
|:-----|:---|
|`assertJsonStringEqualsJsonString($str1, $str2)`|`$str1と$str2がjsonとして等しい`|
|`assertRegExp($ptn, $str)`|`$strが正規表現$ptnにマッチする`|



#boolean is ...
|メソッド|意味|
|:-----|:---|
|`assertTrue($var)`|`$varがTRUEである`|
|`assertFalse($var)`|`$varがFALSEである`|


#array is ...
|メソッド|意味|
|:-----|:---|
|`assertArrayHasKey($key, $array)`|`配列$arrayにキー$keyが存在する`|
|`assertContains($val, $array)`|`配列$arrayに値$valが存在する`|
|`assertContainsOnly($type, $array)`|`配列$arrayの値の型がすべて$typeである`|
|`assertCount($count, $array)`|`配列$arrayの値の数が$countである`|
|`assertEmpty($array)`|`配列$arrayが空である`|

#object/class is ...
|メソッド|意味|
|:-----|:---|
|`assertObjectHasAttribute($attr, $object)`|`オブジェクト$objectにプロパティ変数$attrが存在する`|
|`assertClassHasAttribute($attr, $class)`|`クラス名$classにプロパティ変数$attrが存在する`|
|`assertClassHasStaticAttribute($attr, $class)`|`クラス名$classに静的プロパティ変数$attrが存在する`|
|`assertInstanceOf($class, $instance)`|`$instanceがクラス名$classのインスタンスである`|

#file is ...
|メソッド|意味|
|:-----|:---|
|`assertFileExists($file)`|`$fileが存在する`|
|`assertFileEquals($file1, $file2)`|`$file1と$file2の内容が等しい`|
|`assertJsonFileEqualsJsonFile($file1, $file2)`|`$file1と$file2の内容がjsonとして等しい`|
|`assertJsonStringEqualsJsonFile($file1, $json)`|`$file1の内容と$jsonがjsonとして等しい`|
UnityでWin32Exception..javac.exe..CommandLine='-bootclasspath..エラーが出た時の対処方法

#エラーログ

```
Error building Player: Win32Exception: ApplicationName='C:\Program Files (x86)\Java\jre7\bin\javac.exe', CommandLine='-bootclasspath "C:/Users/hogehoge/Downloads/android-sdk-windows/platforms/android-18\android.jar" -d "C:\Users\hogehoge\Documents\hugahuga\Temp\StagingArea\bin\classes" -source 1.6 -target 1.6 -encoding ascii "com\google\android\gms\Manifest.java" "com\google\android\gms\R.java" "hugahuga\com\Company\ProductName\Manifest.java" "hugahuga\com\Company\ProductName\R.java"', CurrentDirectory='C:\Users\piyopiyo\Documents\hugahuga\Temp\StagingArea\gen'
```

#原因
「JDKがインストールされていない」もしくは「環境変数が通っていない」事が原因です。

#解決策
「JDKのインストール」及び「環境変数のパス」を通す事でこのエラーを解消出来ました。

JDKのインストールは下記サイトが参考になるかと思います。
http://www.javadrive.jp/install/jdk/index1.html

また、環境変数の通し方は下記をサイトを参考にしてください。
http://www.javadrive.jp/install/jdk/index4.html#section2

これにて解決！！
awkでカンマ区切りのデータを指定した列だけカンマ区切りで出力する

# 変換

awkはデフォルトの入力／出力はスペースのためカンマに変更する

## 入力データ

```import.csv
1,foo,bar
```

## 初期設定

入力：`FS=","`
出力：`OFS=","`

## 出力方法
2列目３列目：`{print $2,$3}`

## コマンド

```
$ cat ./import.csv | awk 'BEGIN {FS=",";OFS=","} {print $2,$3}' > ./output.csv
```

## 出力データ

```output.csv
foo,bar
```
swift で Byte Array から文字列に変換する

Byte array から NSString への変換

```swift
var data: [Byte] = [0x41, 0x42, 0x43]  // "A", "B", "C"

println( NSString(bytes: data, length: data.count, encoding: NSASCIIStringEncoding) )
// output: Optional(ABC)
```

String への変換の API は無いっぽい。
Nginx コマンド超シンプル早見表


自分 (Katz) が手っ取り早く nginx のコマンドを使うためだけにまとめて公開している記事となります。 CentOS 7, Amazon Linux 2 & 2023 で動作確認してます。

## 起動

```
nginx
```

## 停止

CentOS 6 & Amazon Linux

```
nginx -s stop
```

CentOS 7 & Amazon Linux 2

```
systemctl stop nginx
service nginx stop
```


## 再起動

CentOS 6 & Amazon Linux

```
/etc/init.d/nginx restart
```

CentOS 7 & Amazon Linux 2


```
systemctl restart nginx
service nginx restart
```

## スタートアップ登録

CentOS 7 & Amazon Linux 2

```
systemctl enable nginx #登録
systemctl disable nginx #解除
```


## 設定の再読み込み

CentOS6 & Amazon Linux

```
nginx reload
service nginx reload
```

CentOS7 & Amazon Linux 2

```
systemctl reload nginx
service nginx reload
```

## 設定ファイルのチェック

```
nginx -t
```

## 設定ファイルの場所

**メインの設定ファイル**

```
cd /etc/nginx/
```

**各 Vhosts 用設定ファイル**

```
cd /etc/nginx/conf.d/
```


以上
【Java】備忘録


##基礎

文字を表示

```
System.out.println("");
```

メソッドを定義
(出力が)何も無い時に使用

```
void hoge   
```

メソッドを定義

```
public void





```

```
abstract...抽象クラス、抽象メソッド。継承されて実装を記述されて初めてインスタンス化可能となる。
static...インスタンス化してもしなくても利用可能なクラス固有のメンバー。
final...継承できずオーバーライドできないメンバー。コア・パッケージのクラスは殆ど final。
strictfp...FP 厳密。不動小数点数が CPU の処理系に依存せずに厳密に同じ演算結果となる。
transient...直列化（シリアライゼーション）不可能。JVM の外部に書き出し不能なメンバー。
volatile...マルチスレッドによるアクセス時に、必ずマスターコピーと同期を取る。
```


メソッドを定義

```
public static
```

「クラス」から「インスタンス」を作るには、new というキーワードを使う。

```
 PiggyBank bank = new PiggyBank();
```



クラスのインスタンス化するには宣言と生成を行う。

（方法1）

```
AnotherClassSample anotherClass;                         
anotherClass= new AnotherClassSample ();    
```

（方法2）

```
AnotherClassSample anotherClass = new AnotherClassSample();
```

書式を指定して数値を文字列に変換する

```
System.out.println(hoge.toString());
```


fooという名前のパッケージに属することを宣言する場合、○○○.javaの先頭に記述する

```
package foo;

```


fooパッケージのMyClassを使用したい場合、
以下のようにしてインポート宣言を行う

```
import foo.MyClass;
```

package内の複数クラスを利用する場合には、

```
import foo.*;
```

###メソッドのオーバーロード

処理の内容が同じであれば、同じメソッド名をつけることが出来る。

```
public void printName(){}
public void printName(String firstName, String lastName){}
public void printName(String name){}
```


##例外内容
概要
ゼロで割り算しようとしたとき

```
ArithmeticException 
```

文字列を数に変換できなかったとき

```
NumberFormatException 
```

配列の範囲外にアクセスしようとしたとき

```
ArrayIndexOutOfBoundsException 
```

##宣言方法

他のクラスでも値を変えたいなら「public」

```
public
```

他のクラスで勝手に値を変えたくないなら「private」

```
private
```

##参考サイト

###入門サイト

・ [いちばんかんたんなJava入門](http://nobuo-create.net/)
・ [初心者のためのJava講座](http://www.acroquest.co.jp/webworkshop/java_course/index.html)
・ [javadrive](http://www.javadrive.jp/)
・[うまくいかない時のトラブルシューティング](http://www.acroquest.co.jp/webworkshop/java_course/J_lecture_ex3.html)


###ドキュメント

・ [Java SE API ドキュメント](http://www.oracle.com/technetwork/jp/java/javase/documentation/api-jsp-316041-ja.html)
・ [コア API ドキュメント 8](http://docs.oracle.com/javase/jp/8/api/)
よくWebOSやJSで禁止されるキー設定

## F5，Ctrl + F5, Ctrl + R を禁止
```js
var event = e || window.event;
var k = event.keyCode;
if((event.ctrlKey == true && k == 82) || (event.ctrlKey == true && k == 78) || (k == 116) || (event.ctrlKey == true && k == 116))
{
    event.keyCode = 0;
    event.returnValue = false;
    event.cancelBubble = true;
    return false;
}
```

## 右クリックのメニューを禁止
```js
document.oncontextmenu = function(){
    return false;
};
```

## ドロップを禁止
```js
document.ondragstart = function(){
    return false;
};
```

## セレクトを禁止、inputとtextareaを除外
```js
document.onselectstart = function( e ){
    var event = e || window.event;
    var tagName = '';
    try{
        tagName = (event.target || event.srcElement).tagName.toLowerCase();
    }
    catch(e){}
    if( tagName != 'textarea' && tagName != 'input'){
        return false;
    }
}
```

## リンクを新ウインドウで開くことを禁止
```js
document.onclick = function( e ){
    //Shift + click 及び Ctrl + click を禁止

    var event = e || window.event;

    var tagName = '';
    try{
        tagName = (event.target || event.srcElement).tagName.toLowerCase();
    }
    catch(e){}

    if( (event.shiftKey || event.ctrlKey) && tagName == 'a' ){
        event.keyCode = 0;
        event.returnValue = false;
        event.cancelBubble = true;
        return false;
    }
}
```

以上！
[Unity]Vuforia + iPhone6+で黒い縁がでるのは、現時点（2014/11/27）では解決できない


## 問題

iPhone6+でARカメラを使うと、画面左側と下側に黒い縁が表示される。

参考画像：（Vuforiaの掲示板に貼られているものです）
https://developer.vuforia.com/sites/default/files/screen_1.jpg

## 解決方法らしきもの

この問題は、Vuforiaの掲示板でも議論されている。

スレッドのURL: https://developer.vuforia.com/forum/unity-3-extension-technical-discussion/background-texture-black-strip-iphone-6

この[スレッドの#14](https://developer.vuforia.com/forum/unity-3-extension-technical-discussion/background-texture-black-strip-iphone-6#comment-2044967)で回避策が提示されている…ことはいる。

具体的には、[BackgroundTextureAccess sample app](https://developer.vuforia.com/resources/sample-apps/background-texture-access-sample-app)から、VideoBackgroundTexture.csというスクリプトをコピーしてきてPlaneに張りつけ、そのPlaneにカメラ画像を表示してARCameraとは別のCameraでPlaneの画像を表示するというもののようだ。

## さらなる問題

しかし、前述の回避策は現時点では使えない。
なぜなら、BackgroundTextureAccess sample appにVideoBackgroundTexture.csというファイルが含まれていないからである。
おそらく、sample appのバージョンが違うのだろう…。

>どなたか、別の回避策をご存知の方は教えてくださると助かります。

## 付記：PerspectiveモードとOrthographicモード

ちなみに、この症状は、ARCameraがPerspectiveモードだと起きるようだ。
Orthographicモードだと起きない…のかもしれない（まじめに確認していない）。

## 真の解決策

スレッドにも書いてあるが、Vuforiaの次のバージョンでこの問題は解決される見込みだ。
なので、バージョンアップを待つのが正しい解決策と言えるだろう。
php4では使えていたsjisのソースをphp5では利用出来ない事がある

sjisソースの全部がダメというわけではなく、ちょっと大きめのファイルでダメだった。

```bash:文字コード確認
$ nkf -g test_*.php
test_sjis.php:Shift_JIS
test_utf8.php:UTF-8
```

```bash:syntax&nbsp;check
$ php -l test_sjis.php
Errors parsing test_sjis.php
$ php -l test_utf8.php
No syntax errors detected in test_utf8.php
```

sjisをutf8に変換して利用できることを確認。
2時間はハマった。

具体例をUPしたいところだがちょっと今はできない。
AWS SDK for PHP v3.0 の特徴・新機能


下記の動画を見たのでメモ

https://www.youtube.com/watch?v=STrtR89f5Pc


## AWS SDK for PHP - Version 3 の特徴

* Guzzle5ベース
* PHP 5.4以上
* パフォーマンスの改善
* スリムなコード
* Semantic Version に従う (semver.org)
* 新機能！

## SDK V3での新機能

* 非同期リクエスト、Promise API
	* https://github.com/reactphp/promise
* カスタム HTTPアダプタ (cURLがデフォルトだけど必須ではない）
* ページネータ
* 結果データの JMESPathでの絞り込み
	* http://jmespath.readthedocs.org/en/latest/specification.html
* "debug" クライアントオプション


## メモ

### SDK V3からは、インスタンス生成時に、version指定が必要

例)

```
$ec2 = Aws\Ec2\Ec2Client::factory([
	'region' => 'us-east-1',
    'version' => '2014-06-05',
]);
```

## 参考
AWS re:Invent 2014 | (DEV305) Building Apps with the AWS SDK for PHP
https://www.youtube.com/watch?v=STrtR89f5Pc
OCamlを始める


OCamlの環境を構築する際のメモです。

ちなみに、私の環境は、

OS : Mac OS 10.9



## インストール

### OCaml
以下の本家サイトにインストール方法があります。

https://ocaml.org


### rlwrap

rlwrapもインストールしましょう。
rlwrapは、ターミナルよりocamlシェルにいるときに、← ↑ → ↓などのキー入力ができるようにします。（これがないとこれらのキー入力をしても文字化けした内容が表示されるだけでした。）

	rlwrap ocaml

ocamlを実行するときは上記のようにします。

	alias ocaml="rlwrap ocaml"

と、上記のようにするととても便利です。


## 日本語の設定

設定内容は同じですが、設定を記述したファイルを実行時に渡す方法と、設定ファイルに予め記述しておく方法がありました。もちろん後者が楽だと思います。

	
1."ocaml -init" で設定ファイルを渡す

【設定ファイルの内容】

	let printer ppf = Format.fprintf ppf "\"%s\"";;
	#install_printer printer


上記をファイルにして起動時に呼び出す

	ocaml -init ocaml_utf8.ml


2.ホームディレクトリの設定ファイル ".ocamlinit" に記述して起動時に読み込ませる。


	$ cat .ocamlinit 
	let printer ppf = Format.fprintf ppf "\"%s\"";;
	#install_printer printer

【注意】設定内容2行目の#は必要です。

##基本の基本

####開始

	$ ocaml
	# 


####終了

これがないと終わられへん。

	exit 0;;

	(* or *)

	#quit;;

#####行の終わり

	;;
	
####コメント

上に出てきましたが、ocamlのコメントは

    (* コメント *)
    
になります。


##### ファイルの読み込み
	
プログラムを記述した.mlファイルを読み込ませるには以下のようにします。

	#use "file.ml";;

（ここでも先頭の#は必要です。入力は#から;;までです。）

## 基本

### 文字列

文字列はダブルクォーテーションで括ります。シングルクォーテーションだとエラーになります。

    let str="wow";;



　　　　
# 付録

## AtomでOCaml

2017/04/08 追記　====>
以下で使用する「Ocamltop HTML」は現在メンテナンスされておらず正常に動作しませんでした。
AtomでOcamlを使う場合はRepl (https://atom.io/packages/repl) を使うのがよいようです。
（私は試せていません。すみません。）

【参照】
https://github.com/etouss/atom-OcamlTopLevel/issues/2

なお、nnabeyangさんがご指摘くださいました。
ありがとうございました。
2017/04/08 追記　<====


GitHub製エディタ - Atom と拡張パッケージを使えば、シンタックスハイライトだけでなくOCamlで書かれたソースコードの実行・結果確認もできるようになります。

【インストールが必要なもの (OCaml周り）】
1. ocaml
2. opam (ocamlのパッケージ管理）
3. caml2html (2を使ってインストール）



### opamの更新とcaml2htmlのインストール

ターミナルより以下のコマンドをそれぞれ実行しました。

    opam init

    opam update

    opam upgrade

    opam install caml2html

###Atomパッケージのインストール

Atomで以下のパッケージを探してインストールします。

1. Language Ocaml
2. Ocamltop H T M L (https://github.com/tekdreamer/atom-OcamlTopLevel)




### 使い方

.mlファイルを開いてctrl + iを押すと、右に実行結果が表示されます。

ただし、日本語はそのままだとちゃんと表示できませんでした。
とりあえず、ソースコードの先頭に前出の日本語設定を入れるとちゃんと表示はできました。

対応方法：以下をソースコードの先頭に入れる。

	let printer ppf = Format.fprintf ppf "\"%s\"";;
	#install_printer printer;;
UbuntuにJava8環境構築

普通にJavaを入れたい場合には

```zsh
$ sudo apt-get install openjdk-7-jdk
```
のような感じでやってたけど，Ubuntu14.04のバージョンではopenjdk-8-jdkのパッケージは入っていないようです．

なので，自前で入れるしかないようです．
インストールするのはopenjdkでは無いですが，oracle-javaもopenjdkも同じような感じらしいので問題ないようです．

```zsh
$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer
```
すると以下のようにインストールが進みました．

![Screenshot from 2014-11-27 07:35:39.png](https://qiita-image-store.s3.amazonaws.com/0/21312/fbbe5c93-4d29-bdc2-1ae2-98ad74e7ae23.png)

![Screenshot from 2014-11-27 07:35:52.png](https://qiita-image-store.s3.amazonaws.com/0/21312/a15df82c-05b5-0b98-31f9-93a987cabf66.png)

よしなに２，３度了解とかはいとか選ぶと入ります．
javaが入ったかどうかを確認しましょう

```zsh
$ java -version
java version "1.8.0_25"
Java(TM) SE Runtime Environment (build 1.8.0_25-b17)
Java HotSpot(TM) 64-Bit Server VM (build 25.25-b02, mixed mode)
```
やったね．

それに加えて，環境変数とかの設定をしてくれてJava8をデフォルトに設定する為に以下のパッケージを入れるようです

```zsh
$ sudo apt-get install oracle-java8-set-default
```


参考
[How to Install Oracle Java 8 (JDK 8u25) In Ubuntu & LinuxMint Via PPA](http://tecadmin.net/install-oracle-java-8-jdk-8-ubuntu-via-ppa/)
[javaのバージョンを切り替える](http://qiita.com/ayihis@github/items/6c9b1739e995ebc3c446)
Dockerfileを編集して確認してまたDockerfileを編集しての一連のサイクルについて考える


Dockerと戯れている今日この頃です。


タイトル通りですが、Dockerfile編集して〜確認して〜というサイクルを回していく上で、どういう感じでやっていくのが効率的なのかちょっと考えてみました。

```sh
# Dockerfileの編集
vim Dockerfile
# イメージのビルド。testという名前
docker build -t test .
# コンテナ起動して確認。hogeという名前。コンテナからexitで抜けたら、そのコンテナを自動的に消す。
docker run -i -t -—rm --name hoge test:latest /bin/bash
# 内容を確認して、またDockerfileを編集する
```

こんな感じで回していく感じなのかなー。

`docker run`の時に`--rm`オプションをつけるのがポイント。`docker run -h`を見てたらあったー。
<del>同じコンテナの名前のものが存在していたら、上書きしてくれるイメージ。</del>

```
  --rm=false                 Automatically remove the container when it exits (incompatible with -d)
```

正確にはコンテナからexitで抜けたら自動的に消すという動作です。
EclipseとAndroid Studioのショートカットの違い for Windows

EclipseとAndroid Studioの開発中によく使うショートカットの違いでイラっとしたので対応をメモしておきます。

一行削除

| Eclipse     | Android Studio |
|:-----------:|:------------:|
| Ctrl + D   | Ctrl + Y    |


やり直し (Redo)

| Eclipse     | Android Studio |
|:-----------:|:------------:|
| Ctrl + Y   | Ctrl + Shift + Z  |


開発環境ごとにショートカットを覚えるのは辛いので、Android Studioの「Settings / Keymap」でプリセットのKeymapsである「Eclipse」にとりあえず設定し解決。
![キャプチャ.jpg](https://qiita-image-store.s3.amazonaws.com/0/60734/e2358edc-5137-9bac-d636-f3c5d36444f3.jpeg)
AdobeAIR for Desktop アプリがCDで動作しないので、ドキュメントにコピーしてキックする

##経緯
- Flash でオーサリングし、Adobe AIR for Desktop で Windows 向けのデスクトップアプリを「ランタイムが埋め込まれたアプリケーション」で書き出して制作していた。
- 書き出したアプリは、ローカルにおいてもLAN上においても動作は問題なかったが、それをCDに焼くと、URLLoader で読み込んでいる外部ファイルがIOエラーで読み込みに失敗する。swf でも txt でも変わらずエラー。
- AIR のランタイムバージョンを変更したり、細かい設定変えてみたけれど変わらず。

##対応
本体のアプリと別に、ドキュメント（マイドキュメント）フォルダーにデータをコピーしてからそれをキックするアプリをつくった

##コード
Flash のタイムラインにコードを書いています。Flex や Flash Builder など使われている場合は少し違う部分もあるかもしれません。

アプリケーションフォルダー内の [CONTENT] フォルダーの中身を丸ごと、ドキュメントフォルダー内に [copyContent] というフォルダを作成してコピーし、その中の「start.exe」をキックして自身は終了します。詳細はコード内のコメント参照


```lang:ActionScript3

import flash.filesystem.File;
import flash.desktop.NativeApplication;

var file;
var existsFlg = false;
//起動する実行ファイル名
var bootFileName = "start.exe";

//コピー元：アプリケーションディレクトリ内
var sourceDir = File.applicationDirectory.resolvePath("CONTENT");
//コピー先：ドキュメントディレクトリ内
var resultDir = File.documentsDirectory.resolvePath("copyContent");
if(resultDir.exists){
	file = resultDir.resolvePath(bootFileName);
	if(file.exists){
		//実行ファイルが存在したらコピーしないでキックする
		existsFlg = true;
	}else{
		//コピー先ディレクトリが存在するけれど実行ファイルが存在しない場合は、ディレクトリを丸ごと削除する（同期処理）
		resultDir.deleteDirectory(true);
	}
}

if(existsFlg){
	//実行ファイルをキック
	bootExe();
}else{
	//コピー処理（非同期）
	sourceDir.addEventListener(Event.COMPLETE, FileCopyToAsyncCompleteFunc );
	function FileCopyToAsyncCompleteFunc(event:Event): void{
		//コピー完了→実行ファイルをキック
		bootExe();
	}
	sourceDir.addEventListener(IOErrorEvent.IO_ERROR, FileCopyToAsyncIOErrorFunc );
	function FileCopyToAsyncIOErrorFunc(event:IOErrorEvent): void{
		//コピー失敗
		//なんからのエラー表示など
	}
	sourceDir.copyToAsync(resultDir,true);
}


function bootExe(){
	//起動ファイルキック
	var nativeProcessStartupInfo = new NativeProcessStartupInfo(); 
	var file = resultDir.resolvePath(bootFileName);
	nativeProcessStartupInfo.executable = file;
	var process = new NativeProcess(); 
	process.start(nativeProcessStartupInfo);
	//アプリ終了
	var app:NativeApplication = NativeApplication.nativeApplication;
	app.exit(0);
}


```