user464180
user464180

Reputation: 1359

Rails: update_attribute calling multiple controllers/models?

In my code, admins can add users and assign them jobs. If the admin decides to delete a user, I want to check for any jobs that the user may be assigned to and update its assignment to the admin. Since the user deletion is taking place in my user_controller and calling Jobs, is this the best way? If not, could you please advise as to the most efficient way to do this is, especially if the user is assigned to 1-N jobs? Thanks in advance.

users_controller.rb

 def destroy
     if admin?
       jobs = Job.where("user_id = ?", params[:id]) #find jobs where user is that being deleted
       jobs.each do |job|         
        job.update_attribute(:user_id, current_user.id)  #for each job set the user_id to the admin_id
       end     
    end
    redirect_to users_url
  end

Upvotes: 0

Views: 106

Answers (3)

Caleb Hearth
Caleb Hearth

Reputation: 3365

I would propose using the update_all call on an ActiveRecord::Relation

In your case, a simple way to make it happen would be:

Job.where(user_id: params[:id]).update_all(user_id: current_user.id)

Note that in newer versions of Rails (at least in the as-yet-unreleased 4), this will be prevented as mass assignment is dangerous. Because of that, you will want to 'whitelist' the user_id attribute.

Upvotes: 1

Jesse Wolgamott
Jesse Wolgamott

Reputation: 40277

You can use the #update_all method to only execute one SQL query:

Here we will update all jobs with user_id of @user.id, set user_id to current_user.id

  def destroy
    @user = User.find(params[:id])
    if admin?
      Job.update_all {user_id: current_user.id}, {user_id: @user.id} 
    end
    @user.destroy
    redirect_to users_url
  end

Upvotes: 1

OpenCoderX
OpenCoderX

Reputation: 6318

I would first select the jobs for that user in an instance variable, then loop over them updating the relevant foreign key to the admins user_id. then destroy the original record.

Upvotes: 0

Related Questions