バグなのか仕様なのかは分からないんですが、仕様ぽい感じもする動きです。
こんなコードを書いても動かない
あくまで一例ですが、テーブル内のdataカラム以外を取得したいなーというときに、以下のようなコードを書いたとします。いろんなテーブルにdataカラムがあるから、いっそActiveRecord::Baseに追加しちゃえという感じのコードです。
# -*- coding: utf-8 -*- ActiveRecord::Base.class_eval do class << self def columns_without(except_columns = []) self.columns .map(&:name) .delete_if{|name| except_columns.include? name} .map{|name| "`#{self.to_s.tableize}`.`#{name}`"} end def columns_without_data columns_without(%w(data data_yml)) end def select_without_data select(columns_without_data) end scope :without_data, -> { select_without_data } end end
これでhoge.pages.without_data
という感じでスコープを使おうとすると、columns_without
メソッドのselfがPage
ではなくActiveRecord::Base
を指してしまっていて、上手く動きません。
どうやらモデルの継承元で定義したスコープのselfは、継承元のクラスを指す動きになるようです。AbstractClassを作成しても、同じくAbstractClassを指す動きになっていました。
というわけで、scopeはそれぞれのモデルで定義をするか、モジュールを作ってそれぞれのモデルに直接mixinする必要がありそうです。