Область ActiveRecord Rails 3 против метода класса - PullRequest
50 голосов
/ 05 мая 2011

Я новичок в новом интерфейсе запросов ActiveRecord, так что я все еще разбираюсь.

Я надеялся, что кто-нибудь сможет объяснить разницу между использованием scope в модели ActiveRecord и просто использованием метода класса (то есть self.some_method)

Из того, что я могу извлечь, ожидается, что область видимости будет возвращать отношение, тогда как метод класса не обязательно должен это делать. Это правда?

Например, я подумал, что имеет смысл сделать что-то вроде:

class Person
  scope :grouped_counts, group(:name).count
end

Но это не работает. Я получаю эту ошибку:

ArgumentError: Unknown key(s): communicating, failed, matched, unmatched
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activesupport-3.0.5/lib/active_support/core_ext/hash/keys.rb:43:in `assert_valid_keys'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/relation/spawn_methods.rb:110:in `apply_finder_options'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/activerecord-3.0.5/lib/active_record/named_scope.rb:110:in `block in scope'
    from (irb):48
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in `start'
    from /Users/bradrobertson/.rvm/gems/ruby-1.9.2-p180@influitive/gems/railties-3.0.5/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:6:in `require'
    from script/rails:6:in `<main>'
r

Однако он работает как метод класса

def self.grouped_counts
  group(:name).count
end

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

Ответы [ 2 ]

82 голосов
/ 05 мая 2011

В Rails 2.x было больше различий, так как named_scopes не выполнял ваши запросы (так что вы могли их связывать), тогда как методы класса обычно выполняли запросы (поэтому вы не могли их цеплять), если вы не вручную обернул ваш запрос в scoped(...) вызов.

В Rails 3 все возвращает ActiveRecord::Relation до тех пор, пока вам не понадобятся фактические результаты, поэтому области можно связать с методами класса и наоборот (если методы класса возвращают ActiveRecord::Relation объекты, а не какой-либо другой тип объекта ( как граф)).

Обычно я использую записи scope для простых однострочников, чтобы отфильтровать мой набор результатов. Однако, если я делаю что-то сложное в «области видимости», для которой может потребоваться подробная логика, лямбда-выражения, несколько строк и т. Д., Я предпочитаю использовать метод класса. И как вы поняли, если мне нужно вернуть количество или что-то подобное, я использую метод класса.

11 голосов
/ 07 ноября 2013

Как отметил Дилан в своем ответе, одним из отличий между областью видимости и методом класса является то, что области оцениваются при загрузке класса.Это может привести к неожиданному результату.

Например,

class Post < ActiveRecord::Base
    scope :published_earlier, where('published_at < ?', Date.today)
end

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

class Post < ActiveRecord::Base
    scope :published_earlier, -> { where('published_at < ?', Date.today) }
end

Лямбда-блок лениво оценивается.Поэтому Date.today запускается при вызове области, а не при оценке класса.

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

class Post < ActiveRecord::Base
    def self.published_earlier
        where('published_at < ?', Date.today)
    end
end

Поскольку для метода класса код выполняется во время вызова метода.

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