Search code examples
ruby-on-railsruby-on-rails-4soft-deleteruby-paranoia

Need to return the :name of an object, even if it was soft deleted (using paranoia)


I have Users in the system which can be soft_deleted using paranoia (2.0.2) and TimeRecords which keep track of how many :hours a user worked on a given assignment and what their total :cost was for the entire assignment (:cost = :rate * :hours to keep it simple).

These records persist so even if a user's rate is changed in the future, you will still have an accurate snapshot of what they charged for a given task in the past. Enter the soft deletes. A user can be removed from the system using a soft delete (setting deleted_at: Time.now) but I need their name to still show up linked to the :hours and :cost they charged in the past. I have a solution that works but feels too hacky for me and I haven't been able to find a more elegant solution. I'd appreciate any suggestions/help people may have to do this the right way instead of the easy way.

Current solution:

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

Solution

  • If your TimeRecord needs the name, regardless of whether the User still exists or not, then I would recommend storing the user_name on TimeRecord as well as on User instead of delegating it.

    When the name changes on the User, I would update the relevant TimeRecords accordingly.