--- layout: old_post title: Railsでお馴染み37signalsのURLが凄い件について permalink: /tatsuya/show/247-rails-37signals-url ---

37signalsのBlogはURLが凄い変だなー、どうやって実装してんの?とか思ってた。

例えば: http://www.37signals.com/svn/posts/247-calling-all-basecamp-customers-in-nyc-or-chicago

これどうやってるの?わざわざidを変換するメソッドとか実装してるの?とか思ってたら、こういうことだったのか!凄い!
Riding Rails: How to get more literal URLs and still use IDs
Obie Fernandez : Weblog : Ruby on Rails and More...

どうもRailsがidを得るときにto_paramメソッドを使っていることを利用してるみたい、↑のBlogを参考にしつつ試してみる。

to_paramメソッドを上書き

まず目的のクラスでto_paramメソッドを上書きする。id+"好きな文字列"を返すよう変更すればOK

def to_param
  "#{id}-#{title.gsub(/[^a-z0-9]+/i, '-')}"
end

英語はこれで良いけど、問題は日本語のタイトルをどうURLにするか?全角からローマ字に変換するライブラリを探そうかと思ったけど、めんどくさいので英語だけ抜き出してとりあえず適当に作ってみる。

class Post < ActiveRecord::Base
  ..........
  def to_param
    title_english = title.gsub(/([a-z0-9]*)([^a-z0-9]*)/i, '\1 ').downcase
    new_id = "#{id}-#{title_english.gsub(/[^a-z0-9]+/i, '-')}".chomp("-")
    return new_id != "#{id}-" ? new_id : id
  end
end

各記事へのLinkをチェック

RailsがURLを作るときにto_paramメソッドを呼ばせる必要があるのでlink部分をチェック。サイドバーの記事一覧とか、RSSの各記事へのリンクとか。

<%= link_to "link", :action=>"show", :id=>@post.id %> #誤:これだとpost.idの値がそのまま入る
<%= link_to "link", :action=>"show", :id=>@post %>    #正:post.to_param がidの値として入る

さあこれで各記事へリンクがhttp://blog.tkmr.org/tatsuya/show/194じゃなくて
http://blog.tkmr.org/tatsuya/show/194-rails-acts-as-taggableみたいになる。

でもそれだとPost.find(id)を修正しなきゃ

と思ったんだけど、RailsはInt型のカラムへ文字列の値を渡した場合、型変換のためにto_iメソッドを呼ぶらしい。そしてRubyのto_iメソッドは文字列を左端から見て数字以外に当るまでを数字として解釈する。本当!?

?> post.title
=> "Subversionで\"already under version control\"が出たら"
>> post.to_param
=> "16-subversion-already-under-version-control"
>> post.to_param.to_i
=> 16
>>

>> Post.find("16-subversion-already-under-version-control")
=> #<Post:0x38496f0 @attributes={"body"=>"<p>subversion</p><br
本当だ!find成功してるw!

ということで実装終了、実質書いたのはto_paramメソッド3行だけ。結果としては

scaffold_resourceでRESTfullなRailsアプリ(2)
http://blog.tkmr.org/tatsuya/show/245-scaffold-resource-restfull-rails-2

今更ながらRails1.2の変更点とか翻訳してみた
http://blog.tkmr.org/tatsuya/show/239-rails1-2

XML-RPC/weblogUpdates.pingを実装してみる
http://blog.tkmr.org/tatsuya/show/200-xml-rpc-weblogupdates-ping

URLは数字が良いかこれが良いかは議論の余地があると思うし、タイトル変更すると記事のURLが変わるのは致命的だとも思う。まあでも数字で始まる文字列ならto_iで同じ結果になるのでアプリケーション的にはOK。

http://blog.tkmr.org/tatsuya/show/200-tatoeba-konnna-url-demo-daijo-bu-daaaaaaaaaaaaasu

またGoogle対策やSEO的にもURLにキーワードが含まれるのは良い・URLは人間が見る物だから視認性が良い、とかっていう意見も出ているみたい
厳密に言うとURLが変化する可能性があるってのはw3cとか的にNGかも。まぁなんでも良いや。