Подтвердить что ты не робот

Как определить, загружена ли Rails-ассоциация?

Кто-нибудь знает, как определить, была ли загружена ассоциация Rails?

Моя ситуация: у меня есть результирующий набор, где иногда одна из ассоциаций загружается, а иногда и нет. Если он не загружен, я хочу найти ассоциации, используя ActiveRecord find. Если он загружен, я хочу использовать функцию обнаружения.

Например, скажем, что у меня есть массив has_many объектов shipping_info в моей модели товаров. Тогда:

Если элемент загружен, наиболее эффективная загрузка:

item.shipping_infos.detect { |si| si.region == "United States" }

Если элемент не загружен, наиболее эффективная загрузка:

item.shipping_infos.where(region: "United States").first

Но если я не знаю, загружен ли он, я не знаю, какой код вызывать, чтобы эффективно записывать запись. Если я использую первый метод, когда он не загружается, тогда мне нужно искать больше записей БД, чем это необходимо. И если я использую второй метод, когда он был загружен, тогда мои загруженные объекты игнорируются.

4b9b3361

Ответ 1

item.shipping_infos.loaded? расскажет вам.

Я должен сказать, что: этот путь приводит к безумию... прежде чем писать код, который проверяет loaded? на выбор между #detect и #find, убедитесь, что этот экземпляр действительно имеет значение, по сравнению со всем остальным, что происходит.

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

Ответ 3

Я бы предложил использовать item.association_cache.keys, который предоставит список жадных загруженных ассоциаций. Итак, вы item.association_cache.keys.include?: Name_of_association

Ответ 4

Вы можете определить, была ли загружена одна ассоциация с загруженным_foo? Например, если shipping_info была ассоциацией belongs_to, то item.loaded_shipping_info? вернет true, когда он будет загружен. Как ни странно, он, кажется, возвращает nil (а не false), когда он не был загружен (в Rails 2.3.10 в любом случае).

Ответ 5

Посмотрите на Bullet gem.. Это скажет вам, когда вы должны и не должны использовать желаемую загрузку.

Ответ 6

Решение этой проблемы должно быть foo.association(:bla).loaded?, НО оно работает неправильно - оно проверяет и маркирует ассоциацию как грязную:

class Foo; has_one :bla, :autosave => true end
foo.association(:bla).loaded? #=> false
foo.save # saves foo and fires select * from bla

Итак, я добавил следующее расширение для ActiveRecord:

module ActiveRecord
  class Base
    def association_loaded?(name)
      association_instance_get(name).present?
    end
  end
end

и теперь:

class Foo; has_one :bla, :autosave => true end
foo.association_loaded?(:bla) #=> false
foo.save # saves foo