CakePHP2->3 ハイパーマイグレーションガイドの目次

とある受託案件があった。Railsで提案すると、「PHPで」とのことだった。

殺された知的好奇心

実はLaravelに興味があった。PHPフレームワークGoogle trendsで見ると、世界ではCodeIgniterをとっくに交わしてダントツのNo.1。
ガラパゴスCakePHP王国日本でもNo.2に躍り出てCakeを激しく追い上げている。チュートリアルをざっと見ても、「イケてるな」と感じていた。


CakePHP3にも興味がないではなかった。DBからEntityを取得すると、配列が返ってくるというCakeの象徴のような仕様。Modelまわりが直感的じゃなくならざるを得ないあの仕様が、ついに変わったという。

しかし僕は100万弱の案件を10日で終わらせるため、過去のコード資産を活用でき、手足のように使えるCakePHP2系を結局選んだ。
経営者として生きるため、技術的好奇心などとっくの昔に殺したんだ。

想定外

だがこのクライアント、予想外だった。
「できるだけ新しい技術使ってほしいなぁ、CakePHPって3があるの?」

打ち合わせから3日後、既に30%を書き上げていて不確定な詰まりを恐れた僕はそれでも渋った。
「既に書いた部分書き換えるコスト負担していただけるなら…ただぶっちゃけ発注側からしたらメリットないですよ?正直コストも読めなくて○○万円くらいだとは思うんですけど…」
「それくらいならいいですよ」

やれやれ、僕はPHPを7した。

概要

CakePHP2系から3系に移行する際、書き換えが必要な部分、詰まった部分をまとめます。
CakePHP3は、思った以上にCakeの気持ち悪さがなくなっててわりと良かったので、みなさんガンガン移行しましょう!

目次

  • YosemiteでCakePHP3環境構築
  • CakePHP2->3 設定項目を移行するお
  • CakePHP2->3 Authプラグインまわりを移行する
  • CakePHP2->3 Controllerを移行する
  • CakePHP2->3 Modelを移行する
  • CakePHP2->3 Viewを移行する

混合肌のメンズがスキンケアについて語る

スキンケアってさまざまな要素が複雑に絡み合いすぎて、なかなかこれだって言い切るのが難しい分野である。
そこで肌の荒れやすい僕が、多くの失敗からある程度安定するまでに学んだ要素をできるだけ汎用的にモデル化してまとめてみる。

前提

まずこの記事は基礎化粧品をどう選び、どう使うかにフォーカスする。
肌のコンディションを語るとき、個人的に以下の要素は欠かせない

  • 炭水化物(ご飯とか麺類、甘いもの)の摂取量を抑える
  • 7時間前後の睡眠時間(長すぎても短すぎても良くない)
  • 汗をかく有酸素運動
  • ・人と会って楽しく話す

しかし、この記事ではこれらの要素を無視して、肌を整える一要素として基礎化粧品にフォーカスする。

基本的な方針

まずは基本的なスキンケアの方針から。朝晩一日二回の洗顔をし、その後に化粧水と乳液をつけている。男としては丁寧な方だろう。
僕は皮脂の質が悪いっぽくて、目に入るとしみるし、皮脂が出た状態で放置すると肌が荒れるので1日2回の洗顔は必須だ。
とりあえず考えるべきことは、いかに水分と脂質の量を適切にコントロールするかだ。ここには3つの要素がある。

  • ・自分の体質と食事による基礎的な保持、分泌量
  • ・季節、空調で変動する湿度
  • ・基礎化粧品による除去、補填

季節、自分の体調の変化を察知しつつ、洗顔と保湿で最高のバランスを実現できる組み合わせを探すことになる。自分にあうものを選ぶのはもちろん、空調には気を使い、季節により基礎化粧品は変えよう。

基礎化粧品の探し方

アットコスメを使おう。評価上位予算に合うものを選べばいい。ここでのポイントは、レビュワーの肌タイプとレビュー内容を確認することだ。脂性肌の人が乾燥肌の人に保湿力を絶賛されているものを使えば、悲劇が待っている。
各アイテムを、さっぱり、しっとりの軸でどの位置にいるのかだけは確認してから試してみよう。
ここからは具体論に入る。メンズの混合肌の体験が前提だが、できるかぎり汎用的にしようとはしている。

洗顔料の選び方

