default_scopeは便利ですね。
以下のような単純な記述で、デフォルトではヒットしない隠しデータを用意することなどができます。
class Prefecture < ActiveRecord::Base # 47都道府県に加えて「未開の地」を定義して、それはis_displayed=0にしておく! default_scope where(:is_displayed => true) end Prefecture.all # 未開の地はとれない Prefecture.unscoped.all # 全部とれる
しかし、単純にこれだけだと、belongs_toしたときも隠されてしまうので、未開の地にすんでいるユーザは困ってしまいます。
class User < ActiveRecord::Base belongs_to :prefecture end user.prefecture # もしprefecture_idが未開の地の場合、nullが返る
これを解決する方法は、そのまんまStackOverflowに書いてある訳ですが、今回はこれを簡単に使えるメソッドを作ってみました。
以下をApplicationModel(各モデルの抽象クラス)に定義しておけば、
class << self def belongs_to_with_unscoped(model, options = {}) belongs_to_without_unscoped(model, options.reject{|k,v| k==:unscoped}) if options[:unscoped] define_method "#{model}_with_unscoped" do model.to_s.camelize.constantize.unscoped { __send__("#{model}_without_unscoped") } end alias_method_chain model, :unscoped end end alias_method_chain :belongs_to, :unscoped end
各モデルでは以下のように短く書けます。
class User < ApplicationModel belongs_to :prefecture, :unscoped => true end
unscopedしているので注意は必要ですが、割と便利。