ng-templat​e でテンプレートを HTML に埋め込む

script タグの type に text/ng-template を指定したら、 AnguarJS が中のテキストを $templateCache にキャッシュしてくれる。

そして、ルーターでテンプレートの URL を指定するとき、 その script タグの id にすると $templateCache にキャッシュされているテンプレートが使える。

 <!DOCTYPE html>
 <html ng-app="SampleApp">
   <head>
     <meta charset="utf-8">
     <title>SampleApp</title>
   </head>
   <body ng-controller="MainCtrl">
       <ul class="nav">
         <li><a href="#/">Home</a></li>
         <li><a href="#/tags">Tags</a></li>
       </ul>
       <div class="main" ng-view></div>
     </div>

     <!-- type を text/ng-template にすると $templateCache にキャッシュされる -->
     <script id="home_template" type="text/ng-template">
       <h2>Timeline</h2>
       <ul ng-repeat="activity in activities">
         <li>
           <span ng-bind="activity.account"></span> - <span ng-bind="activity.action"></span>
         </li>
       </ul>
     </script>
     <script id="tags_template" type="text/ng-template">
       <h2>Tags</h2>
       <ul ng-repeat="tag in tags">
         <li ng-bind="tag.name"></li>
       </ul>
     </script>

     <script src="js/angular.js"></script>
     <script src="js/angular-route.js"></script>
     <script>
       window.App = angular.module("SampleApp", ["ngRoute"]);

       // templateUrl には script タグで書いたテンプレートの id を指定する
      App.config(["$routeProvider", function($routeProvider) {
           $routeProvider.
             when("/", {
               controller: "HomeCtrl",
               templateUrl: "home_template"
             }).
             when("/tags", {
               controller: "TagsCtrl",
               templateUrl: "tags_template"
             })
       }]);

       App.controller("MainCtrl", ["$scope", function($scope) {
       }]);

       App.controller("HomeCtrl", ["$scope", function($scope) {
           $scope.activities = [
             { account: "foo", action: "create" },
             { account: "bar", action: "delete" }
           ];
       }]);

       App.controller("TagsCtrl", ["$scope", function($scope) {
           $scope.tags = [
             { name: "hoge" },
             { name: "fuga" }
           ];
       }]);
     </script>
   </body>
 </html>

ページ数の少ない Single Page Application なら、これでテンプレートを分けて書けばよさそうだな。

UITableView 編集時に挿入用の行を表示したい

UITableView 編集時のみ、挿入用の行を表示したい。こんなやつ。

f:id:griefworker:20140513201354p:plain

アイコン自体は tableView:editingStyleForRowAtIndexPath で UITableViewCellEditingStyleInsert を返せば表示できる。 ただ、編集時のみ挿入用の行を表示するとなると、結構面倒だった。

以下、RubyMotion でのサンプルコード。

# coding: utf-8

class AppDelegate
  def application(application, didFinishLaunchingWithOptions:launchOptions)
    @window = UIWindow.alloc.initWithFrame(UIScreen.mainScreen.bounds)
    @window.rootViewController = MasterViewController.controllerWithNavigation
    @window.makeKeyAndVisible
    true
  end
end

class MasterViewController < UITableViewController
  CELL_ID = "cell-id"

  def self.controllerWithNavigation
    UINavigationController.alloc.initWithRootViewController(
      self.alloc.initWithStyle(UITableViewStylePlain)
    )
  end

  def items
    @items ||= [
      { title: "foo" },
      { title: "bar" },
    ]
  end

  def viewDidLoad
    super
    self.title = "Sample"
    self.navigationItem.rightBarButtonItem = self.editButtonItem
  end

  def tableView(tableView, numberOfRowsInSection:section)
    if self.isEditing
      # 編集中は追加行を表示するので行数 +1 する
      self.items.size + 1
    else
      self.items.size
    end
  end

  def tableView(tableView, cellForRowAtIndexPath:indexPath)
    cell = tableView.dequeueReusableCellWithIdentifier(CELL_ID) ||
      UITableViewCell.alloc.initWithStyle(UITableViewCellStyleDefault, reuseIdentifier: CELL_ID)
    
    if self.isEditing and
      indexPath.row >= self.items.size
      # 追加行のとき
      cell.textLabel.text = "追加"
    else
      item = self.items[indexPath.row]
      cell.textLabel.text = item[:title]
    end

    cell
  end

  def setEditing(editing, animated:animated)
    super

    # 追加行の IndexPath を求める
    row = self.items.size
    indexPath = NSIndexPath.indexPathForRow(row, inSection:0)

    # 追加行の挿入/削除
    self.tableView.beginUpdates
    if editing
      self.tableView.insertRowsAtIndexPaths(
        [indexPath],
        withRowAnimation:UITableViewRowAnimationFade
      )
    else
      self.tableView.deleteRowsAtIndexPaths(
        [indexPath],
        withRowAnimation:UITableViewRowAnimationFade
      )
    end
    self.tableView.endUpdates
  end

  def tableView(tableView, didSelectRowAtIndexPath:indexPath)
    if self.isEditing
      if indexPath.row < self.items.size
        # 編集ページに移動
      else
        # [追加] をタップしたので追加ページに移動
      end
    else
      # 詳細を表示
    end
  end

  def tableView(tableView, editingStyleForRowAtIndexPath:indexPath)
    if indexPath.row < self.items.size
      UITableViewCellEditingStyleDelete
    else
      # [追加] 行には + アイコンを表示
      UITableViewCellEditingStyleInsert
    end
  end
end

UITableView のプロパティ一発で出来るようになったらいいんだけど。

つけめん 咲きまさ

