Итак, у меня есть сообщение и пользователь. У пользователя has_many есть пользователь, а пользователь принадлежит к сообщению. Мне нужна находка, которая найдет все сообщения, у которых нет пользователей, таких как:
Post.first.users => []
Post.where("id not in (select post_id from users)")
Узнал это только сегодня:
Post.eager_load(:users).merge(User.where(id: nil))
Работает как минимум с Rails 4+.
Обновление:
В Rails 5+ вы можете использовать left_joins вместо:
left_joins
Post.left_joins(:users).merge(User.where(id: nil))
Я знаю, что это помечено как Rails 3, но если вы используете Rails 4, я делал это следующим образом.
Post.where.not(user_id: User.pluck(:id))
что-то в этом роде:
p = Post.arel_table u = User.arel_table posts = Post.find_by_sql(p.join(u).on(p[:user_id].eq(u[:p_id])).where(u[:id].eq(nil)).to_sql)
Если вам нужно что-то быстрое, используйте оператор SQL, например:
SELECT * FROM posts p LEFT OUTER JOIN users u ON p.id = u.post_id WHERE u.id IS null
Я думаю, что sql с in может вызвать проблемы с производительностью, если таблица базы данных имеет много строкосторожнее с этим
Post.first.users.empty? должно быть достаточно, если пользователь возвращает массив.
Post.first.users.empty?
Если вы хотите проверять каждое сообщение, вы можете сделать
Post.each do |p| if p.users.empty? do whatever end end