Zen-Coding + Eclipse を導入する
posted at 2010-02-18  [ ]

昨夜、「Ustreamで生Zen-Codingやってみましょうか」という内容がTwitter上で賑わっていました。

Zen-Codingってなに?

HTMLとCSSを効率良く記述するためのスニペット生成マクロです。効果の程については、まずこの動画を見てもらえればわかると思います。

Zen Coding v0.5 from Sergey Chikuyonok on Vimeo.

こういう手法はEmacs使いの人には馴染み深い物と思います。過去にはRuby on RailsのデモがTextMateを使って、上記のようなコーディング動画を配信されていました。私もその当時、TextMateいいな!と思って導入しましたが、日本語対応がうまくできず、EclipseベースのIDEに戻りコード補完をガシガシ使ってコーディングしてきました。

Zen-Codingはどうやって使うの?

現在ですと、Aptana, NetBeans, Coda, Espresso, TextMate, VisualStudio, Dreamweaver CS4とクロスプラットフォームで使用できます。これは素晴らしいことですね。私は現在、Eclipse + PDT + Aptanaという開発環境で諸々の言語を使用していますので、今回はEclipseで使うための方法について補足したいと思います。

前提として、EclipseMonkeyというプラグインが必要になります。これはEclipse上で動かせるマクロを作成するためのプラグインです。マクロは標準ではJavaScriptで記述することになっており、Rubyで書いたりもできるようです。Zen-CodingはJavaScriptで記述されています。

Zen-Codingを導入する前の準備

公式サイトにてインストール方法が紹介されています。まずは、Installingの手順に従ってAptanaのインストールとEclipseの再起動までを行いましょう。インストール時に依存関係を追って、一通りのツールがインストールされます。

その後、Zen Coding for Aptana v0.6 をダウンロードし、中のファイルすべてを以下の画像のように配置します。

image

新規プロジェクトで一般のプロジェクトを作成した後、scripts/libというディレクトリを作成しています。すると、メニューのスクリプトに「Zen Coding」という項目が現れます。早速、デモのように適当なHTMLファイルを作って試しましょう!Expand Abbreviation という項目がスニペット展開を行ってくれます。快適です。

Zen-Codingのショートカットキーをカスタマイズ

image

ショートカットキーをカスタマイズするには、まず該当するマクロのファイルを開きます。5行目にKeyという内容があるので、そこを編集します。M3って何だ?と思うかと思いますが、以下のような対応になっています。

  • M1->コマンド(Mac)
  • M2->Ctrl
  • M3->Alt or Option(Mac)
  • M4->Ctrl(Mac) 上記画像の設定だと Alt + E で Expand Abbreviation が実行されるということになります。

    ショートカットキーが動かない?

    Eclipseデフォルトのショートカットキーと競合している可能性があります。ウィンドウ->設定->一般->キーで競合しているショートカットキーを探し、別なショートカットキーを割り当てるか、コマンドのアンバインドで削除します。ちなみにフィルターのところで Ctrl+Shift などと入力するとCtrl+Shiftから始まるショートカットキーを探すことができて便利です。

ここまでできれば、快適なコーディングライフの歩みを一歩進めることができるでしょう。逆にZen-Codingの内容を参考にして、よく使うスニペットマクロを作成して行くと、楽しみが広がってくると思います。

[Rhaco]時間がない人のためのアプリケーション日本語化メモ
posted at 2009-12-21  [ ]

Rhacoは国際化機能も持っています。
setup画面のi18nメニューから自分で用意したテンプレートを利用することも可能なようです。

とはいえ、Viewsを拡張して作った部分をとりあえず日本語化したい人(というか自分)へのメモ。
これでvalidate後のメッセージなども日本語化されます。
以下の手順はRhaco本体をローカルに取得済みとします。

・Rhaco本体のresources/setup/po/message-ja.potをアプリケーション側のsetup/poに配置
・Rhaco本体のresources/locale/messages/message-ja.phpをアプリケーション側の同ディレクトリに配置
・アプリケーション側のindex.phpで以下の2行を追加

Rhaco::import("resources.Message");
Message::loadMessages("ja");

試しにconfirmedCreateで作成したフォームや一覧などで英語表記だった部分が日本語になっていればOKです。本当にとりあえずなので、エラーメッセージのカスタマイズ時の手順は、

