2013年10月31日木曜日

CakePHP データ型による input 項目の決定方法

CakePHPのバージョンが 1.x の時も調べたような気がするのだけども、忘れたので備忘録として 2.x の仕組みをさぐる。 正直、ここら辺の実装の仕方は、気に入らない部分なんですよね。 まず、label タグと、input タグが混ざってコード中に隠蔽されていて、デザインの介在する余地が無い。1.x 時よりは、だいぶ良くなっている気がするけど、それでもダーティで、とてもDRYの原則に沿った修正ができるような代物ではない。改造しようと思ったら、ここら辺の仕組みを、ほぼ書き直ししないといけない。もしくは個別に何度も同じ作業を手作業で繰り返しながら個別に指定するかだ。
FormHelper::input( $field, $options );
で呼び出される $options は、テンプレート・ベースでは、通常 null だ。
その場合、FormHelper::_magicOptions($options) により、デフォルトのオプションが構築される。
そして、ここで input タグが text なのか select なのか checkbox なのか・・・と決定されるのである。
やるなら、_magicOptions をラップした public な magicOptions 関数を作成して、テンプレートの Form::input 呼びだし直前で options を取得し、その options の値を元に、デザインを細かく変更できるようにリファクタリングが、一番の近道だろうか?
  protected function _magicOptions($options) {
    $modelKey = $this->model();
    $fieldKey = $this->field();
    $options['type'] = 'text';
    if (isset($options['options'])) {
      $options['type'] = 'select';
    } elseif (in_array($fieldKey, array('psword', 'passwd', 'password'))) {
      $options['type'] = 'password';
    } elseif (in_array($fieldKey, array('tel', 'telephone', 'phone'))) {
      $options['type'] = 'tel';
    } elseif ($fieldKey === 'email') {
      $options['type'] = 'email';
    } elseif (isset($options['checked'])) {
      $options['type'] = 'checkbox';
    } elseif ($fieldDef = $this->_introspectModel($modelKey, 'fields', $fieldKey)) {
      $type = $fieldDef['type'];
      $primaryKey = $this->fieldset[$modelKey]['key'];
      $map = array(
        'string' => 'text', 'datetime' => 'datetime',
        'boolean' => 'checkbox', 'timestamp' => 'datetime',
        'text' => 'textarea', 'time' => 'time',
        'date' => 'date', 'float' => 'number',
        'integer' => 'number'
      );

      if (isset($this->map[$type])) {
        $options['type'] = $this->map[$type];
      } elseif (isset($map[$type])) {
        $options['type'] = $map[$type];
      }
      if ($fieldKey == $primaryKey) {
        $options['type'] = 'hidden';
      }
      if (
        $options['type'] === 'number' &&
        $type === 'float' &&
        !isset($options['step'])
      ) {
        $options['step'] = 'any';
      }
    }

    if (preg_match('/_id$/', $fieldKey) && $options['type'] !== 'hidden') {
      $options['type'] = 'select';
    }

    if ($modelKey === $fieldKey) {
      $options['type'] = 'select';
      if (!isset($options['multiple'])) {
        $options['multiple'] = 'multiple';
      }
    }
    if (in_array($options['type'], array('text', 'number'))) {
      $options = $this->_optionsOptions($options);
    }
    if ($options['type'] === 'select' && array_key_exists('step', $options)) {
      unset($options['step']);
    }
    $options = $this->_maxLength($options);
    return $options;
  }

2013年10月29日火曜日

BitCasaが本気出してきた?

 バージョン 1.3 build 1248 まではグタグタで、まともにアップデート終了もできないので、手動で バージョン 1.3 build 1249 をダウンロードしてきてインストールしたんですわ。 そしたらですよ?全てにおいて天と地ほどの差が出るぐらいキビキビと動くようになりました。反応速度も速い。これだったら、全然使えるレベルですね。自分のネットワーク環境はADSL-12Mの帯域しかないので、かなり、しんどいと思うんですよ。  正直、このペースだと半年ぐらいは BitCasa 使わずに寝かせたままかなぁ?と思ってたんですけど、BitCasaを人に勧められるレベルに到達しちゃったんじゃないですかね? スタート・アップの反射神経は、凄いものがありますね! 2013/11/3 追記:mac 版は、まだ Finder がハングするバグがあって、もう一声ですかね。相変わらず ps ax | grep Bitcasa と kill -9 xxxx は必須です。どうも、フロント部分がハングしているっぽいです。

