トップ 最新 追記

2011-03-06 [長年日記]

_ JavaScript Url DispatcherとかRouterについて調べた

あるいは kanazawa.js v1.0.1 勉強会 : ATND に参加してきた。(前回と同じパターンの使い回し)

なぜdispatcher(あるいは router)か

実はピンときてなかったけど、なんかこういう手法があるっぽいということだけ知ってた。

pixiv Tech MeetingでpixivのJSの話をしました

から辿れるスライドを見てなるほどなと思った。自分がいちばんなるほどと思ったのは

WAFの不自由さ

というか layout ファイルの <script> を可変にできるように仕組み用意していちいちそこに何か文字送ったりするのってめんどくさいよねというか、要するに

script loading も DRY に

ってことじゃないかな。もっかい整理すると

  • layout ファイルで JavaScript のライブラリの読み込みは共通にできる
  • でも layout ファイルの中に手を出せるのはサーバサイドだけだし、一部でだけ共通な JS ファイルの読み込みは面倒
  • 集中管理できないし、分業してると何かと面倒

という問題を解消するために dispatcher(あるいは router)が有用だよってことだね。なるほどなぁ。

いくつか見つけた

日本語で読めるものもいくつか。kayac と pixiv は手作りで、ライブラリ側にこの機能が統合されているものはまだあまり見かけない。もしかして uupaa が初めて?

kayac バージョン
pixiv バージョン

先ほどの納得のいった資料の元ですな。

uupaa バージョン

uupaa-js - Project Hosting on Google Code

jsdo.it にサンプルが載ってる。

uu.ready("href:URL Dispatcher", callback...) test code - jsdo.it - Share JavaScript, HTML5 and CSS

jDispatcher(ちょっと意図と違う)

みんな大好き jQuery の plugin であったら便利じゃねーのと思ったので探したんだけど、これは Ajax Request を飛ばすのが目的のものなので除外。

dispatch | jQuery Plugins

jQuery Router

こっちが今回の目的に合致する jQuery plugin.

複数ページの window.onload をまとめて書ける jQuery プラグインを書きました | Tanablog

jQuery Router を試す

全部のコードを晒すのもアレなので一部だけ。Ruby の WAF だとだいたいこんな感じでまとめられるはず。実際に以下のコードは Sinatra 上で動かして確認した。

これで application.js だけで必要な script の読み込みを制御できるので、サーバサイドの処理には手を加える必要がないし、分業している場合はサーバサイドの人に処理の追加を頼む必要がない。

楽ちん。

ちなみに $LAB.script() は LABjs のメソッド。

感想

個人的にはもっと Sinatra ライクな rouing ができると嬉しいと思う。正規表現のみの routing は罠にハマりやすいんじゃないかな。まぁテスト書けってことなんだろうけど、このままだとテストも書きにくい(というか書ける?)。

制御したい URL のパターンが増えたらテスト書ける router を別に探した方がいいのかもしれない。routing が一カ所に集まっていれば差し替えも楽だし。

※ 今回紹介した中では pixiv バージョンにはテストがついてる。

LABjsはこの辺参照

Loading And Blocking JavaScript だそうで。

非同期 load、同期 load を自在に設定できる便利ライブラリ。JavaScript を細かく分割して必要なものだけロードしたいなら持ってこい。つまり dispatcher, router と相性がよい。はず。

まとめ

