log

セリアのスマートフォンスタンドを買ってきた

ケータイWatchの記事で前々から気になってたセリアのスマートフォンスタンドを買ってきた。100円だし駄目なら捨てればいいや、くらいの感覚で。

iPod touch と HTC EVO WiMAX をそれぞれ置いてみたけどいい感じ。

ただ、EVO WiMAX に標準で付いてくるUSBケーブルだとうまく収まらなくて残念な感じに……。

100均で別途ケーブルを買ってくる予定。

showoff で PDF を作成する

markdown 形式のテキストからスライドを自動生成してくれる showoff で、PDF 生成するのにアレコレ修正する必要があったのでメモ。
環境は以下。


  • Mac OSX 10.7.2

  • Ruby 1.9.2-p180

  • showoff 0.7.0

  • pdfkit 0.5.2

  • wkhtmltopdf 0.8.3


ちなみに Ruby 周りは rvm で、wkhtmltopdf は brew で入れた。

showoff のドキュメントによると http://localhost:9090/pdf にアクセスすると PDF が出力されるとのことだけど、実際アクセスされるとエラーが出た。
showoff のログを見てみると以下を発見。

 
Unknown long argument --quiet

Usage: wkhtmltopdf [OPTION]... <input file> [more input files] <output file>
converts htmlpages into a pdf


おそらく showoff が wkhtmltopdf に渡すオプションを間違ってるんだろなってことで、showoff のソースを追ってみる。

そうすると、どうやら PDF 生成は pdfkit に任せてるってことがわかった(390行目辺り)。



382 def pdf(static=true)
383 @slides = get_slides_html(static, true)
384 @no_js = false
385 html = erb :onepage
386 # TODO make a random filename
387
388 # PDFKit.new takes the HTML and any options for wkhtmltopdf
389 # run `wkhtmltopdf --extended-help` for a full list of options
390 kit = PDFKit.new(html, :page_size => 'Letter', :orientation => 'Landscape')
391
392 # Save the PDF to a file
393 file = kit.to_file('/tmp/preso.pdf')
394 end

というわけで、今度は pdfkit のソースを読んでみる。

「quiet」で grep かけてみるとそれらしい箇所が出てきたのでコメントアウトした(35行目辺り)。



32 def command(path = nil)
33 args = [executable]
34 args += @options.to_a.flatten.compact
35 #args << '--quiet' # 不要なオプションなのでコメントアウト
36
37 if @source.html?
38 args << '-' # Get HTML from stdin
39 else
40 args << @source.to_s
41 end
42
43 args << (path || '-') # Write to file or stdout
44
45 args.map {|arg| %Q{"#{arg.gsub('"', '\"')}"}}
46 end

この状態で改めて http://localhost:9000/pdf にアクセスすると、今度はちゃんと PDF が生成された。

さくらVPSの使い道

今のところ主に動かしてるサービスは以下。

で、ここで WordPress を動かしたいんだけど、正直メモリが足りない。

あえてどれか落とすとしたら、FacebookIrcGateway かな。FacebookFirefox の AppTab で十分使えそうなので。

あと、Dropbox もメモリ食いまくってるので落としたいけど、そうすると dotfiles の運用が面倒になる……。
とりあえず FacebookIrcGateway だけ落としてみて、様子見かな。

Play--Scaffoldを使ってみた

最近、Play framework を触ってみてる。

かなり Rails っぽくサクサク開発できそうなので気に入ってるんだけど、やはり Rails といえば scaffold が欲しい。

Play は標準では scaffold は持ってないけど、モジュールとして Play--Scaffold が提供されている。

Rails の scaffold とは若干機能が違う。以下、相違点。


  • Model はユーザ自身でファイルに記述(scaffold は Model を元に Controller, View を自動生成する)

  • Model 間の関連性(多対一や多対多)を考慮して form を生成

  • ログイン機能を自動生成(オプション)

Play--Scaffold をインストールして使うまでは以下な感じ(今回は Play 1.2.3, Play--Scaffold 0.1 を使用)。