POTファイル編集->setupのi18nからPHPファイル生成

となります。あまりにあっけなく終わりましたが、こういうのが嬉しかったりします。

[OSX]NetBeansからsvn+sshでリポジトリにアクセス
posted at 2009-11-18  [ ]

ここに手順はありますが、解りづらいので自分でググって辿っていきました。

まずコマンドベースでsvn+sshできるところまで

さくらインターネットの場合、SSHログインの際に$PATHに読み込まれるパスにユーザ制限がかけられるそうです。
よって、任意に配置したプログラムについては、 $HOME/bin へシンボリックリンクを貼っておく事で
問題を解決できます。
私の場合は、svn関連のコマンドは $HOME/local/bin に配置されていますので、以下の手順になりました。


% ln -s $HOME/local/bin $HOME/bin

続いて、リポジトリの初期化を行います。Berkeley DBは使用していないので、ファイルシステムにFSFSを
利用することとします。


% mkdir -p $HOME/svn/repos
% svnadmin create $HOME/svn/repos --fs-type fsfs

クライアント側で鍵認証のための手続きを行っていきます。
公開鍵を作成し、サーバ側に配置。その後、パスフレーズのスキップまでをついでに行います。
初期ディレクトリは /Users/ とします。


$ ssh-keygen -t rsa #パスフレーズを聞かれるので、入力しておきます。
$ scp .ssh/id_rsa.pub  @.sakura.ne.jp:.ssh/id_rsa.pub

#続いて、サーバにSSHログイン
% cd .ssh
% cat id_rsa.pub >> authorized_keys
% chmod 600 authorized_keys
% rm id_rsa.pub

#ここからクライアント側
$ ssh-agent bash
$ ssh-add
$ ssh -l username username.sakura.ne.jp

これでパスフレーズの入力なしでログインできたらOKです。

NetBeansからsvn+sshでリポジトリにアクセスする

NetBeansのバージョンは6.7です。まずはローカルのsvnクライアントについて設定を加えます。
/Users//.subversion/config を編集。
[tunnels]の項目で

ssh = ssh -l username

を追加。
NetBeansからのインポート、コミット時などのメッセージで日本語があるとエラーが表示されるので、
/Applications/NetBeans/NetBeans 6.7.1.app/Contents/Resources/NetBeans/etc/netbeans.conf
を編集し、netbeans_default_optionsの最後尾に以下を追加。

-J-Dfile.encoding=UTF-8

次に、
/Users//.subversion/config を編集。
[miscellany]の項目で

log-encoding = utf-8

と編集。

その後、NetBeansを再起動。
[チーム] -> [Subversion] -> [リポジトリにインポート]

リポジトリURLの項目に

svn+ssh://username.sakura.ne.jp/home/username/svn/repos
トンネルコマンドの項目に

ssh -l username

これでリポジトリにプロジェクトがインポートされます。
他に注意するのは、日本語のファイル名を持つファイルです。
ファイル名自体がUTF-8となっていないと、コミット時にエラーとなります。

私はDreamweaverを使ってないのですが、これでDreamweaverからもリポジトリにアクセス
できるはずなので、協業の際には役立ちそうです。
#Dreamweaver CS4からsvnクライアントの機能があり、svn+sshにも対応しています。

参考

  • [ssh] さくらサーバでsvn+sshを利用する方法(Linux/Mac)

さくらインターネットで今更subversionをインストール
posted at 2009-11-17  []

すでにgitでプロジェクトのソースを運用していましたが、以下の理由でsubversion(以下、svn)を
インストールすることに。

  • 個人かつ一人での開発がほとんど
  • デザイナーにバージョン管理を進めたいのだけど、IDEに統合されてるのはsvnが主流

というわけで、さくらインターネットのサーバにインストール。
今回インストールするバージョンは最新の1.6.6。以下、注意点。

  • deps(依存関係にあるパッケージをまとめたもの)を解凍するとsvnのソースディレクトリ内に展開されるので、面倒が少なくなる。
  • svnのバージョンが1.4.xあたりだと、自分でaprなどのパッケージをインストールしていかないといけない模様。
  • また、その場合はaprのバージョンが0.9.xか1.xかでも分かれる。

  • httpでリポジトリにアクセスするためにserfかneonのどちらか一方が必要だが、今のsvnはdefaultでneon。
    configure時に–without-serfを今回はつけた。
  • configure時にBerkeley DBが入ってないと警告がでるけど、そもそもオプションのパッケージなので無視でOK。
  • 結局のところ、各詳細はINSTALLを読めばOK。(英語やだとか言うんじゃありません)