久しぶりにCakePHPを見てディスりたくなったのでディスる i18n


CakePHP 2.4.1 を使う事になりました。 template エンジンは smarty だよね?ふむふむ・・・ふむふむ・・・あー、CakePHPとsmarty を混合して使うのは、しんどそうだからやめておこう。

 それじゃ、Locale のあたりでも・・・。ほむほむ cake.pot ファイルとか、綺麗に分かれて作成されてて、これは感心感心と思ったのもつかの間の事。誰か日本語の cake.po 公開してないの???
どれどれ・・・ふむふむ・・・おおーっ・・・おおぇえええ?
ひとつも無い、誰も CakePHPを使ってないようです。はぁあああ?

 どれどれ、default.po でも見ますかね・・・
msgid "The Hoge has been saved."
msgstr ""

msgid "The Hoge could not be saved. Please, try again."
msgstr ""

msgid "The Hoge has been deleted."
msgstr ""

msgid "The Hoge could not be deleted. Please, try again."
msgstr ""

msgid "New Hoge"
msgstr ""

msgid "Edit Hoge"
msgstr ""

msgid "The Fuge has been saved."
msgstr ""

msgid "The Fuge could not be saved. Please, try again."
msgstr ""

msgid "The Fuge has been deleted."
msgstr ""

msgid "The Fuge could not be deleted. Please, try again."
msgstr ""

msgid "New Fuge"
msgstr ""

msgid "Edit Fuge"
msgstr ""

...以下延々と続く
 馬鹿なの?DRYの原則もクソもないでしょコレ?以下のように置き換え可能でしょうが?
msgid "The %s has been saved."
msgstr ""

msgid "The %s could not be saved. Please, try again."
msgstr ""

msgid "The %s has been deleted."
msgstr ""

msgid "The %s could not be deleted. Please, try again."
msgstr ""

msgid "New %s"
msgstr ""

msgid "Edit %s"
msgstr ""
 という事で直しましたさ。template /cake/lib/Cake/Console/Templates/default/views/index.ctp こんな感じで・・・けど、もう bake した後で、結構手を入れてるみたいなんで後の祭りみたいです(ToT)
<?php
/**
 *
 * PHP 5
 *
 * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
 * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 *
 * Licensed under The MIT License
 * For full copyright and license information, please see the LICENSE.txt
 * Redistributions of files must retain the above copyright notice.
 *
 * @copyright     Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
 * @link          http://cakephp.org CakePHP(tm) Project
 * @package       Cake.Console.Templates.default.views
 * @since         CakePHP(tm) v 1.2.0.5234
 * @license       http://www.opensource.org/licenses/mit-license.php MIT License
 */
?>
<div class="<?php echo $pluralVar; ?> index">
 <h2><?php echo "<?php echo __('{$pluralHumanName}'); ?>"; ?></h2>
 <table cellpadding="0" cellspacing="0">
 <tr>
 <?php foreach ($fields as $field): ?>
  <th><?php echo "<?php echo \$this->Paginator->sort('{$field}'); ?>"; ?></th>
 <?php endforeach; ?>
  <th class="actions"><?php echo "<?php echo __('Actions'); ?>"; ?></th>
 </tr>
 <?php
 echo "<?php foreach (\${$pluralVar} as \${$singularVar}): ?>\n";
 echo "\t<tr>\n";
  foreach ($fields as $field) {
   $isKey = false;
   if (!empty($associations['belongsTo'])) {
    foreach ($associations['belongsTo'] as $alias => $details) {
     if ($field === $details['foreignKey']) {
      $isKey = true;
      echo "\t\t<td>\n\t\t\t<?php echo \$this->Html->link(\${$singularVar}['{$alias}']['{$details['displayField']}'], array('controller' => '{$details['controller']}', 'action' => 'view', \${$singularVar}['{$alias}']['{$details['primaryKey']}'])); ?>\n\t\t</td>\n";
      break;
     }
    }
   }
   if ($isKey !== true) {
    echo "\t\t<td><?php echo h(\${$singularVar}['{$modelClass}']['{$field}']); ?>&nbsp;</td>\n";
   }
  }

  echo "\t\t<td class=\"actions\">\n";
  echo "\t\t\t<?php echo \$this->Html->link(__('View'), array('action' => 'view', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
  echo "\t\t\t<?php echo \$this->Html->link(__('Edit'), array('action' => 'edit', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
  echo "\t\t\t<?php echo \$this->Form->postLink(__('Delete'), array('action' => 'delete', \${$singularVar}['{$modelClass}']['{$primaryKey}']), null, __('Are you sure you want to delete # %s?', \${$singularVar}['{$modelClass}']['{$primaryKey}'])); ?>\n";
  echo "\t\t</td>\n";
 echo "\t</tr>\n";

 echo "<?php endforeach; ?>\n";
 ?>
 </table>
 <p>
 <?php echo "<?php
 echo \$this->Paginator->counter(array(
 'format' => __('Page {:page} of {:pages}, showing {:current} records out of {:count} total, starting on record {:start}, ending on {:end}')
 ));
 ?>"; ?>
 </p>
 <div class="paging">
 <?php
  echo "<?php\n";
  echo "\t\techo \$this->Paginator->prev('< ' . __('previous'), array(), null, array('class' => 'prev disabled'));\n";
  echo "\t\techo \$this->Paginator->numbers(array('separator' => ''));\n";
  echo "\t\techo \$this->Paginator->next(__('next') . ' >', array(), null, array('class' => 'next disabled'));\n";
  echo "\t?>\n";
 ?>
 </div>
