適当な思いつきで書くブログ

UbuntuやPerlやJavaScriptやVimやZshやShellScriptやMySQLと戯れている中で適当な思いつきでやってみたことを書いています。

View::JSONで静的JSONファイルを出力・保存してから改めてView::TTでページを出力したときに大幅にハマったので自分メモ

タイトル見返して見て思ったのですが、そうそうないシチュエーションなことをしています。
(自分は変なことするの結構好きかも知れないとちょっと感じています…。


やりたいことは、

  • /hogeページを表示する際に、
  • View::JSONを使ってJSONファイルを出力・保存してから
  • /hogeのページを表示したい。

です。

sub hoge : Local {
  my ( $self, $c ) = @_;
  my $data = qw/foo bar/;

  # ここでfuga.jsonを作って・保存したい><

  $c->stash->{data} = $data;
  return 1;
}


四苦八苦十ロッ苦><
九割方、Perl先生に教えてもらいできました(^ー^;

use IO::All

sub hoge : Local {
  my ( $self, $c ) = @_;
  my $data = qw/foo bar baz/;

  # forwardで generate_json を実行します。 $data も渡してあげます
  $c->forward('generate_json', $data);

  $c->stash->{data} = $data;

  return 1;
}

sub generate_json : Private {
  my ( $self, $c, data ) = @_;

  $c->stash->{data} = $data;

  # コールバック関数を付加するときはこんな感じ
  # param('callback') に入れてあげる必要があります
  $c->req->param('callback', 'cb');

  # 「ViewにはJSONを使ってくださいね」
  $c->forward('View::JSON');

  # 出力されたJSONの中身は $c->res->body に入っているので、IO::Allで保存
  # ここでやりたいことが終わります。
  $c->res->body > io( '/fuga.json' );

  # ここからは↑の処理をなきものとしてhogeページの出力に全力
  # ContentTypeが"application/json"のまま?(未確認)なのでいったんリセットしてあげます
  $c->res->headers->remove_content_headers;

  # 「今度はViewにはTTを使ってくださいね」
  $c->forward('View::TT');

  # $c->res->body の中身も消してあげます
  $c->res->body(undef);

  return 1;
}

まとめ

$c->res->headers と $c->res->body をリセットしてあげることが大事

ということで、

Perl先生ありがとうございました。

蛇足

IO::Allは本当に便利ですねぇ。

追記

タイトルをちょこっと修正