インストールまでのコマンド


% wget http://subversion.tigris.org/downloads/subversion-1.6.6.tar.gz
% wget http://subversion.tigris.org/downloads/subversion-deps-1.6.6.tar.gz
% tar xvfz subversion-1.6.6.tar.gz
% tar xvfz subversion-deps-1.6.6.tar.gz
% cd subversion-1.6.6
% ./configure --prefix=$HOME/local --with-ssl --without-serf
% make all install clean

参考

Shadowbox.jsをAjax.Updaterと併用する
posted at 2009-10-29  [ ]

Lightbox系のライブラリとして任意のJavaScriptライブラリを使ってもOKなShadowbox.js。
非常に便利でおすすめ。私はprototype.jsをよく使うのでそれと併せています。jQuery対応のものばかりで肩身が狭いですが。

Shadowbox.jsの仕様として、下記のようにheadタグ内のscriptタグで初期化する必要があります。

//日本語表示、画像とHTMLをレンダリング対象とする
Shadowbox.init({language : "ja", player: ["img", "html"]});

このためAjax.Updaterなどで部分的に反映された要素はShadowbox.jsのイベントハンドラ登録が行われていない状態です。

そこで、下記の要領でAjax.Updaterを使用後に再度イベントハンドラ登録を行うと要素の更新後もShadowbox.jsを利用できます。

私の場合はForm.EventObserverと併用しているので、その中でcallしているAjax.Updater内に記述しています。

new Ajax.Updater(id,
	url,
	{
		asynchronous:true,
		evalScripts:true,
		onComplete:function(request){
			//その他の処理
			//最後にイベントハンドラの登録をし直す
			Shadowbox.setup();
		},
		onLoading:function(request){
			//その他の処理
			//現在のイベントハンドラをすべてクリア
			Shadowbox.clearCache();
		},
		parameters:value
	})

prototype.js以外のライブラリを使用している場合も、同様にonCompleteやonLoadingに相当するイベントにフックさせれば大丈夫だと思います。

参考:

Shadowbox.js API

追記 2010.01.04

IE6, IE7の場合、Shadowbox.clearCache()を呼ばず、Shadowbox.setup()のみ呼び出すと
正常に動きます。原因はソースを追ってみないとわかりませんが、とりあえず。

また、Shadowbox.setup()の呼び出しタイミングはCGIから返されるHTMLの末尾でscriptタグ内に記述した方が良いです。
DOMのロードとJavaScript実行のタイミングを調整するためです。

[Rhaco]viewでPHPコード埋め込みがうまく動かない場合がある
posted at 2009-09-03  [ ]

相変わらずRhacoで現プロジェクトの開発をぼちぼち進めている。

Rhacoのレンタルサーバでも大丈夫!というポリシーは素晴らしい。
専用サーバやVPSを提案しなくとも良いので、運用費がコストダウン。

今、開発で困っているのがviewへのPHP埋め込み。
下記のような状況でだけ、うまく動いたり動かなかったりする。

<a href=”<?php H::linkTo(‘hoge’) ?>”>どっかにリンク</a>

Hはhtmlヘルパークラスへのショートカットで、linkToメソッドは引数を受け取って、各アクションへのURLを生成する。

ググっても、なかなか情報がない。after railsならフレームワークだとしたら、上記のような書き方は真っ先に試しそうなものなのだけど、そうでもないのだろうか?

Rhaco UrlsとFlowを利用して他クラスのメソッドを呼び出すときの注意事項
posted at 2009-08-20  [ ]

Rhacoを使って開発してるのだけど、細かな情報はまだまだ把握しきれてないので手探りが多い。
自分用のメモ。

index.phpでやること

  • generic.Urlsのインポート
  • urlパターンの定義
  • 取得したparserでの実行

$parser = Urls::parser($pattern);
$parser->write();

他クラスでやること

  • extends TagParse
  • flowでテンプレートと変数を定義
  • $flow->parser()みたくparserを返す

IE7でAjaxのその後
posted at 2009-06-27  [ ]

前回のエントリでIE7でAjaxリクエストの挙動がローカルとリモートで異なる件に触れた。

