Railsのフォーム検証プラグイン(Client Side Validations)を試す

モデルに設定したバリデーションをクライアントサイドで再現するClient Side Validationsを試してちょっとハマったのでメモ。

普通に使う分には下記サイトに書かれてあることを素直にやっていけば期待通りに動いてくれる・・・
https://github.com/bcardarella/client_side_validations

のだけど、自分の場合、少し普通じゃなくて検証対象のフォームがページがロードされた後に動的に出現する。
この場合、上記サイトに書かれていることをやっても期待通りに動いてくれない。

原因は動的に追加されたフォームに対してこのプラグインが提供するvalidate()が呼び出されていないためなのでフォームを追加した後に以下のように呼び出してあげれば良い。

$('form[data-validate]').validate();

ロケールに変数を使用する

ロケールファイルに変数を仕込む。形式は{{変数名}}。

# RAILS_ROOT/config/locales/ja.yml
en:
  hello: "hello {{name}}!"

ローカライズする際に変数値を渡す。変数名となるハッシュのキーは予約されている:default, :scope以外なら何でもOK。

I18n.t(:hello, :name => 'world') #=> 'hello world!'

group(ActiveRecord::QueryMethods)とsize

ActiveRecordのgroupメソッドが返すGROUP BYした結果に対してsizeメソッドを呼び出すとグループ毎の件数を返す。

# グループ毎の該当件数
Person.group(:gender).size #=> {"male" => 10, "female" => 8}

# 本当のレコード該当件数を取得するにはlengthメソッドを使う
Person.group(:gender).length #=> 18

イテレータのショートカット

Symbolを&を使ってProc化するとイテレータのショートカットなどができる。

# これを
collection.map {|member| member.id}

# このように書ける。(:idの前に&を付けて、SymbolをProc化している。)
collection.map &:id

便利だな、こりゃ。

以下を参考にしました。感謝です。
http://www.infoq.com/jp/news/2008/03/to_proc-currying-ruby19

X is not missing constant Y

Railsで階層化されたモデルの関連レコードのセッターメソッドを使用すると「X is not missing constant Y」というエラーが発生する。

# 以下のモデルがあったとして
# models/hatena/diary.rb
# models/hatena/comment.rb

class Hatena::Diary < ActiveRecord::Base
  has_many :comments
end

class Hatena::Comment < ActiveRecord::Base
  belongs_to :diary
end

# こうするとエラーが出る
comment = Hatena::Comment.new
comment.diary = Hatena::Diary.create # ここでエラー
=> ArgumentError: Hatena is not missing constant Diary!

この問題はアソシエーションの定義時にクラス名を指定すると直る。

class Hatena::Diary < ActiveRecord::Base
  has_many :comments, :class_name => 'Hatena::Comment'
end

class Hatena::Comment < ActiveRecord::Base
  belongs_to :diary, :class_name => 'Hatena::Diary'
end

日本語でルーティングする方法

メモ

# /config/routes.rb
map.connect "emails/#{ERB::Util.url_encode('下書き')}/*folders",
:controller => 'emails',
:action => 'draft',
:conditions => { :method => :get }

URLエンコードしてあげれば良いということです。