Home > Software engineering >  Passing a variable in an after_update action
Passing a variable in an after_update action

Time:01-25

I have an UserProfile model:

class UserProfile < ApplicationRecord
  after_update :check_changes

  def check_changes
    AuditRecord.create(account_id: self.id, fields: self.saved_changes , account_type: 'UserProfile', admin_id: 3) if self.saved_changes?
  end
id user_id name last_name
1 1 john doe
2 2 foo bar

and AuditRecord model:

id account_type account_id field admin_id
1 UserProfile 1 {} 3
2 UserProfile 2 {} 3

This AuditRecord saves all of the updates of the profiles, but could be updated by different admins.

How can I send to check_changes function the admin_id? Because right now always is going to be 3.

CodePudding user response:

  1. If I understand correctly, you just want to pass an admin_id to AuditRecord, which means you need another model Admin, which is related to AuditRecord in some way.
  2. Start by generating Admin model, set up the appropriate active record association and references. Rails docs for this
  3. You should be able to access associations now, with something like admin.auditrecords depending upon how you set up the associations.

CodePudding user response:

after_update is called automatically. You can't pass some variables there dynamically

But you can evenly distribute tasks between admins

class AuditRecord < ApplicationRecord
  class << self
    def most_free_admin_id
      select(:admin_id).
        group(:admin_id).
        order('COUNT (admin_id)').
        first.
        admin_id
    end
  end
end

AuditRecord.most_free_admin_id will generate SQL like this

SELECT admin_id
FROM audit_records
GROUP BY admin_id
ORDER BY COUNT (admin_id)
LIMIT 1;

It will return id of the admin who has the least audit records

Also it's better to create such records not after update, but after commit when record is 100% saved in DB. For this purpose after_update_commit is better

Also in Ruby we use self. only in situations where it is impossible without it

Finally you can apply it in the model

class UserProfile < ApplicationRecord
  after_update_commit :check_changes

  private

  def check_changes
    AuditRecord.create(
      account_id: id,
      fields: saved_changes,
      account_type: 'UserProfile',
      admin_id: AuditRecord.most_free_admin_id
    )
  end
end
  • Related