スケルトン・エピ

letsspeakのブログです。

初心者が土日でrailsに鞍替えしてみた

色々思うところありFuelPHPからRuby on Railsに鞍替えし、土日の半分の時間をbootstrap + Ruby on Railsに使ってみました。主な理由は下記の通りです。

 

・普段Objective-Cに触っているので型のゆるい?PHPよりも馴染みやすいと思った

twitterrailsを使っていたと知ってパフォーマンス面で安心した

・2週間ほど前にGitLabを導入しようとした時にrailsを入れていた

・職には困っていなかったが彼女と身長(主に彼女)が欲しかった

(参考:twitter bootstrap railsを使ったら職が見つかり彼女も出来て背も3センチ伸びました。

 

今回作ったモノ

・作品とキャラクターとグッズの登録と閲覧

・タグで各ページを紐付ける(作成中)

 

f:id:letsspeak:20120709012537p:plain 

f:id:letsspeak:20120709012607p:plain

 

 

今回はとにかくモノが出来る事を最優先として、細かい所は敢えて詰めずに進めてみました。0からのスタートでしたが、予想以上に簡単に形になっていき、初見でもかなり効率的に進められることを改めて実感しました。

しかしながら、ぶっとばした結果といってはなんですが、ActiveRecordの実体や、どのタイミングでクエリが発行されるのか、generateしたmodel同士から新たなresultを得た時にどうやってViewに渡せば良いのか、など未解決の問題が山積みな状態でもあります。

 railsは簡単と言われる割には学習コストが高いという話もありますが、まだ触っていない方も挑戦してみる価値は十分あると思います!!

OpenSSHの鍵のメモ

・サーバー側OpenSSHの設定はサイトの通りで問題なし

・鍵作成とログインまでの手順は下記の通り

 【共通】rsaの公開鍵ペアを作成

   ssh-keygen -t rsa

   ※サーバー側で作成実験したがクライアント側でもいけるはず。

   ※鍵の転送にはftpやscpなどを使う。

   

 <サーバー側>

 【1】サーバー側でログインしたいユーザーのホームディレクトリに移動

 【2】~/.ssh/authorized_keys に公開鍵を追加する

   cat hoge.pub >> ~/.ssh/authorized_keys

 【3】authorized_keysの初回生成時はパーミッションを600に設定する

 

 <クライアント側(MacOSXで確認)>

 【1】秘密鍵をクライアント側の任意の場所に保存しておく

 【2】鍵を指定してssh接続する

   ssh -i hoge.key hoge@192.168.XXX.XXX

 【3】rsa公開鍵ペア作成時のパスワードを入力する

 

その他

MacOSXの場合は鍵が自動でキーチェーンに追加されるためクライアント側【1】で保存した鍵を消してもログインできてしまう仕様。

・クライアント側【2】で秘密鍵のパーミッションが744になっていたら怒られた。600にしたらうまくいった。

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@         WARNING: UNPROTECTED PRIVATE KEY FILE!          @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0744 for 'hoge.key' are too open.
It is recommended that your private key files are NOT accessible by others.
This private key will be ignored.
bad permissions: ignore key: hoge.key
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

追記

・クライアント側【2】で秘密鍵のファイル名に.keyが付いていなかった場合、無反応になった。(Control-Cで中断)

 

まとめ

サーバー側に公開鍵、クライアント側に秘密鍵が必要で、パーミッションの設定に厳しい。万が一接続できなくなった時のことは考えておいた方が良い。
 

初心者がFuelPHPでValidationを使ってみた

本来の順序通り行けばここでFormクラスを紹介するのが順当なのですが、Formクラスにあまりハマりどころが無くスムーズに進んでしまったので、今回はValidationクラスとView::set_globalの話を書きます。

Validationクラスとは、読んで字の如くFormから送信されたPOSTデータの正当性を確認するクラスで、フォームデータが空欄になっていないか、文字数制限をオーバーしていないか、といった条件をadd_rule()で簡単に指定でき、それぞれのエラーをはいてくれるとても便利なクラスです!

が、私のような初心者ともなれば、吐かれたエラーをどのようにすれば画面に表示できるのかですら右往左往してしまいました。エラーを表示するまでの流れで分かった事を簡単にまとめていきます。

 

Validationの実行部分

実行はわりと簡単で、下記サンプルコードのようにValidation::forge()を呼び出し、条件を追加したうえで、Validation::run()を実行するだけで終わります。

public function validate_addstory()
{
  $validation = Validation::forge();
  $validation->add('storytitle', '作品名')
      ->add_rule('required')
      ->add_rule('max_length', 32);
  $validation->add('kanatitle', '作品名(かな)')
      ->add_rule('required');
      
  $validation->run();
    
  return $validation;
}

 

エラー時の分岐処理

Validation::run()の後にValidation::error()を呼び出してエラーを配列に格納した上で、配列が空かどうかを調べれば良いようです。

$validation = $this->validate_addstory();
$errors = $validation->error();
      
if(empty($errors)){ // 正常時の処理 }else{ // エラー時の処理 }

 

エラー時の出力処理で右往左往

ここで私は右往左往しました。
Validation::show_errors()という素晴らしいメソッドが用意されており、初期状態で、

<ul><li>The field 作品名 is required and must contain a value.</li><li>The field 作品名(かな) is required and must contain a value.</li></ul>

 という風にリスト表示されるようになっているのですが、当初これをそのまま

$result_validate = $validation->show_errors();
$view->set_global('result_validate', $result_validate);

としてしまい、タグがエスケープされてしまっていました。

また別の表示方法としてcore/class/validation.phpを参考に、

$errors = $validation->error();
$view->set_global('errors', $errors);

 とした上でにviewから

<?php foreach ($errors as $err):?>
<p><?=$err->get_message()?></p>
<?php endforeach;?>

という風に呼び出した際には

ErrorException [ Error ]: Call to a member function get_message() on a non-object

とのエラーが発生してしまい、表示さえもままならない状態になってしまいました。

 

エラーを正しく表示する

さて、ここまで来ると初心者の私といえども薄々勘づいてきます。

View::set_global()が怪しい!怪しすぎる!というか黒だ!

公式ドキュメントを見直すと3つ目の引数 $encode に答えがありました。

$encode null set to true or false to encoding, defaults to main auto encoding setting

 訳:引数を省略した場合、trueにした場合はエンコードします。

上記の例ではいずれも省略していたので、タグをエンコードしてくれたり、Validation_Errorオブジェクトを他の何かに変更してくれたりしたみたいです。

それぞれ下記の修正で正常に動きました。

$view->set_global('errors', $errors, false);
$view->set_global('result_validate', $result_validate, false);

 

おまけ

ValidationクラスのConfigrationを設定しておくと、Validation::show_errors() から出力されるエラーの記法を変えられるようですので、<ul>などが邪魔な場合はこれを取っ払ってしまうというのも一つの手かもしれません。(Validation Class 公式ドキュメント参照)

が!ソースを見た限りエラーごとの改行がまったくされておらず汚いです・・・。
上記のように$errorsに格納してValidation_Errorオブジェクトの配列を丸ごと投げるのが、実は最も良いのかもしれないなーと思いました。

 

Xcode起動時に古い証明書が自動登録される件

文章だけで分かりづらいですがメモ。

Provisioning PotalのCertificatesとmobileprovisionファイルは対になっているので、たとえばCertificatesを更新した場合には、mobileprovisionも新しいものが必要になります。

ただ、旧いmobileprovisionの有効期限が切れておらず、旧いCertificatesがまだMac上に残っている場合には、これをそのまま使用して実機転送することも可能っぽいですね。

しかしながら問題がありまして、

キーチェーンのログイン項目に同じアカウントでProvisioning PotalからダウンロードしたCertificatesが2つ以上あると実機転送時にXcodeがCode Signing Error を吐きます!

そのため、自分が使用したくない方のCertificatesをキーチェーンから削除するのが鉄則のようです。

※「書き出す」などで証明書の一時退避が可能なようです。

 

さて、無事キーチェーンからの削除が終わりとりあえずXcodeを再起動してもういっかい試してみるか〜と思うと、Xcodeちゃんがまた同じエラーを吐きます。

あれ、よくみるとXcodeの起動時に消したはずの証明書がまたキーチェーンに出現しているよ。

そんな場合は、Organizerから古いmobileprovision(Provisioning Profile)を削除するといいようです。

Xcodeさんは気が利くので、対になったCertificateをこっそり保持していて、足りない場合にキーチェーンに登録してくれるのです!うzやさしい!

参考
xCode 4 -reinstalls keychain certs that I delete - stackoverflow
http://stackoverflow.com/questions/5264481/xcode-4-reinstalls-keychain-certs-that-i-delete

 

古いmobileprovisionの削除が完了しXcode再起動時に古い証明書も登録されない。

新しいmobileprovisionと証明書の登録も済んでいる。

でも実機転送が失敗するよ!っていう方は、試しに適当なプロジェクトを新規作成してみてください。

もしこれで実機転送がうまくいく場合、プロジェクトファイルにゴミ(古い証明書などを使用する設定)が残っているのかもしれません。

実機転送がうまくいかないプロジェクトのファイル .xcodeprojを右クリックして「パッケージの内容を表示」から下記ブログ記事に記載されているファイルを修正すると、治るようです。

参考
Code Sign error:Provisioning profile 'xx' can't - cowのブログ
http://ameblo.jp/iphone0126/entry-10862455082.html

初心者がFuelPHPで動的リンクを張ってみた

前回のFuelPHPの記事でスタートアップは完了したのですが、FuelPHP+mod_rewriteでのURI指定は把握したけれど、リンクをうまく貼れない!というところで少し詰まってしまいましたので、記事にしておきます。

f:id:letsspeak:20120312081541p:plain

 動的なリンクアンカーの生成

今回はbootstrapを使用しつつ、ナビゲーションバーをheaderとして共通で読み込んでいます。ブランドロゴ部分では最初、次のようにリンクアンカーを貼っていました。

<a class="brand" href="admin">charag Admin</a>

一見うまく動作するようにも思えるのですが、相対リンク指定となってしまう為、下層であるroot/admin/storydb/からロゴを選択すると、localhost/~eveningsun/charag/public/admin/storydb/adminに移動しようとしてしまい、404エラーが発生します。

FuelPHPでは動的なリンク生成を行ってくれるHtml::anchorを使用し、下記のように記述するのが正解のようです。

<?php echo Html::anchor('admin', 'charag Admin', array('class' => 'brand')); ?>

 

階層構造の定義

Html::anchorを使用すると、並列なcontroller構造に対しても、構成図のような階層構造を定義することができます。

/fuel/app/config/routes.phpの内容を次のように編集します。

return array(
'_root_'  => 'admin/index',  // The default route
'_404_'   => 'welcome/404',    // The main 404 route

'admin/storydb' => 'storydb/index',
'admin/storydb/add' => 'storydb/add', 
);

このように左辺に名前、右辺に実際の指定位置を定義することでHtml::anchorを次のように使用できました。

<?php echo Html::anchor('admin/storydb', 'storydb'); ?>
<?php echo Html::anchor('admin/storydb/add', 'addstory'); ?>

これで擬似的な階層構造(つまりエイリアス?)をどんどん定義することができますね。変数を渡すような場合は右辺でさらにarrayを使用するようですが、今回は解説を省略します。

 

mod_rewriteを設定済みの場合

リンク自体は問題なく動作するようになりましたが、既にmod_rewriteを設定しているにもかかわらず、初期設定のままだと、上記で生成されたリンクにpublic/index.php/adminという風にindex.phpが含まれてしまいます。

これを解決するために /fuel/app/config/config.phpを編集します。

/**
* index_file - The name of the main bootstrap file.
*
* Set this to false or remove if you using mod_rewrite.
*/
'index_file'  => false,

コメントにもありますが、mod_rewriteを設定した人は、falseを定義するか、設定自体を削除すれば良いようです。

 

以上でFuelPHPの基本的な動的リンク生成については終了です。これからDBへデータを追加するためのFormにも挑戦していく予定のため、また問題や難しい箇所があれば記事にしていこうと思います!

TwitterAPIでxml取得時にsearchではまった件

はまった記事が続いています。こんばんはletsspeakです。

いまさらTwitterAPIでxml取得している人なんていないと思いますが、searchAPI時にちょっとした事ではまってしまったので記事に残しておきます。理由は主に私自身の技術力不足と注意力不足なのですが・・。

対象者

 ・TwitterAPIを使用している
 ・TwitterAPIで今更フォーマット指定xmlを使用している。
 ・iOS4.x用にMGTwitterEngineを使っている。
 ・MGTwitterEngineでsearchを使いたい。
 ・でも何故かjsonが自動で有効になるしYAJLのリンクとか分からない!

経緯

iOS 4.xでTwitterAPIを使用するべくMGTwitterEngineを使っているのですが、前述の通りMGTwitterEngineでのデフォルトjson取得がYAJLだったりしたため、難しそうなライブラリリンクを回避してxmlフォーマットでのデータ取得を利用していました。

普通のTwitterAPIを叩く分には何も問題がなかったのですが、search関連のAPIはMGTwitterEngine上でYAJLを有効にしなければならず、#defineをコメントアウトしたりして無理矢理seachを使用しようと試みました。そしてはまりました。

問題

searchAPIを叩いても何故か40Xエラーが出まくる。
調べてみると次のURLを叩いている。 http://search.twitter.com/search.xml?q=hoge

発生原因と理由

SearchAPIは.jsonと.atomのみに対応しており.xmlは無効です。また、RESTの場合は.jsonのみに対応していますので、正しいAPIの叩き方は以下の通りになります。

SearchAPI (json) http://search.twitter.com/search.json?q=hoge
SearchAPI (atom) http://search.twitter.com/search.atom?q=hoge
REST http://api.twitter.com/1/search.json?q=hoge 

以上です。MGTwitterEngineのコメントやTwitter公式のAPIDocumentをもう少しちゃんと読んでおけばすぐに解決する問題でしたが、今回は3時間ほどはまってしまいました。もう時代はjsonなのですね。無念。

NSLogで日本語を表示できない事もある

こちら随分前ですが、解決策が見つかったので追記しておきます。

Debuggerの問題で、LLDBだと日本語が正常に吐き出せないようです。

DebuggerをGDBに変更すれば今の所100%日本語が吐き出せているので、下記に手順を書いておきます。

 

1.上部のメインメニューから Product -> Edit Scheme...を選択

f:id:letsspeak:20120709013651p:plain

 

2.InfoタブのDebuggerをLLDBからGDBに変更。

f:id:letsspeak:20120709013712p:plain

 

以上で問題なく日本語が表示されるようになるかと思います。

-----

 

XcodeのNSLogでコンソールに日本語をデバッグ出力しようとしても出来ない事がある。

結論から言ってしまいますが、コンソールへの日本語デバッグ出力がどうしてもうまくいかない事があるようなので、NSLogを信用するなという事です。iOS開発ならとりあえずUILabelやNotificationでも良いですが、ロジックを疑う前に画面に表示してみてください。


仕事で使っている PCがまさにその状況になっていて、体感では7割方の日本語は正しく表示されますが、稀に日本語の半分が消えたり、文字化けしたり、日本語部分どころか該当の行がまるごと消えてしまったりします。Xcodeエディタ部分のエンコード設定、コンソールのエンコード設定、Terminalのエンコード設定、initWithUTF8Stringなど考えられうる設定を試しましたが駄目でした・・・。

 

可能性として、

・関係無い箇所のメモリリーク(可能性としては多いにあり得る、行で消えてるし。)
Xcodeの設定ファイルの悪さ(com.Apple.Xcodeで検索しましたが見当たりませんでした。)

 等々考えられますが、もし発生した場合に設定をちまちま見直したり、ロジックを疑って無駄な工数を割くよりも、まずは画面に表示させて確認をした方が効率は断然良いと思います。私の環境では画面に表示させられない事はありませんでした。

 私の環境ですが、英語圏用macbook+snowLeopard + Xcode4.2 から 現在のLion+Xcode4.3 へ移行した辺りで気づきました。 移行時にDeveloperをゴミ箱に移動したのが駄目だったのか、あるいは最初から発生していたのか、まったく原因がつかめないです。ARC環境、noARC環境の両方で発生しています。もし同じ現象が発生した方がいましたら、気を落とさずにプロジェクトを前に進めましょう!

 最後になりますが、もし原因をご存知の方がいらっしゃいましたら、
対処方法等についてご教授頂けますと幸いです!!