Debuginfo

思考とアウトプット

初めてのCarton + Mojolicious

Deployを容易にしてくれるCarton使ってみます。(Need to note that the carton is not fully production but it doesn’t matter for my joke app :) ) いつかはHerokuにデプロイしてみたいです。

$ cpanm carton
$ vi Makefile.PL
$ cat Makefile.PL 
use inc::Module::Install;
name 'knowhow3';
version '0.1';

requires 'Mojolicious', 3.84;

WriteAll;

まずMojoliciousを入れてみます。

$ carton install
Installing modules using Makefile.PL
Usage: cpanm [options] Module [...]

Try `cpanm --help` or `man cpanm` for more options.

I nstalling modules failed

エラーがでました。ググると Module::Installが必要のようで。

$ cpanm Module::Install

の後にcarton installはうまくいきました。

 $ ls META.yml MYMETA.json MYMETA.yml Makefile Makefile.PL
carton.lock inc local

次にMojolicious appを作成。

$  carton exec -- mojo generate app Knowhow3

現在のディレクトリにknowhow3ができてその中にMojolicious app用のディレクトリ、ファイルが作成されます。私の環境では階層を深くする必要なないのでknowhow3ディレクトリはいらない。全部version以下にもってきます。

$ mv knowhow3/* .
$ rmdir knowhow3
$ ls
carton.lock  inc  lib  local  log  ls  Makefile  Makefile.PL  META.yml  MYMETA.json  MYMETA.yml  public  script  t  templates

沢山ファイルがあって開発してる感じがジワジワでてきました。 起動確認してみます。(lib,script,log,templates,public,tはMojoliciousのもの)

$ carton exec — ./script/knowhow3 daemon

127.0.0.1:3000にアクセスできるか確認。動いてる!

Plackupできるようにする

Plack::Middlewareを将来的に使えるようにしときます。

$ vi Makefile.PL
# add the below line
requires 'Plack', 1.0016;
requires 'Plack::Middleware::Session', 0.15;
$ carton install

psgiを作る。ぐぐって色々なサイトを参考にしました。

# knowhow3.psgi
use Mojo::Server::PSGI;
use Plack::Builder;
use FindBin qw($Bin);
use lib "$Bin/../lib";
use Knowhow3;

my $psgi = Mojo::Server::PSGI->new( app => Knowhow3->new );
my $app = sub { $psgi->run(@_) };

builder {
    enable 'Session', store => 'File';
    $app;
};

Plackupで上がるか確認。”Welcome to ...” が http://localhost:5000でアクセスできるか確認する。”Your Mojo Working”はtemplate等が読み込まれていないくてWorkingしてないので注意。

$ carton exec -- plackup ./script/knowhow3.psgi 

Mojolicousの階層構造を整える

$ tree lib
lib
|-- Knowhow3
|   |-- API
|   |-- Controller
|   |   `-- Example.pm
|   |-- DB
|   |   `-- Schema.pm
|   |-- Model.pm
|   `-- Role
`-- Knowhow3.pm

Controllerのパスを変える。

# in lib/Knowhow3.pm

#$r->namespace('Knowhow3::Controller');  <- it seems it’s depreciated
push @{$r->namespaces}, ‘Knowhow3::Controller';

Proveやスクリプトもcarton execで走らせるのを忘れないようにしとけばオッケー。 Cartonのおかけで将来あるであろうMigrationが楽しみです:D

mroongaで色々検索してみた

以前書いた記事でインストールを行ったので挙動を確認してみる。groongaは簡単な説明しか読んでないので内部で何がおこっているか、理解してない^^;;とりあえず、実用重視で。

複数文字入れてみるとOR検索のようだ

SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("sort with")
mysql> SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("'sort with’”);     
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
| record_id | user_id  | know                              | how             | example                          | created_at          |
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
|         1 | 43874010 | How to sort with file size #linux | use du and sort | $ du -Sk . | sort -rn | head | 2013-02-11 11:03:49 |
|         3 | 43874010 | Change space with newline #linux  | use tr command  | $ tr ' ' '\n'                | 2013-02-11 11:03:49 |
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
2 rows in set (0.01 sec)

where colname = ‘’ との組み合わせ

whare match順番で速度が変わるのかは不明。。

SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("'sort with'") and user_id = '43874010'; 

where .. and .. で組み合わせることができるようだ

SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("sort") and MATCH(know) AGAINST("with")

Dプログマ!。何それ?

調べてみたらプログマを使うとANDとOR検索ができるっぽい。

 D+ IN BOOLEANMODE : AND検索 * *DOR IN BOOLEANMODE : OR検索

下記のように使える。

mysql> SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("*D+     sort with" IN BOOLEAN MODE);                 
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
| record_id | user_id  | know                              | how             | example                      | created_at          |
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
|         1 | 43874010 | How to sort with file size #linux | use du and sort | $ du -Sk . | sort -rn | head | 2013-02-11 11:03:49 |
+-----------+----------+-----------------------------------+-----------------+------------------------------+---------------------+
1 row in set (0.01 sec)

Dプログマとwhere colname = ‘’との組み合わせ

これです。欲しいのは。OR検索はほぼ使用しないので無視しよう^^

mysql > SELECT * FROM Knowhow WHERE MATCH(know) AGAINST("*D+ jquery" IN BOOLEAN MODE) and user_id = '43874010';

mroongaのインストール

全文検索したいので探していたらmysql全文検索できるmroongaというのを発見。使ってみようと思います。Namazuが懐かしい。

http://mroonga.github.com/ja/docs/install.htmlを参考にするも途中でエラー

# yum install  mysql-mroonga
...
Error: Package: mysql-mroonga-2.10-1.el6.x86_64 (groonga)
Requires: mysql = 5.1.66-2.el6_3
Installed: mysql-5.1.67-1.el6_3.x86_64 (@updates)

どうやらmysqlのバージョンがあってないみたい。特にこのバージョンに強い思いはないのでダウングレード。そしたら、mysql-mroonga入りました^^

# yum downgrade mysql*-5.1.66-2.el6_3.x86_64
# yum install  mysql-mroonga

mecabを入れる。

# yum install -y groonga-tokenizer-mecab

インストールできたか確認する。私の環境では入っていなかったのでマニュアルどおり、INSTALL PLUGINを実行。

# mysql -uroot test -p
mysql> show engines;
mysql> INSTALL PLUGIN mroonga SONAME 'ha_mroonga.so';

どうやら2つのモードがあるらしい。ラッパーモードを使ってみる。 んで、例の通りにテストしてみる。 http://mroonga.github.com/ja/docs/userguide/wrapper.html

mysql>  CREATE TABLE diaries (
 -> id INT PRIMARY KEY AUTO_INCREMENT,
 -> content VARCHAR(255),
 -> FULLTEXT INDEX (content)
    -> ) ENGINE = mroonga COMMENT = 'engine "innodb"' DEFAULT CHARSET utf8;
Query OK, 0 rows affected (0.04 sec)

mysql>  INSERT INTO diaries (content) VALUES ("明日の天気は晴れでしょう。");
Query OK, 1 row affected (0.00 sec)

mysql> INSERT INTO diaries (content) VALUES ("明日の天気は雨でしょう。");
Query OK, 1 row affected (0.00 sec)

mysql> SELECT * FROM diaries WHERE MATCH(content) AGAINST("晴れ");
+----+-----------------------------------------+
| id | content                                 |
+----+-----------------------------------------+
|  1 | 明日の天気は晴れでしょう。 |
+----+-----------------------------------------+
1 row in set (0.01 sec)

mysql> drop table diaries;

Mojolicious::Plugin::Configでファイルをどう読み込んでいるか調べてみた

Testでファイルをアプリケーションと分離して自前で読み込みたかったので調べてみた。下のようにperl6:Slurpとか使わずに関数を定義しているみたい。

sub slurp {
    my $path = shift;
    croak qq{Can't open file "$path": $!} unless open my $file, '<', $path; 
    my $content = '';
    while ($file->sysread(my $buffer, 131072, 0)) { $content .= $buffer }
        return $content;
    }
}

これをコピーしてevalすれば良し。

my $config = eval slurp("$Bin/../etc/knowhow3.conf");
sub slurp {
    my $path = shift; 
    open my $file, '<', $path;
    my $content = '';
    while ($file->sysread(my $buffer, 131072, 0)) { $content .= $buffer }
    return $content;
}

こんなファイルの読み込み方もあるのかと勉強になった。

cssやjsをCDNからFallbackさせる方法[Bootstrap][Jquery]

サーバへのトラフィックを減らすにも有効なCDN。

でも、そのホストが落ちたときは自前のを使いたい。

そんなときはこんな風にやるみたい。

参照元がわかんなくなってしまったけど、yepnope.jsを使って実現する。

<script type="text/javascript" src="/js/yepnope-min.js"></script>
<script type="text/javascript" src="/js/load_jquery_bootstrap.js"></script>

ヘッダで下記のように宣言して下記のように読み込む。

#load_jqury_bootstrap.js
function cssLoaded(href) {
    var cssFound = false;

    for (var i = 0; i < document.styleSheets.length; i++) {
        sheet = document.styleSheets[i];
        if (sheet['href'].indexOf(href) >= 0 && sheet['cssRules'].length > 0) {
            cssFound = true;
        }
    };

    return cssFound;
}

yepnope([{
    load: '//ajax.aspnetcdn.com/ajax/jQuery/jquery-1.9.0.min.js',
    complete: function () {
        if (!window.jQuery) {
            alert('local jquery');
            yepnope('js/jquery-1.9.0.min.js');
        }
    }
}, {
    load: '//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/js/bootstrap.min.js',
    complete: function () {
    if (!$.fn.button) { // just picked a random element from the bootstrap to test
        alert('local twitter js');
        yepnope('js/bootstrap.min.js');
    }
}
}, {
    load: '//netdna.bootstrapcdn.com/twitter-bootstrap/2.2.2/css/bootstrap-combined.min.css'
}, {
    test: cssLoaded('bootstrap-combined.min.css'),
    nope: 'css/bootstrap-combined.min.css'
}]);