AuthenticationAttempt.where(ip: ip_address)<del>.last(5)</del>.exists?(successful: true)
<del>AuthenticationAttempt.where(ip: ip_address).order(id: :desc).limit(5).exists?(successful: true)</del>
Вы можете использовать ActiveRecord :: FinderMethods # существующие? для проверки успешной попытки без извлечения каких-либо данных или создания каких-либо записей.
Обновление: нам нужно использовать .order(id: :desc).limit(5)
вместо .last(5)
, чтобы убедиться, что у нас есть экземпляр ActiveRecord :: Relation для вызова exists?
.
Update2 : exists?
заменяет любой limit
, заданный на limit(1)
AuthenticationAttempt.limit(5).exists?
=> SELECT 1 AS one FROM "authentication_attempts" LIMIT $1 [["LIMIT", 1]]
Поэтому нам нужно заключить подзапрос в запрос внешнего существования:
AuthenticationAttempt.exists?(AuthenticationAttempt.limit(5))
=> SELECT 1 AS one FROM "authentication_attmepts" WHERE "authentication_attmepts"."id" IN (SELECT "authentication_attmepts"."id" FROM "authentication_attmepts" LIMIT $1) LIMIT $2 [["LIMIT", 5], ["LIMIT", 1]]
Thisэто немного более сложный запрос, но он все еще имеет преимущества в производительности, не загружая ничего из базы данных.Внутренний подзапрос дает нам последние 5 попыток, а внешний запрос проверяет наличие успешной попытки:
AuthenticationAttempt
.where(successful: true)
.exists?(AuthenticationAttempt.where(ip: ip_address).order(id: :desc).limit(5))