Сохранение именованных расширений области действия в сухом состоянии


В Rails вы можете добавить блок после named_scope для дополнительных контекстно-зависимых методов, таких как:

class User < ActiveRecord::Base
  named_scope :inactive, :conditions => {:active => false} do
    def activate
      each { |i| i.update_attribute(:active, true) }
    end
  end
end

В этом примере метод activate определяется не на классе User, а на объекте ActiveRecord::NamedScope::Scope.

У меня есть ряд из трех областей, которые должны иметь идентичные определения методов. В интересах не повторяющегося кода, как бы я абстрагировал этот блок таким образом, чтобы я мог определить его один раз и передать его каждому named_scope?
2 2

2 ответа:

Во-первых, отличный вопрос-я не знал об этой особенности именованных областей! Для меня работает следующее:

class User < ActiveRecord::Base
  add_activate = lambda do
    define_method "activate" do
      each { |i| i.update_attribute(:active, true) }
    end
  end

  named_scope :inactive, :conditions => {:active => false}, &add_activate
end

Вы можете передать блок add_activate в качестве последнего аргумента в любую именованную область, для которой требуется метод activate.

Гораздо лучше:

Http://tuxicity.se/rails/dry/2009/01/04/share-named-scopes-in-rails.html

module NamedScope
  def self.included(base)
    base.class_eval do
      named_scope :inactive, :conditions => {:active => false} do
        def activate
          each { |i| i.update_attribute(:active, true) }
        end
      end
    end
  end
end

Сохраните в вашем каталоге /lib (Поместите требование в инициализаторы в rails 3) и include NamedScope в вашем классе User