Необходимо вернуть: имя объекта, даже если он был удален (используя паранойю)

Я имею Users в системе, которая может быть soft_deleted с помощью paranoia (2.0.2) а также TimeRecords которые отслеживают, сколько :hours user работал над заданием и какова их общая :cost был для всего назначения (:cost = :rate * :hours чтобы было проще).

Эти записи сохраняются, даже если userСкорость будет изменена в будущем, у вас все равно будет точный снимок того, что они взяли за определенную задачу в прошлом. Введите софт удаляет. user можно удалить из системы, используя мягкое удаление (настройка deleted_at: Time.now) но мне нужно, чтобы их имя все еще отображалось на :hours а также :cost они заряжены в прошлом. У меня есть решение, которое работает, но мне кажется, что оно слишком хакерское, и я не смог найти более элегантного решения. Буду признателен за любые предложения / помощь людям, возможно, придется сделать это правильно, а не легкий путь.

Текущее решение:

class TimeRecord < ActiveRecord::Base
  belongs_to :user

  delegate :name, to: :user, prefix: true, allow_nil: true

  def name
    user_name || "#{User.with_deleted.find(user_id).name}" rescue 'n/a'
  end
end

3 ответа

Решение

Если вашему TimeRecord нужно имя, независимо от того, существует ли пользователь или нет, то я бы рекомендовал хранить user_name как в TimeRecord, так и в User, а не делегировать его.

Когда имя меняется на пользователя, я обновляю соответствующие TimeRecords соответственно.

Лучше делать вид, что мягкие удаленные записи удаляются по-настоящему, чтобы сохранить ссылочную целостность. Так как вы уже сказали TimeRecord хранит "снимок" пользователя в то время, решение должно быть ясным: добавить name на поля, которые вы храните в TimeRecord как снимок.

Это идеальный вариант использования для такого рода нормализации, даже если пользователю не разрешено менять свое имя.

Если вы хотите включить связанные мягко удаленные объекты, вы можете просто снять область видимости ассоциации следующим образом:

class TimeRecord < ActiveRecord::Base
  belongs_to :user, -> { with_deleted } # associate soft-deleted user
  delegate :name, to: :user, prefix: true, allow_nil: true
end
Другие вопросы по тегам