raw rails query left joins includes active ruby-on-rails ruby database ruby-on-rails-3 eager-loading

ruby-on-rails - left - raw query ruby on rails



Carga impaciente: la forma correcta de hacer las cosas. (2)

Después de mi carga ansiosa, ¿es posible / correcto hacer algo como @ article.comments = my_eager_loaded_comments para "pasar" / "asociar" / "interpolar" los comentarios a los artículos?

Sí, es posible. Hago esto regularmente.

Tenga en cuenta que mi solución todavía recupera TODOS los objetos asociados de la base de datos. No creo que haya ninguna solución para recuperar solo los objetos de asociación filtrados si su condición es dinámica. Mi solución se centra en el filtrado de los objetos de asociación recuperados.

Supongo que el requisito es get a list of articles y, en cada artículo, eager load the comments of only one particular user .

En el modelo de Article :

def self.get_articles_with_comments_of_user( article_ids, user_id ) articles = Article.where( id: article_ids ).includes( :comments ) articles.each do |article| filtered_comments = article.comments.select { |comment| comment.user_id == user_id } article.association("comments").target = filtered_comments end articles end

En la colección de artículos devueltos por el método anterior, la asociación de comentarios tendrá solo los comentarios de ese usuario en particular.

Espero que esto sea lo que estás pidiendo.

Estoy ejecutando Ruby on Rails 3.1. Leí los siguientes artículos y documentaciones sobre la carga de entusiasmo y me gustaría encontrar una manera correcta de hacer las cosas:

  1. Eager Loading Associations [Documentación oficial]
  2. ActiveRecord::Associations::ClassMethods (consulte la sección "Carga impaciente de asociaciones") [Documentación oficial]
  3. Eager cargando [artículo del blog]

El # 2 dice:

Tenga en cuenta que el uso de condiciones como Post.includes ([: author,: comments]). Where ([''comments.approved =?'', True]). All puede tener consecuencias no deseadas.

El # 3 dice que esas consecuencias no intencionadas son ( nota : los ejemplos son muy parecidos, por lo que cito el texto exacto del artículo del blog, pero hay que tener en cuenta la solución, no la implementación específica):

Esta consulta, ya que usaría un IZQUIERDA IZQUIERDA, también descartaría todas las publicaciones sin un comentario con la palabra "primero" en cualquiera de sus comentarios.

Es decir, si hay objetos no "asociados", el objeto "asociado principal" no se cargará. Esto es lo que sucede cuando trato de usar la carga impaciente agregando alguna condición como .where(:category_relationships => {:user_id => @current_user.id}) en mi pregunta anterior , pero no quiero que eso suceda.

Entonces (derrotista porque probablemente no puedo usar la carga impaciente en mi caso donde la condición no se puede establecer en la declaración has_many - tenga en cuenta que en el código anterior el @current_user.id está "configurado dinámicamente" a diferencia de los ejemplos presentes en los sitios mencionados) , Me gustaría saber si existen prácticas / técnicas / estrategias para limitar las consultas de la base de datos ya que tengo un "problema N + 1" .

Tal vez esas prácticas / técnicas / estrategias sean implementables usando el marco de Ruby on Rails en absoluto ... el # 1 dice:

A pesar de que Active Record le permite especificar condiciones en las asociaciones cargadas de entusiasmo, como las uniones, la forma recomendada es usar uniones en su lugar.

¿Qué y cómo resolver este problema de la manera correcta?

Tal vez una solución es recuperar y compilar lo que se necesita cargar ejecutando consultas de base de datos específicas y separadas, pero el problema sería cómo "pasar" / "asociar" / "interpolar" los objetos "recuperados" asociados "al" ¿Objeto principal asociado para que se puedan utilizar de una manera "cargando ansiosamente là"? Es decir, ¿cómo hacer posible (consulte la pregunta mencionada para obtener más información) usar un código como @article.comments y obtener solo los comentarios que estoy ansioso de cargar? Después de mi carga ansiosa, ¿es posible / correcto hacer algo como @article.comments = my_eager_loaded_comments para "pasar" / "asociar" / "interpolar" los comentarios a los artículos?


De # 2 ActiveRecord::Associations::ClassMethods viene esto:

Si desea cargar con entusiasmo solo algunos miembros de una asociación, normalmente es más natural incluir una asociación que tenga condiciones definidas:

class Post < ActiveRecord::Base has_many :approved_comments, :class_name => ''Comment'', :conditions => [''approved = ?'', true] end Post.includes(:approved_comments)

Esto cargará las publicaciones y cargará con entusiasmo la asociación authorized_comments, que contiene solo los comentarios que han sido aprobados.

Si entiendo esto correctamente en contexto, existe una ambigüedad cuando aplica .where () a su Consulta principal con un includes (), y AR aplica el lugar donde toda la consulta limita los resultados de su principio a aquellos que tienen predicados asociados que califican. Pero si aplica el predicado a la asociación anterior, AR comprende y le proporciona todos los resultados principales y los objetos asociados que coinciden con su condición de predicado.