読者です 読者をやめる 読者になる 読者になる

jQuery : セレクタフィルタの様々な罠

月花です。

チェックボックスjQueryでわちゃわちゃしていたときにハマったのでメモします。
jQuery、卒業したいですね。

前提

こういうフォームがあります。

<!doctype html>
    <body>
        <form name="hoge">
            <label><input type="checkbox" name="fruits[]" value="4種盛り合わせ">4種盛り合わせ</label>
            <label><input type="checkbox" name="fruits[]" value="3種盛り合わせ">3種盛り合わせ</label>
            <label><input type="checkbox" name="fruits[]" value="レモン">レモン</label>
            <label><input type="checkbox" name="fruits[]" value="オレンジ">オレンジ</label>
            <label><input type="checkbox" name="fruits[]" value="ぶどう">ぶどう</label>
            <label><input type="checkbox" name="fruits[]" value="なし">なし</label>
        </form>
    </body>
</html>

果物を選択するチェックボックスが6つ並んでいます。

問題はこの「盛り合わせ」という2つの選択肢で、これに関しての仕様として、
1. チェックされたら、盛り合わせ以外の他の選択肢のチェックを外す
2. チェックされている間は、盛り合わせ以外の他の選択肢をチェックできない
3. ただし盛り合わせ同士は相互にチェックし合えるが、片方を押したら片方が非選択に戻る
ということになっています。

しかもなんとこのチェックボックス、上位フレームワークの影響でid属性を付けることはできません。
さらに、value値はなんと日本語です。勘弁してほしい。

セレクタだけで直接1要素を拾うことができず、value値が日本語で比較もあんまりしたくないので、フィルタを駆使して、上記を実装します。

:first は使えない

仕様の、3 が邪魔をして、:firstだけでなく、2番目を取る必要があります。
2番目をビシっと抜き出す、:second があれば良かったんですが、無いので、筆者は:nth-child()を使うことにしました。

わかってる人はアレっと思うでしょうが、後述ですし、そういう人にとって為になる情報はこの記事にはありません。

:nth-child() も使えない

とりあえずjQueryで1番目のチェックボックスが拾えれば、2番目も同様に拾えるし、なんとかなるやろってことで、やってみます。

$('input[name^=fruits]:nth-child(1)').change( function(){
    alert($(this).val());
});

しかしこれはうまく行きません。
1番目だけでなく、どこを押しても押した要素が拾われてしまいます。

これは、inputタグは全てそれぞれのlabelタグの中に入っているためです。
:nth-child() は親要素の長子を1とし、次子を2というように指定するのですが、それぞれのinputはそれぞれのlabelの長子なので、全てのinputが適合してしまい、全てのinputにchangeイベントがバインドされる結果となりました。

:nth-of-type()も、名前にchildが入っていないのですが、これは子要素のうち、このフィルタがくっついているセレクタで絞り込むため、長子しかいないこの場合は結局同じです。

:eq()を使う

筆者は、:eq()を知りませんでした。
正確には、知ってはいたんですけど、「eqがイコールの省略なのはわかるけど、何と何を比べてんねん」と思って詳しく知りませんでした。

:eq() は、そのセレクタの、親子関係を気にせず、ページの上から順番に振った通し番号を比較します。
要するに、DOM配列のインデックスです。なので、 :first と :eq(0) は等価になります。

ここで筆者は、しばらく nth-child() について考えていたため、インデックスの振り方でハマりました。
:nth-child() は、何番目の子供か、という通し番号です。0番目の子供というのは存在しないため、1から始まります。
:eq() はインデックスです。添字なので0から始まります。 めんどくさいですね。

これを使って、

$(function(){
    $('input[name^=fruits]:eq(0)').change( function(){
        if ($(this).is(':checked')) {
            //チェックされたとき
        } else {
            //チェックが外されたとき
        }
    });
    $('input[name^=fruits]:eq(1)').change( function(){
        if ($(this).is(':checked')) {
            //チェックされたとき
        } else {
            //チェックが外されたとき
        }
    });
});

これで、1番目の要素と2番目の要素だけにchangeイベントがバインドできました。

以外 をセレクタで表現する

1番目と2番目の要素だけにchangeイベントをバインドすることに成功しました。
その中で、問題の選択肢以外、というセレクタが必要になってきます。

これは、 :not() で解決します。

$('input[name^=fruits]:eq(0)').change( function(){
    if ($(this).is(':checked')) {
        //チェックされたとき
        $('input[name^=fruits]:not(:eq(0))').prop('checked', false);
        $('input[name^=fruits]:not(:eq(0))').attr('disabled', 'disabled');
    }
});

このように、さきほどの :eq() を :not() の引数の中に押し込めてやります。
これで、フィルタを反転させて、押した要素以外の全てのチェックを外し、選択不可にしました。
しかし、問題の選択肢2つの間では自由に選択することができなければいけません。