</div>
<div class="actions">
 <h3><?php echo "<?php echo __('Actions'); ?>"; ?></h3>
 <ul>
  <li><?php echo "<?php echo \$this->Html->link(__('New %s',__('" . $singularHumanName . "')), array('action' => 'add')); ?>"; ?></li>
<?php
 $done = array();
 foreach ($associations as $type => $data) {
  foreach ($data as $alias => $details) {
   if ($details['controller'] != $this->name && !in_array($details['controller'], $done)) {
    echo "\t\t<li><?php echo \$this->Html->link(__('List %s',__('" . Inflector::humanize($details['controller']) . "')), array('controller' => '{$details['controller']}', 'action' => 'index')); ?> </li>\n";
    echo "\t\t<li><?php echo \$this->Html->link(__('New %s',__('" . Inflector::humanize(Inflector::underscore($alias)) . "')), array('controller' => '{$details['controller']}', 'action' => 'add')); ?> </li>\n";
    $done[] = $details['controller'];
   }
  }
 }
?>
 </ul>
</div>
あ、肝心の cake.po ですが、そもそも template がドメインを意識して書かれてない\(^o^)/オワタ

2013年10月28日月曜日

近況などを

 まぁ、もう完全に写真にはまってますね。はまりすぎてて怖いぐらいです。SD-1 Merrill だいぶ価格が下がってきててグラッと来ますね。ちょい前までは、このカメラが良いなぁと思ってたんですけど、ちょっと撮影テンポが悪いのが気になりますよね。というか、ブラケット撮影にはまりすぎてて、撮影スタイルが自分に合わないんじゃないかという懸念材料があります。

 NEX-5Rを使い倒したおかげで、色々とわかってきまして、まずブラケット撮影がリモートでもできないと駄目ですし、5枚ブラケットぐらい出来て欲しいし、露出の値をEXIFに記録しておいて欲しいんですよ。この辺がNEX-5Rでは満たせないので、そろそろNEX-5Rは卒業かなぁと考えてます。

 次に、ファインダー要らないだろうとか思ってたんですけど、やっぱりファインダーが欲しいです。ファインダー無しでピント合わせるのは、無理ゲーに近いです。NEX-5RがiPad からRAW撮影できるんだったら、まだ我慢できたかもしれませんけど、小さいモニターだけでは、雰囲気でピントをあわせるしかなく、撮影した後もピントが合ってるのかどうか、さっぱりわかりませんわ。

 Google+ で「美瑛の青い池」のmac の壁紙で有名な Kent Shiraishi さんが、色々と写真(カメラ)にまつわる事を発信して、教えてくださるので、その影響もあって、自分自身の色彩感覚が鋭敏になってきていると感じてます。そうするとカメラのホワイトバランスの性能とかも気になってくるんですよ。

 最近出た中だと、K-3 がめちゃくちゃ気になります。HDRer がこぞって PENTAXを使っているだけあって、ブラケット撮影に関しては文句無しです。最近、フランジバックの短いカメラは緑被りしやすいのかなぁ?とか、センサーサイズを大きくしてカメラを無理にコンパクトにすると、周辺光量が落ちるなど、あちこちに皺寄せが来るという事がわかってきまして、そういう意味からもK-3は良いカメラだなぁって感じてます。フルサイズのカメラも欲しいんですけど、フルサイズに見合うレンズを揃えるとなると、非常に金がかかりそうなんで、自分は、APS-C サイズでいいかなぁ?と考えてるのもあります。K-3は14bit 階調なんで、ダイナミックレンジも広そうなんですよね。センサーサイズの割には解像度も高いので文句なしです。

 EOS-6D も ISO感度上げてもめちゃくちゃ綺麗で、クラクラするレベルなんです。ただ、作例を見てて思ったのは、あっさりしているかなぁ?というのが気になりました。考えてみたんですけど、ノイズキャンセリングで高周波成分が、ちょっとカットされているのかも知れない(直感で根拠ありません)という部分で、自分の中でひっかかってます。
 
 と、まぁ、こんな感じです。仕事の方は、マネジメントの比重が大きくなっても、プログラミングおよび周辺知識において、他との差が圧倒的すぎて、代替が効かないようです。

