Необходимо вернуть: имя объекта, даже если он был удален (используя паранойю)
Я имею 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