HerokuからElastiCache(Redis)へのアクセス

既存のWebサービスでセッションストアにAWSのElastiCache(Redis)を使用しているが、それに対し新たに立ち上げるHerokuサーバからアクセスできないかを検討した。

まず第一に、ElastiCache上のRedisではパスワード認証を行うことができない。

Amazon ElastiCache よくあるご質問 | アマゾン ウェブ サービス(AWS 日本語)

そのため、セキュリティグループによって制限をかけることになる。

セキュリティグループの中でIPアドレスを指定して該当のHerokuアプリを特定できればよいが、Herokuの場合IPアドレスは定期的に変更されてしまうため、これはできない。

Heroku自体もベースはAWSであるため、該当のHerokuアプリに紐づくセキュリティグループというのが存在するのではないかと思ってしまうが、 そういったものは存在しない。Heroku全体のセキュリティグループは存在するが、それを許可してしまうとすべてのHerokuアプリからアクセスが可能になってしまう。また、Heroku全体のセキュリティグループを利用すること自体が推奨されていない。

Use of Heroku AWS security group and account id no longer recommended | Heroku Dev Center

RDSであればDB自体の設定で認証をかけることができる(暗号化も)が、Elasticache上のRedisの場合はそれができないため、Herokuのアプリから利用するのは難しいという結論になる。

もしもHerokuからRedisにアクセスしたいのであれば、HerokuのAdd-Onを使うか、自身でEC2上にRedisサーバを立ち上げるという方法になると思う。もしくはアクセスする元のサーバにHerokuを使わずにEC2を使うか。

それか、Proximo | Heroku Dev Center という有料Add-onで固定IPを利用できるので、それを使うという手もありそう。

年月でループする

指定した期間の年月ごとにループするシェルスクリプトを作ってみた。意外と面倒くさかった。

用途としては、ログを年月ごとに分けたりとか、ディレクトリを年月ごとに作ったりとか、そんなのに使えると思う。

#!/bin/sh

START_YEAR=2012; START_MONTH=1
END_YEAR=2013; END_MONTH=12

YYYY=$START_YEAR; MM=$START_MONTH

while [ $YYYY -le $END_YEAR -a  $MM -le $END_MONTH ]
do
  YYYYMM=${YYYY}`printf "%02d" ${MM}`
  echo $YYYYMM
  if [[ $MM -eq 12 ]]; then
    MM=1
    YYYY=`expr $YYYY + 1`
  else
    MM=`expr $MM + 1`
  fi
  YYYYMM=${YYYY}`printf "%02d" ${MM}`
done

最初は期間指定するための変数YEARとMONTHをくっつけていたが、都度YEARとMONTHを分離したり結合したりと大変だったので個別に分けて指定する形にした。

rubyで作るとこんな感じ。

require 'date'
(Date.new(2012, 1)..Date.new(2013, 12))
  .select {|d| d.day == 1}
  .each do|d|
     yyyymm = "%04d%02d" % [d.year,d.month]
     puts yyyymm
     # `mkdir #{yyyymm}`
  end

Markdown用のリンク記述を取得するブックマークレット

Markdown記法で外部リンクを記述したい。その場合にURLだけでなくそのページのタイトルもテキストとして記載したい。そんな時のためのブックマークレット

javascript:window.prompt('', '[' + document.title + '](' + location.href + ')' );

実行するとプロンプトで以下のようなテキストが表示される。

[Gaishimo](http://gaishimo.hatenablog.com/)

これをコピーしてそのまま貼りつければOK!

Boostrapのリッチテキストエディタプラグイン: bootstrap-wysiwyg

Twitter Bootstrapネタ。

Githubのexploreページでホットなプロジェクトのいくつかを眺めていたら、Bootstrap用のリッチテキストエディタを実現するjQuery Plugin : bootstrap-wysiwygを見つけた。

試しにドキュメントを参照しながらjsFiddleで作成してみた。ほとんどサンプルと同じだけど。。

ツールバーのボタンでフォントの変更や位置変更とか基本的な操作ができた。設定でショートカットキーを割り当てることも出来る。

リッチテキストエディタが気軽に設置できてありがたい!

ちなみにこのプラグイン名の"wysiwyg"、何て読めばいいかわからなくて辞書で調べてみたら、"what you see is what you get." (見た通りのものが結果に反映されること) という意味らしい。読み方はワイシーワイジーかな?

RequireJSでのライブラリの依存設定

RequireJSを使って以下のようにjQuery-UIを利用するコードを記述したところ、 JSエラーが出た。

define([
    '../bootstrap/bootstrap',
    '../jquery/ui/jquery-ui.custom',
    '../jquery/ui/jquery.ui.widget',
    '../jquery/ui/jquery.ui.mouse'
  ], function(){
      ....
    });
  });
Uncaught TypeError: Object function ( selector, context ) {
    // The jQuery object is actually just the init constructor 'enhanced'
    return new jQuery.fn.init( selector, context, rootjQuery );
  } has no method 'widget' jquery.ui.mouse.js:21

jquery.ui.mouse.jsをロードするタイミングで依存しているjquery.ui.widgetがロードされていないらしい。 Chromeのdeveloper-toolで見るとその時のロード順序は以下のようになっていた。

f:id:t_gaisho:20130317140549p:plain