そこで、 :not() を複数のフィルタで指定します。

$('input[name^=fruits]:eq(0)').change( function(){
    if ($(this).is(':checked')) {
        //チェックされたとき
        $('input[name^=fruits]:not(:eq(0))').prop('checked', false);
        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
    }
});

:not() の引数は、カンマ区切りでOR条件で複数のフィルタを指定できます。
この結果、1番目と2番目以外を選択不可にするということが実現できました。
ちなみに、半角スペースで区切ると、AND条件になります。

今回は、1番目でもなく かつ 2番目でもない、となればよいのでOR条件を使って ¬(1∨2) とし、実質 (¬1)∧(¬2) なので実現できています。
ド・モルガンの法則です。頻繁に使うんですが、普段は名前を意識しないので、名前を言われると懐かしさを感じますよね。

チェックが外されたときの挙動を追加して

$('input[name^=fruits]:eq(0)').change( function(){
    if ($(this).is(':checked')) {
        //チェックされたとき
        $('input[name^=fruits]:not(:eq(0))').prop('checked', false);
        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
    }else{
        //チェックが外されたとき
        $('input[name^=fruits]').removeAttr('disabled');
    }
});

2番目の要素にも同様にバインド

$('input[name^=fruits]:eq(0)').change( function(){
    if ($(this).is(':checked')) {
        //チェックされたとき
        $('input[name^=fruits]:not(:eq(0))').prop('checked', false);
        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
    }else{
        //チェックが外されたとき
        $('input[name^=fruits]').removeAttr('disabled');
    }
});
$('input[name^=fruits]:eq(1)').change( function(){
    if ($(this).is(':checked')) {
        //チェックされたとき
        $('input[name^=fruits]:not(:eq(1))').prop('checked', false);
        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
    }else{
        //チェックが外されたとき
        $('input[name^=fruits]').removeAttr('disabled');
    }
});

共通化できそうなんですけど、共通化すると同じ要素に2度バインドしたりしてしまうのでうまく行きませんでした。
もう少しスマートにできる気はするんですけど。

最終的にはこう

<!doctype html>
    <head>
        <script
            src="https://code.jquery.com/jquery-3.1.1.slim.min.js"
            integrity="sha256-/SIrNqv8h6QGKDuNoLGA4iret+kyesCkHGzVUUV0shc="
            crossorigin="anonymous"></script>
        <script type="text/javascript">
            $(function(){
                $('input[name^=fruits]:eq(0)').change( function(){
                    if ($(this).is(':checked')) {
                        $('input[name^=fruits]:not(:eq(0))').prop('checked', false);
                        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
                    } else {
                        $('input[name^=fruits]').removeAttr('disabled');
                    }
                });
                $('input[name^=fruits]:eq(1)').change( function(){
                    if ($(this).is(':checked')) {
                        $('input[name^=fruits]:not(:eq(1))').prop('checked', false);
                        $('input[name^=fruits]:not(:eq(0),:eq(1))').attr('disabled', 'disabled');
                    } else {
                        $('input[name^=fruits]').removeAttr('disabled');
                    }
                });
            });
        </script>
    </head>
    <body>
        <form name="hoge">
            <label><input type="checkbox" name="fruits[]" value="4種盛り合わせ">4種盛り合わせ</label>
            <label><input type="checkbox" name="fruits[]" value="3種盛り合わせ">3種盛り合わせ</label>
            <label><input type="checkbox" name="fruits[]" value="レモン">レモン</label>
            <label><input type="checkbox" name="fruits[]" value="オレンジ">オレンジ</label>
            <label><input type="checkbox" name="fruits[]" value="ぶどう">ぶどう</label>
            <label><input type="checkbox" name="fruits[]" value="なし">なし</label>
        </form>
    </body>
</html>

終わりです。

ついでに色々調べてたんですけど、セレクタって結構やるやつですね。
jQueryの是非はともかく、ちゃんと論理演算を考えながら実装すれば、行数とバインドの節約が捗りそうです。
とはいっても、仕様変更・追加で継ぎ足し継ぎ足しのjQuery、まとめて改善しようにもすでに稼働しているので余計なテストが・・・。厄介すぎる・・・。

参考文献

www.jquerystudy.info

bootstrap : twinviteでbootstrapを活用してエモい招待サイトを作る

月花です。

先日、関西で行われるクラブイベントのWebページと、twinviteを公開しました。
そのとき使った手法が極めて有効であったため、下記に残します。

この記事は、イベントのWebサイトを作ったりtwinviteで凝ったことがしたい方の手引書を目指して書きました。
・気合をいれたイベントであることを強調したい。
・次は周年記念回なので、いつもよりきれいに作りたい。
・他のイベントとの差別化を図りたい。
様々な動機はあると思いますが、Webページをこだわることは、どれにも有効な手段です。

