Catalyst-Authentication-Store-FromSub-Hash

Catalyst::Authentication::Store::DBIx::Class はModelをCatalystで管理していることが前提.
ModelがCatalystの管理外である場合は,Catalyst-Authentication-Store-FromSub-Hash を使って外部のModelにアクセスする.
つうわけで認証まわりはOK.これで後顧の憂いはすべて絶てたか.
おやすみなさい.

Catalyst – M

行き詰まってJiftyの導入というでっかい現実逃避をしている間に名案を思いついたので実行.
CatalystではModelを管理しないことにした.独自にDBIx::Classを利用してModelをつくるほうが僕にとっては都合がよいのでした.
こんな時間になったけど,ああ,すっきり.
FormValidatorまわりも少し書き直す必要があるので,それやってから寝よう.
できた.C,R まできたので,あとはU,D,認証でだいたい一揃い.
おやすみなさい.

ClearSilver + Catalyst::Plugin::FormValidator::Simple(2)

前回の手間を省力化.
form_error.yml の内容を動的に生成.

# myapp.yml
validator:
plugins:
- Japanese
options:
charset: utf8

ユーザ作成フォームのテンプレート.

<html>
<head>
<title><?cs var:page.title ?></title>
<head>
<body>
<h1>ユーザ作成</h1>
<?cs if:subcount(page.status_msg) > 0 ?>
<div id="statusmsg" style="color:red">
<?cs each:item = page.status_msg ?>
<?cs if:item == "id_not_blank" ?>ユーザIDが空白です.<br><?cs /if ?>
<?cs if:item == "id_length" ?>ユーザIDの長さは,4字以上20字以下です.<br><?cs /if ?>
<?cs if:item == "id_regex" ?>ユーザIDに利用できな文字が含まれています.<br><?cs /if ?>
<?cs if:item == "email_not_blank" ?>E-mailが空白です.<br><?cs /if ?>
<?cs if:item == "email_length" ?>E-mailの長さは,40字以内です.<br><?cs /if ?>
<?cs if:item == "email_email_loose" ?>E-mailの形式が正しくありません.<br><?cs /if ?>
<?cs if:item == "password_not_blank" ?>パスワードが空白です.<br><?cs /if ?>
<?cs if:item == "password_length" ?>パスワードの長さは,8字以上20字以下です.<br><?cs /if ?>
<?cs if:item == "password_regex" ?>パスワードに利用できない文字が含まれています.<br><?cs /if ?>
<?cs /each ?>
</div>
<?cs /if ?>
(中略.id, email, password を入力するフォーム.)
</body>
</html>

コントローラ.ユーザ作成フォーム.
前回と同じ.

sub create : Local {
my ( $self, $c ) = @_;
 $c->stash->{page} = {
title => "Create User",
status_msg => $c->flash->{status_msg},
 };
 $c->view('CS')->process($c);
}

ユーザ作成フォームから呼び出されるアクション

