開発メモや日ごろ思ったことなどを書きためるサイトです。サイト管理者は、SE、Web開発者。最近はiPhone、Android開発に興味が出てきてすこしずつ勉強中。
CakePHPの動作が難解なのでめも。
1.同一モデルの複数レコードの保存
※insertしたいのでidは指定しない
$data = array(
'Article' => array(
'0' => array(
'name' => 'a',
'price' => 1000),
'1' => array(
'name' => 'b',
'price' => 5000)));
$this->Article->saveAll($data);
2.単一レコードに結びつく複数モデルの保存
Categoryに結びつくArticleを作成
$data = array(
'Category' => array(
'id' => 1),
'Article' => array(
'0' => array(
'name' => 'a',
'price' => 1000),
'1' => array(
'name' => 'b',
'price' => 5000)));
$this->Article->saveAll($data);
ここで一つ問題が発生
Articleモデルのarticle.phpのvalidateに下記のような記述をした。
$validate = array(
'category_id' => array(
コントローラーの応答にリダイレクトが含まれるとtestActionを実行したときにテストケースが終了してしまうという落とし穴がある。対処方法がリンク先にいろいろ書いてあるが、とりあえず簡単な対処方法が見つかった。
testActionで呼ぶURL部分でcake bakeで作成されたテストケースのTest◯◯Controllerクラスを呼ぶように書き換える。
変更前: $result = $this->testAction('/admin/categories/xxxx');
変更後: $result = $this->testAction('/admin/test_categories/xxxx');
#categories_controller.test.php
class TestCategoriesController extends CategoriesController {
var $autoRender = false;
function redirect($url, $status = null, $exit = true) {
$this->redirectUrl = $url;
}
}
class CategoriesControllerTestCase extends CakeTestCase {
<省略>
function testSomeCase() {
$result = $this->testAction('/admin/test_categories/xxxx');
}
リダイレクトを前提とするテストケースでtestActionに'return' => 'var'を設定するとエラーになる。ビューが呼ばれないのにビューの変数を読み込もうとしてしまったのが原因みたい。
ディレクトリ内のDMで始まるファイル名からDMを取り除く
ls DM* | sed 's/DM//g' | xargs -I FNAME mv DMFNAME FNAME
Carbon Emacs設定メモ
・PHPプログラミング用にPHP+mmm-modeの設定
・JavaプログラミングのためにJdeeとcedetを導入
jdee入手元・設定参考サイト JDEE開発元
cedetインストール・jdk(class.jar)パスエラー対応参考サイトさむしんぐにゅぅさん
・JdeeでMacBookに付属しているJavaとantを使ってのビルド設定
ant設定 参考サイト: 紹介マニアMoinMoinさん
以下~/.emacs.elの内容
;; mmm-mode用にlispのパス追加
(setq load-path
(append
(list (expand-file-name "/Applications/Emacs.app/Contents/Resources/share/emacs/site-lisp/")) load-path))
;; mmm-modeの設定
(require 'mmm-mode)
(setq mmm-global-mode 'maybe)
(mmm-add-mode-ext-class nil "\\.php?\\'" 'html-php)
(mmm-add-classes
'((html-php
:submode php-mode
:front "<\\?\\(php\\)?"
:back "\\(\\?>\\|//END\\)"))) ; phpの閉じカッコをつけない場合のためのダミー
;"//END"というコメントをファイルに挿入
;してphpが終わっていること明示
(add-to-list 'auto-mode-alist '("\\.php?\\'" . xml-mode))
(defun save-mmm-c-locals ()
(with-temp-buffer
(php-mode)
(dolist (v (buffer-local-variables))
(when (string-match "\\`c-" (symbol-name (car v)))
(add-to-list 'mmm-save-local-variables `(,(car v) nil ,mmm-c-derived-modes))
)
)
)
)
(save-mmm-c-locals)
(set-face-background 'mmm-default-submode-face nil) ;; mmm-modeで背景色をつけない
;; jdeの設定
(add-to-list 'load-path
"/Applications/Emacs.app/Contents/Resources/share/emacs/site-lisp/jde/lisp")
(add-to-list 'load-path
"/Applications/Emacs.app/Contents/Resources/site-lisp/cedet/semantic")
(add-to-list 'load-path
"/Applications/Emacs.app/Contents/Resources/site-lisp/cedet/speedbar")
(add-to-list 'load-path
"/Applications/Emacs.app/Contents/Resources/site-lisp/elib")
(add-to-list 'load-path
"/Applications/Emacs.app/Contents/Resources/site-lisp/cedet/eieio")
(load "cedet")
(setenv "JAVA_HOME" "/System/Library/Frameworks/JavaVM.framework/Versions/CurrentJDK/Home")
(setenv "ANT_HOME" "/usr/share/ant")
(setq jde-ant-enable-find t)
(setq jde-ant-program "/usr/bin/ant")
(setq jde-ant-read-target t) ;;Targetを選択するための変数
(setq jde-build-function (quote (jde-ant-build)))
(require 'jde)
(add-hook 'java-mode-hook
'(lambda()
(setenv "LC_ALL" "en") ;; エラーメッセージの英語化をして文字化け回避
(setq indent-tabs-mode nil)
(setq c-basic-offset 4)
(setq c-set-style "java")
))
;; その他雑多な設定
(column-number-mode) ;; 列番号を表示
(global-set-key "\C-h" 'delete-backward-char) ; C-hでバックスペース
(setq inhibit-startup-message t) ;スタートアップメッセージを表示しない
(tool-bar-mode nil) ; ツールバーを表示しない
(set-scroll-bar-mode nil) ; スクロールバーを表示しない
(setq ring-bell-function 'ignore) ; ビープ音を消す
(cd "~/")
会社の人がMacBookにEmacsを入れて嬉しそうにしているので家のMacBookにCarbon Emacsを導入した。
MacでaltキーがoptionキーになってしまっているのでMetaキーはEscをおすしかないと諦めていたが、そこはしっかりケアされていて、commandキーにMetaが割り振られていた。シェルも起動できるし、日本語入力も問題ないのでWindowsでMeadowを使っているのとほぼ変りなく作業が出来そうだ。iPhone開発には通常はXcodeを用いていて、開発者初心者にはコードの補完機能がとても重宝しているのだが、操作にうまく馴染めずとてもストレスがたまっているので、これを期に俺もEmacsに移行しようか。
Emacsを一度使い始めると、キー操作は最強だと思うけど、反面この特殊なキー操作から離れられなくなってeclipseやXcodeやVisual Studioやらと他にも開発環境が沢山出てくるのに、必ずキーボード操作で大きなストレスを抱えてしまうので、これからいじろうと思っている人は一度考えた方がいいと思う。
viewDidAppearについて数時間はまったのでメモ。
二つのUIViewControllerのサブクラス、FirstViewControllerとSecondViewControllerを準備してFirstViewControllerからSecondViewControllerに遷移させた直後にpresentModalViewControllerを呼び出して別画面を開くことを考えた。
最初、SecondViewControllerに下記のようにした。
- (void)viewDidLoad {
ThirdViewController *thirdViewController = [[TherdViewController alloc]
initWithNibName:@"ThirdView" bundle:nil];
[self presentModalViewController:thirdViewController animated:YES];
[thirdViewController release];
[super viewDidLoad];
}
これだとうまく行かない。viewDidLoadが呼ばれた時点ではSecondViewControllerのビューが呼び出されていないのでmodalがうまく行かない。
なので、こういうふうに書いてみた。
- (void)viewDidAppear:(id) animated {
ThirdViewController *thirdViewController = [[TherdViewController alloc]
initWithNibName:@"ThirdView" bundle:nil];
[self presentModalViewController:thirdViewController animated:YES];
[thirdViewController release];
[super viewDidAppear: animated];
}
が、うまく行かなかった。viewDidAppearメソッドにブレークポイントを入れてみたがどうやらこれ自体が呼ばれていないらしい。ここから数時間ネットの海を徘徊することになるのだが、全く情報をつかめなかったので色々なところをいじくりまわしたら解決策を発見した。
SecondViewControllerを呼び出しをこのように書き換えた。
[self.viwe addSubview:secondViewController.view];
↓
[self presentModalViewController:secondViewController animated:NO];
どうやらaddSubviewでは少なくとも呼び出し直後はviewDidAppearが呼び出されないらしく、
presentModalViewControllerをつかえばすぐに呼び出されるらしい。
学んだこと
1.viewDidLoadにmodal処理を書いてもうまく動作しないのでviewDidAppearに記述する。
2. addSubViewで呼び出されたコントローラーのviewDidAppearは少なくともすぐには呼び出される
ことはないない。presentModalViewControllerはすぐに呼び出される。
iPhoneプログラミング初めて1,2週間の人間がこんな事書いて良いのかしら。ちゃんとした対処法があれば教えていただきたいです。
Google App Engineでストレージをとりあえず試そうと思ってEclipse 3.5 + Junit4 + GAE/J 1.3.0で ユニットテストを作成してうまく動かず路頭に迷っていたらkoumiyaの日記さんの記事 GAE/Jでデータストアの単体テストCommentsAdd Starを偶然発見して即解決、感謝!。これでうまく動く理由がわからなかったけど、まあいいでしょう。
GAEのドキュメント読み進めているが、RDBじゃないので解決が困難な状況が場面が多々ありそうだ。
複数のEntityグループでトランザクション処理をできないので、在庫数減らして、購入履歴作って、決済レコード作って、ユーザに購入ポイントとか付与するようなシステムですべてのEntityを正確に更新できることを保証するにはどうしたら良いのだろうか。
在庫数と購入履歴と決済履歴はタイミングがシビアな処理なので同じEntityグループで処理する。
商品の情報を入れる商品マスタは参照が多いはずなので別のEntityグループにしておく。
購入後のポイントの反映処理は多少遅れても良いのでバッチ処理、会員マスタのポイント反映時刻よりもあとに購入履歴が追加されていたら会員マスタにポイントを反映させてポイント反映時刻を更新する。
Entityグループ1
在庫数(親) - 購入履歴(子) - 決済履歴(子)
Entityグループ2
商品マスタ
Entityグループ3
会員マスタ(ポイント)
こんな感じで良さそうだと思ったけど。ポイントを使って商品を買う時にはポイントをリアルタイムに減らさないといけないので、これではだめだ・・・。なにも考えずにやったら会員マスタもEntityグループ1に含めるだけだけどトランザクションに含まれる範囲が大きすぎるので却下。それ以外だと最後の購入履歴に所持しているポイントを計算し直して格納しておくぐらいしか思いつかないがこんな実装でいいのだろうか。RDB以外のDB使った事ないので他に発想ができない。
他に気になる点はデータのバックアップ手段がないこと。
物理的な障害は、冗長化して保存されているから大丈夫だけど、これではプログラムのバグ、オペミスによる論理障害には対処できない。
ネット経由でデータを吸い出してもいいけど、1リクエストを30秒以内に収まるようにしなければならないしスナップショットの取りようも
ない。
あとは、SSLが独自ドメインを使えないので要件によってはアウトになるかも。
インフラの管理から開放されるのは魅力的だけど基幹的なシステムを作り込むのはいろいろ考えなければならないことが多そうなので、同じクラウドならAmazonでLinuxとかを使ってしまうほうが現時点では無難そうだ。
なんか動作がもっさりしていたFirefoxが設定を変えたら、むちゃくちゃ速くなった。
"Firefox 遅い"で検索してヒットしたサイト:: Spice up my day :: "死ぬほど遅い"FireFoxがよみがえった!"を参考に
about:configで
network.dns.disableIPv6=true
に設定して再起動したら、レンダリングがキビキビ動作。
どうやら先にIPv6でDNSを検索するらしい。インターネットの今後の方向性を考えるとIPv6も対応していることが大事なのかもしれないが、やっぱブラウザなんて今の使い勝手のほうが大事。
Vaio Type Pともう一台のPCで開発をしたくなった場合に、ソースコードをどうやって同期とろうかと考えた。
1. eclipseのワークスペースをUSBフラッシュメモリ上に作成して、開発するPCでeclipseを起動時にフラッシュメモリ上のワークスペースを指定する。
2.サーバ上にSubversionを導入して、作業前にリポジトリをチェックアウトし、作業終了後に中途半端なソースコード状態でも必ずコミットする。
Subversionを立ち上げるのがめんどくさかったので、とりあえず1を試してみた。結果はうまく動作することはできたけどUSBメモリのI/Oが遅くてとても実用的に利用できるレベルじゃなかった。USBのHDDにすれば速くなるだろうけど、HDDを持ち歩いて荷物を増やしたらせっかくのVaioの可搬性が損なうことになったので却下。なので2の案で行くことにした。eclipseとSubversionを連携は、ちょっとしか触っていないけどいい感じで統合されている。SubversionもApache経由なのでネットワークの設定に手を加える事なくすんなり導入できた。
導入手順Wiki
・Subversionの導入
・Subversiveの導入 ← eclipseのプラグイン
Firefoxのプラグイン、Ubiquityを使ってみたがとても素晴らしい。
Firefoxをコマンドラインで操ってしまおうというプラグイン。実際にインストールしてみると日本語入力でうまく動かないものがあるもののとてもよくできている。できることは、ブラウザの挙動の操作やGoogleやAamazon検索の検索のショートカットのみならずTwitterへの投稿やgoogleマップのURL貼り付けたりいろいろできる。
コマンドしだいでほかにもいろいろなことができそうだし、WEBサービスとの相性がものすごくよさそうなので、自分でコマンド作って試してみようか。
Twitterへの投稿はこんな感じ
・Ctrl+Space twitter
Google mapを日本語で使うにはParser2をとめなければうまく動作しなかった。
・Ctrl+Space help
・[設定]-[言語設定]で[Parser 2 (次世代パーサ) を使用]のチェックをはずす