簡素な記事のため、説明不足の箇所が多いですが、分からないワードは積極的にググってみましょう。よく使われるライブラリについて書いているので、日本語で記事を起こしている先駆者はたくさんいます。

これらは、ある程度のHTML+CSSの知識は必要ですが、仕様などの深い理解は必要ありません。

今回作ったもの

・Webサイト
IzanagiDistribution3.0
いわゆるランディングページです。誘導対象はtwinviteですが、商業的な色を出さないために動線は最小限にしてあります。

・twinvite
IzanagiDistribution Ver.3.0 - twinvite
イベント招待サイトです。
自由にHTMLを書いてデザインできる部分がある、twiplaとかtweetviteみたいなやつです。
今回はここを攻略していきます。

bootstrapについて

Webサイト、twinvite共、bootstrapというライブラリを使っています。
getbootstrap.com
このライブラリは、Webサイトのあらゆるパーツのデザインを定義したCSSの詰め合わせと、便利なJavaScript関数の集合体です。
つまり、このライブラリで定義しているクラス名やID名を指定するだけで、グリッドシステムやモーダルの起動が可能です。
twinviteなどのHTMLを自由記述できる部分を含むページでは、スタイルは基本的にHTMLタグのstyle属性を使って、

<div style="〜〜〜〜"></div>

とすべてのタグに記述する必要がありますが、bootstrapに定義されているデザインを使う分にはクラス名の指定があればよいので、style属性が必要なくなります。

ここで、なぜtwinviteでbootstrapが使えるか、についてですが、twinviteは元々bootstrapを使って作られていて、私達が記述するより前の時点でリンク済みであるためです。
また、font-awesomeもリンク済みであるため、こちらもクラス名の指定だけで、様々なアイコンフォントを活用することができます。
fontawesome.io

つまり、Webサイトを別途作成する場合、そちらもbootstrapを使って実装してやれば、理想的にはHTML部分のコピペだけで、ほぼ同じページが作れる、ということです。
今回私が作成した2つは、そのようになっているため、Webサイト完成後の極めて迅速なtwinvite対応が可能でした。

ちなみに、こちらは以前私が作成した、LoveDive! というイベントのtweetviteページのソースコードです。
エディタの横幅に収まらないほど、style属性にガリガリ記述していることがわかると思います。
f:id:gekka9:20170108180509p:plain
このコードは、下記のサイトの開催日時や金額が書かれたテーブル部分だけです。
http://gekka.sexy/love_dive.html

bootstrapが使えれば、もはやこのような苦労は必要ありません。

bootstrapの主な要素

レスポンシブ対応

近年、デバイスの増加により、様々な解像度の環境でWebサイトが見られることになります。
スマホ・PC・タブレットなど、その全てに対応するためにいくつもファイルを作り、デバイスを判断して読み込むHTMLやCSSを変えるといった解決策は非常に非効率です。
そこで、画面の幅だけを頼りに、CSSを出し分け、たとえばPCでは3カラムでスマホでは1カラムといったことが、1つのHTML、1つのCSSで実現可能になりました。そういった実装をレスポンシブデザインと呼びます。
冒頭で提示したサイトは両方ともレスポンシブです。PCでご覧になっているのであれば、ブラウザの幅をぐりぐり変えてみてください。手っ取り早くわかると思います。

bootstrapはレスポンシブに対応しており、デザインが切り替わる境界は全部で3つあります。
すなわち、4つの解像度レンジでデザインを出し分けることが可能です。当然、クラス名の指定だけによって。

グリッドシステム

グリッドは網目と言った意味がありますが、例えば正方形の画像を8つ並べるのであれば、PCでは横4つ縦2つ、スマホでは横2つ縦4つ、といった出し分けが適切でしょう。
このようなブラウザ解像度に合わせたグリッドレイアウトのカスタマイズが、bootstrapでは非常に強力にサポートされています。
CSS · Bootstrap

基本的には横幅を12分割し、そのうちどれくらいをHTML要素に割り当てるかによって指定します。
さらに、さきほどの、PCでは横4つ縦2つ、スマホでは横2つ縦4つといった実装は、グリッドの要素1つ1つに対して、下記のようなクラス名を当ててやります。

<div class="row"> <!--行の開始-->
  <div class="col-xs-6 col-sm-3 col-md-3"></div> <!--このdivが1つの要素-->
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
  <div class="col-xs-6 col-sm-3 col-md-3"></div>
</div> <!--行の終了-->

この例は、さきほどのページであれば、下記の部分に対応しています。
・PC表示
f:id:gekka9:20170108172230p:plain