モジュールをインストール

$ play install scaffold

対象プロジェクトを作成

$ play new play-scaffold
$ cd play-scaffold

モジュールのパスを指定

$ vim conf/application.conf
module.scaffold=${play.path}/modules/scaffold-0.1

DB を使用可能にしておく

$ vim conf/application.conf
db=mem

Model クラスを作成

今回は Play framework のチュートリアルにて使用されている yabe ( Yet Another Blog Engine ) の Model を使うことにした。

ER 図(Taggingは仮想的なテーブルで、実際にクラスは作成しない)
yabe の ER図

User クラス

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;
import play.data.validation.*;

@Entity
public class User extends Model {

@Email
@Required
public String email;

@Required
public String password;

public String fullname;
public boolean isAdmin;

public User(String email, String password, String fullname) {
this.email = email;
this.password = password;
this.fullname = fullname;
}

public String toString() {
return email;
}
}

Post クラス

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;
import play.data.validation.*;

@Entity
public class Post extends Model {

@Required
public String title;

@Required
public Date postedAt;

@Lob
@Required
@MaxSize(10000)
public String content;

@Required
@ManyToOne
public User author;

@OneToMany(mappedBy="post", cascade=CascadeType.ALL)
public List comments;

@ManyToMany(cascade=CascadeType.PERSIST)
public Set tags;

public Post(User author, String title, String content) {
this.comments = new ArrayList();
this.tags = new TreeSet();
this.author = author;
this.title = title;
this.content = content;
this.postedAt = new Date();
}
}

Comment クラス

package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;
import play.data.validation.*;

@Entity
public class Comment extends Model {

@Required
public String author;

@Required
public Date postedAt;

@Lob
@Required
@MaxSize(10000)
public String content;

@ManyToOne
@Required
public Post post;

public Comment(Post post, String author, String content) {
this.post = post;
this.author = author;
this.content = content;
this.postedAt = new Date();
}
}

Tag クラス



package models;

import java.util.*;
import javax.persistence.*;

import play.db.jpa.*;
import play.data.validation.*;

@Entity
public class Tag extends Model implements Comparable {

@Required
public String name;

private Tag(String name) {
this.name = name;
}

public String toString() {
return name;
}

public int compareTo(Tag otherTag) {
return name.compareTo(otherTag.name);
}
}

以上のファイルをそれぞれ app/models/ 以下に作成する。

それが終わったら、コマンドを実行する。

コマンドにはオプションがいくつかあって、それぞれ下記のような感じ。

–with-layout: 標準で用意されている main.html と Application.index を上書きする
–with-login: User class を生成し、ログイン/ログアウト機能を提供する
–include=…: View と Controller を生成する Model を指定
–exclude=…: View と Controller を生成しない Model を指定
–overwrite: 自動生成されるファイルと同名のファイルが存在する場合、上書きする

    • with-login を使う場合、Secure モジュールを有効化しておく必要がある。

$ vim conf/application.conf
module.secure=${play.path}/modules/secure

今回は --with-layout と --with-login, --overwrite を指定したが、その場合、User class が上書きされてしまう。
じゃあ User class を作っておく必要はないかと言うと、あらかじめ作っておかないと他モデルとの関連が解決できずにエラーになる。

Exception in thread "main" play.exceptions.CompilationException: User cannot be resolved to a type
at play.classloading.ApplicationCompiler$2.acceptResult(ApplicationCompiler.java:246)
at org.eclipse.jdt.internal.compiler.Compiler.handleInternalException(Compiler.java:672)
at org.eclipse.jdt.internal.compiler.Compiler.compile(Compiler.java:516)
at play.classloading.ApplicationCompiler.compile(ApplicationCompiler.java:278)
at play.classloading.ApplicationClassloader.getAllClasses(ApplicationClassloader.java:412)
at play.modules.scaffold.Generate.generateScaffolding(Generate.java:121)
at play.modules.scaffold.Generate.run(Generate.java:178)
at play.modules.scaffold.Generate.main(Generate.java:190)

