views:

64

answers:

4

How do I come to know whether a create or any other action has been called from inside a model. Basically I am doing database logging and want to track whether a create or other actions are being performed.

For doing the logging part I am using the concept of ActiveRecord::Observer. But there I am not able to find out whether the user is creating or doing something else. So please tell me some way that rails provides us to identify the action inside the model.

thanks in advance.

A: 

Hi, Which ever action is called in application is stored in params[:action] and params is not accessible in models. So i don't think you can see which action is getting called from models.

Thanks,Anubhaw

Anubhaw
hey thanks @Anubhaw. I knew that part. But ActiveRecord::Observer is a ActiveRecord class i.e model-like and there might be some way around.
Rohit
hey you can look at the following post http://m.onkey.org/2007/10/17/how-to-access-session-cookies-params-request-in-model, but it is not the best method to as you would find out in the post itself. I don't have knowledge about Observers.
Anubhaw
+3  A: 

Such this kind of tracking should be performed on the Controller. Observers are only model-aware and should be model-aware only.

Consider the case where you are updating the object from the console. The observer will be triggered, but you have no request context here.

Simone Carletti
Thanks for the extra knowledge, but I want to create a log as I told earlier and I have a column which stores the action that has been performed. And the logging part is being performed in the Observer.
Rohit
this, listen to simone. There is a reason you don't have access to request data in your models.
Faisal
I understand @Faisal but that is the need of the situation. What can I do?
Rohit
What I would do is forget the entire model observer idea. Create a before/after filter on your controller (or ApplicationController to monitor everything), and create a specific Log model that the filter would use to log actions. If you need to log the object being created itself, you can switch from a filter to a private method that you call from your controller action whenever you want to log anything and pass the appropriate parameters.
Faisal
A: 

You can use a before_save to trigger an event when the model is saved. To determine if it is a save or a create you have this method new_record? which will tell you if it's a new instance or not. You can also know which attributes have changed

hellvinz
@hellvinz this will definitely distinguish between the new and update action but what if the user has deleted a record. How do you track a destroy action
Rohit
before_destroy: http://railsapi.com/doc/rails-v2.3.8/classes/ActiveRecord/Callbacks.html#M001205
hellvinz
oops sorry forgot the before_destroy callback :)
Rohit
what if I use the after_save trigger can this be done
Rohit
A: 

This is not recommended from architectural point of view but this is used only for low level logging deep inside Model and doesn't do any harm. Also this is thread-safe solution.

ApplicationController or just single controller:

around_filter :store_remote_ip_in_thread

def store_remote_ip_in_thread
  begin
    Thread.current[:remote_ip] = request.remote_ip
    yield
  ensure
    Thread.current.delete :remote_ip
  end
end

Reusable module for retrieval:

module RemoteIpAware
  def current_remote_ip
    Thread.current[:remote_ip] || '-'
  end
end

Somewhere in model/mailer/lib class:

 include RemoteIpAware
 ...
 #use current_remote_ip method anywhere

Keep in mind I wrote it from my memory.. syntax may not be ok ;) In you case instead of remote IP you can save params[:action] :controller name etc..

gertas
Please DON'T DO THAT. Threads are not PHP-like global variables and shouldn't be used in that way.
Simone Carletti