スマホ表示
f:id:gekka9:20170108172237p:plain

それぞれのクラス名を説明します。

col-xs-6

このうち、xs の部分と、6の部分が重要です。
xsはブラウザの横幅が768pxより小さいときに適用するという指定で、
6は、先述の、横幅を12分割したうち、6個分の幅を使う、ということです。
同時に、

col-sm-3

を指定していますが、
mdはブラウザの横幅が768px以上のときに適用するという指定で、
3は、12分割中3個分の幅を使う、ということになります。
さらに、

col-md-3

によって、ブラウザの横幅が992px以上の場合も指定しています。

なので、
ブラウザの横幅が992pxより小さいときは、親要素の幅の半分の幅の要素が8個並び、
ブラウザの横幅が992px以上のときは、親要素の幅の1/4の幅の要素が8個並ぶ
という指定になります。

ここで、ひとつの div class="row" の中に合計12を超える指定をしていることになりますが、12を超えるごとに折返されるので、問題はありません。

その他の要素

見出しやアオリ文などのデザインを定義したTypography群、テーブルやボタン、フォームなど、ありとあらゆるものがすでに定義されており、単にHTMLを書いたものに適用するだけで非常に見栄えの良いサイトになります。

JavaScript

さきほどグリッドのところで提示した画像の1つ1つはボタンになっており、ボタンを押すとモーダルが起動するようになっています。
これは、bootstrapに元々組み込まれているJavaScriptによって、起動用のIDをボタンに設定し、対応するIDをモーダルの要素に設定してやれば、それだけで動作をします。
当然、このモーダルの中にもグリッドシステムなどの使用が可能です。
f:id:gekka9:20170108174642p:plain
画像はtwinviteでの動作例ですが、私はこのためのJavaScriptを1文字も書いていません。
この他にも様々な関数が用意されています。

twinviteへの適用

twinviteでは元々bootstrapが読み込まれているため、上記のような機能がすべて実装済みです。
twiplaやtweetviteでこったことをしようとして、HTMLタグにstyle属性をガリガリ書いている方であれば、これがどれほど強力なことかがわかるでしょう。
twinviteでは、linkタグやstyleタグが使えるため、そのようなことはもはや必要ありませんが、これらのタグはセキュリティ上の危険を孕むため、いつ使えなくなるかわかりません
その日が来る前に、是非bootstrapの学習をオススメ致します。

ただし、1つだけ大変なところがあります。
それは、自由記述部分の横幅が、ブラウザの横幅と一致しないことです。

先程のグリッド部分を、同じ幅のブラウザで表示してみました。
・Webサイト
f:id:gekka9:20170108174039p:plain

・twinvite
f:id:gekka9:20170108174049p:plain

Webサイト方はグリッドシステムがブラウザの横幅すべてを使っているため4つ入りますが、twinviteでは自由記述部分はかなり狭くなるため4つ入れると画像のサイズが極めて小さくなってしまいます。
そのため、グリッドシステムだけは、調整しています。
といっても、 col-sm-6 のようなクラス名を書き換えてやるだけです。

総括

さまざまなイベントが増え続ける今、同じハコや同じテーマでイベントをやることも多いでしょう。
その際、他と違うことを強調したい場合に、凝った招待サイトを作るといったことは非常に有効な手段だと考えています。もしくは、周年記念回のときだけ凝ってみるとか。

気合の入れた宣伝ページを作ることは、そのイベントの本気度や意気込みにそのまま直結していきます。
本気のイベントを気合を入れて打ち出し、最高のイベントへと導くことは、本当に楽しいです。

この記事の内容は私のような職業エンジニアでなくとも、十分に達成できる難易度のものだと思っています。
私自身もそういった告知ページを見ることは好きなので、こういった技術が浸透することを願っています。
是非、気合の入ったページを見せてください。

AWS : Fluentdを使ってEC2からApacheのログをS3へ

月花です。
久しぶりの技術記事です。

最近AWSを触っていて、わかりにくいなあと思ったS3との連携について。

AWSでは、障害が起こったりAutoScalingしてたりすると、EC2インスタンスが勝手にシャットダウンされてしまう。
このとき、ログが吹っ飛ぶのでS3へ逃しておく必要がある。

前提

  • WebサーバとしてのEC2が複数
  • OSはAmazon Linux
  • Apache
  • S3バケットはサーバ分作る

やりたいこと

  • Apacheの アクセス/エラー ログを両方S3へ逃す
  • 設定は軽いほうがいい
  • 自動でやってほしい
  • {server_name}/access_log/{YYYY}/{MM}/{DD}/access_log_{YYYY}-{MM}-{DD}_{HH}.log みたいにしてほしい

アプローチ

まずはどのみちS3へ転送が必要なため、EC2インスタンスそれぞれにS3フルアクセス権限を付与する。