で、その後の調査結果。
IE7でJavaScriptを含んだプログラムを動かすと、ActiveXコントロールを含んでいるけど大丈夫?というポップアップがブラウザ上で表示される。動いてくれないと困るので、「はい」と答える。これが落とし穴。

この時点でActiveXObjectを使って動く前提とブラウザは思いこんでしまう模様。にも関わらず、XMLHttpRequest判定を前に持ってきているので、そっちでリクエストを投げようとするのが不整合の原因のようだ。

そう、つまりリモートにコンテンツを配置した場合はXMLHttpRequestで扱うとブラウザが思ってくれるので、エラーはでなくなるということだろう。うん、やっぱりXMLHttpRequestに統一してくれとして言えない。

ここからは最近なんとなく思うこと。Ajaxってもう、終わりな気がする。というかHTMLで何でも表現するのはいい加減限界だし、DojoやExt.jsのようなリッチUIを用意するのもブラウザ互換吸収とかで苦労するし、無理がきていると感じる。
なのでUI部分をFlashにという流れが今は主流なのだけど、コントロールの出来でいったらSilverlightのが上だろと思うので、棲み分けを作る側が理解して使い分けるのが正解なんだという当たり障りのない結論に落ち着いた。

とりあえず、業務アプリのUIはSilverlightでいきたい。今はまだFlashかなと思う。後々の浸透度次第か。

IE7でローカルからXMLHttpRequestを使うとエラー?
posted at 2009-06-19  [ ]

ActiveXObjectの判定タイミングは前か後か?

とある案件でここと同じであろう現象に遭遇。
IE7からXMLHttpRequestとActiveXObject両方に対応するようになっており、ActiveXObjectの判定は後ろに持っていくべきと言われている。

が、実際のところローカルで実行するとXMLHttpRequestの判定は通るけれども、GETリクエストを投げたところで「アクセスが拒否されました」というエラーが。これはバグと言いたい。

で、結局ActiveXObjectの判定を前にもってくることで解決。腑に落ちない。


        if (window.ActiveXObject) {
            req = new ActiveXObject("Microsoft.XMLHTTP");
            if (req) {
                req.open("GET", url, false);
                req.send();
            }
        } else if (window.XMLHttpRequest) {
            req = new XMLHttpRequest();
            req.open("GET", url, false);
            req.send(null);
        }

ちょっとしたテストをすると、XMLHttpRequestでもActiveXObjectでもtrueとIE7はなる。うーん、善し悪しだこれは。
そうじゃない、ちゃんと仕様を統一してください。
ちなみに、上記の修正を行う前にはFirefoxとChromeは問題なし。IE7とSafariはNG。

やはりいらない子なのか。

とある案件のクライアントは、それまでIE6を使用していたことを考慮すると、IE7の使用率が増えたことでこういった不具合が起きている可能性があるかもしれない。この案件のリリース時はIE7対応しないという契約だったので、よくよく考えてみればこれって、有償にしていいんじゃないか?

冗談はさておき、ブラウザのバグとか仕様解釈の違いをこれだけシェアの大きいソフトウェアで製作者に押しつけたままというのは不満。だけど、それもプログラマの仕事という事実なのは否定できない。

jQueryベースのフォーム入力チェックを実装中
posted at 2009-04-23  [ ]

CSS-Nite Aomoriで5分プレゼンを行うので、その準備中。
それと並行して、自分のサイトをWordPressベースで作ってみた。というか、テーマとして作るという宿題がほったらかしだったという。

で、RubyでYAML形式の定義を元にFormを自動生成したくて、ちまちま書いているのだけど、せっかくだしvalidationはjQueryで作ってみることにした。巷にあふれているものではあるけど、自分の勉強がてらだ。

jQuery自体はバージョンいくつの頃だろう・・・だいぶ前に、prototype.jsとjQueryどちらをベースにしていくか?というテーマがプロジェクト内であって、jQueryの挙動が気に入らず、prototype.jsでいくことに。Railsもprototype.jsが前提なんだけど、あまりにjQueryの名前を聞くようになったし、今だと良くなってるのかもね?と思って使ってみた。バージョンは1.3.2。

 確かにCSSセレクタを使ってDOMにアクセスできるのは快適だし、直感的に書けるコードも多いのだけど、ちょっとHTMLやセレクタが複雑になってくると、思うように要素がとれなかったり、Arrayで値が返ってくるのかjQueryオブジェクトが返ってくるのかがまちまちだったりと、複雑なことやろうとすればするほど、DOM直接いじってる方が楽だな・・・とか思ってしまう。正しい使い方ができてないのだろうか?

