Je n'ai aucune idée. Pourriez-vous me donner des indices (comme des sites de référence). Toute aide serait appréciée.
Model1: GROUP(id, name)
Model2: USER_GROUP_CMB(id, user_id, group_id)
Déclaration SQL attendue:
SELECT *
FROM groups AS g LEFT OUTER JOIN user_group_cmbs AS cmb
ON g.id = cmb.group_id
WHERE cmb.user_id = 1
J'ai essayé de créer des associations ci-dessous mais je ne sais pas quoi faire après cela.
class Group < ActiveRecord::Base
has_many :user_group_cmb
end
class UserGroupCmb < ActiveRecord::Base
has_many :group
end
Rails Version: 3.1.1
Je crois qu'une includes
utilisera une requête LEFT OUTER JOIN
si vous créez une condition sur la table que l'association includes
utilise:
Group.includes(:user_group_cmb).where(user_group_cmbs: { user_id: 1 })
Rails 5+ vous permet d'effectuer les tâches suivantes:
Group.left_outer_joins(:user_group_cmb)
http://api.rubyonrails.org/classes/ActiveRecord/QueryMethods.html#method-i-left_joins
Vous pouvez le faire dans Rails 3.x, que vous référeniez la table ou non, dans une clause where:
Group.eager_load(:user_group_cmb)
... et il effectuera une jointure externe gauche
Il peut être très important de mentionner que l’utilisation inclut a peut-être des effets secondaires indésirables.
si l'association filtrée est ensuite étendue, tout le filtrage d'origine disparaît
En fin de compte, en ciblant l’association filtrée, nous avons perdu l’effet De filtrage en tant qu’effet indésirable que nous avons obtenu à partir d’inclusions. Et ce n’est pas À cause de la façon dont nous avons cherché.
Assurez-vous de lire l'article complet et alternativement il y a un bijou pour cela .
Utilisez une déclaration de jointure personnalisée:
Group.joins("left outer join user_group_cmbs as cmb on groups.id = cmb.group_id")
.where("cmb.user_id = ?", 1)
Le problème avec la réponse acceptée est qu’il effectuera un LEFT INNER JOIN
techniquement car il n’affiche pas les entrées où le user_group_cmbs. user_id
est nul (ce qui serait la raison de faire un LEFT OUTER JOIN
).
Une solution efficace consiste à utiliser #references
:
Group.includes(:user_group_cmb).references(:user_group_cmb)
Ou encore plus pratique #eager_load
:
Group.eager_load(:user_group_cmb)
Lisez l'explication plus détaillée ici .
Utilisez has_and_belongs_to_many si vous avez juste besoin de lier des utilisateurs à des groupes. Utilisez has_many: through si vous devez stocker des informations supplémentaires sur les membres.
Exemple:
class User < ActiveRecord::Base
has_and_belongs_to_many :groups
end
class Group < ActiveRecord::Base
has_and_belongs_to_many :users
end
Je ne peux pas commenter une réponse précédente car je n’ai pas 50 points de réputation.
la relation includes-référencé déclenche une exception StatementInvalid, en se plaignant du manque d'une entrée de la clause FROM. Je dois ajouter un appel explicite à rejoindre, qui est par défaut interne.
Je devais utiliser .references et mentionner le nom de la table ou être ajouté à la clause FROM