洗顔料の役目は、皮脂と汚れを落とすことだ。ネットで泡立てて、こすらないように泡で優しく洗おう。
自分にベストの皮脂の落ち具合を見つけて欲しくて、表面の脂のとれ具合と、毛穴に詰まった汚れのとれ具合の二軸で考えるのがポイントだ。

高いものと安いもの

洗顔料は、数百円ものから4000円くらいのものまで使った。基本的に安いものは、表面の脂がとれすぎてつっぱる代わりに毛穴もそこそこすっきりするか、皮脂を残しつつ毛穴の汚れも残してザラザラになるかだ。
一方高いものは、毛穴をすっきりさせつつ、程度は違えど表面の脂を程よく落としてくれる。泡をのせる時間でさっぱり具合は多少コントロールできるのだが、高いものはさっぱり系を長時間乗せてもつっぱらない。

使用方法によるコントロール

四季と朝晩での使い分けを考えよう。湿度の高い夏場、汚れのたまる夜は比較的さっぱり目のものを使い、乾燥する冬、ほぼ自分の皮脂で紫外線も浴びていない朝はしっとり目のものを使うといいだろう。
また毎日同じものを使う必要はなく、基本しっとりめのものを使い、週1で洗浄力強めのものでさっぱりするという方針もありだと思う。
また前述のように、泡を乗せる時間でも多少コントロール可能だ、特に安くて洗浄力が強いものを使う際は長時間乗せないよう気をつけよう。脂性肌だからといって皮脂をとりすぎ、さらに皮脂分泌を増やしてしまうケースは多いのだ。

個人的なおすすめ


資生堂 dプログラム コンディショニング ウォッシュ 150g
洗顔に使っている。しっとり目。とにかく洗い心地が優しくて、刺激ないですわって感じ。脂性肌だとこれだけを使い続けるのは物足りなそう


カバーマーク ミネラルウォッシュ 125g
洗顔に使っている。ややさっぱり。しっかり皮脂が落ちたなと感じるが、全くつっぱらない優秀な一品


ロゼット 洗顔パスタ 白泥リフト 120g
ド定番。ややさっぱり目な使い心地。安いわりには良いというレベルではある

化粧水の選び方

化粧水はベースの水分を補給する役目を持つ。しかし水分だけだと脂質のバリアがある肌には浸透せず肌が柔らかくならないので、脂質も多かれ少なかれ含んでいる。
化粧水は使用直後のモチっとした質感だけでなく、乳液と合わせて長時間たってもべたつかないバランスを見つけるのが大事。

高いものと安いもの

化粧水も数百〜4000円くらいのものを使った。化粧水は浸透度合い保湿成分量が変わる。高いものはすっと浸透してしっとりしつつベタつかない。浸透度合い関係なく、保湿成分というか、脂質が入っていると肌が柔らかくなる。
しかし、保湿成分が多いと最初さらっとしても結局ベタついたりするので難しいところだ。

使い方による保湿度合いの調節

単純に使用量を調節してもいいのだが、少なめにする場合はさっぱり目の化粧水にまぜて水分は十分に補充するのがおすすめ。その際ベースとなるさっぱり目の商品としては、ナチュリエのスキンコンディショナーを大プッシュしておく。

個人的なおすすめ


ナチュリエ スキンコンディショナー
超さっぱり。というかほぼ保湿力がないんじゃないかって感じでもっちりはしない。だが脂性肌には嬉しい存在。大容量で激安


dプログラム アクネケアローション (医薬部外品) 125ml
ややさっぱり。浸透してもちっとする。2プッシュを推奨しているが、個人的には1プッシュがべたつかず、モチっと感も得られてちょうどいい

乳液の選び方

乳液は補った水分の上から蓋をして、乾燥を防ぐ役目を担う。化粧水とのバランスが求められる。脂性肌、混合肌の人にとっては、乾燥は防ぎたいがベタつきの原因となってしまうという板挟みを生みやすい鬼門。乾燥しない、しかし表面はさらっとするバランスを見つけよう。

高いものと安いもの

乳液は最近使い始めたのでサンプルが多くない。数百~3500円くらいのものを使った。安いものは、異物感が結構ある気がして、角栓ができやすかった。値段がそこそこするものは、しっかり保湿しつつも肌になじむ感がある。
細かい成分を語るのは好きじゃないのだが、脂性肌や混合肌の人に1つ進めたいのがセラミドだ。高濃度で配合しているものは、合う合わないはあれど、総じて脂っぽくならないわりに保湿できる印象を受けた。値段は張るけど。