$の挙動からいけば、やはりprototype.jsが自分には合っているようだ。というか、まずブラウザ側の挙動を統一してほしい。それに尽きる。挙動の違いを吸収してほしくて、javascriptフレームワーク使っているようなもんだし。今更すぎる内容だけど、改めて使ってみても、やはり思うことは同じだったりする。

となると、棲み分けなのだろうという結論。すでに固定のHTMLがあって、それに対して簡易的なエフェクトやDOM操作を行うなら、jQueryは非常に効率的だと思う。逆に何らかのデータフォーマットやHTTPレスポンスを元にHTML生成したりと、動的な実装をしたいのであればprototype.jsかなと思う。

エフェクトやGUIなどオールインワンのライブラリを求めるなら、Ext.jsかDojoあたりなのだろうか。思い立つことがあれば、今度はそっち側を試してみようと思う。

gitignoreにファイルを追加する方法
posted at 2009-04-20  []

.git/info/excludeにファイルパターンを記述する

EclipseとかAptanaを使ってると.settings, .loadpath, .projectとかが邪魔なので追記必須かな。
特定ディレクトリ以下のファイルのみだと、logs/**/*とかでいける模様。

git on さくらインターネットに移行してみた
posted at 2009-04-03  []

もともとXREAを自分のサーバとして利用していたのだけど、さくらインターネットに引っ越しをした。
それまでは、svnでソースを管理していたのだけど世間の流れに乗ってみようとgitを使ってみる。 

手段のために目的を変えるのはプログラマにはよくあることだと思う。勝手な偏見。というか自分がそうだ。
早速、先達の後を追ってgitの環境を構築。あっさり。素晴らしい。svnもめすぎ。

で、TortoiseGitの人柱になろうと思って導入したけど、どう見てもコマンドの方が楽です本当にありがとうございました。
いや、使いこなせてないだけだと思う。本当に。git-svnはさくらインターネットへの svnインストールのめんどくささから断念。
それまでsvnで管理してたものを切り離し、今後も開発が続いていくものだけをピックアップしてgitに移行。

それぞれのプロジェクトでちまちまコマンド打ってられないので、簡単なシェルを作ってさくさく。
私はWindows使いなのでcygwinですべての作業を行った。 
今月に開催されるCSS Nite Aomori でしゃべることになったので、そこで使おうと思っているネタをgit管理で作ろうと画策。
予定は未定なので、とりあえず言うだけにしておこう・・・ 

先月のRuby勉強会@青森でしゃべってみたりと、ちょっとずつ表に顔を出し始めている。
参加された方に少しでも意味のある内容になればと思うばかり。 
世の中の最前線で開発するプログラマ達に比べれば、自分のは稚拙な内容だと思うのだが、最終ビジョンが「町の IT屋さん」と思い描くようになってからは、プログラミングをしない、知らない人たちに対して、どうやったら自分たちの世界に対して敷居を下げつつ、楽しさとおもしろさ、便利さを伝えられるだろうかと考えている。

そのために自分の技術力の低さにへこむこともあるのだけど、技術は磨くのみだし、自分だけ満足してちゃもったいない。
基本、おせっかいなので地道にやれることをやっていきたい。 

なんか最後は日記的なひとりごとになってしまった。とりとめないので、今日はここまで。

PDO For WordPressインストールでハマる
posted at 2009-03-23  [ ]

レンタルサーバにWordPressをインストールというのはよくある話だけど、
SQLiteで動かそうとしたら、予想外に大ハマり・・・

というわけで、作業メモ。

環境:
PHP 5.1.6
WordPress 5.7.1
PDO For WordPress 1.0.2

こちらを参考にさせてもらいつつ作業するも、なぜか画面が真っ白。
結局、PDO For WordPressのソースをさらに追ってみる。

こんな長時間のprintデバッグとか久し振り。
で、原因はここ。

line 206 on wp-content/pdo/driver_sqlite/pdo_sqlite_driver_create.php

//need this line to comment out.
//$this->_errors[] = preg_last_error();

