Mac版Lokkaの始め方。

仕事を邪魔されない非同期コミュニケーションのやり方を模索中。

ランチャーと簡単なスクリプトを使って受信せずにTwitterとメールを送信する。

前回最低限のテーマの作り方を紹介しました。今回は無くてもいいけど使うと便利なテンプレートタイプについて紹介します。

Lokkaにはデフォルトのentry, entries以外に様々なテンプレートタイプがあります。テンプレートは一覧、個別、その他のどれかに分類されます。

テンプレートタイプ

一覧

  • index --- トップページのテンプレート
  • category --- カテゴリー別の一覧ページのテンプレート
  • tag --- タグ別の一覧ページのテンプレート
  • yearly --- 年別の一覧ページのテンプレート
  • monthly --- 月別の一覧ページのテンプレート
  • search --- 検索結果の一覧ページのテンプレート
  • entries --- 一覧ページのテンプレート。上記のテンプレートが無い場合に使われる。

個別

  • post --- 投稿(Post)の個別ページのテンプレート
  • page --- ページ(Page)の個別ページのテンプレート
  • entry --- 個別ページのテンプレート

その他

  • partial --- テンプレートの一部分を共有するテンプレート
  • layout --- テンプレートの外枠を共有するテンプレート

一覧テンプレート

一覧はentries、個別はentryというテンプレートがありますが、例えば一覧で"検索結果だけに必要なもの"があった場合、entriesの中がごちゃごちゃしてしまうのでsearchという名前でテンプレートを作っておくと、検索結果の場合はそちらが優先して使われます。

個別テンプレート

同じようにentryとpostというテンプレートがあった場合投稿(Post)の場合はpostが優先的に表示されます。投稿とそれ以外で別の内容にしたい時に便利です。

どのテンプレートが選ばれるかはURLで決まります。実際には厳密なルールがありますが長くなるので代表的な例を紹介します。

  • index --- /
  • category --- /category/foo/
  • tag --- /tag/foo/
  • yearly --- /2011/
  • monthly --- /2011/01/
  • search --- /search/foo/
  • post --- /1
  • page --- /2

(postやpageやcategoryはIDの他にスラッグと呼ばれる自由なURLを持つことができます。そちらでもアクセスすることも可能です。)

上記以外に特殊なテンプレートタイプが存在します。それがpartialとlayoutです。

partialテンプレート

partialは複数のテンプレートで共通の部分等を別ファイルとして作成して共有するためのテンプレートです。好きな名前で作成することができます。

例えば、Copyright部分をpartialテンプレートとして下記のように作成し、別のテンプレートから読み込む事ができます。

copyright.erb:

<p>Copyright FJORD, LLC</p>

entries.erb:

(省略)
<%= partial 'copyright' %>

entry.erb:

(省略)
<%= partial 'copyright' %>

同じ内容が複数のテンプレートで出てくる場合にpartialを使うと楽でしょう。

layoutテンプレート

もう一つのlayoutテンプレートはpartialとは逆に、テンプレートの一部分を共有するのではなく、外枠の殆どを共有するイメージです。

layout.erb:

<h1 id="header">Title</h1>
<%= yield %>
<div id="footer">Powered by Lokka</div>

entry.erb:

<h2>Post Title 1</h2>
<div class="body">body ...</div>

yieldの部分にentryやentriesのテンプレートの結果が全部入るイメージです。layoutテンプレートはWordPressなどには無い機能なので多少取っ付きづらいですが、テンプレートの大部分を共有できる非常に便利な機能で、上手く使うとテーマコーディングが大幅に楽になります。数多くのフレームワークに採用されている機能なので是非とも活用してみてください。

機能としては簡単だけど名前の付け方で悩んでいる。どうでもいいことかも知れないけど数日悩んでいる。

ブログ(Lokka)に記事のドラフト機能を追加したい。つまりデータとしては存在するけどおもてには表示しない記事。そこで下記のようにフラグを用意し、その一覧をとってくるメソッドを用意する。

class Post
  property :title, String
  property :draft, Boolean

  def self.draft # 重複!
    all(:draft => true)
  end

  def self.not_draft
    all(:draft => false)
  end