使い方による保湿度合いの調節

これも単純に量を調節すると良い。極端な例だが、僕は10円玉サイズが標準の使用量のものを、夏は米粒一粒、冬は二粒というレベル感で使っている。またその程度の量だとさすがに伸び難いので、化粧水を混ぜて伸ばして馴染ませている。

個人的なおすすめ

※権利関係問題なさそうな画像なしでした
トゥベール セラミドミルク
さっぱり目の乳液。僕は昔から皮脂分泌が多くすぐニキビができるので、乳液はほとんど使わず冬は粉をふいていた。しかし米粒程度の量の使用で、冬はもちろん、夏場でも乳液を使えるようになった個人的にエポックメイキングな一品

冬ルーティー

ということで最後に現在の僕の冬ルーティーンをまとめる。

ちなみにおすすめであげたのは、男が使う化粧品としては決して安くない。ただ化粧水&乳液は少量ずつしか使わないので見かけほどお金かかりません。洗顔料3ヶ月に1個、化粧水、乳液半年に1個って感じ。
合うものを見つけるまでが大変なので、あればサンプルなど駆使して頑張りましょう。以上何かの参考になれば幸いです!

CakePHP2系でSearch Pluginを自由自在に

検索は、Web開発で超頻出の項目です。
そしてシステムをしらない人が、なぜか「開発超大変」と思っている項目でもあり、さらっとできると割とおいしいなぁと感じています。
今回はCakeDC/search、いわゆるSearchプラグインを使い、僕流のCakePHPで検索を自由に実装するポイントを書いてみます。

Searchプラグインを避けるという選択肢

唐突ですが、「CakePHP始めて2週間です」みたいな人がいたら、Searchプラグインを使わないという選択肢を検討してみてください。

検索って、「フォームから受け取った値を元にクエリの条件変えて表示する」という行為で、特に難しくもないです。知らないライブラリで詰まった際、問題を把握し解決するよりも圧倒的に。

初めてCakePHPで検索を実装した時のこと。3日間ほどSearchプラグインで詰まり、切り替えて自前で実装したら数時間でできてしまった。

プラグインにはコードが整理される、引き継ぎやすい等メリットがあります。ただ、時には一日も速いリリース、達成感が大事なタイミングもあるかと。CakePHPに慣れてから、いつでもさくっと使えますから。

Pluginの導入

composer, git clone, コピペ何でもいいのでapp/Plugin内にPluginのファイルを導入します。
app/Config/bootstrap.php内でプラグインをloadするのを忘れずに。

CakePlugin::load('Search');

Searchプラグインの概要

SearchプラグインPrgComponentSearchableBehaviorから成ります。

PRG ComponentはユーザーがPOSTした値を処理し、検索条件を保持しつつGETでも使える形に処理します。

これはPRG(Post Redirect Get)パターンというものに沿った処理で、
POSTのメリット(少しだけセキュアなのと文字数制限のなさ)
GETのメリット(ブラウザリロード時に問題が起きない、ブックマーク可能)
を組み合わせて利用するものです。

SearchableBehaviorは、渡された値を元に、find()やpaginate()で使える条件配列を返します。

以下具体的なコードと共に、Controller, Model, Viewそれぞれでやることを記述します。

Controllerでやること

<?php
class ArticlesController extends AppController {

  // 1.componentを定義します
  public $components = array(
        'Search.Prg' => array(
        'commonProcess' => array(
          'paramType' => 'querystring',
          'filterEmpty' =>  true,
        ),
  );

  // 2.presetVarsを定義します
  public $presetVars = true;

  public function find() {
  // 3.Prg->commonProcessを呼び出します
    $this->Prg->commonProcess();
  // 4.Searchable BehabiorparseCriteriaで、検索条件を取得します
    $this->Paginator->settings['conditions'] = $this->Article->parseCriteria($this->Prg->parsedParams());
    $this->set('articles', $this->Paginator->paginate());
  }
}

サンプルを元に、色々と改変しています。

1.PrgComponentの読み込み

いつもこの設定で使っています。お好みで。

