Пустой прицел с Ruby on Rails - PullRequest
       4

Пустой прицел с Ruby on Rails

16 голосов
/ 17 сентября 2010

Следующая проблема:
Мне нужно что-то вроде пустой области. Это означает, что эта область является emtpy, но отвечает на все методы, на которые обычно отвечает область. В настоящее время я использую маленький грязный хак. Я просто поставляю "1 = 0" в качестве условия. Я нахожу это действительно уродливым, так как он попадает в базу данных. Простое возвращение пустого массива не сработает, так как результат должен реагировать на методы области действия.

Есть ли лучшее решение для этого или мне нужно будет это самому кодировать?

Может быть, пример кода поможет объяснить, что мне нужно:


class User < ActiveRecord::Base
  named_scope :admins, :conditions => {:admin => true }
  named_scope :none_dirty, :conditions => "1=0" # this scope is always empty

  def none_broken
    []
  end

  def self.sum_score # okay, a bit simple, but a method like this should work!
    total = 0
    self.all.each do |user|
      total += user.score
    end
    return total
  end
end
User.admin.sum_score # the score i want to know
User.none_drity.sum_score # works, but hits the db
User.none_broken.sum_score # ...error, since it doesn't respond to sum_score

Ответы [ 7 ]

21 голосов
/ 11 апреля 2014

Rails 4 представляет область действия none.

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

Если вы хотите, чтобы область возвращала неизмененную область, используйте all:

Больше не вызовет Model.all, чтобы немедленно выполнить запрос и вернуть массив записей. В Rails 4 вызовы Model.all эквивалентны устаревшим Model.scoped. Это означает, что к Model.all может быть привязано больше отношений, и результат будет лениво оцениваться.

11 голосов
/ 07 февраля 2013
User.where('false')

возвращает ActiveRecord :: Relation с нулевыми элементами, то есть цепочечную область, которая не попадет в базу данных, пока вы на самом деле не попытаетесь получить доступ к одному из ее элементов.Это похоже на решение PhilT с ('1 = 0'), но немного более элегантно.

2 голосов
/ 18 ноября 2011

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

Я видел where('1 = 0'), предложенный ранее, и Rails, вероятно, также должен его кешировать.

Также, where('1 = 0') не попадет в базупока вы не выполните .all, .each или один из методов расчета.

0 голосов
/ 21 ноября 2012

Глядя на ваш пример кода, вы можете не знать об агрегированных запросах в SQL, которые представлены в Rails как методы вычислений:

User.sum(:score) даст вам сумму баллов всех пользователей

Взгляните на Rails Guides для получения дополнительной информации:

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

0 голосов
/ 20 августа 2012

Как насчет User.where(id: nil)?

или User.where(_id: nil) для монгоида.

0 голосов
/ 13 ноября 2010

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

0 голосов
/ 17 сентября 2010

Я думаю, что вам нужно User.scoped({})

...