end
>> Post.draft
>> Post.not_draft.all(:title.like => '%foo%')

draftがフラグ名だとメソッド名とかぶるので使えない。この例はDataMapperだけどActiveRecordのnamed_scopeでも同様だ。

こういう場合、今までの俺は、

フラグ名:publish
メソッド名:published, unpublished

みたいな名前を付けてたんだけど、draftというフラグ名を見てこっちの方が具体的な名前だからいいなと思った。できればdraftを採用したい。publishは動詞でdraftは名詞だから上手くいかないのかな。こういうモノを作る場合のRuby/Rails界隈の簡単ルールみたいなものがあったら知りたい・・・。

[OSX]理想のランチャーを探す Alfred ? | diary NET. 1.2mg

@milligrammeさんのエントリーを見てAlfredのPowerpackを買ってみた。Terminalのコマンドを実行できるという機能があったからだ。

System

>からテキストを打ち始めるとTerminalが新しく開いてコマンドを実行してくれる。これはかなり僕の求めてたものに近い。しかしopen http://google.comのような結果の表示が必要無いコマンドの場合は実行するたびにTerminalのウィンドウが1枚増えるので閉じて回るのが面倒臭い。

ところが、open http://google.com;exitのように打てば問題無いことに気づいた。特に僕はzshのaliasでexitをqに割り当てているので;qを末尾に書くだけで勝手に閉じてくれる。上記スクリーンショットの様に結果を見たい場合は普通に打って、そうでない場合は;qを付ける。

これはマジメに使えそうだ。しばらく常用してみます。(常用=Spotlightのショートカットと入れ替えること)

DataMapperのdefault_scopeのマージされ方がおかしい。

class Entry
  default_scope(:default).update(:draft => false)
end
>> Entry.count
SQL: (0.000099) SELECT COUNT(*) FROM "entries" WHERE ("draft" = 'f'))
=> 1
>> Entry.count(:draft => true)
SQL: (0.000099) SELECT COUNT(*) FROM "entries" WHERE ("draft" = 'f' AND "draft" = 't')
=> 0

ActiveRecordでも多用していた機能なので困ったなと思ってたら・・・。

#1202 Overwriting default_scope conditions is broken - DataMapper - datamapper

It's a private API so the ticket should be treated more like a suggestion to make the default_scope a public method and of course make it work correctly.

default_scopeはprivate APIなのでbugではなくsuggestion扱いだそうです。ticketのstateもholdになってました・・・。

tikushoo

Debian -- News -- Debian 6.0 "Squeeze" released

After 24 months of constant development, the Debian Project is proud to present its new stable version 6.0 (code name Squeeze).

おめでとうございまーーーす!

しかしLennyの時に比べて自分の心の動かなさにビビった。2年しかたってないのに。

Debian Lennyリリース - komagata [p0t]

Heroku使い始めてからホントにサーバー触らなくなってしまった。(HerokuもDebianベースなのに)

一応実家にはサーバーあるんだけど、オフィスの引越しで社内サーバーを撤廃してから本当に触る機会が減った。以前はローカルのcoLinux内のDebian+仕事の公開用サーバーがDebianって感じのDebian尽くしだったのが、今はローカルのMac+Herokuだから寧ろMacの設定を触ってる感じ。その代わりコード各量は増えてる気がするのでいいか。

"受動的なコミュニケーションツール"の件はとりあえず"非同期コミュニケーション"と"私書箱"の二つの問題に分けて考えることにする。まずは"非同期コミュニケーション"の方。

同期コミュニケーションが仕事に与える問題は"総量は同じでも小分けにすると質が下がる"というところ。Json Friedは"睡眠"のメタファーを紹介している。"都市部と高速道路での燃費"のメタファーでもいいかもしれない。

要は会話や電話を辞めてメールを使えということ。ついでにTwitterやSkypeチャットやGrowlも非同期、要するに1日1回まとめて処理すればいい。

そんなモノは簡単だ。メールもTwitterもフィードリーダーもSkypeも朝一回確認したら終了して使わなければ良い。でも実際にはなかなかそうはならないのは何故か。

"受信がデイリーになっても送信は一日何度もある"からだ。