          'paramType' => 'querystring',

URLがクエリストリング形式(例 /search?blog_id=3&author_id=5)になります
          'filterEmpty' =>  true,
inputに値が入力されなかった場合、クエリストリングにその項目を含みません
例 /search?blog_id=&author_id=5 が /search?author_id=5 に

2.presetVarsの設定

この後Model内のfilterArgsというパラメータで、各値の形式等を設定します。presetVarsではそれを上書きできます。ユーザーの入力がない場合の、デフォルト値を設定したりも。
現在は設定しなくて大丈夫なので、特殊なことをしなければ例のようにtrueに、または記述しなくてOKです。

3.Prg->commonProcessを呼び出す

特に考えることはありません。ただ呼び出すだけです。

ちなみにSearchPluginの動作を確認する際は、
1.POSTされたデータ処理の流れがうまくいっているか
2.ただしい条件配列が作成されているか
の2点の切り分けがポイントです。Controllerの全て、ModelのpresetVars設定、Viewのフォームが揃ったら、一度POSTされたデータの処理がうまくいっていることを確かめてみましょう。
例えばblog_idを指定してsubmitボタンを押した時、search?blog_id=3のようなURLに遷移すれば、後はpaginate()に適切な条件配列を渡すだけです。

4.SearchableBehavior parseCriteriaを呼び出す

parseCriteriaは、find()、paginate()で使える条件配列を作成します。

  array(
    'Article.blog_id' => 2,
    'Article.title' => 'タイトル',  
  );
こんなのが返ります。これを条件配列を渡すとしぼりこまれます。
  $conditions = $this->Article->parseCriteria($this->Prg->parsedParams());

  $articles = $this->Article->find('all', array(
    'conditions' => $conditions,
  ));
  $articles = $this->Paginator->paginate('Article',
    $conditions
  );

Modelでやること

<?php
    
  class Article extends AppModel {
    // 1.SearchableBehaviorを読み込む
    public $actsAs = array(
        'Search.Searchable'
    );

    public $belongsTo = array(
        'User',
        'Blog',
        'Author',
    );

    public $hasAndBelongsToMany = array(
        'Tag' => array(
            'with' => 'Tagged'
        )
    );

    // 2.filterArgsを設定する
    public $filterArgs = array(
        'title' => array(
            'type' => 'like'
        ),
        'status' => array(
            'type' => 'value'
        ),
        'keyword' => array(
            'type' => 'like',
            'field' => array('Article.title', 'Blog.title', 'Author.name')
        ),
        'tags' => array(
            'type' => 'query',
            'method' => 'findByTags',
        ),
    );

    // 3.独自メソッドを定義する
    public function findByTags($data = array()) {
      $articleIds = $this->Tagged->find('list', array(
        'fields' => 'Tagged.article_id',
        'conditions' => array('Tagged.tag_id' => $data['tags']),
      ));
      $condition[1] = array(
        'Article.id' => $articleIds,
      );
      return $condition;
    }
}

1.SeachableBehaviorの読み込み

読み込むだけです。

2.filterArgsの定義

検索で使う項目ごとに1.どのフォームの値を2.どのフィールドに対して3.どのような方法で行うかを定義します。
まず、配列の第一階層のキー(例ではtitle,blog_id,keyword,tags)は項目名になります。
対応する配列内では、基本的に以下3項目を指定します。
formField 1.を定義するもので、対応するフォームのフィールド名(name attributeの末尾の値)を指定
field 2.を定義するもので、モデルのフィールドを指定(例, title, Blog.titleなど)
type 3.を定義するもので、検索する方法を指定
1.と2.を指定しない場合、先ほどの項目名がデフォルト値になります。
例えば、Articleモデルのフォーム内で、titleという項目に入力された値を受け、Articleモデルのtitleを検索する場合、typeだけを指定すれば良いです。
やりたいことによっては、上記以外の項目の指定が必要になります。

fieldについて
fieldでは、該当モデルにContainされている、またはリレーションされているモデルのフィールドも指定することができます。
typeについて
typeに関しては、元々定義されているメソッドを使う場合と、自分で定義するメソッドを使う場合があります。

元々定義されているものではvalue, likeを良く使います。
valueは値を完全一致で検索します。selectなど単一選択、checkboxなど複数選択、textなど文字列全てに対応します。
likeは文字列の部分一致検索です。 WHERE 'Article'.'title' = '%タイトル%' みたいな感じ。例のように複数フィールドをまとめて検索も可能です。

あとは比較演算子の使用や、前方/後方一致、between等が定義されていますが、割愛します。

自分で定義したメソッドを使う
この場合は、typeにquery、subqueryを指定します。
僕はqueryタイプしか使わないのでそちらの解説を。

queryタイプは定義したメソッド内で、フォームで入力された値を受け取り、条件配列を作成するものです。
上の例のように、filterArgs内でmethodという項目でメソッド名を指定し、モデルのメソッドとして実装します。