『つけめん 咲きまさ』に行って来た。 材料費が高騰しているため閉店準備している、というツイートを見て営業しているか不安だったけど、開いていて一安心。 つけ麺を食べるのはおよそ5年ぶりで、人生2度目になる。

f:id:griefworker:20140510120827j:plain

つけ麺中盛(850円)を注文して、まず出てきたのがこれ。 どんぶりいっぱいの太麺。 大盛りは食べきれない人がいる、という注意書きを信じてよかった。

f:id:griefworker:20140510120914j:plain

つけ汁は超濃厚な魚介豚骨。 魚介のうまみが凝縮されていて旨かった。 粘度の高いつけ汁が麺に良く絡むから、つけ汁の減るペースに気を配る必要アリ。

とにかく圧倒的な、胃がはちきれんばかりのボリュームだった。 食後はお腹がパンパンで非常に苦しかったけど満足。 今まで食べた中で一番のつけ麺だと思う。 2回しか食べたことないけど。

このつけ麺が食べれなくなるのは惜しい。 あと 100~200 円高くても、食べにくる人はいるんじゃないかな。

関連ランキング:つけ麺 | 渡辺通駅薬院駅天神南駅

Rails で外部キー制約を使う方法

Rails で外部キー制約を設定したいなら、foreigner を使うのが良さそう。

foreigner をインストールすると、マイグレーションで外部キー制約を設定できる。

テーブル作成時なら

class CreateComments < ActiveRecord::Migration
  def change
    create_table do |t|
      t.reference :entry
      t.string    :content
      t.timestamp
      t.foreign_key :entries, dependent: :delete
    end
  end
end

テーブル変更時なら

class AddForeignKeyToComments < ActiveRecord::Migration
  def change
    change_table do |t|
      t.foreign_key :entries, dependent: :delete
    end
  end
end

という風に書ける。

SQLite では外部キー制約が設定されないので、動作確認は MySQLPostgreSQL でやる必要あり。

MySQL で試してみたところ、Comment に存在しない entry_id をセットして保存しようとしたら

ActiveRecord::InvalidForeignKey: Mysql2::Error: Cannot add or update a child row: a foreign key constraint fails 

というエラーが発生した。外部キーで紐づいている Entry を削除したら、Comment もちゃんと削除された。

データの整合性を保つのはデータベースの得意分野なのだから、Rails でゴリゴリやらずにデータベースに任せてしまえ、って思うようになった今日この頃。

じゃこくじら

夕食は家で食べる予定だったけど、買い物で歩き回ってお腹が空いてしまったので、天神で食べて帰ることにした。

向かったのは水鏡天満宮の横町にあるイタリアン角打『じゃこくじら』。

f:id:griefworker:20140505172429j:plain

炉端焼き磯貝の姉妹店で、前から気になっていた。時間が早かったのが幸いしたのか、カウンター席にすぐ座れてラッキー。

まずは『ゆず酒のサイダー割り』を注文。

f:id:griefworker:20140505173021j:plain

料理は『ほたてのクリームコロッケ』

f:id:griefworker:20140505173418j:plain

ムール貝のワイン蒸し』

f:id:griefworker:20140505174708j:plain

『フォアグラオムライス』

f:id:griefworker:20140505174752j:plain

『うに山もりパスタ』

f:id:griefworker:20140505175753j:plain

デザートに『ティラミス』

f:id:griefworker:20140505180510j:plain

どれも旨かった。中でもフォアグラのオムライスが一番気に入った。これで 480 円というから驚き。安いフォアグラはあるらしいけど、しっかり味付けしてあって気にならない。これだけランチで食べたい。夜だけの営業なのは残念。ランチやってたらちょくちょく利用するんだけどなぁ。

これだけ注文して 4000 円弱と、コストパフォーマンスは上々。気になるメニューを一通り注文して満足したけど、会社の飲み会とかでまた来てもいいかな、って思えた。

関連ランキング:イタリアン | 天神駅中洲川端駅天神南駅

スパイスロード

日中少し汗ばむくらいの陽気になってきて、 そろそろ辛いものが恋しい時期。 そこで福岡市中央区高砂にある『スパイスロード』に行ってみた。

f:id:griefworker:20140426121045j:plain

怪しい外観だけど、ここはれっきとしたカレーのお店。

f:id:griefworker:20140426122825j:plain

注文したのは『ムガル帝国のチキンカレー』。 ランチタイムのメニューはこの1品のみ。 チキンカレーで一本で勝負する潔さは嫌いじゃない。

カレーは食べるとすぐ辛さが襲ってくる。 普通の辛さで注文したけど、一般的なカレー店の辛口くらいはありそう。 汗がにじむくらい辛いけど、しっかり旨い。 鶏も柔らかくて、ビーフ派だったけど、チキンもありだなって思えた。

食後は口直しのラッシーが出る。

f:id:griefworker:20140426123551j:plain

ラッシーは濃厚で甘くて、口の中が癒された。 インドカレーにラッシーは必須だな。

関連ランキング:インドカレー | 西鉄平尾駅薬院駅

homebrew-cask でインストールしたアプリを Alfred から呼び出せない

homebrew-cask を使って Alfred と、Mac アプリをいくつかインストールしたけど、Alfred からその Mac アプリを呼び出せなかった。アプリ名を入力しても一覧に上がってこない。

homebrew-cask でインストールしたアプリは ~/Applications 下にシンボリックリンクが作成される。そこで Alfred の Search Scope に ~/Applications を追加したみたけど、やっぱり表示されない。Alfred はシンボリックリンクを検索できないようだ。

homebrew-cask はアプリ本体を /opt/homebrew-cask/Caskroom 下にインストールする。Alfred にはそのパスを登録すればいい。パス登録用のサブコマンドを homebrew-cask は提供していて、

brew cask alfred link

を実行すれば OK。