これで、S3への操作権限を得た。このままcpコマンドでコピーすることもできるが、勝手にシャットダウンされて吹っ飛ぶので極めて短い間隔のcronかなにかでcpすることになる。
しかも、都度時間を見て、ディレクトリなければ作るなんてコード書くのめんどくさいし非効率。

そこで Fluentd を用いて、自動化してもらう。
こういうのを、Web Storage Archiveパターン と呼ぶらしい。
CDP:Web Storage Archiveパターン - AWS-CloudDesignPattern

S3へのアクセス権限を与える

まずはIAMロール・・・ではなく、既にEC2インスタンスは動いてしまっているので、IAMユーザを作成する。
サーバ分作ったら(1つでもいいのかしら)、アクセスキーとかをメモしておく。

下記の「AWS CLI を使用してロールを切り替えるには」を参考に、起動中EC2インスタンスに接続し、ユーザを割り当てる。
docs.aws.amazon.com

$ aws configure
AWS Access Key ID [None]: your_key_id
AWS Secret Access Key [None]: your_sec_key
Default region name [None]: ap-northeast-1
Default output format [None]: json

これでアクセス権限を付与できた。
Amazon LinuxにはデフォルトでAWS CLIという、AWSサービスをいじるためのクライアントが搭載されており、S3関連のコマンドは以下の記事に詳しい。
www.task-notes.com

なお、再起動は必要ないので、そのまま叩いてみて、成功なら成功である。失敗したら頑張れ。

NTPを設定する

Amazon LinuxのデフォルトはUTCなので、設定してないと、Fluentdくんが作るファイルを時刻を使って階層化するとき、めちゃくちゃになる。
docs.aws.amazon.com

インスタンスのセキュリティグループのルールでは、ポート 123 (NTP) でアウトバウンド UDP トラフィックを許可する必要があります。ネットワーク ACL のルールでは、ポート 123 でインバウンドとアウトバウンドの UDP トラフィックを両方許可する必要があります。

筆者はこれを忘れてハマった。

Fluentd のインストール

公式ページ
docs.fluentd.org
を参考に、とりあえず入れるだけ入れる。

$ curl -L https://toolbelt.treasuredata.com/sh/install-redhat-td-agent2.sh | sh

こういうインストール方法、めちゃめちゃ助かる。

素のままでも使いやすいっぽいのだが、やりたいことがあるので、Fluentdのプラグインをいれる。
github.com

$ /usr/sbin/td-agent-gem install fluent-plugin-forest

Fluentd の設定

どのファイルをどれくらいの間隔で、どんな名前でどこに転送するのかを定義する。
その定義ファイルは、以下にある。

/etc/td-agent/td-agent.conf

まずは、source節を編集して、どのファイルを対象とするかを定義する。
なお、基本的に末尾に追記で問題ない。

<source>
  @type tail
  format apache
  path /var/log/httpd/access_log
  pos_file /var/log/td-agent/httpd.access.log.pos
  tag s3.httpd.access
</source>

ここでは例として、Apacheアクセスログを対象とする。

type tailにするとtailコマンドで末尾をフォローしてくれる。このタイプによってオプションが変わる。ここから先は全部tailが対象のオプション
format 対象とするログのフォーマットを選択する*1
path 対象のログへのフルパス
pos_file 前回どこまで読んだかが書いてある栞ファイル。Fluentdが勝手に生成するので、わかりやすい名前にしておく
tag ソースごとにタグ付けが行える

このあと、エラーログを見るsourceも書いておいた。
タグは s3.httpd.error とした。


次に、さきほどのソースを、どれくらいの間隔で、どんな名前で、どこに転送するのかを定義するために、match節を記述する

<match s3.*.*>
  type forest
  subtype s3
  <template>
    aws_key_id your_key_id
    aws_sec_key your_sec_key
    s3_bucket bucket_name
    s3_region ap-northeast-1
    path ${tag_parts[1]}/${tag_parts[2]}_log/
    buffer_path /var/log/td-agent/s3/${tag_parts[2]}_log
    time_slice_format %Y/%m/%d/${tag_parts[2]}_log_%Y-%m-%d_%H
    time_slice_wait 10m
    #flush_interval 3s
    buffer_chunk_limit 256m
  </template>