    public function methodName($data = array()) {
      //処理
      $condition = array(/* 条件配列 */);
      return $condition;
    }
フォーマットは上記です。
値の受け取り
$data['フォームのキー']という形で値を受け取れます。filterArgsで指定した項目以外の値も使用できます。
返り値と条件配列の挙動
メソッド内で条件配列の要素を作成し、返り値として渡すような形です。
返り値として渡された条件配列の要素は、前のフィールドまでで作成された条件配列にどんどんマージされていきます。
注意が必要なのは、要素間で条件指定するフィールドが被った際の挙動です。
この場合、先に定義された要素は上書きされます。array_mergeされているような挙動ですね。

これは防ぐ方法があって、例のように返り値にする条件配列の要素に、通し番号を振ると上書きされません。

//独自メソッドの返り値として
array('Article.blog_id' => 1); と array('Article.blog_id' => 2); があった場合 
前者は上書きされ array('Article.blog_id' => 2) の要素だけ適用

array(1 => array('Article.blog_id' => 1)); と array(2 => array('Article.blog_id' => 2)); があった場合
上書きされず、両要素がAND条件で適用
といった形になります。

AND条件とOR条件
検索に限らずModelの一般論ですが、条件配列の中身は
・1つのフィールドの条件として複数の値を指定した場合はOR条件
・異なるフィールド間ではAND条件
として処理されます。
異なるフィールド間でOR条件として処理したい場合は、キーにORをつけた配列を作成します。

array(
  'OR' => array(
    'Article.blog_id' => 2,
    'Article.title' => 'タイトル',
  ),
);  

Viewでやること

echo $this->Form->create();
echo $this->Form->input('title', array(
        'div' => false
    )
);
echo $this->Form->input('blog_id', array(
        'div' => false,
        'options' => $blogs
    )
);
echo $this->Form->input('keyword', array(
        'div' => false,
    )
);
echo $this->Form->input('tags', array(
        'div' => false,
        'multiple' => 'checkbox',
    )
);
echo $this->Form->submit(__('Search'), array(
        'div' => false
    )
);
echo $this->Form->end();
普通にフォームを定義するだけです。

Form->create

querystring指定をしていれば、本家サンプルのように$this->param['pass']を指定する必要はありません。

multipleの場合の値

例のtagsのように複数選択可能なフォームにすると、フォームから渡される値が配列になり、クエリストリングもtags[]=1(tags%5B0%5D=1)のような形になります。

データの設計

最後にですが、DB設計の段階で、検索を意識してスキーマを定義することが非常に重要だと思います。
イメージとしては、filterArgsができるかぎりvalueとlikeだけですむように設計段階から考えていくことが重要かと。

人生とキャリアの桃鉄理論

桃太郎電鉄というゲームがある。サイコロを振って、物件を買って、ボンビーをなすりつけあうあれだ。
僕はあれが大好きで、10代で狂ったように友達とやりまくっていた時期があった。

桃鉄運ゲー

桃鉄が好きだと言うと、かなりの確率で言われる言葉がある。
「でもあれって結局運ゲーじゃん?」

つまり、サイコロとか、カードとか、ボンビーがキングになるかとかで決まるじゃん?という話だ

この言葉に僕はいつも全力で反論する。期待値に基づく確率計算、カードに購入&使用のタイミング、ボンビーをくらわないための備えと毎ターンの状況判断。
そういった「筋のいい判断」の積み重ねで、最終的には差がつく。実際にやっても、公式戦(3年間のモード)を数試合やれば、ほぼトータルでは勝っていた。

運という言葉を使う意味

本当のことをいうと、実際は桃鉄運ゲーかどうかなんてどうでもいい。
僕は、安易に運という言葉を使うのが嫌いだ。時折、自分が理解できない、しようとも思えないスケールのものに「○○なんて運だよ」と言ってしまう人がいる。

友人とキャリアについて話してる時「Webサービスで成功するかなんて結局運だよね」という趣旨の発言をされて、ちょっとカチンときてしまったことがあった。その友人は電機メーカーの内定者で、僕は会社をやめて自分で事業をたちあげ始めたころだった。

「筋のいい判断」を繰り返せば、成功する

極端な言い方をするが、Webサービス開発は必然的に成功できる業種だと思う。
ユーザーに対するバリューとは何か?それが売上に結びつく条件は?こういったことを成功しているサービスや、ユーザーの観察をし考え抜く。その上で、プロモーションもCVRも、データに基づき改善し続ける。こういった積み重ねで「筋のいいサービス」を作ることは可能だと思うのだ。
そして、開発の全体像を理解し、コストのかかる部分を抑え、それなりの資本を準備すれば、何度もバッターボックスにたつことができる。

僕がWeb業界を選んだ理由の一つが、この小資本でできる+スピード感の組み合わせで、自分が考える筋のいい試行を、短い人生の中で十分な回数繰り返すことができるという点だった。

運なんて言葉は、成功者が謙遜で使うためのものだ。外部の人間や駆け出しが使うのは、真面目に考えている人間に失礼だ。もちろん上記を踏まえても失敗者がおり、自分がそうなりうるのは百も承知だが、それは「筋のいい判断」ができていなかったと考えなければ、そこで思考停止だ。

そして、「こんなん買える時くるのかよ!」と笑ってしまう桃太郎ランドも、地道な積み重ねで買える日がくることも知っているのだ。

Herokuのasset_precompileとdb:pushに詰まる

久しぶりにHeroku使ったらいくつかこけたのでメモ。

