Область применения метода класса в Rails 3
На основе Rails 3 API разница между областью действия и методом класса почти не существует.
class Shipment < ActiveRecord::Base
def self.unshipped
where(:shipped => false)
end
end
совпадает с
scope :unshipped, where(:shipped => false)
Однако, я нахожу, что иногда получаю разные результаты, используя их.
Хотя оба они генерируют одинаковый правильный SQL-запрос, область не всегда возвращает правильные значения при вызове. Похоже, эта проблема возникает только тогда, когда она называется так же дважды, хотя и на другой стороне, в методе. Во второй раз, когда он вызывал, при использовании области видимости он возвращал то же самое, что и в первый раз. Если я использую метод класса, он работает правильно.
Существует ли какое-то кеширование запросов при использовании области видимости?
Edit:
order.line_items.unshipped
Вышеуказанная строка - это то, как вызывается область. Заказы имеют много строк.
Метод generate_multiple_shipments вызывается дважды, потому что тест создает порядок и генерирует отгрузки, чтобы узнать, сколько их есть. Затем он вносит изменения в заказ и регенерирует поставки. Однако group_by_ship_date возвращает те же результаты, что и в первой итерации порядка.
def generate_multiple_shipments(order)
line_items_by_date = group_by_ship_date(order.line_items.unshipped)
line_items_by_date.keys.sort.map do |date|
shipment = clone_from_order(order)
shipment.ship_date = date
line_items_by_date[date].each { |line_item| shipment.line_items << line_item }
shipment
end
end
def group_by_ship_date(line_items)
hash = {}
line_items.each do |line_item|
hash[line_item.ship_date] ||= []
hash[line_item.ship_date] << line_item
end
hash
end
Ответы
Ответ 1
Я думаю, что ваш вызов неверен. Вы должны добавить так называемый метод запроса для выполнения области действия, например all
, first
, last
, т.е.:
order.line_items.unshipped.all
Я заметил некоторые несоответствия, особенно в rspec, которых можно избежать, добавив метод запроса.
Вы не опубликовали свой тестовый код, так что трудно сказать точно, но, по моему опыту, после изменения связанных записей вам необходимо принудительно перезагрузить, поскольку кеш запросов не всегда достаточно умен, чтобы обнаружить изменение. Передав true
в ассоциацию, вы можете принудительно перезагрузить ассоциацию и повторить запрос:
order.line_items(true).unshipped.all
Ответ 2
Предполагая, что вы ссылаетесь на Rails 3.1, на область видимости может влиять область по умолчанию, которая может быть определена на вашей модели, тогда как метод класса не будет.