メールを送る時に未読メールを見てしまう。Twitterでメッセージを送るときにTimelineを見てしまう。

「あれ?何をしてる途中だったんだっけ?そうだ、仕事のメールを送ろうとしてたんだ。」

これが仕事の妨げになっていることに気付いた。送信と受信(一覧)の機能が一緒になっているのがいけない。メールは完璧な非同期コミュニケーションツールなんだから、送信専用のメーラーがあればいい。

ということで簡単なスクリプトを書いてみた。

% vi ~/bin/ml
#!/usr/bin/env ruby                                                                                                                                              
to = ARGV[0]
body = ARGV[1]
length = 30
subject = body.split(//u)[0, length].to_s
IO.popen("mail -s '#{subject}' #{to}", 'r+') {|io| io.puts body }

gist: 812535 - MTA *sending only*- GitHub

% ml machida@fjord.jp 来週の打ち合わせの場所をGカレンダーに入れときました。

頻繁に送る相手はたいしていないのでshellのhistory補完で十分だ。でもどうせRuby使うなら普通に直接GmailのSMTPにつないでもいいかも知れない。しかしその代わりに伝統的な~/.mailrcとかが使える。

% vi ~/.mailrc
alias komagata komagata@gmail.com
alias machida machida@fjord.jp
% ml machida キムチもって帰りました。超うまかったす。

TwitterやSkypeも上記の様な感じの送信専用が欲しい。

関連:受動的なツール - komagata [p0t]

Railsを追いきれる自信が無かったから。Rails文化に引っ張られてアプリが一生完成しない気がしたから。あとアプリとしては問題無いのにベースのRailsのバージョンが低いだけで残念っぽくなってるアプリ(Redmineとか)を見たから。

半年やってみてSinatra面倒クセー!っていっぱいあったけど、(Sinatra本体の)ソースが短いので完全把握できる掌握感は独自のOSS作る上で心強かった。

Macで気軽にメールしたい。

Snow LeopardではSMTPサーバーとしてpostfixが入っている。smtp.gmail.comと直接やり取りするプログラムを書いてもいいけど、せっかくSMTPサーバーがあるのでその辺はそっちに任せてsendmailコマンド等を使うことにした。

「Macはpostfixが動いてるの?そんな無駄なモノ今すぐ止めなきゃ!」

と思った方、ご安心下さい。Snow LeopardのpostfixはlaunchdのQueueDirectories機能を使っているので/var/spool/postfix/maildropディレクトリに変化が起きた時だけ立ち上がって、60秒後に終了するので慢性的な負荷は書けません。(/System/Library/LaunchDaemons/org.postfix.master.plistに設定がある。)

gmailにリレーするにはSASLとTLSの設定が必要なので下記のようにする。

% sudo vi /etc/postfix/sasl_passwd
smtp.gmail.com:587 komagata@gmail.com:パスワード
% sudo postmap /etc/postfix/sasl_passwd
% sudo rm /etc/postfix/sasl_passwd
% sudo vi /etc/postfix/main.cf
relayhost=smtp.gmail.com:587
smtp_sasl_auth_enable=yes
smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options=
smtp_use_tls=yes
smtp_tls_security_level=encrypt
smtp_sasl_mechanism_filter = plain # if you use Yosemite
% sudo postfix stop
% sudo postfix start
% date | mail -s test komagata@gmail.com

ひゃっほう。

何か問題があれば% tail -f /var/log/mail.logしてログを確認しましょう。

二段階認証を使ってる場合はアプリパスワードを発行してそれを上記のパスワードに入力してください。

2012/06/05追記:Lionでも同じでOKでした。

2013/05/02追記:Mountain Lionでも同じでOKでした。

2014/03/11追記:Mavericksでも同じでOKでした。(by tagawaさん)

2015/06/04追記:Yosemiteではmain.cfに一行追加する必要がありました。あとは同じ。

2017/07/25追記:Sierraでも動きますが、Googleから「安全性の低いアプリのログインをブロックしました」として弾かれてしまいます。Googleのアカウント設定で「安全性の低いアプリのログインを許可」すればOKです。(推奨できませんが)