0

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

Эти записи сохраняются, поэтому даже если в будущем будет изменен тариф user, у вас все равно будет точный снимок того, что они взимали за данную задачу в прошлом. Введите мягкие удаления. A 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 

ответ

1

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

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

+0

Благодаря Арьян, я обсуждала делал это раньше, но в конечном итоге будет более легкий маршрут. Теперь я знаю лучше! – DerProgrammer

1

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

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

+0

Спасибо за ответ Дэвид; это то, что я собираюсь сделать - я бы вручил вам ** ответ ** на этот вопрос, но Арьян получил там две минуты раньше с примерно таким же ответом! – DerProgrammer

1

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

class TimeRecord < ActiveRecord::Base 
    belongs_to :user, -> { with_deleted } # associate soft-deleted user 
    delegate :name, to: :user, prefix: true, allow_nil: true 
end 
+0

Спасибо, что ответили на Hieu; к сожалению, это не работает на Rails 4.0.0 (или может быть, что я делаю что-то неправильно). – DerProgrammer

+0

Работает ли этот запрос? 'User.with_deleted.count'? –

+0

Этот запрос работает, но при вызове '# user_name', созданного' # delegate', он возвращает: TimeRecord Load (0.4ms) SELECT 'time_records'. * FROM' time_records' ORDER BY 'time_records'.'id' DESC LIMIT 1 Пользовательская нагрузка (0.3ms) SELECT 'users'. * FROM' users' WHERE 'users'.'deleted_at' IS NULL AND' users'.'id' = 62 ORDER BY 'users'.'id' ASC LIMIT 1 => nil – DerProgrammer