Область применения против метода класса в Rails 3 - PullRequest
14 голосов
/ 25 января 2012

Основываясь на 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

Строка выше - это то, как вызывается область. Заказы имеют много line_items.

Метод 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

Ответы [ 2 ]

1 голос
/ 30 января 2012

Я думаю, что ваш вызов неверен.Вы должны добавить так называемый метод запроса для выполнения области, такой как all, first, last, то есть:

order.line_items.unshipped.all

Я наблюдал некоторые несоответствия, особенно в rspec, чтоможно избежать, добавив метод запроса.

Вы не опубликовали свой тестовый код, поэтому трудно сказать точно, но мой опыт заключался в том, что после изменения связанных записей вы должны принудительно выполнить перезагрузку, так каккэш запросов не всегда достаточно умен, чтобы обнаружить изменения.Передав true ассоциации, вы можете принудительно перезагрузить ассоциацию и повторно выполнить запрос:

order.line_items(true).unshipped.all
1 голос
/ 30 января 2012

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

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