Herokuにcandycaneをインストールする2 candycaneを魔改造する

もうPHPのpaasならAppFogでも良かったんじゃないかと思い始めるも、railsも勉強したいので引き続きHerokuやります。

Herokuにしろ、AppFogにしろ、Webサーバー上にファイルの保存ができない。
デプロイにgitを使ってるから今のところしょうがないのかもしれないけど。
参考情報:知っておきたい!Herokuを使う上では当たり前?の16の常識 常識2. Dynoにファイルアップロードしても再起動時に消える

candycaneでは、チケットに添付したファイルがこれに相当するので、
Herokuの再起動もしくはソースコードをpushすると、添付ファイルが消えてしまう。
チケットを活用するにあたってこれはちと辛い。

そこで、「チケットの添付ファイルそのものをSQLの中にデータとしてブッコんじゃうんでヨロシク!」魔改造
あくまでも魔改造なので自己責任でお使いください。



attachmentsというテーブルがチケット内容(2014.02.03修正)添付ファイルのレコードとなっているようなので、
attachmentsテーブルにcontentというカラム名(TEXT)を追加してそこにデータを入れてしまうのだ。

candycaneの初期設定が終わってる場合(既にテーブルが作られている場合)はSQLのカラム追加は自力で行う。
(このためにphpPgAdminをインストールしたかったw)

candycaneの初期設定が終わっていない場合(テーブルが作られていない場合)なら、テーブルの雛形ファイル
mysql.sql
pgsql.sql
postgres.sql
に事前にカラム追加しておけばテーブル作成時に自動的に作られると思う(未実践)。


ソースコードの改造箇所はたった3箇所。

app/Config/Schema/schema.php

public $attachments = array(
...中略
	'description' => array('type' => 'string', 'null' => true, 'default' => NULL, 'collate' => 'utf8_unicode_ci', 'charset' => 'utf8'),
>>>追加
	'content' => array('type' => 'text', 'null' => true, 'default' => NULL, 'collate' => 'utf8_unicode_ci', 'charset' => 'utf8'),
>>>追加終わり
	'indexes' => array('PRIMARY' => array('column' => 'id', 'unique' => 1)),
	'tableParameters' => array('charset' => 'utf8', 'collate' => 'utf8_unicode_ci', 'engine' => 'InnoDB')
);

app/Model/Attachment.php

public function beforeSave($options = array()) {
	parent::beforeSave($options);
	if (!empty($this->data[$this->alias]['temp_file']) && !empty($this->data[$this->alias]['filesize'])) {
		$this->data[$this->alias]['disk_filename'] = $this->create_disk_filename($this->data[$this->alias]['temp_file'], $this->data[$this->alias]['filename']);
>>>追加
		$this->data[$this->alias]['content'] = base64_encode( @file_get_contents($this->data[$this->alias]['temp_file']) );
>>>追加終わり
		$this->log("saving '{$this->diskfile()}'", LOG_DEBUG);
		@copy($this->data[$this->alias]['temp_file'], $this->diskfile());
...中略
	return true;
}

public function diskfile() {
>>>置き換え
	$filepath = $this->storage_path . $this->data[$this->alias]['disk_filename'];
	if(file_exists($filepath)==false)
	{
		@file_put_contents( $filepath, @base64_decode($this->data[$this->alias]['content']) );
	}
>>>置き換え終わり
	return $filepath;
}

そんでもってHerokuにpushしてデプロイして終わり。
これで、Herokuが再起動してファイルが消されたとしても、データベースから復元できるようになる。
が、魔改造たる所以、でかい画像を添付したりするとデータベースのディスク使用量が暴力的に増える。
2013年12月現在、HerokuのpostgresSQL(無料プラン)では、使用制限がディスク容量ではなくレコード数(Enforced row limits of 10,000 rows for hobby-dev)のようなので、なんとか逃げきれる、かも。