  • ・sqlite3で budle install 失敗
  • ・rake asset:precompile 失敗
  • ・tapsで rake db:push 失敗

sqlite3で $ budle install 失敗

appをherokuにpushしたところ…

Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
       /usr/local/bin/ruby extconf.rb
       checking for sqlite3.h... no

原因

gem 'sqlite3'を本番にも入れてた。

解決方法

Gemfileを編集し、sqliteをtest環境に限定

group :test do
  gem 'sqlite3'
end

この記事あたりを見るに、Herokuはsqlite使えないので、buildに必要なライブラリを入れてなくてエラーが起きるということでしょうか。
App templateで初期Gemfileをベースにしているのですが、testでしか使わないsqlite3をそのままにしていた罰があたりました。

rake asset:precompileに失敗

-----> Preparing app for Rails asset pipeline
       Running: rake assets:precompile
       rake aborted!
       could not connect to server: Connection refused
       Is the server running on host "127.0.0.1" and accepting
       TCP/IP connections on port 5432?
       Tasks: TOP => environment

対処方法

config/application.rbに下記を追記。

config.assets.initialize_on_precompile = false
ローカルでprecompile
$ RAILS_ENV=production bundle exec rake assets:precompile
エラーメッセージに解説のURLが含まれています。asset precompileの際にDBを見に行くのですが、この時使用する環境変数がslug compile(Herokuへのpushをhookにした処理の呼び名)時には存在しないため、仮で用意した変数を見てlolhostのDBを見に行きエラーが起こるそうです。

tapsで rake db:push 失敗

dev環境でmysql→herokuでpostgresへの移行です。

原因

見落としてたポイントは3点
・rbenv+Heroku Toolbeltの組み合わせで発生するエラーがある
・localのherokuコマンドはlocalのgemのみを参照する
・使用するrdbmsのgemに加え、sqlite3のgemが必須

解決方法

bundleではなくlocalにgem"mysql2","taps(0.3.24)","sqlite3"をinstall
Heroku Toolbeltを削除しlocalにgem"heroku(2.33.0)"をinstall
いくつかミスが重なったので順に見ていきます。

rbenv+Heroku Toolbeltで起こるらしいエラー

heroku db:push mysql2://USER@localhost/APPをすると…

 !    Taps Load Error: cannot load such file -- taps/operation
 !    You may need to install or update the taps gem to use db commands.
 !    On most systems this will be:
 !    
 !    sudo gem install taps
tapsは当然インストール済みだし最新版。調べてみるとこんな記事が。
下の方に何件かrbenv+Heroku Toolbeltでこのエラーの報告が。
Heroku Toolbeltを削除し、gem版herokuをinstall。deprecatedされてるものにあえて戻す
$ rm -rf /usr/local/heroku
$ sudo rm -rf /usr/bin/heroku
$ gem i heroku
$ source ~/.bash_profile

sqlite3は必須

再トライ

