rails joins includes ruby-on-rails ruby associations ruby-on-rails-4

ruby on rails - joins - Rails 4: Cómo usar includes() con where() para recuperar objetos asociados



rails joins includes (2)

No puedo averiguar cómo usar el método .where() para recuperar los datos del modelo asociado. En este ejemplo, Projects pertenece a los usuarios ...

class Project < ActiveRecord::Base belongs_to :user has_many :videos end class User < ActiveRecord::Base has_many :projects end class ProjectsController < ApplicationController def invite @project = Project.includes([:user]).where( {:hashed_id=>params[:id]} ).first end end

En App / views / projects / invite.html.erg <%= debug( @project ) %> returns:

--- !ruby/object:Project attributes: id: 22 name: Some Project Name belongs_to: 1 instructions: Bla bla bla active: true max_duration: 2 max_videos: created_at: 2013-08-26 15:56:50.000000000 Z updated_at: 2013-08-26 15:56:50.000000000 Z hashed_id: ''1377532589''

¿No debería incluirse el hash / array del usuario asociado en esto? Sé que podría agregarlo manualmente llamando a un segundo find / where ( @project.user = User.where( {:id=>@project.belongs_to} ) pero esto no se siente como "The Rails Way". ?

Solución Mi pregunta inicial se formuló bajo la suposición incorrecta de que debug() devolvería los objetos asociados (esto funciona en CakePHP porque agrupa todo en matrices).

Entonces mi código original debería funcionar. Sin embargo, he nombrado incorrectamente la clave externa archivada en la tabla. Me confundí al mirar el método de migración t.belongs_to (que crea automáticamente el campo foreign_key correctamente nombrado, no un campo llamado "belongs_to"). Así que también tuve que cambiar el nombre de esa columna a user_id y ahora funciona tal como se describe en la respuesta de @ Veraticus a continuación.


Ansiosa carga, la optimización de consultas N + 1 es realmente una forma eficiente de cargar asociaciones en una sola llamada.

- includes () con where () y find ()

@project = Project.includes(:user).where(hashed_id: params[:id]).first @project = Project.where(hashed_id: params[:id]).includes(:user).first

* En algunos casos, puede ser útil *

@projects = Project.find(:all, :includes => :user) @projects = Project.find(:all, :include => [{:association1 => [:associationA, :associationB, ....]}]


El objeto del user no es parte del objeto del project , por lo que no podrá verlo en el proyecto: más bien, al decir Project.includes(:user) , le está diciendo a Rails que cargue ansiosamente la asociación a la que se hace referencia cuando encuentra el proyecto. Esto le ahorra una llamada a la base de datos en el camino. Por ejemplo, sin entusiasmo:

@project = Project.where(id: params[:id]).first # one database call, fetching the project @project.user # another database call, fetching the user

Y con entusiasmo

@project = Project.includes(:user).where(id: params[:id]).first # one database call, fetching both project and user @project.user # no database interaction

Esto es más importante con has_many consultas donde las asociaciones de carga ansiosa pueden guardar consultas de bases de datos N + 1.

Puede verificar que esto está funcionando adecuadamente llamando a @project.user en algún momento después de la carga ansiosa y verificando sus registros: debería ver que no hubo una llamada a la base de datos en ese momento.