sub create_do : Local {
my ( $self, $c ) = @_;
my $validate_rule = [
id => [qw/NOT_BLANK/, [qw/LENGTH 4 20/], ['REGEX', qr/^[\w\-_]+$/]],
email => [qw/NOT_BLANK EMAIL_LOOSE/, [qw/LENGTH 1 40/]],
password => [qw/NOT_BLANK/, [qw/LENGTH 8 20/], ['REGEX', qr/^[a-zA-Z0-9\^\~\_\!\#\%\&\(\)\*\+\-\/\.\:\;\\'\"\\\?\@\[\]\^\`\{\|\}]/]+$]
];
$c->form($validate_rule);
if($c->form->has_error){
# messagesの自動生成
my $message_table = {};
while(@$validate_rule){
my $key = shift @$validate_rule;
my $value = shift @$validate_rule;
foreach my $rule (@$value){
if(ref($rule) eq 'ARRAY'){
$rule = (@$rule)[0];
}
$message_table->{DEFAULT}{$key}{$rule} = $key . "_" . lc($rule);
}
}
FormValidator::Simple->set_messages($message_table);
my $messages =$c->form->messages("");
$c->flash->{status_msg} = $messages;
$c->response->redirect($c->uri_for('create'));
}
(以下略)
}

$message_tableの中身はこうなります.

{
'DEFAULT' => {
'id' => {
'LENGTH' => 'id_length',
'NOT_BLANK' => 'id_not_blank',
'REGEX' => 'id_regex'
}
'email' => {
'LENGTH' => 'email_length',
'NOT_BLANK' => 'email_not_blank',
'EMAIL_LOOSE' => 'email_email_loose'
},
'password' => {
'LENGTH' => 'password_length',
'NOT_BLANK' => 'password_not_blank',
'REGEX' => 'password_regex'
},
}
};

FormValidatorによるチェック結果を配列に収めるには
my $messages =$c->form->messages(“”);
(引数が”なのでDEFAULTが利用される.)
チェックに引っかかった項目は,DEFAULT内の対応する値が配列に入ります.$messagesは配列へのリファレンス.
最終的に$c->stash->{page}の中身はこんな感じになります.

$c->stash->{page} =  {
'title' => 'Create User',
'status_msg' => [
'id_regex',
'email_not_blank',
'password_not_blank'
]
};

これは Catalyst::View::ClearSilver 内で次のようなHDFに変換されます.

page {
title = Create User
status_msg {
0 = id_regex
1 = email_not_blank
2 = password_not_blank
}
}

ClearSilver + Catalyst::Plugin::FormValidator::Simple

こんな感じではないかと.

# myapp.yml
validator:
plugins:
- Japanese
options:
charset: utf8
messages: form_error.yml

form_error.ymlには,FormValidatorのチェック項目と,それに対応するClearSilverへ渡す値とを記述する.

# form_error.yml
---
createuser:
user_id:
NOT_BLANK: id_not_blank
LENGTH: id_length
REGEX: id_regex
user_email:
NOT_BLANK: email_not_blank
EMAIL_LOOSE: email_email_loose
LENGTH: email_length
user_password:
NOT_BLANK: password_not_blank
LENGTH: password_length
REGEX: password_regex

ユーザ作成フォームのテンプレート

<html>
<head>
<title><?cs var:page.title ?></title>
<head>
<body>
<h1>ユーザ作成</h1>
<?cs if:subcount(page.status_msg) > 0 ?>
<div id="statusmsg" style="color:red">
<?cs each:item = page.status_msg ?>
<?cs if:item == "id_not_blank" ?>ユーザIDが空白です.<br><?cs /if ?>
<?cs if:item == "id_length" ?>ユーザIDの長さは,4字以上20字以下です.<br><?cs /if ?>
<?cs if:item == "id_regex" ?>ユーザIDに利用できな文字が含まれています.<br><?cs /if ?>
<?cs if:item == "email_not_blank" ?>E-mailが空白です.<br><?cs /if ?>
<?cs if:item == "email_length" ?>E-mailの長さは,40字以内です.<br><?cs /if ?>
<?cs if:item == "email_email_loose" ?>E-mailの形式が正しくありません.<br><?cs /if ?>
<?cs if:item == "password_not_blank" ?>パスワードが空白です.<br><?cs /if ?>
<?cs if:item == "password_length" ?>パスワードの長さは,8字以上20字以下です.<br><?cs /if ?>
<?cs if:item == "password_regex" ?>パスワードに利用できない文字が含まれています.<br><?cs /if ?>
<?cs /each ?>
</div>
<?cs /if ?>
(中略.user_id, user_email, user_password を入力するフォーム.)
</body>
</html>

コントローラ.ユーザ作成フォーム.

sub create : Local {
my ( $self, $c ) = @_;
 $c->stash->{page} = {
title => "Create User",
status_msg => $c->flash->{status_msg},
 };
 $c->view('CS')->process($c);
}

ユーザ作成フォームから呼び出されるアクション

sub create_do : Local {
my ( $self, $c ) = @_;
$c->form(
user_id => [qw/NOT_BLANK/, [qw/LENGTH 4 20/], ['REGEX', qr/^[\w\-_]+$/]],
user_email => [qw/NOT_BLANK EMAIL_LOOSE/, [qw/LENGTH 1 40/]],
user_password => [qw/NOT_BLANK/, [qw/LENGTH 8 20/], ['REGEX', qr/^[a-zA-Z0-9\^\~\_\!\#\%\&\(\)\*\+\-\/\.\:\;\\'\"\\\?\@\[\]\^\`\{\|\}]/]+$],
);
if($c->form->has_error){
my $messages =$c->form->messages('createuser');
$c->flash->{status_msg} = $messages;
$c->response->redirect($c->uri_for('create'));
}
(以下略)
}

FormValidatorによるチェック結果を配列に収めるには
my $messages =$c->form->messages(‘createuser’);
チェックに引っかかった項目は,form_error.ymlのcreateuser内の対応する値が配列に入ります.$messagesは配列へのリファレンス.
$c->stash->{page}の中身はこんな感じになります.

$c->stash->{page} =  {
'title' => 'Create User',
'status_msg' => [
'id_regex',
'email_not_blank',
'password_not_blank'
]
};

これは Catalyst::View::ClearSilver 内で次のようなHDFに変換されます.

page {
title = Create User
status_msg {
0 = id_regex
1 = email_not_blank
2 = password_not_blank
}
}

form_error.yml を書くところが手間になっています.書くべき内容は決まりきってるので.