また、あらかじめ作成した User class のプロパティと scaffold により生成される User class のプロパティが異なると生成される View がちぐはぐになって実行時にエラーとなる。

仕方ないので、以下の手順で解決することにした。


  • 一旦仮の User class を作成

  • scaffold のコマンドを実行して、User class を上書き

  • 再度 scaffold を実行して、Controller と View を生成しなおす

というわけで、以下の要領で二回コマンドを実行した。

% play scaffold:gen --with-layout --with-login --overwrite
% play scaffold:gen --with-layout --with-login --overwrite

アプリケーションを実行してみる前に、生成された View の JavaScript 周りにいくつか修正が必要となる。

main.html の jQuery のバージョンを修正する(1.4.2 -> 1.5.2)

$ vim app/views/main.html
<script src="@{'/public/javascripts/jquery-1.5.2.min.js'}" type="text/javascript" charset="utf-8"></script>

jQuery UI をダウンロード

$ wget http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.2/jquery-ui.min.js
$ mv jquery-ui.min.js public/javascripts/jquery-ui-1.8.2.min.js

修正が終わったら、実際にアプリケーションを実行してアクセスしてみる。

$ play run
$ open http://localhost:9000

Model のリストと、右上に login へのリンクが表示されている。

このままだと login リンクが機能してないので、ソースを一部修正する。

$ vim app/views/main.html
<span style="float:right;">
#{if session.get("username") == null}
<a href="/secure/login">Login</a> <!-- /login から /secure/login へ -->
#{/if}
#{else}
<a href="/secure/logout">Logout</a> <!-- /logout から /secure/logout へ -->
#{/else}
</span>

ブラウザをリロードして login リンクをクリックしてみる。

デフォルトでは admin/admin でログイン可能(ソースに直書きなので実利用の際は修正が必要)。

ログインすると、top 画面へ戻るが右上のリンクが logout に変わっている。

Tags をクリックすると、タグ一覧のページへ移動するがこの時点ではデータが存在しないので空の状態。

Create をクリックすると新規作成のフォームへ移動する。

項目に入力して save ボタンを押すと、リストに項目が追加されているのが確認できる。
ついでにもう一つタグを作っておいて、今度は Postsの画面を見てみる。

同じように Create をクリックし、新規作成画面へ進む。

驚くのが、postedAt にフォーカスを合わせるとカレンダーが表示される点。Rails の scaffold だとここまでやってくれなかった記憶。

あと、Author(多対一)や Tags(多対多)のフォームがそれぞれセレクトボックスになってる点。ここも、Rails だと自分であれこれいじらないといけない。

Comments と Users はだいたい同じ感じなので割愛。

使ってみて思ったのは以下の二点。


  • Rails に比べて手数が増えるのが難点

  • ログイン機能やフォームなど、欲しい機能が最初から入ってるのは便利

Modelが自動生成できて、モジュールが Play 本体に組み込まれてくれると最高なんだけどな。

定期的にやる気がでなくなる病

どうもやる気に波があって、今週頭はいい感じだったのに腸炎でダウンして回復する頃には一切のやる気がなくなっていた。

この辺り自分で制御できればいいんだけど、それやりだすとうっかり怪しい自己啓発とかの道に行きそうで怖い。サプリ的なものでなんとかならないかしら。

他人の WordPress に導入されてるプラグインを知りたい

傍目にわからないやつはともかく、例えばシンタックスハイライトとか画像系とかテーマとか「これなんだろ」ってときにわかる仕組みがあると嬉しい。

実は /plugins 辺りにアクセスするとプラグイン一覧が取得できたりしないのかしら。だめか。

テーマ変えた

エクストリームオフラインと同じテーマを使ってるサイトを見つけたので「あれ、もしかして普通に配布されてる?」ってことで調べてみたらあっさり見つかった

せっかくなので早速使ってみてる。いい感じだけど、記事の横幅が減った気がして少し微妙。あちらを立てればこちらが立たず。