Considérez ces deux modèles:

class User < ApplicationRecord
  has_many :blogs
end

class Blog < ApplicationRecord
  belongs_to :user
end

J'aimerais faire quelque chose comme ça mais ça ne fonctionnera pas:

my_users        = User.where(age: 35) 
all_assoc_blogs = my_users.blogs # errors out

Voici l'erreur:

méthode non définie `blogs 'pour User :: ActiveRecord_Relation:

Je comprends pourquoi cela ne fonctionne pas: vous ne pouvez appeler blogs que sur un seul objet user. Vous ne pouvez pas appeler blogs sur un objet de relation d'enregistrement actif de users.

En fin de compte, je veux un objet de relation d'enregistrement actif qui consiste en un agrégat de tous les blogs pour tous les utilisateurs dans l'objet de relation d'enregistrement actif my_users. Y a-t-il un moyen de faire cela avec des rails lisses? C'est la seule façon dont je peux penser et c'est assez moche:

my_users   = User.where(age: 35)
temp_blogs = []
my_users.each {|u| temp_blogs << u.blogs.to_a}
blog_ids = temp_blogs.flatten.pluck(:id)
Blog.where(id: blog_ids)
2
Neil 20 nov. 2018 à 01:02

4 réponses

Meilleure réponse

C'est ce que je cherchais:

my_users = User.where(age: 35)
Blog.where(user: my_users)

Ce qui m'a fait trébucher, c'est que je devais changer de vitesse. Je saisis d'abord les users pertinents, puis je les transmets users dans une requête Blog.

Puisque je veux finalement une relation d'enregistrement active de blogs, le moyen le plus simple est de m'assurer que le modèle supérieur avec lequel je commence dans la requête est Blog.

0
Neil 19 nov. 2018 à 22:17

Enregistrements actifs où Metrodome vous renvoie une relation activerecord, pas un résultat unique. Tu dois:

my_users = User.where(age: 35).first

Ensuite, vous devriez pouvoir obtenir les blogs d'un utilisateur avec:

my_users.blogs

Mais si votre intention est d'avoir tous les blogs d'utilisateurs différents, vous devriez essayer de:

my_user_ids = User.where(id: 35).pluck(:id)
Blog.where(user_id: my_user_ids)
1
hernanvicente 19 nov. 2018 à 22:21

Les autres réponses sont correctes, mais vous pouvez le faire plus efficacement et réduire ainsi vos requêtes de base de données.

my_users = User.includes(:blogs).where(age: 35)  # this makes one db query to get all data
all_assoc_blogs = my_users.map(&:blogs)
0
Nick Ellis 19 nov. 2018 à 22:25

Peut-être que cela vous aidera:

Blog.joins(:user).where(user: User.where(age: :35))

Ou

Blog.joins(:user).merge(User.where(age: :35))
1
piton4eg 19 nov. 2018 à 22:56