preg_last_error() >= PHP 5.2.0
というわけで、5.1で未対応のメソッドを呼び出していたためにDBの初期化で停止していた模様。
ものすごい時間かけたわりに作業が1行いじっただけとかよくある話ですけどね。

cygwinからmanage.pyを起動できない
posted at 2008-07-11  [ ]

だいぶブログがご無沙汰でした。コーディングでのインプットと人と会うことがメイン業務でブログをまた怠け・・・なんでもないです。

現在、とあるWEBアプリのプロトをDjangoで開発中。といっても、Djangoに慣れようとしているところ。そもそもPythonが初めてですが、Rubyやった後だと違和感少ないですね。

現象


>python manage.py validate

Traceback (most recent call last):
  File "manage.py", line 2, in ?
    from django.core.management import execute_manager
ImportError: No module named django.core.management

原因

cygwinでインストールしたPythonとWindowsバイナリとしてインストールしたPythonどちらを呼び出すべきかわからなくなっていた

解決策

WindowsバイナリのPythonを利用することにし、cygwinからPythonをアンインストール

初歩的なミスを・・・

Rails 2.1のnamed_scopeが良すぎる件
posted at 2008-06-05  [ ]

いつの間にかRuby on Rails 2.1がリリースされていました。
これは試さねばと、gem update rails -yと実行するとrails 2.1.0がお目見え。とりあえず、他のリリースノートを見ていくと、named_scopeという新機能。・・・こ、これは!

さようならbuild_condition

私の場合、これまでは検索条件は各コントローラでbuild_conditionというメソッドを用意し、そこで管理するという実装ポリシーでした。例えばこんな感じ。


def build_condition
    conditions = Array.new
    if (params['price'] && params['price'] != '')
        conditions << "products.price < '#{params['price']}'"
    end
    conditions.join(' and ')
end

まぁ、複数条件を指定したい場合や、修正箇所を1か所にできるなどを考えて、美しくないと思いながらもこのような実装をしていました。このコードは例えば任意の価格未満の商品を探すといったものです。
しかし、実際は10,000円未満の商品は?といった探し方、つまり価格帯で探すのが、世のオンラインショッピングにおけるUIパターンの基本です。

10,000円未満の商品が欲しい

この要望をnamed_scopeによって実現します。まずは、model/product.rb


named_scope :below_10000, :conditions => ["products.price < 10000"]

#controllers/products_controller.rbでの呼び出し
@products = Product.below_10000

商品名でキーワード検索したい


named_scope :by_keyword, lambda {|*args|
    {:conditions => ["products.name like ?", '%' + args.first + '%']}}

#controllers/products_controller.rbでの呼び出し
@products = Product.by_keyword("Rails")

デフォルトの並びは商品の新着順にしておきたい


named_scope :o rder_default, :o rder => "products.created_at desc"

#controllers/products_controller.rbでの呼び出し
@products = Product.order_default

10,000円未満の商品を新着順に並べたい


@products = Product.below_10000.order_default

す、スマートすぎる・・・MVCアーキテクチャにおいて、知りあい関係をどう分担するかが肝となりますが、RailsにおけるModelはO/RマッピングにおけるEntityつまりDB上の1テーブルに対する実態とDAOの基本機能という存在でした。
結局のところ、検索・登録・更新・削除といった基本メソッドをもったところで、サービスの中心である「検索条件」という点についてはコントローラ側の役割と私は解釈していました。

しかし、これでControllerの役割であるユーザ入力からModelへのデータ引き渡しという本来の姿により近くなることができました。Modelの役割が増えたと考えるか、DAOとしての機能がModelに収まるので分業化が楽と考えるかはMVCアーキテクチャに対する解釈によりけりでしょうね。
ただ、実装側からすれば、より直観的な方法で実装できる分、嬉しいですね。

#2008/06/06 追記
orderに関する記述とconditionsに関する記述の順番が入れ替わっても平気だった


@products = Product.order_default.below_10000

ここはLinqより頭いいです。素晴らしい。

#2008/06/08 追記
:includeと:conditionsが併用できました。申し分ありません。


named_scope :by_genre, lambda {|*args|
    {:include => [:genres], :conditions => ["genres.uri = ?", args.first]}}

ほぼ完全にSQLをcontrollerに記述しなくてよいです。modelはDAOとvalidationがメインということで大分すっきりしました。