</match>
match タグに対応している。このmatch節はどのソースに使うのか、ここで定義する
type さきほどインストールしたプラグインを使うのでforestとする
subtype S3に投げるため。この辺は用途によって決まってくる
aws_key_id IAMユーザのキーID
aws_sec_key IAMユーザのシークレットキー
s3_bucket S3バケット名。なければ作ってくれる
s3_region S3のあるリージョン。例では東京
path バケット直下からの共通のパス。forestによって、${tag_parts}が有効になっている。matchのところで指定した、*の部分が配列になって1から順に収まっている。このおかげで、複数のソースに対して1つのmatchで済むようになる
buffer_path S3へ転送する前のバッファファイル。わかりやすい名前にしておく
time_slice_format 生成したいファイル名。年月日とかはforestがなくても取れるから階層化しておこう
time_slice_wait S3へ転送する間隔
flush_interval こいつがあると、上記の間隔より優先される。例ではコメントアウトしているが、3秒なのでテスト向け
buffer_chunk_limit 指定したサイズを超えたバッファファイルはエンキューされて、次のバッファファイルが作られる

Fluentd を起動してみる

いつものやつで起動して、ログを見てみる。

$ chkconfig td-agent on
$ service td-agent start
$ td-agent td-agent:                                         [  OK  ]
$ cat /var/log/td-agent/td-agent.log

起動はしたが、エラーがでていた。

2016-11-08 17:13:58 +0900 [error]: Permission denied @ rb_file_s_stat - /var/log/httpd/access.log
2016-11-08 17:13:58 +0900 [error]: suppressed same stacktrace

出たー、Permissionだ!!!!
ありがちなハマり。

多少強引だが、他の設定をいじらなくてよいので、Fluentd の実行ユーザをrootにしてしまおう。
kenzo0107.hatenablog.com

TD_AGENT_USER=td-agent 
TD_AGENT_GROUP=td-agent 

↓ここをこう↓

TD_AGENT_USER=root
TD_AGENT_GROUP=root

restartしてログを見てみると、

2016-11-08 18:51:54 +0900 [info]: listening fluent socket on 0.0.0.0:24224
2016-11-08 18:51:54 +0900 [info]: listening dRuby uri="druby://127.0.0.1:24230" object="Engine"
2016-11-08 18:51:54 +0900 [info]: following tail of /var/log/httpd/access_log
2016-11-08 18:51:54 +0900 [info]: following tail of /var/log/httpd/error_log

ということで、無事にログファイルがフォローされた。

S3を確認

AWSのサイトでバケットを見に行こう。

今回の例では

すべてのバケット /bucket_name/httpd/access_log/2016/11/08/access_log_2016-11-08_17_2.gz

という具合になって、終わり。

*1:一覧 : docs.fluentd.org

飯テロ : 料理を撮るのに5秒以上かけてはならない

月花です。

もうだいぶ前から、表題のようなポリシーのもとで飯テロを実施しています。
本当は3秒に納めたいのですが「4秒以上」だと語呂が悪く「3秒以上」だとセンセーショナルではあるが、実際厳しいのでこの表題になりました。

ここでは、私の飯テロにおけるポリシーを紹介します。

以下の目次でお送りします。

  • なぜ5秒なのか
  • 5秒に収める理由
  • メリット・デメリットとは
  • 動画は例外である
  • さいごに

なぜ5秒なのか

昨今、スマホのカメラ性能が爆上がりしていて、3秒に収まるからです。

iPhone5ではピントの合わせにかかる時間が微妙ではあったのですが、iPhone6にもなれば瞬間で合うため、カメラアプリさえ立ち上がればすぐ撮れます。
カメラアプリの起動はiOS10になってから、コントロールセンターにアクセスしなくてもロック画面で左フリックをするだけで起動します。
こちらの方法であれば、横持ちに変える動作と並行することができ、さらなるタイム短縮ができるでしょう。

5秒に収める理由

席に料理が到達した瞬間が、その料理にとっての最高の一瞬だからです。

料理というものは、席に到着した瞬間、2つの最高ポイントを持っています。
つまり、

  • 見た目

です。

味に関しては言わずもがな、出来たてを食べるのが美味しいに決まっています。ホイル焼きを席でちょっと蒸らせみたいなやつは、そのホイルを誰かが開ける瞬間が最高点です。
見た目は誰も手を付けなければ崩れませんが、重力に負けることはありますし、写真を撮らない人間を待たせるわけにはいきません。

なので、席についていい感じの場所においたら、秒で決めましょう。
前の章の通りにやれば、秒で決められますね?
そしてここが重要なのですが、Twitterの誘惑を断ち切り、スリープ状態にする時間も惜しみ、できるだけ早く食器を持って確保に向かいましょう。

今、出来る限り最高の瞬間の料理を食べようとしています。
この状態にある人間を待たせる飯テロリストは時間がかかりすぎです。
なので自分も誰かを待たせないよう、秒でキメましょう。

メリット・デメリットとは

メリットとしては、その料理の最高の瞬間を体験できることが一番大きいと考えています。
また、写真を撮らない友人・恋人を待たせておく時間を最小限にできます。
さらに、すぐにスマホをいじりつづけないことで、会話がしやすくなります。誰かまごついている人が居たとしても、すぐに写真をキメたか撮らなかった人間は会話で間をもたせることができるのです。
撮った後全員がツイートのためにスマホをいじっていれば、その空間は料理が冷めていくばかりで会話もない完全な無が広がるばかりです。これだけは絶対に避けたいところですよね。