kanazawa.js 超かっこよくてオサレなのでみんな来ればいいよ!(えー

LABjs と Sinatra で別エントリ書くと思う。

おまけ

git の bundle ファイル を上げてみた。fetch してから*1 git clone するとどんな風に作業進めたか見れるよ。

*1 bundle ファイルをただ上げただけなので直接 clone できません。


2011-03-07 [長年日記]

_ 今さらSinatra最低限メモ

今度は Sinatra. 次もすぐに動かせるように公式のドキュメントを圧縮する感じで、自分の欲しい情報だけ。アプリを書く以前のレベルで、まずはページを表示できる状態を目指す。

実は昨日の kanazawa.js の成果その2

環境

今回の環境は

  • MacOSX 10.5
  • Ruby 1.8.7
  • Sinatra 1.1.3
  • Ruby 1.9.2
  • Sinatra 1.2.0

で確認した。Sinatra のバージョンが合ってないことに特に意味はない。

インストール

(ry

動かし方

1ファイルの場合は
$ ruby app.rb

でもよい。例の感じで中に

require 'rubygems' unless defined? ::Gem
require 'sinatra'

get '/' do
  'Hello, World'
end

で終了。デフォルトで port 4567 で起きる。

ちなみにこれだけで response header とこの文字列だけの response body が返る。PHPer 的には print や echo で出力したくなるけどそれは間違い。これは

get '/' do
  return 'Hello, World'
end

の return を省略してるだけ。return が response になる。rack の header を省略できると思えばいいはず。

設定とか分離したい

rack の流儀に則って config.ru を用意(別名でもいいけど)。

config.ru

require 'rubygems' unless defined? ::Gem
require File.dirname( __FILE__ ) + '/app'

run Sinatra::Application

app.rb

require 'sinatra'

get '/' do
  'Hello, World !'
end

この場合は rackup する。*1

$ rackup

デフォルトで port 9292 になる。rack の流儀で変更可能。

$ rackup --port 80

※ ただし Un*x なシステムでは 1024 以下は特権ポート。のはず。

Handler を明示すれば option を与えられるけど、Handler を与えない方針なので以上。

自動でReload

mod_php や Rails の development 環境に慣れてしまったのでこれがないとやってられない。方法は3つ。

  • Rack::Reloader
  • Shotgun
  • Sinatra::Reloader

What happened to reloading in Sinatra 0.9.2? - Sinatra: Frequently Asked Questions

Rack::Reloader

普通の Rack Middleware

use Rack::Reloader

すればオッケー。でもちゃんと動かないらしい。動いてるように見えるけど、そうとは限らないということか。却下。

Shotgun

rtomayko/shotgun - GitHub

shotgun の名前がインパクトがあってよく覚えてたんだけど、今 Sinatra のサイトで読むといちばん遅いのと、fork を使うので JRuby や Windows で動かないとのこと。あやや。

インストールはもちろん

gem install shotgun

これは普通のアプリの起動にも使えるし、

shotgun app.rb

rackup 代わりにもそのまま使える。

shotgun [config.ru]

今度は port はデフォルトで 9393 になる。

Sinatra::Reloader
gem install sinatra-reloader

個人的には予想以上に依存が多い。

if development?
  require 'sinatra/reloader'
  Sinatra.register Sinatra::Reloader
end

で使える。Rack Middleware の要領で use ってやったら怒られた。Sinatra Extension と Rack Middleware は違うのね。

あと当たり前だけど

reloaderに関する書き換えを行うときは再起動した方がいいよ。

ディレクトリ構成とsetによる設定

project/
 ├── app.rb
 ├── config.ru
 ├── public/
 │     └── javascripts/
 │             ├── LAB.js
 │             ├── application.js
 │             ├── jquery-1.5.1.min.js
 │             └── jquery.Router.js
 └── views/
        ├── hello.erubis
        ├── index.erubis
        └── layout.erubis

Rails流とちょっと違う。

この public, views はそれぞれ以下のように設定できる。

README.rdoc

set :public, File.dirname( __FILE__ ) + '/static'
set :views, File.dirname( __FILE__ ) + '/templates'

要するにアプリケーションのファイルを基準にして自分で決めたきゃ決めろと。この設定方法は Capistrano に似てるなぁ。

何が設定できるかはここを見るといい。

Sinatra: Configuring Settings

root も変更できる。

テンプレートの選択とrender

基本系
get '/' do
  erb :index
end

こんな感じ。これで

  • index.erb を探して
  • erb でレンダリング

という意味になる。拡張子の変更はできるのかなぁ。できないような気がする。中で render メソッドを読んでるんだけど、ちゃんと追いかけると何か分かるかも。

render は最後に
erb :index

って書き方だけだと index.erb を表示用に使うよ、っていう宣言に見えちゃうんだけど、これはれっきとした render メソッドの呼び出しなので、処理はこの前に書くこと。と言うか

erb :index とかは最後に書け

の方が分かりやすいか。

erubis でHTMLのエスケープをデフォルトに

Rails 3 以降デビューなのでこれがないとやってられない。

require 'erubis'

set :erubis, :escape_html => true

get '/' do
  erubis :index
end

こんだけ。

オブジェクトの割り当て

これは Rails の View に似ていて(同じ?)、

  • インスタンス変数は直接参照可能
  • ローカル変数は明示的に :locals で割り当て

という方法を採る。

app.rb

get '/' do
  erubis :index, :locals => {:key => value}
end

views/index.erubis

<%= key %>

こんな感じで value が表示できる。

layoutファイル

layout ファイルは

views/layout.#{ENGINE}

になるはず。layout ファイルと個々のテンプレートで種類を変えることができるのかどうか分からない。たぶんしない方がいいと思う。

erubis の「エスケープしない」出力

layout.erubis

<!DOCTYPE html>
<html>
  <head>
    <meta charset="UTF-8">
    <title><%= @title %></title>
  </head>
  <body>
    <h1><%= @title %></h1>

    <%== yield %>

  </body>
</html>

こういう風にしとくと個々の

erubis :index

などの中身に HTML をそのまま書くことができる。

<%== %>

が決め手。

参考

*1 Handler を直接 config.ru に書く方法もあるんだけど、それだと環境を変えるためにはいちいち書き直さなきゃいけないから嬉しくないと思う。


2011-03-08 [長年日記]

_ 今さらRails3メモ - 番外編その2: gitに入れてないファイルの洗い出し -

  • 以下の内容を Rails.root/lib/tasks/git.rake に置く

  • Rails.root/.gitignore に cache, tmp など除外したいファイルのパターンを追加

以上。

もっといい方があるような気もするけど、今のところ満足。

rake -s git:untracked | xargs git add

とか、まとめてできる。

Tags: Ruby Rails

2011-03-17 [長年日記]

_ CentOS 5 + Rails 3 + native extensions のメモ

とても今さらな環境の話と Rails 3 が組み合わさってるけど、だからこそのメモ。

まとめ

  • 開発環境が Mac OSX 10.5 ( のちに 10.6 )
  • staging および production が RHEL 5 ( clone )

で、Rails 3, 特に面倒の多い native extension をどうするかを整理した。最終的には以下のような感じに。

ちなみに DBMS は development, test を SQLite で、それ以外を PostgreSQL で構築している。

できあがったGemfile
gem 'sqlite3-ruby', '< 1.3', :require => 'sqlite3'
gem 'rmagick', '< 2'
group :production do
  gem 'pg'
end

※ あとで気づいたけど

bundle install --without=production

すれば development 環境で PostgreSQL は要らなかった…。

OSX 10.5

MacPorts を使って必要なバイナリをインストールしている。

  • Ruby 1.8.7
  • ImageMagick 6.6.7 + rmagick 1.15.17
  • SQLite 3.7.4 + sqlite3-ruby 1.2.1
  • PostgreSQL 8.1.x + pg 0.10.1
CentOS 5

もちろん yum 管理。Ruby は endpoint の repository を使って REE を利用。

  • Ruby Enterprise Edition ( 1.8.7 via endpoind )
  • ImageMagick 6.2.8 + rmagick 1.15.17
  • SQLite 3.3.6 + sqlite3-ruby 1.2.1
  • PostgreSQL 8.1.x + pg 0.10.1

cf.

補足

Ruby 1.8 なら RMagick 1 を入れられる
  • ImageMagick 6.3.0 で新機能が加わった
  • RMagick 1 は 6.3.0 の新機能が必要なければ使える
  • RMagick 1 は Ruby 1.9 はサポートしていない

ということで production で Ruby 1.8 を使う場合、開発環境では rvm で 1.8 を使うことで RMagick 1 をインストールして動作を合わせることができる。最近の開発環境はたぶん Ruby も ImageMagick も工夫しないと新しいものが入ってしまうので注意が必要かも。

今回のケースでは RHEL 5 clone で欲張って Ruby 1.9 を使おうとしてしまった場合にはややこしいことになっていた。

cf.

Which version of RMagick is right for me? - RMagick Download Page

RMagick は root 権限が必要で bundle install できない?
  • /usr/share/RMagick とか /opt/local/share/RMagick にファイルを起きたがるため root 権限が必要で bundle install に失敗する
  • でもここでインストールするものはドキュメントだけ
  • 一度 bundle じゃなくて yum なりで ImageMagick をインストールする、手でディレクトリ掘るなどして permission 周りの問題を解消しておけば gem については root 権限なしで全部 vendor 以下に入れられる
MacPorts には postgresql-devel ないけど?

エラーメッセージを読んだり pg の README.OS_X を読めば分かるけど

--with-pg-config

で pg_config を指定してやれば ok.

自分の場合は

/opt/local/bin/pg_config -> /opt/local/lib/postgresql81/bin/pg_config

と link を張ってごまかした。


2011-03-25 [長年日記]

_ Rubyのif式で気づいたこと

安心してください。とても今さらな話です。

jpmobile を読んでいたら if も式だと

今日 jpmoile 1.0.0.pre を読んでいてふと

lib/jpmobile/mailer.rb

@mobile = if tos.size == 1
            # for mobile
            (Jpmobile::Email.detect(tos.first) || Jpmobile::Mobile::AbstractMobile).new(nil, nil)
          else
            # for multi to addresses
            Jpmobile::Mobile::AbstractMobile.new(nil, nil)
          end

こんなコードが目に留まった。

あーそうか。

Rubyは制御構造も式です

ってこういうことか。あまり意識してなかった。式とか文とか普段あまり意識してなくて、

基本的には値が返るので return を省略できる

程度にしか覚えてなかった。

Ruby は条件演算子をかっこよく書けないけど問題にならない

※ 実際に気づいたのは 4/5 のこと。

PHP を書いているときによく

function funk() {
  return ( condition )
    ? val1
    : val2;
}

と、いわゆる三項演算子、厳密には条件演算子を使って if 文を書かずに済むなら書かないようにしていた。そうでないと

function func() {
  if ( condition ) {
    return val1;
  } else {
    return val2;
  }
}

と書かねばならず*1、とても記述量が増えてしまうから。後置 if も使えないし、とにかく短く書けない PHP での必死の抵抗として条件演算子にはとてもお世話になっている。この場合は単に return するだけなのでそうでもないが、例えば

var = ( condition )
        ? val1
        : val2

となると、もはや条件演算子を使わずにスッキリ書くなど不可能と言ってよい。

ところが Ruby では逆にこの条件演算子を気持ちよく書きにくい。というのも

? を次の行に下ろすことができない

から。なんと syntax error になるのだ。そうすると

( condition ) ?
  val1 :
  val2

こう書くのか。しかしこれではとても読みやすいとは言えない。実はこれずーーっと困ったなぁ思っていたんだけど、上のように

var = if ( condiition )
        val1
      else
        val2
      end

と書けるんならこれでいいな。いやはや、式とか文とかあまり興味ないんだけど、ちゃんと分かってないとダメだなぁ。

Tags: Ruby

*1 ブレースは必ず書く派なので書いてあるだけ

本日のツッコミ(全1件) [ツッコミを入れる]

_ lol [<script>alert("HelloWorld")</script>]


2011-03-27 [長年日記]

_ kanazawa.js v1.2 に参加します

kanazawa.js v1.2 セミナー : ATND

基本はもくもく会スタイルで勉強している kanazawa.js ですが、今回はセミナー形式ということで

Firebugの使い方を中心にそもそものWebの基礎的な内容

で発表を行う予定です。JavaScript に限りません。

正直自分もフロントエンドの話はもうずいぶんご無沙汰なので Firebug もそれほど使い込んでいるわけではないのですが、何ができるか、言い換えると

どんな働きをさせることが大事だとFirebugや開発者向けツールの作者たちは考えているか

に思いを寄せることができればいいなと考えています。

4/16(土)会場でボクと握手!