2012-06-10 2 views
2

Я пишу метод экземпляра модели, который должен найти AR-ассоциацию, если он существует, или создать его, если это не так. Как я могу сделать это, чтобы после первого поиска база данных не запрашивалась снова? У меня есть две версии этого метода ниже, но у обоих есть недостатки.Самый эффективный способ не повторять вызов базы данных внутри метода?

Этот метод выполняет запрос каждый раз, когда он неэффективен.

def cart 
    carts.order('created_at desc').where(:purchased_at => nil).first || carts.create 
    end 

Этот метод не только поиск дб один раз, но выходит из синхронизации после чего-то вроде cart.destroy.

def cart 
    @cart_ || @cart_ = carts.order('created_at desc').where(:purchased_at => nil).first || @cart_ = carts.create 
    end 

ответ

2

ActiveRecord отношение имеет малоизвестную функцию, которая позволяет создать экземпляр из них:

User.where(name: 'John').new #=> <User @name="John"> 

Объедините это с find_or_create и вы на своем пути:

Cart.order('created_at DESC').find_or_create_by_purchased_at(nil) 

Каждый раз, когда вы вызываете cart Rails запускает запрос, однако он очень результатен, потому что он попадет в q uery cache, срок действия которого истекает в конце запроса. Предполагая, что вы не очищаете все тележки между вызовами этого метода, вы должны быть в порядке.

+0

Вау, это здорово. Я подумаю, что поеду с этим, но я не могу сказать, попадает ли он в кеш запросов. – pixelearth

+0

См. Здесь: http://pastie.org/4062197 – pixelearth

+0

Я * думаю * запрос кеширования происходит только во время фактических запросов. Сделайте «tail -f log/development.log» и проверьте вывод во время фактического запроса, и вы увидите «CACHE» вместо «Загрузка корзины», если он использует кеш соответствующим образом. – coreyward

Смежные вопросы