Какова реальная польза областей

Я просмотрел более 10 страниц, пытаясь найти преимущество области над любым другим классом класса ActiveRecord, который возвращает ActiveRecord:: Relation.

В следующем примере, например, почему области лучше, чем альтернативные под ним, которые делают то же самое:

  #scope :pat1,  lambda {{:conditions => ["name like ?", 'J%']}}    
  #scope :pat2,  lambda {{:conditions => ["id  > 5"]}}  

  def self.pat1
    where("name like ?", 'J%')
  end  

  def self.pat2 
    where("id  > 5")
  end  

  def patx 
    self.class.pat1.pat2.first
  end

Документация снова и снова говорит о том, что области полезны, потому что они могут быть скованы...

"Все методы области будут возвращать объект ActiveRecord:: Relation, который позволит вызывать на нем дополнительные методы (например, другие области)". - guides.rubyonrails.org

"Основная область видимости лучше, чем простые методы класса, заключается в том, что они могут быть привязаны к другим методам" http://ruby.railstutorial.org

... но вышеприведенная альтернатива также может быть скована, производя те же результаты.

Просто пытаясь выяснить, есть ли здесь новая одежда императора. Даже с синтаксической точки зрения, похоже, нет никакой пользы. Бывают ли они быстрее - некоторые источники смутно предлагают это.

Ответ 1

Области ActiveRecord - это действительно синтаксический сахар, завернутый в лучшую практику, как уже отмечалось.

В 2.x дни Rails, когда их называли "named_scope", они имели значение немного больше. Они позволили легко связать условия для генерации запроса. С улучшениями в Rails 3.x с Arel, как вы заметили, просто создать функции для отношений с запросами. Области просто предоставляют простые и элегантные решения для целых предопределенных запросов. Наличие всех областей в верхней части модели улучшает читаемость и помогает показать, как используется модель.

Ответ 2

Когда вы пишете область, она по сути делает то же самое. Вот как выглядит источник Rails:

    def scope(name, scope_options = {})
      name = name.to_sym
      valid_scope_name?(name)
      extension = Module.new(&Proc.new) if block_given?

      scope_proc = lambda do |*args|
        options = scope_options.respond_to?(:call) ? unscoped { scope_options.call(*args) } : scope_options
        options = scoped.apply_finder_options(options) if options.is_a?(Hash)

        relation = scoped.merge(options)

        extension ? relation.extending(extension) : relation
      end

      singleton_class.send(:redefine_method, name, &scope_proc)
    end

Преимущества в этом случае заключаются в том, что они являются идиоматическим способом определения запросов, в некоторых случаях меньше строк кода, и вы можете делать расширения.

Пример в источнике выглядит следующим образом:

scope :red, where(:color => 'red') do
  def dom_id
    'red_shirts'
  end
end

Позволяет вам вызывать Model.red.dom_id.

Ответ 3

Да, это синтаксические сокращения, которые в основном представляют методы, которые вы нашли.
Почему лучше?
Самый непосредственный эффект заключается в том, что 2-строчный код легче читать и поддерживать, чем 9 строк кода.

Rails всегда ищет подход DRY, и здесь повторяющиеся def self.method end скрывают фактический код.

Ответ 4

Есть несколько очень интересных различий между областями и методами класса, которые возвращают отношения.

  • Легче иметь дело с параметрами nil для областей с простой проверкой param.present?, для методов класса вы должны явно возвращать отношение non-nil, если параметр вызовет отношение nil.

  • Области более легко расширяемы, чем методы класса. Просто передайте блок (например, для разбивки на страницы), чтобы добавить методы. Методы класса могут быть расширены, но не так элегантно.

Для полного сокращения см. этот пост из Plataformatec.