Tuesday, August 27, 2013

Rubyのワンライナーを使ってファイルの中で最も長い行を調べる

表題の通り、以下の処理をするワンライナー。

  • target.txtを読み込んで
  • ユニークをとって
  • 最も長い行(文字数)を調べ
  • 長い順にソートして
  • 先頭の5行を表示する

$ cat target.txt | uniq | ruby -ne 'puts sprintf("%03d %s",$_.chomp.size,$_)' | sort -r | head -5

Tuesday, August 20, 2013

MySQLでMD5のハッシュ値を計算する

今まで知らなかったが、MySQLではSQLで直接MD5のハッシュ値を計算できる。

mysql> select md5('test');
+----------------------------------+
| md5('test')                      |
+----------------------------------+
| 098f6bcd4621d373cade4e832627b4f6 |
+----------------------------------+

ちなみにコマンドラインで計算する方法もいつも忘れるのでメモ。

# -sオプションの直後に変換する元の文字列を続ける
$ md5 -stest
MD5 ("test") = 098f6bcd4621d373cade4e832627b4f6

Monday, August 19, 2013

Ruby製のテスト用メールサーバーmocksmtpdをBase64に対応

仕事でメール送信の機能を作るとき、ダミーのSMTPサーバーが必要になり、kosekiさんによるmocksmtpdというRuby製のものを見つけた。ただしBase64エンコードされたメールで日本語が表示できていなかったので、GithubでフォークしてBase64に対応した。あと、出力されるHTMLも若干変更しています。

daixque/mocksmtpd

特徴

  • Ruby製のSMTPサーバー
  • 受信したメールは転送せず、HTMLファイルに書き出す
  • Base64に対応

詳細な使い方は作者のkosekiさんのブログも参考に。

開発用のメールサーバ mocksmtpd を gem にしてみた。

インストール

今はGithubがgemのホスティングをやめているので、specific_installというgemを利用する。これを使うとGithubのソースから直接gemをインストールできる。

$ gem install specific_install
$ gem specific_install -l https://github.com/daixque/mocksmtpd.git

起動

mocksmtpd initでmocksmtpdフォルダに設定ファイルなどを生成。そのままの設定でよければ、そのフォルダに移動してmocksmtpdコマンドを実行する。デフォルトでは25番ポートを使おうとするので、sudoが必要。メールを受信するとinboxフォルダにHTMLファイルが作られる。
$ mocksmtpd init
$ cd ./mocksmtpd
$ sudo mocksmtpd

Saturday, August 10, 2013

Spring MVCでアスペクト(インターセプター)を実装する

Spring MVCでアスペクト(インターセプター)を実装するのは結構簡単。アスペクトっていうのは、要するにメソッドに対して前後処理をするモジュールのこと。フィルターみたいなやつですね。Springの場合はSpring配下にある任意のクラスのメソッドに適応可能。アスペクトで実装する一番ありがちな処理はログでしょうね。私もそのために使いました。あとはエラー処理とか。

SpringではどうもAspect Jを使ってAOPをしていて、用語もそれに従っている。ここでは面倒なので細かい用語の説明はなし。気になる人はアドバイス、ポイントカット、ジョインポイントあたりについて調べるといいんじゃないでしょうか。もっと色々ありそうですけど。

アスペクトの種類

アスペクトには以下の種類がある。

  • Before : メソッドの処理の前
  • AfterReturning : メソッドの処理の後例外は除く)
  • AfterThrowing : メソッドで例外が発生したとき
  • After : メソッドの処理の後(例外も含む)
  • Around: メソッドの前後処理を記述
単純なログならBeforeやAfter*、処理時間の計測とかを含むならAround、っていうのがありがちのようですね。

アスペクトのクラスを実装

すごい簡単。アスペクトのクラスに@Aspect、インターセプターの処理のメソッドに、種類に応じて上記の名前のアノテーション(@Beforeとか)をつけるだけ。

例えば、Service層のクラスの中で、自作の@UpdateDatasourceというアノテーションのついているメソッドのみ特定のログを出力したいときの例。ここで、サービス層はorg.opentechnica.sample.serviceパッケージにあるとする。

アノテーションは普通に実装。

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface UpdateDatasource {
    public String value();
}

アスペクトも、アノテーション以外は普通に実装。

@Aspect
@Component
public class LoggingAspect {
    @Before("execution(public * org.opentechnica.sample.service..*(..))")
    public void before(JoinPoint jp) {
        try {
            Class targetClass = jp.getTarget().getClass();
            String methodName = jp.getSignature().getName();
            MethodSignature signature = (MethodSignature) jp.getSignature();
            Method method = signature.getMethod();

            UpdateDatasource updateDatasourceAnnotation = method
                    .getAnnotation(UpdateDatasource.class);
            if (updateDatasourceAnnotation != null) {
                Logger logger = Logger.getLogger(targetClass);
                logger.info("before");
            }
        } catch (SecurityException e) {
            // do nothing
        }
    }
}

@Beforeアノテーション

@Beforeアノテーションでメソッドの実行前にインジェクションする処理であることを表している。アノテーションの引数("execution(public * org.opentechnica.sample.service..*(..))")は、この処理を実行する対象をフィルタリングする条件。ポイントカットっていやつですね。ここでの指定は以下のような意味。

  • publicで
  • 任意の戻り値型で
  • org.opentechnica.sample.serviceパッケージ以下の任意のクラスの
  • 任意の引数を持つ

対象のメソッドが目的のアノテーションを持つかどうか調べる

Javaは同一のメソッド名でも引数が違うと違うシグニチャになるので普通のリフレクションだと面倒だけど、beforeメソッドに渡されるJoinPointから、以下のようMethodSignatureにキャストすると直接取得できる。

MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod();
で、methodがとれたらもうmethod.getAnnotation(UpdateDatasource.class)とすれば、自作の@UpdateDatasourceが付加されているかどうかわかる。

applicationContext.xmlでAOPの設定

アスペクトを実装したら、applicationContext.xmlに以下の一行を追加するだけで動く。便利!

<aop:aspectj-autoproxy/>

jQueryでsubmitするとき、name属性があるとうまくいかない

タイトルで全て。

jQueryを使ってフォームをsubmitするとき、submit要素にname属性ががあるとうまく動作しないようなので、使わないようにする。

jQueryでチェックボックス

jQueryでラジオボタン/チェックボックスを操作するとき、attr("checked", "checked")だと2回目以降うまく動かないので、prop("checked", true)を使うのが正解。

// これはOK
$("input[type=radio]").prop("checked", true);

// こっちは2回目以降うごかない
$("input[type=raido]").attr("checked", "checked");