Rails 2.1 リリース
Rails 2.1の安定板がリリースされました。新しい機能はこんな感じとのこと。
ぱっとみで「おぉ」って思ったのは2つ。
マイグレーション番号がタイムスタンプに(UTC-based migrations)
Instead of the migration file being named 001_one.rb it now has a more unique prefix that will less likely conflict with another migration somebody else happened to check-in around the same time.
そうそう。似たような場合で、別々のブランチで開発している場合とかも、マイグレーションファイル作成時にIRCで全員に確認しなきゃいけないことが多い。で、ブランチと同時にトランクにもコミットして個々のブランチにも反映してもらうみたいな。
タイムスタンプで管理できればこの問題はなくなるかなー。少なくとも、ファイル名が衝突してバージョン管理できないってことはなくなる。
Named scope
has_finderを取り込んだ。本家の説明をみると、こんな感じで使える。
class User < ActiveRecord::Base named_scope :active, :conditions => {:active => true} end # Standard usage User.active # same as User.find(:all, :conditions => {:active => true})
ブロック使えば、もっと便利。
class User < ActiveRecord::Base named_scope :registered, lambda { |time_ago| { :conditions => ['created_at > ?', time_ago] } end User.registered 7.days.ago # same as User.find(:all, :conditions => ['created_at > ?', 7.days.ago])
スコープそのものでも扱うことができる。
# Store named scopes active = User.scoped(:conditions => {:active => true}) recent = User.scoped(:conditions => ['created_at > ?', 7.days.ago) # Which can be combined recent_active = recent.active # And operated upon recent_active.each { |u| ... }
うひゃーこれは便利だ。よく使用する検索って、モデルに定義してないと、DRYじゃないから、いちいちメソッド化しなきゃいけなくて面倒だった。
has_finderも知らなくて自分で簡単なやつを作って使ってました。必要なのは、大抵find, find_by_id, count なので、そこにしか対応しないっていう、今思うと、なんとも微妙。method_missing使えば他のfind_by_xxxにも対応できたな〜。
module ActiveRecord class Base # scoped_finder :except_deleted, :conditions =>"company_tags.approval_status != 0" # # Above definition defines following class method in the class # # def self.count_except_deleted(*args) # with_scope(:find => {:conditions =>"company_tags.approval_status != 0"}) do # count(*args) # end # end # def self.find_except_deleted(*args) # with_scope(:find => {:conditions =>"company_tags.approval_status != 0"}) do # find(*args) # end # end # def self.find_by_id_except_deleted(*args) # with_scope(:find => {:conditions =>"company_tags.approval_status != 0"}) do # find_by_id(*args) # end # end def scoped_finder(method_name, options = {}) %w(count find find_by_id).each do |n| instance_eval <<-DEFINE def #{n}_#{method_name}(*args) with_scope(:find => #{options.inspect}) do #{n}(*args) end end DEFINE end end end end