Обхват срещу метод на клас в Rails 3

Въз основа на API на Rails 3, разликата между обхват и метод на клас почти не съществува.

class Shipment < ActiveRecord::Base
  def self.unshipped
    where(:shipped => false)
  end
end

е същото като

scope :unshipped, where(:shipped => false)

Откривам обаче, че понякога получавам различни резултати, използвайки ги.

Въпреки че и двете генерират една и съща, правилна SQL заявка, обхватът не винаги изглежда да връща правилните стойности при извикване. Изглежда, че този проблем възниква само когато се извика по същия начин два пъти, макар и на различна пратка, в метода. При второто извикване, когато използва обхват, той връща същото нещо, което направи първия път. Докато, ако използвам метода на класа, той работи правилно.

Има ли някакъв вид кеширане на заявки, което се случва при използване на обхват?

Редактиране:

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

person blim8183    schedule 25.01.2012    source източник
comment
Можете ли да предоставите пример (фрагмент от код), където смятате, че заявката се кешира при двукратно извикване.   -  person George Yacoub    schedule 27.01.2012
comment
Добавих допълнителна информация към оригиналната публикация.   -  person blim8183    schedule 27.01.2012
comment
Проверката на дневника на Rails ще ви покаже дали резултатът се кешира.   -  person Sasha    schedule 30.01.2012


Отговори (2)


Мисля, че извикването ви е неправилно. Трябва да добавите така наречения метод на заявка за изпълнение на обхвата, като all, first, last, т.е.:

order.line_items.unshipped.all

Наблюдавах някои несъответствия, особено в rspec, които се избягват чрез добавяне на метода на заявка.

Не сте публикували своя тестов код, така че е трудно да се каже точно, но моят опит е, че след като промените свързаните записи, трябва да принудите презареждане, тъй като кешът на заявките не винаги е достатъчно интелигентен, за да открие промяна. Като подадете true към асоциацията, можете да принудите асоциацията да се презареди и заявката да се изпълни отново:

order.line_items(true).unshipped.all
person Wolfram Arnold    schedule 30.01.2012
comment
Принуждаването на асоциацията да се презарежда изглежда е свършило работа. Все още не съм напълно наясно как кешът на заявките определя дали е имало промяна, но поне сега работи. Благодаря! - person blim8183; 31.01.2012
comment
@blim8183 И аз не знам отговора на това, но подозирам, че това може да е бил компромис в дизайна. Радвам се, че презареждането ти е свършило работа. - person Wolfram Arnold; 31.01.2012

Ако приемем, че препращате към Rails 3.1, обхватът може да бъде повлиян от обхвата по подразбиране, който може да бъде дефиниран във вашия модел, докато метод на клас няма да бъде.

person Sasha    schedule 30.01.2012