0

I have a Rails 3.2 app. It is a publishing app where we kick off several Sidekiq jobs in response to changes in content. I was calling this from the controller but there's now getting to be multiple points of entry and are now duplicating logic in multiple controllers. The proper place for this to be is in a callback in the model. However, accessing current_user is frowned upon in the model but for things like logging changes or app events, it is critical.

So I have two questions (1) Is there something I'm missing regarding the argument about accessing current_user when you want to be logging changes across complex model structures? and (2) Is the proposed solution here an effective one with last update over 2 years ago in terms of thread-safety? I use a three Unicorn processes on Heroku. https://stackoverflow.com/a/2513456/152825

Edit 1

Thinking through this, wondering if I should just do something like this in my application.rb

class ArcCurrentUser
  @current_user_id
  def self.id
    return @current_user_id
  end

  def self.id=id_val
    @current_user_id=id_val
  end
end

and then in my current_user method in application_controller, just update ArcCurrentUser.id to @current_user.id? I will only be using it for this logging functionality.

Community
  • 1
  • 1
timpone
  • 19,235
  • 36
  • 121
  • 211

1 Answers1

0

You're correct in that you can't access current_user from a model.

As for the answer you linked, I'm not entirely sure but I think it's not fully thread-safe. From the same question, I like this answer https://stackoverflow.com/a/12713768/4035338 more.

Say we have a controller with this action

...
def update
  @my_object = MyModel.find(params[:id])
  @my_object.current_user = current_user
  @my_object.assign_attributes params[:my_model]
  @my_object.save
end
...

and this model

class MyModel < ActiveRecord::Base
  attr_accessor :current_user

  before_save :log_who_did_it

  private

  def log_who_did_it
    return unless current_user.present?
    puts "It was #{current_user}!"
  end
end

Or my favourite

...
def update
  @my_object = MyModel.find(params[:id])
  @my_object.update_and_log_user(params[:my_model], current_user)
end
...

class MyModel < ActiveRecord::Base
  ...

  def update_and_log_user(params, user)
    update_attributes(params)
    puts "It was #{user}!" if user.present?
  end
end
Community
  • 1
  • 1
sjaime
  • 1,480
  • 9
  • 16
  • thx, sjaime - I like your alternatives but wonder if this is making it harder than it needs to be. Why not just make a global curernt user and manage it along with my current_user in application_controller. It prevents me from having to change a bunch of classes or adding attributes that don't really belong there. I've updated my question with an edit with some code. – timpone Dec 27 '14 at 16:04