はてなブックマーク - CakePHPでPartialHelperはじめました
    このエントリーをはてなブックマークに追加

    こんにちは。
    今週末、GALAXY Sを買うFusicサクこと桜川です。
    ついに自分もスマートフォンにランクアップです。

    さて、今回は前回と同じくCakePHPになります。
    PartialHelper」というヘルパーを作成しましたのでご紹介させて頂きます。

    PartialHelper

    CakePHPはコントローラーに特化したelementを作りにくいと思ったことはないでしょうか?

    たとえば、shopsコントローラー内のみで使うelementを作る場合
    /app/views/elements/shop_form.ctp
    とか、
    /app/views/elements/shop/form.ctp
    といったような名前やディレクトリ名を付ける必要があります。

    これが1個2個くらいなら問題ないのですが、大規模案件になってくるとelementの数も膨大で管理が大変だったり、elementの名前を考えるだけでも大変になったりします。

    また、コントローラーに特化しているにも関わらず、elementというどこからでもアクセス可能な領域に配置しないといけないところも作りにくいポイントになるかと思います。

    PartialHelperを使うとelementファイルをviewファイルと同じディレクトリに配置できるようになり、コントローラーに特化したelementを作る場合にちょっとだけ楽にしてくれます。

    PartialHelperの使い方

    kozo’s PartialHelper at master – GitHub -

    1. PartialHelperをgithubからダウンロードします。
    2. PartialHelperの配置
      「/app/views/helpers」に配置します。
    3. PartialHelperの読み込み
    4. PartialHelper用のviewファイルの配置
      「/app/views/shops/_form.ctp」に配置します。
      ※Partialのviewファイルは先頭にアンダーバーをつけます。
    5. PartialHelperの使用
      ※読み込みの場合は先頭にアンダーバーをつけません。
    6. これでブラウザから「/shops/index」アクセスすると「PartialHelperのテスト」の文言が表示されるはずです。

    ポイント

    1. viewファイルと同じ位置にPartialViewファイルを配置する
    2. PartialViewファイルはファイル名の先頭にアンダーバーをつける
    3. PartialViewファイルの中身はelementとまったく同じである
    4. $this->Partial->render()の引数は$this->element()の引数とまったく同じである
    5. 機能面も読み込むファイルの位置が違うだけでelementとまったく同じである

    まとめ

    PartialHelperを導入することで、elementが全体で共通して使う小さいviewファイル、Partialがコントローラーに特化したviewファイルと切り分けることができすっきりします。
    ぜひPartialHelperをお使いください!!

      はてなブックマーク - PHPでのAmazonAPIの使い方
      このエントリーをはてなブックマークに追加

      3度目のアドベントカレンダーという、まさかの誕生日プレゼントをもらってしまいました・・・。
      小さいころの夢はお母さんを冥王星につれていくことだった、本日誕生日の萩原です。
      (bitshiftersの皆さん、昨日はありがとうございました。)

      アドベントカレンダーよりもっと別のプレゼントください。

      PHPでのAPI使い方の紹介

      さて、最近AmazonAPIを使って商品検索をする機会がありましたので、その使い方を簡単に紹介したいと思います。

      まずはじめにAmazonから自分のアクセスキーとシークレットキーを取得してきます。

      後は、実際にコードを。
      私はCakePHP使いなのでPHPを使って商品情報を取得します。
      前々回先頭のCを小文字にしてしまったら弊社小山から苦情が来ました・・・すみません・・・

      $access_key_id = 'アクセスキー';
      $secret_access_key = 'シークレットキー';
      // RFC3986 形式で URL エンコードする関数
      function urlencode_rfc3986($str) {
      return str_replace('%7E', '~', rawurlencode($str));
      }
      // 基本的なリクエストを作成します
      $baseurl = 'http://ecs.amazonaws.jp/onca/xml';
      $params = array();
      $params['Service'] = 'AWSECommerceService';
      $params['AWSAccessKeyId'] = $access_key_id;
      $params['Version'] = '2009-03-31'; //←バージョンを入れてください。
      $params['Operation'] = 'ItemSearch'; // ← ItemSearch オペレーションの例
      $params['SearchIndex'] = 'All';
      $params['Keywords'] = $word; // ← 検索ワード
      $params['ItemPage'] = $page;
      // Timestamp パラメータを追加します
      // - 時間の表記は ISO8601 形式、タイムゾーンは UTC(GMT)
      $params['Timestamp'] = gmdate('Y-m-d\TH:i:s\Z');
      // パラメータの順序を昇順に並び替えます
      ksort($params);
      // canonical string を作成します
      $canonical_string = '';
      foreach ($params as $k => $v) {
      $canonical_string .= '&'.urlencode_rfc3986($k).'='.urlencode_rfc3986($v);
      }
      $canonical_string = substr($canonical_string, 1);
      // 署名を作成します
      // - 規定の文字列フォーマットを作成
      // - HMAC-SHA256 を計算
      // - BASE64 エンコード
      $parsed_url = parse_url($baseurl);
      $string_to_sign = "GET\n{$parsed_url['host']}\n{$parsed_url['path']}\n{$canonical_string}";
      $signature = base64_encode(hash_hmac('sha256', $string_to_sign, $secret_access_key, true));
      // URL を作成します
      // - リクエストの末尾に署名を追加
      $url = $baseurl.'?'.$canonical_string.'&Signature='.urlencode_rfc3986($signature);
      //XMLで情報を取得。
      $xml = @simplexml_load_file($url);

       

      注意する点

      まず、一度に取得できる商品の件数は10件固定です。
      一度に飛ばせるリクエストの数は2件までなのでまとめて20件は表示することが可能です。

      私は今回5件ずつ取得したかったので、10件取得して前後5件ずつに分けることで対応しました。
      ちょっと無駄にデータを取ってきてしまうのが気にはなりましたけどね。

      次に、開発は基本皆さん仮想環境で開発を行っていると思います。
      その際、時間がずれていることがよくあるかと思いますが、時間がずれすぎているとAmazonからアクセスを拒否されます。
      多分10~15分くらいずれていると検索できません。
      私は取りあえずの対応で、cronで5分ごとに時間を合わせることで対応しました。(正確に合わせる必要はなかったので)

      後は、xmlを取得する際、エラー回避することを忘れないようにしましょう。
      エラーが出てしまうと、XMLの取得に使用するURLがそのまま出てしまうのですが、上記を見てもらえたらわかるとおりURLにはそのままアクセスキーとシークレットキーが書いてあります。ですので、エラーが出たら即情報が漏れてしまいます。

      今回は、デモでやっているのでとりあえず”@”をつけています。

      まとめ

      今回、こういったAPIを利用することは初めてだったので色々苦労しました。
      よくあることとは思いますが、Amazonに条件を投げて帰ってくるパターンは変えられないので、そのなかで自分がほしい情報に編集するのが少々面倒でした。
      また、XMLをいじることも初めてでしたし、javascriptでも苦労したことがあったのですが、これに関してはまた機会があれば。

      毎度おなじみどうでもいい化学豆知識

      炭素原子が三重結合までしかできないのは皆さん(多分)ご存知かと思いますが、タングステンやクロムなどは四重結合をすることがあります。
      まぁ、だからなんだと言われても困るんですけど。

      それでは、また。

      { 2010.12.15 }

      無限ループのRSpec

        はてなブックマーク - 無限ループのRSpec
        このエントリーをはてなブックマークに追加

        はじめましての人ははじめまして。
        たぶん、Fusic社員の中野です。

        Advent Calendarに当たってない社員はいるのに、もう2回も当たってしまいました。ルーレットバグってんじゃね?
        さて、今回は実際に活用したRSpecのTipsについて書いていこうかと思います。

        RSpecはRubyのテスト用フレームワークです。(RSpecを知らない人はごめんなさい。詳しい説明は省きます。)
        例えば、こんな感じでテストを書いていきます。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        
        class Hoge
          def run
            puts foo
          end
          def foo; "foo" end
        end
         
        describe Hoge do
          it "#run" do
            hoge = Hoge.new
            hoge.should_receive(:foo).and_return("foo") # 一度だけHoge#fooがコールされるよ                                                                                                                                                           
            hoge.run
          end
        end
        # >> foo
        # >> .
        # >>  
        # >> Finished in 0.00048 seconds
        # >> 1 example, 0 failures

        それでは、Hoge#runの中に無限ループがあるときはどうするのか?

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        
        class Hoge
          def run
            while true do 
              puts foo
            end
          end
          def foo; "foo" end
        end
         
        describe Hoge do
          it "#run" do
            hoge = Hoge.new
            hoge.should_receive(:foo).and_return("foo")
            hoge.run
          end
        end

        もし、これをそのままテストすると、Hoge#runの中の無限ループが実行されて処理が帰ってきません。
        無限ループを終わらせる判定があれば、テストは可能なので・・・。

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        15
        16
        17
        18
        19
        20
        21
        22
        23
        24
        25
        
        class Hoge
          def run
            while bar do
              puts foo
            end
          end
          def foo; "foo" end
          def bar; true end
        end
         
        describe Hoge do
          it "#run" do
            hoge = Hoge.new
            hoge.stub!(:bar).and_return(true, true, true, false)
            hoge.should_receive(:foo).exactly(3).times.and_return("foo")
            hoge.run
          end
        end
        # >> foo
        # >> foo
        # >> foo
        # >> .
        # >>  
        # >> Finished in 0.00085 seconds
        # >> 1 example, 0 failures

        という感じにしてあげたら、(擬似的な)無限ループを使ったテストができると思います。

        それでは、次の人にバトンタッチ〜。