 !    Taps Load Error: cannot load such file -- sqlite3
 !    You may need to install or update the taps gem to use db commands.
 !    On most systems this will be:
sqlite3?今関係ないし、そもそも入ってるんだけど…
と思ったら必須らしい+bundleで入れてlocalには入れてませんでした。
$ gem i sqlite3
やっと成功です。
> app
Sending schema
Schema:        100% |==========================================| Time: 00:00:14
Sending indexes

おまけ:昔入れたHeroku Toolbelt使ってた

実は最初こんなミスをしていました。エラー発生

Failed to connect to database:
  Sequel::AdapterNotFound -> LoadError: no such file to load -- mysql2
mysql2入ってるけど…と思って良くみると
Loaded Taps v0.3.23
Tapsのバージョンが違う。
$ heroku version
heroku-gem/2.33.0 (universal-darwin10.0) ruby/1.8.7
今はruby1.9.3系を使っています。以前入れたherokuを使っていて、その際のrubyのgemを参照していました。
herokuをuninstallして、Heroku Toolbeltをinstall
$ heroku version
heroku-toolbelt/2.33.0 (x86_64-darwin10.8.0) ruby/1.9.3

vimに関する設定メモ

vimへの移行を試みています。設定などはgit管理しているものの、やっていることをここにメモしておこうと思います。
最近はいわゆるdotfilesをgithubで管理している人が多いので、非常に参考になります。もちろん、自分が実際に試せる範囲で徐々に取り入れていく必要はあると思いますが。

概要
  • MacVim本体の導入
  • プラグインの導入と管理
  • .vimrc記入事項
  • .gvimrc記入事項

MacVim本体の導入

http://code.google.com/p/macvim-kaoriya/
日本語対応などを改良したMacVim-KaoriYaを使用。

汎用性はないですがApplicationsに入れるまでのスクリプト。パッケージ名やURLは上のリンクから要確認。

#install vim
wget http://macvim-kaoriya.googlecode.com/files/macvim-kaoriya-20120823.dmg

hdiutil mount ~/macvim-kaoriya-20120823.dmg
sudo cp -R /Volumes/MacVim-KaoriYa/MacVim.app /Applications/
hdiutil unmount /Volumes/MacVim-KaoriYa/

rm -f ~/macvim-kaoriya-20120823.dmg

このMacVimをコマンドラインでも使う場合。

使ってるシェルの設定ファイルに追記。僕は.bashrc。

#set MacVim as a default editor

export EDITOR=/Applications/MacVim.app/Contents/MacOS/Vim
alias vi='env LANG=ja_JP.UTF-8 /Applications/MacVim.app/Contents/MacOS/Vim "$@"'
alias vim='env LANG=ja_JP.UTF-8 /Applications/MacVim.app/Contents/MacOS/Vim "$@"'

プラグインの導入と管理

プラグイン管理にはVundleを使います。Rubyのbundleの影響でできたvim版といった感じ。
.vimrcに使用するプラグインを記載し、コマンド一発でinstallやupdate、使用不使用を管理できるようになります。
他の選択肢だと改良版のNeoBundleプラグインの依存関係も管理するVAMなんかもあります。

Vundleのインストール

githubに書いてあるままで問題ないかと。
githubからファイルとディレクトリをclone

 git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle

.vimrcを編集

#install plugins by Vundle
 vim +BundleInstall +qall
 
 "Vundle(plugin manager)

 set rtp+=~/.vim/bundle/vundle/
 call vundle#rc()

 Bundle 'gmarik/vundle'

 "インストールしたいプラグインを Bundle 'githubの名前/githubのレポジトリ名' で記載
 Bundle 'vim-ruby/vim-ruby'
 Bundle 'tpope/vim-rails.git'
 Bundle 'scrooloose/nerdtree'
 Bundle 'chriskempson/vim-tomorrow-theme'

 filetype plugin indent on

:Bundleinstallを実行

