¿Cómo determinar si Rails Association está Eager Loaded?


¿Alguien conoce una forma de determinar si una asociación Rails ha sido cargada con ansias?

Mi situación: Tengo un conjunto de resultados donde a veces una de las asociaciones está eager loaded, y a veces no. Si no está eager-loaded, entonces quiero buscar asociaciones usando find de ActiveRecord. Si está ansioso cargado, quiero usar detect.

Por ejemplo, digamos que tengo una matriz "has_many" de objetos shipping_info en mi modelo item. Entonces:

Si item está ansioso loaded, la carga más eficiente es:

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

Si el elemento no está ansioso cargado, la carga más eficiente es:

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

Pero a menos que sepa si está ansioso cargado, no se qué código llamar para obtener el registro de manera eficiente. Si utilizo el primer método cuando no estaba ansioso cargado, entonces tengo que buscar más registros de DB de los necesarios. Y si utilizo el segundo método cuando estaba eager loaded, entonces mis objetos eager loaded son ignorados.

Author: Adam Lassek, 2009-09-04

7 answers

item.shipping_infos.loaded? te lo diré.

Tengo que decir, sin embargo: este camino conduce a la locura... antes de escribir código que pruebe loaded? para decidir entre #detect y #find, asegúrese de que esta instancia realmente importa, en relación con todo lo demás que está sucediendo.

Si esto no es lo más lento que hace tu aplicación, agregar rutas de código adicionales agrega complejidad innecesaria. El hecho de que pueda perder un poco de esfuerzo en la base de datos no significa que necesite arreglarlo, probablemente no importe en ninguna de manera medible.

 44
Author: Bryan Stearns,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-01 15:49:54

Use .association(name).loaded? en un registro.


Para Rails loaded_foo?.

(Está obsoleto desde Rails 3.1. Véase: https://github.com/rails/rails/issues/472.)

 46
Author: gamov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-22 06:39:46

Sugiero usar item.association_cache.claves que proporcionarán una lista de las asociaciones cargadas ansiosas. Así que tu artículo.association_cache.claves.incluir? : name_of_association

 20
Author: dabobert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-26 21:09:44

¿Puede detectar si se ha cargado o no una sola asociación con loaded_ foo?. Por ejemplo, si shipping_info era una asociación belongs_to, entonces item.loaded_shipping_info? volverá verdadero cuando ha sido ansioso-cargado. Curiosamente, parece devolver nil (en lugar de false) cuando no se ha cargado (en Rails 2.3.10 de todos modos).

 3
Author: Jim Stewart,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-04-21 19:34:06

La solución a este problema debería ser foo.association(:bla).loaded?, PERO funciona incorrectamente-comprueba y marca la asociación como sucia:

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

Así que he añadido la siguiente extensión a ActiveRecord:

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

Y ahora:

class Foo; has_one :bla, :autosave => true end
foo.association_loaded?(:bla) #=> false
foo.save # saves foo
 2
Author: Lev Lukomsky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-10 16:01:17

Echa un vistazo a la gema de viñetas .. Esto le dirá cuándo debe y no debe usar eager loading.

 2
Author: Bitterzoet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-18 07:48:10

association_cached? podría ser un buen ajuste:

item.association_cached?(:shipping_infos)
 0
Author: phil pirozhkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-04 12:19:08