преобразовать запрос MySQL в запрос рельсы - PullRequest
2 голосов
/ 24 сентября 2019

Привет всем, у меня проблема с преобразованием запроса mysql в запрос rails.У меня есть эти модели -

class User < ApplicationRecord
   has_many :comments, foreign_key: "commenter_id"
end

class Comment < ApplicationRecord
  belongs_to :commenter, class_name: "User"
end

Может кто-нибудь помочь мне с преобразованием следующего запроса в запрос рельсов -

UPDATE comments 
INNER JOIN users on comments.commenter_id = users.id 
SET comments.deleted_at = users.deleted_at 
WHERE users.deleted_at IS NOT NULL

Я пытаюсь сделать мягко удаляемые комментарии, чей комментатор был мягко удален.

ОБНОВЛЕНИЕ 1: пока я могу сделать это с помощью этого -

User.only_deleted.includes(:comments).find_each do |u|
  u.comments.update_all(deleted_at: u.deleted_at)
end

Но я хочу сделать это для одного запроса без необходимости перебирать результат.

ОБНОВЛЕНИЕ 2: я использую гем от activ_as_paranoid, поэтому нужен неопубликованный пользователь, и мой последний запрос стал:

User.unscoped{Comment.joins(:commenter).where.not(users: {deleted_at: nil}).update_all("comments.deleted_at = users.deleted_at") 

Ответы [ 3 ]

2 голосов
/ 24 сентября 2019

Это должно работать на MySQL:

Comment
    .joins(:user)
    .where.not(users: { deleted_at: nil })
    .update_all("comments.deleted_at = users.deleted_at")

Это не будет работать на Postgres, так как в нем отсутствует предложение FROM для пользователей.

Менее производительный, но параметр полиглота:

Comment
  .joins(:user)
  .where.not(users: { deleted_at: nil })
  .update_all("deleted_at = ( SELECT users.deleted_at FROM users WHERE comments.id = users.id )")

Это, вероятно, на порядок лучше, чем перебирать записи в Ruby, поскольку вы устраняете задержку трафика между сервером приложений и базой данных.

0 голосов
/ 24 сентября 2019

Приведенный ниже код должен выполнить количество запросов, соответствующих удаленным_пользователям и без загрузки пользователя и любых связанных комментариев в памяти

deleted_users_data_arr = User.only_deleted.pluck(:id, :deleted_at)

deleted_users_data_arr.each do |arr|
  deleted_user_id = arr[0]
  user_deleted_at = arr[1]

  Comment.where(commenter_id: deleted_user_id).update_all(deleted_at: user_deleted_at)
end
0 голосов
/ 24 сентября 2019

Из ваших комментариев, я думаю, это то, что вы хотите:

Comment.where.not(user_id: nil).each { |comment| comment.update_attributes(deleted_at: comment.user.deleted_at)

Или чуть более читабельно:

Comment.all.each do |comment|
  next unless comment.user.present?
  comment.update_attributes(deleted_at: comment.user.deleted_at)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...