デメリットとしてはまず、飯テロの速報性が失われることが大きいです。
また、友人と一緒に写真を上げることで、だれだれと一緒に来ていますアピールができますが、このチャンスがなくなります。
しかし、速報性に関しては、友人間で出遅れるだけで、3口ほど味わって食べてからやればいいです。フォロワーにとってはさほど影響ありません。
本当に美味しかった場合、ツイートを忘れてしまうこともありますが、大丈夫です。飯テロのゴールデンタイムは深夜なので、持って帰って派手にやりましょう。

友人と一緒に来ていますアピールは、複数のやり方があります。
終わってから、今日はだれだれとどこそこに行きました♡スタイルや、引用ツイート、タグ付け、などなど時間に縛られない方法がいくらでも用意されています。

このことから、デメリットは工夫次第で解消できるといえます。

動画は例外である

動画は例外です。実際に無理ということもありますし、かといって動画は録りたいですよね。

では、動画が必要な料理の状態を整理してみましょう。

  1. 煮えたぎっていて、その状態を良しとする鍋などの料理
  2. 煮えたぎっていて、冷めるまで食べられない麻婆豆腐などの料理
  3. セルフスタイルの焼肉やお好み焼き
  4. 店員が仕上げまたはパフォーマンスをしている最中

これくらいではありませんか?
このような状態にあっては、すぐ食べることができなかったり、多少放っておいても劣化することはありません。
であれば、ゆっくり動画を撮る余裕があります。

静止した状態の料理では、3秒より長い時間同じ料理が写っている状態というのは、間延びし過ぎではないかと思っています。
わざと手ブレをさせるvineなどを使った技については、そもそも短い時間の動画であることが前提のため、表題と照らし合わせば、そう悪くはないはずです。

さいごに

いかがだったでしょうか。
最高の飯テロと最高の料理、最高の友人たちで幸せな時間を過ごす秘訣は、これです。
酔うなどのアクシデントにより、私自身100%はできていませんが、出来る限り心がけています。

さて、私が所属する同人音楽サークル dat file records では、同人音楽を中心に据えながらも、飯テロリストとして貪欲な活動をしております。
過去には、飯テロE.P.という、飯テロコンピレーションを発表しています。

いよいよ今週末に迫りました東方紅楼夢では、二色蓮花蝶アレンジオンリーコンピ、「ここに神社を建てよう」を頒布いたします。
スペースは た-24b でございます。当日私は霊夢のコスをして、売り子をしています。

また、11/19には、過去東京で行われた IzanagiDistribution が大阪日本橋BAR Guildにて再起動いたします。
私はこの IzanagiDistribution Ver.2.0 の特設サイトのデザイン・コーディングを担当いたしました。
こちらでのコスは未定ですが、スタッフとして参加致します。

この記事が皆様の最高の飯テロライフの参考になれば幸いです。

NetBeans : 既存のプロジェクトをBitBucketにpushする覚書

よくBitBucketでプロジェクト作るの忘れたまま書き始めるので覚え書き。

既存のプロジェクトの初期化

まず、NetBeans上の既存プロジェクトのgit初期化をする。
プロジェクトを選択して、 チーム > Git > リポジトリの初期化
で、ダイアログが出るのでパスを確認してOKならOK。

gitの構成をBitBucket用に設定する

次に、BitBucketにリポジトリを作成し、リポジトリ名を控えておく。
仮にログインユーザ名をuser、リポジトリ名をtestProjectとする。

NetBeansリポジトリの初期化が済んだプロジェクトを選択し、 チーム > リポジトリ > 構成を開く を選択すると、エディタでconfigファイルが開かれる。
ここに、下記のフォーマットをコピペする。

[pack]
	buildbitmaps = false
[core]
	repositoryformatversion = 0
	filemode = true
	logallrefupdates = true
	precomposeunicode = true
	bare = false
[remote "origin"]
	url = https://user@bitbucket.org/user/testProduct.git
	fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
	remote = origin
	merge = refs/heads/master
[user]
	name = Name
	email = Email

このうち、[remote "origin"]と、[user]を改変する必要がある。

ここでついでに設定を書き換えてもいいし、NetBeans上とかコマンドで設定してもいい。
あとはこのままcommitしてpushするだけ。

amazon : 動画をPS4で見る

筆者はプライム会員である。
話すとよくびっくりされるのだが、意外と安いことを話すと、みんなも意外だと思うらしい。
年会費で4桁は私の中では十分お手軽なサービスなのだ。

