Что такое scope / named_scope в рельсах?

106

Я недавно начала стажировку. Мой работодатель использует Ruby on Rails, и я часто сталкиваюсь с новым синтаксисом, который мне нужно найти, чтобы понять. Я искал в Google хорошее объяснение named_scope, но до сих пор я нашел в основном сообщения в блогах, в которых его высоко оценивают, а не прямое определение или введение.

Что именно называется named_scope (теперь называемым просто областью видимости) в Ruby on Rails?

Зигги
источник
2
Это сообщение в блоге было бесценным для меня, когда я изучал именованные области: ryandaigle.com/articles/2008/8/20/…
Питер Браун
@notapatch ссылка мертва у вас есть еще одна?
mbigras
Райан Дейгл: Именованный объем: дело не только в условиях,
понимаете

Ответы:

213

Область видимости - это подмножество коллекции. Звучит сложно? Это не так. Представьте себе это:

У вас есть пользователи. Теперь некоторые из этих пользователей подписаны на вашу рассылку новостей. Вы отметили тех, кто получает информационный бюллетень, добавив поле в базу данных пользователей (user.subscribed_to_newsletter = true). Естественно, иногда вы хотите получить тех пользователей, которые подписаны на вашу рассылку.

Конечно, вы всегда можете сделать это:

User.where(subscribed_to_newsletter: true).each do #something

Однако вместо того, чтобы всегда писать это, вы можете сделать что-то вроде этого.

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, where(subscribed_to_newsletter: true)
  #yada yada
end

Если вы используете Rails 4 или новее , сделайте это:

#File: users.rb
class User < ActiveRecord::Base
  scope :newsletter, -> { where(subscribed_to_newsletter: true) }
  #yada yada
end

Это позволяет вам получить доступ к своим подписчикам, просто выполнив следующие действия:

User.newsletter.each do #something

Это очень простой пример, но в целом области могут быть очень мощными инструментами, облегчающими вашу работу.

Проверьте эту ссылку: Описание API

Михаэль Шефермейер
источник
7
Могу я спросить, в чем преимущества этого по сравнению, скажем, с определением метода в пользовательском классе под названием «subscribedUsers»? например 'def self.subscribedUsers self.where (: subscribed_to_newsletter => true) end
redroot
3
@redroot преимущество в том, что scopeсинтаксис намного чище, вы получите тот же результат, но всего с одной строчкой
Aldo 'xoen' Giambelluca
9
@redroot Раньше было большое преимущество в эффективности, поскольку области выполняли ленивые запросы к базе данных, в то время как методы выполняли это с нетерпением. В Rails 3 методы тоже стали ленивыми, так что теперь разница более синтаксическая. Источник
evanrmurphy
Ссылка на документ API не работает, обновите api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/…
Lohith MV
Также позволяет использовать ссылку
Benjineer
34

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

Например, если у вас есть модель зомби (таблица зомби) с указанными ниже методами области видимости,

class Zombie
  scope :rotting, -> { where(rotting: true) }
  scope :fresh, -> { where('age < ?', 25) }
  scope :recent, -> { order(created_at: :desc) }
end

И ты звонишь

Zombie.rotting.fresh.recent.limit(3)

Это переводится в SQL ниже,

select "zombies.*" from "zombies" where "zombies"."rotting" = 't' and (age<20) order by create_at desc limit 3

Пример выше основан на синтаксисе rails 4

Акшатха
источник
Я не могу найти пример порядка (: created_at,: desc) ни в одной документации. Неужели вы имели в виду scope :recent, -> { order(created_at: :desc) }? apidock.com/rails/v4.2.9/ActiveRecord/QueryMethods/order
notapatch
7

Лучший способ разобраться в деталях - обратиться к документации по API.

Вы получите полную информацию о том, как мы можем использовать Scopes.

Документация API по объему

123
источник
7

Области видимости - это не что иное, как методы класса.

Зачем их использовать?

Область действия позволяет вам указывать часто используемые запросы (это можно рассматривать как ярлык для длинных или наиболее часто используемых запросов), на которые можно ссылаться как на вызовы методов для объектов или моделей ассоциации. С этими областями действия вы можете использовать все ранее описанные методы, такие как where, joins и includes. Все методы области будут возвращать объект ActiveRecord :: Relation, который позволит вызывать для него дополнительные методы (например, другие области).

Чтобы определить простую область видимости, мы используем метод области видимости внутри класса, передавая запрос, который мы хотели бы запустить при вызове этой области:

class Article < ActiveRecord::Base
  scope :published, -> { where(published: true) }
end

Это в точности то же самое, что и определение метода класса, и то, что вы используете, зависит от личных предпочтений:

class Article < ActiveRecord::Base
  def self.published
    where(published: true)
  end
end

Пожалуйста, перейдите по следующей ссылке для полного описания с примером. Я надеюсь, что это поможет вам.

http://guides.rubyonrails.org/active_record_querying.html

Имран Ахмад
источник
3
Это не совсем то же самое, что определение метода класса . Методы класса возвращаются nilв нескольких случаях и, следовательно, не могут быть объединены в цепочку для определенных условий.
Арслан Али
1
  • Представьте, что у вас есть модель: Человек .

А теперь представьте себя:

  • хочу, чтобы все люди в мире имели рыжие волосы.
  • хочу, чтобы все люди в мире играли в крикет

Вы можете получить эти конкретные классы людей, используя прицел!

Person.red_hair.cricket ## finds all people with red hair who play cricket
Person.red_hair ## finds all people with red hair
Person.cricket ## finds all people who play cricket.

Теперь это было не так уж сложно, правда?

BKSpurgeon
источник