2013年10月17日木曜日

Bitcasa を使ってみた

 たまには、なんか書いとかないとね。

 はい、BitCasa を試しもせずに年間契約しました。ばんばん撮影している写真のバックアップ用途として使えればいいかなぁ?というのが動機です。その野心的なサービスに興味があったので、半分応援の気持ちもありました。

 正直、アプリケーションの作りがいまいちです。まず、コピーできたのかどうかがわかりません。mac だと、しょっちゅうエラーでデーモンが止まります。
 $ ps aux | grep Bitcasa
 $ kill -9 xxxx

 これが日課です。Finder がハングしたように止まりまくるので恐ろしく作業効率が落ちます。このデーモンを開発したやつを小一時間問い詰めてやりたい気分です。非同期通信で淡々と負荷をかけずに、バックアップ・タスクをこなしてくれるだけで良いんです。

 TimeCapsule との相性も悪い。ディスクのマウントが外れるもんだから、ここのファイルをバックアップするのは、まず無理です。なので macbook 本体側のディスクにコピーしてから、Bitcasa でファイル転送するのですが、成功したのか失敗したのか皆目わからない。確認しようと Bitcasa 側のフォルダーを見に行くと、ディレクトリ一つをトラバースするのに5分ぐらいかかる。そして、続きのファイルを地道にコピーするんです。おかげで、バックアップ作業が全然進みません。

 ディスクのミラーリング、これは、なかなか安定して動きます。ところが、そんな機能別に欲しくないんです。

  mac 版に比べて、Windows 版は安定している印象があります。けど、動作が重たいですよね。やっぱり、このサービス・アプリケーションを書いたやつを小一時間問い詰めてやりたい気分です。 どうやったら、こんな糞重たいアプリケーションを書けるのか?何かハッシュを計算してサーバ側と重複データが無いかどうかをクライアント・パソコン側で延々と計算してサービス・コストを下げているのでしょうか?こんな糞重たいアプリケーション、書こうと努力しても、なかなか書けるものではありませんので、興味は尽きません。

 自分がサービスする側だったら、ファイル・カタログを別にして、そのファイルの状態を保持するKVSパートと、ファイルが格納されているディスク・パートを分離して、タスクでファイルの相互転送ジョブ・サービスを構築しますね。この手のサービスにリアルタイム性を求めるやつなんて、そんないないと思います。リアルタイム性が必要なら、サービスにもっとお金を払うべきだと思います。

 半分、失敗したかな?と思いつつも、アーリーアダプターの立ち位置を楽しみたいと思いますw

2013年10月5日土曜日

android 画面表示時にIMEの起動を抑制する

忘備録
http://www.erhancetin.com.tr/2013/09/android-activity-ilk-acls-edittext.html
にあるように、android:windowSoftInputMode="stateHidden" を追加しておく
<activity  
       android:name="com.example.MainActivity"  
       android:label="@string/example_activity"  
       android:windowSoftInputMode="stateHidden">  
  </activity>  
# android sdk disable ime