私がアマゾンで動画を見なかった理由

結論から言うと、PS4にネイティブアプリがあることを知らなかったのだ。
PS4で見るならブラウザで見るのかな、となんとなく思っていてちゃんと調べていなかったからだ。

私のPCはMac Book Airである。つまり、HDMI端子がない。
ところが、うちで一番いいディスプレイはThunderboltケーブルに対応していない。

なので、一番いいディスプレイはPS4のためだけにあり、なんならFF14専用と言っても差し支えない。
完全にFF14のためと思っているたため、MBAを使っているときはPS4は動いていなかった。
PS4を使っているときは、クラフターなので基本的にMBAはエリオネスを表示している。

この間、プライム会員の話をしたときに、ちゃんと調べようと思って調べたのだが、どうやらPS4でも専用アプリがあるようだった。
ちょうど、FF14から離れている時期で、PS4が完全に停止している状況だったのでちょうどよかった。

インストール

これはものすごく簡単だった。

メニューから、ディスプレイ型のアイコン(テレビ&ビデオ)を選択すると、下に各種動画配信サービスのアイコンが現れる。
それらは、アプリが存在するもので、好きなのを選んでクリック数回でインストールができた。

amazonの場合はここからもお手軽で、メールアドレスとパスワードを打ち、登録しているクレジットカードを選択すればそれで完了だった。
プライム会員ならばクレジットカードは登録してあるので、もろもろコミで一瞬で終わった。

そのぶん、パスワードはしっかりしてないといけないが。

何見たの?

孤独のグルメです。

Elixir : エリクサーをとりあえずひとくち

ことはじめ記事の一歩前のやつです。

新しい言語を触りたい

筆者はこれまでに、JavaJavaScriptPHPPythonRubyを、書けると言えるくらい書いてきた。
CodeIQの初級問題レベルのトイプログラムならもっと多いのだが、まあここらへんは人によってボーダーが違うのでなんとも。

結果的にWebプログラミングに落ち着き、仕事ではPHPを使っている。

でもいいかげんPHPも飽きてきた。ここらで一発足りないやつをやろうということで、いろいろ考えてはいた。
Webデザインも研究中だし、個人Webページもあってもいいかも、いっそ安いvpsを遊び場サーバとして借りるか、となり、いよいよ現実味を帯びてきていた。
さて、Ruby on Rails・nodeJS・Scala ・・・って結局使ったことある言語じゃん!

このタイミングで、雑談中にある言語を教えてもらった。

それが Elixir(エリクサー) だった。
この言語はErlang(アーラン。削除さんの曲ではない)のVM上で動く言語であり、言語実装もErlangでなされている。
Erlang自体にも興味はあり、触ってみたかったところでいい出会いを果たすことができた。

しかもこのElixirのWebアプリケーションフレームワークとして、 Phoenix(フェニックス) が存在するらしい。
筆者は根っからのスクウェアファンであり、エリクサーとフェニックスという名前だけでもうやるしかないという結論に至った。

f:id:gekka9:20160824120039p:plain
Elixir
ロゴの紫が美しい。

Elixirとは

Elixir自体はこの記事が詳しい。

qiita.com

2012年に登場した、かなり新しい言語であるらしく、並行処理に長けている。
もともとのErlang自体はインフラのために作られた言語で、並行処理と障害耐性の観点で、有効になるような特徴を備えている。
だからネットユーザの増加に伴い、並行処理に移行していく流れの中で(TwitterScalaに移行したように)、その選択肢として登場したということ・・・らしい。
ElixirはRuby on Railsの開発コアメンバーが開発した言語であり、Webアプリケーションの流れの中でのまさに正統な変遷であると考えていいのではないかと思う。

もうRuby on RailsとかnodeJSでウオオスゲエなんて言っていては遅すぎるし、なんなら私もElixirを知ること自体が既に遅すぎるくらいの激流であることに改めて気付かされた。
既に選択肢としてある程度の知識を持ち、常に提示できるようにしておかなければならない。

ということで、多少の焦りとともに、学んでいく。

とりあえず読みたい

プログラミングElixir

プログラミングElixir

技術書って現物があるとやる気が出ると思う。
確かにネットに記事はいっぱい転がってるんだけど、余計なサーフィンしちゃったり、断片化した情報を集めたりするのって時間がかかる。
あと、ネットでいくらか記事を見たら、この本の中のサンプルを引用しているところがいくつも見つかった。
じゃあもう買えばいいじゃん。
技術書買ったからにはやらないとね、というモチベーションも維持できる。

そしてこの本には、オブジェクト指向に慣れた体を徐々に関数型に慣らしていく過程を追体験できるというレビューがあり、その通りならばバチバチのオブジェクト指向プログラマの筆者に適すると考えたからだ。

続きは、これを読んでから。