jquery.ui.mouse.jsが先にロードされてしまっている。 ただこのロード順序は非同期のため、その時によってバラバラ。運がよければエラーにならなかったりする。。

依存するライブラリを必ず読み込んだ後にロードするようには以下のようにRequireJSのshim設定を定義する必要がある。

    <script>
    var require = {
      shim: {
        '../jquery/ui/jquery.ui.mouse' : {
          deps: [ '../ui/jquery-ui.custom', '../ui/jquery.ui.widget' ]
        }
      }
    };
    </script>

depsの所でjquery.ui.mouseはjquery-ui.customとjquery.ui.widgetに依存しているという情報を定義している。

更にdefine関数の呼び出し箇所で依存しているファイルの記述を削除。shim設定しているため自動で読み込んでくれる。

define([
    '../bootstrap/bootstrap',
    '../jquery/ui/jquery.ui.mouse'
  ], function(){
    ...
  });

この状態で画面のロードを行うとjsエラーは発生しなくなった。

f:id:t_gaisho:20130317141256p:plain

'../ui/jquery-ui.custom', '../ui/jquery.ui.widget' が '../jquery/ui/jquery.ui.mouse' よりも先にロードされている。常に。

Gitのpre-commitフックでgruntビルドを実行

前回の記事でJS Hint、CSS Lint 等をGruntを使って実行する方法を書いたが、gruntビルド自体を実行することを忘れてコミットしてしまったらあまり意味が無いので、コミットする直前に実行するようにしてみた。

プロジェクトの.git/hooks以下に pre-commitファイルを配置する。

#!/bin/sh

grunt build

pre-commitファイルには実行権限を付与

chmod u+x .git/hooks/pre-commit

これでgit commit する時にgruntビルドが走り、エラーがあった場合はcommitが中止されるようになる。必ずチェックが走ったものしかコミットが出来なくなるため、おかしなものが上がってしまうことがなくなる。

ただこれだと、一部の修正だけをコミットしたい場合、それ以外のワークツリー上にあるファイルのせいでビルドエラーになった場合、それを直すまでコミットができなくなってしまう。インデックスに存在するファイルに対してgruntビルドができたらいいなあ。

GRUNT とJSHintのコードチェックをビルドプロセスに組み込む

はじめに

JavaScript にはJSHintというコードチェッカーが存在する。このチェッカーの実行を、タスク実行ツールGRUNTを使ってビルドプロセスの中に組み込む方法を試してみた。

以下の英語のブログ記事を参考にした。 Let tools define JavaScript style

GRUNT とは?

GRUNT は、JSファイルのminifyやコンパイル、テスト、コードチェック等の様々なタスクを実行してくれるタスク実行ツール。用途に応じたプラグインを利用することができる。 プラグインの一覧はこちら

GRUNTとcontrib-jshintプラグインのインストール

まずgruntのCLIツールをインストール

npm install -g grunt-cli

次にプロジェクトのpackage.jsonにgruntとgrunt-contrib-jshintを記述してnpm installを実行。

  "dependencies": {
    "grunt": "*",
    "grunt-contrib-jshint": "*"
   }  

grunt-contrib-jshintはGruntでJSHintチェッカーを実行するためのプラグイン)。

.jshintrcの設定

.jshintrc はJS Hintのパラメータを指定するための設定ファイル。プロジェクト直下に配置。 以下サンプル

{
  "curly": true,
  "eqnull": true,
  "eqeqeq": true,
  "evil": false,
  "forin": true,
  "immed": true,
  "indent": 2,
  "latedef": true,
  "maxdepth": 5,
  "maxparams": 5,
  "maxlen": 80,
  "trailing" : true,
  "undef": true,
  "unused": true,
  "node": true,
  "jquery": true,
  "browser" : true,
  "globals": {
    "describe" : false,
    "it": false,
    "before": false,
    "after": false,
    "define": false
  }
}

パラメータの内容、記述方法は JSHintのドキュメントページ や、Qiitaの以下のページを参考にするとよい

JSHint入門 - JSHintを使ってJSコードの信頼性を高める

もしも対象外としたいファイル(ライブラリ等)が存在する場合は.jshintignoreファイルを記述してプロジェクト直下に配置する。

Gruntfile.js の作成

GRUNTの設定はプロジェクト直下にGruntfile.jsというファイルを配置して記述。

サンプル

module.exports = function (grunt) {

  grunt.initConfig({
    jshint: {
      files: [
        'Gruntfile.js',
        'routes/**/*.js',
        'package.json',
        'test/**/*.js',
        '*.js',
        '.jshintrc'
      ],
      options: {
        jshintrc: '.jshintrc'
      }
    }
  });

  grunt.loadNpmTasks('grunt-contrib-jshint');
  grunt.registerTask('build', ['jshint']);

};

この中の一番外側の以下記述はGruntfile.jsを記述するときの基本。

module.exports = function (grunt) {
  ...
};

initConfig()で各プラグインへの設定項目を指定する。jshint.filesはコードチェックの対象となるファイル。

loadNpmTasks()でプラグインをロードし、

grunt.loadNpmTasks('grunt-contrib-jshint');

registerTask()でタスクを登録している

grunt.registerTask('build', ['jshint']);

Gruntの実行

gruntコマンドで 登録したタスク名を指定してあげればOK.

grunt build
Running "jshint:files" (jshint) task
>> 11 files lint free.

Done, without errors.