 vim +BundleInstall +qall

一点下記のコメントが引数として認識されてエラーになることがあり、コメントを消して対応。
https://github.com/gmarik/vundle/issues/13

.vimrc記入事項

まだ思考錯誤中なのでおいおい更新

.gvimrc記入事項

GUIVimでcolorschemeを起動時に反映させるには、.gvimrcの記入または.gvimrcを読み込まないようにする必要があります。
僕はtomorrow-themeに入っているTomorrow-night-brightが好きです。Vundle使用の場合はinstallを忘れずに。

$ vim ~/.gvimrc
colorscheme Tomorrow-night-bright

チューンホテル(Tune Hotel)+アヤラ(Ayala Center Cebu)で仕事をする

セブでの滞在中、僕はほとんどチューンホテルに泊まっていました。
そして、チューンホテルすぐそばにあるアヤラ(Ayala Center Cebu)で生活のほとんどをまかなっていました。
仕事もアヤラのCafe放浪を中心にしており、それなりに便利だったのでこの2つの施設を紹介します。

Tune Hotel

有力LCCであるAirAsiaが経営しているホテルです。
LCCさながらの合理的なコスト削減+アドオンによる課金が特徴です。リゾート感は皆無ですが、寝床と割り切ればコスパはセブ最高だと思います。

立地

「セブ」をビーチリゾートとのマクタン方面と街のセブシティ方面にざっくりわけて、セブシティの北よりに位置する感じです。夜遊びのマンゴーやオスメニアサークルはタクシーで60ペソ、マクタン方面へは160ペソくらい。
そしてなんといっても後述のAyala Center Cebuに徒歩すぐです。道路2本渡るだけです。シティ方面中心の滞在ならかなりよい立地かと。

料金

公式からとって、一泊700ペソ強でした。この料金に冷房、wifi、タオルなどが別料金になっており、それぞれ一日100〜200ペソ程度かかります。
ちなみにagodaでとると、上述のadd-onがデフォルトでつき、こみこみの値段でとれます。けど結構値上がりしてますね。僕の宿泊時期はagodaからで一泊表示が700ペソ、諸費用込み1000ペソ程度でとれたのですが。

部屋の評価

日本のビジネスホテルに泊まっているような感じです。他ホテルの評価を見るに、これはフィリピンの安いホテルでは珍しいみたいです。

安定&速度十分。滞在の間一度もトラブルなし。ただログインで少し戸惑う。あとagoda予約のボーナスは日数分×24時間のID支給で、1チケット1台のみ接続可。フロントで購入した場合は、同一IDで複数台の接続可。

  • ・シャワー

十分な勢いで温かいお湯が出る。ただ、シャワーカーテンがなくトイレ&洗面台のスペースが水浸しに。

  • ・冷房

十分な強さ。5分ほどでちょっと寒くなるレベル。

  • ・清潔さ

基本的に清潔。シーツも毎日交換。部屋で虫は滞在中一度も見ず。ただ、ちょっと埃っぽい。

  • ・洗濯

フロントに洗濯物渡すと、外の洗濯屋に出してくれて翌日フロントで受け取れる。140ペソ〜で3日分で300ペソとか。

  • ・その他

部屋に13インチPCが入るセキュリティボックスがあるのは良い。あと備え付けのドライヤーがかなりパワフル。部屋はちょっとせまい。

Ayala Center Cebu

セブの中では高級なモール。ブティック、イオンみたいなスーパーに、理髪店といろいろ入っており、本当に何でも揃います。
食事は50ペソ程度から食べれるフードコートから、安定したフィリピン料理店、それなりのクオリティの各国料理まで選び放題。また、多くのwifiと電源を備えたCafeがあります。

wifi事情

館内には無料wifiが飛んでいますが、残念ながらつながりません。その代わり、各店舗が独自にwifiを整備しており、どこもそれなりに安定しています。
形式は店を利用するとパスワードを教えてくれる店、接続すると2時間制限のIDとパスをくれる店などがあります。トラブルは3日に1度ほど遭遇するイメージ。だいたい1〜2時間で復旧しますが、僕は遭遇したら別の場所に移動していました。

治安

渡航前は、Macを広げて作業することに不安があったのですが、特にトラブルには遭遇しませんでした。入り口で手荷物検査もありますし、外より比較的安全とはいえそうです。
基本的ですが、PCを広げるのはカフェ内のみ、トイレに行く時は荷物は持っていくという運用でした。カフェに入ればPCを使っている人はそれなりにいます。ちなみにMacはあまりいません。フードコートでタブレットいじってる人、PC広げている人なんかもいます。

おすすめのお店

  • アヤラ&周辺でオススメのレストラン
  • アヤラ&周辺で仕事がはかどるCafe