Is it a good idea to access an observer session or not?

I want to register user actions in my Ruby on Rails application.

So far I have a model observer that inserts the logs into the database after the updates and creates. To save which user performed the action that was logged in, I need access to the session, but this is problematic.

First, it breaks down the MVC model. Secondly, the methods range from hacker to outlandish, perhaps even linking the implementation to the Mongrel server.

What is the right approach?

+7
ruby ruby-on-rails logging session observers
source share
6 answers

I think this is a very interesting question. I'll think out loud here a minute ...

Ultimately, what we are faced with is the decision to violate the acceptable design pattern practice in order to achieve a certain set of functionality. So we have to ask ourselves

1) What are the possible solutions that would not violate the MVC pattern

2) What are the possible solutions that would violate the MVC pattern

3) Which option is better? I believe that design patterns and standard methods are very important, but at the same time, if holding them makes your code more complex, the rule may be a violation of the rules. Some people may disagree with me about this.

Let's take a look at # 1 first.

From above my head, I would think of the following possible solutions

A) If you are really interested in who performs these actions, should this data be stored in the model in any way? This will make this information available to your supervisor. And that also means that any other user interface of your ActiveRecord class gets the same features.

B) If you are not very interested in understanding who created the record, but are more interested in registering the web actions themselves, then you can think about "observing" the actions of the controller. It has been a while since I climbed the Rails source, so I’m not sure that their ActiveRecord :: Observer "watches" the model, but you can adapt it to the controller observer. In this sense, you no longer observe the model, and it makes sense to make this information about the session and other information such as a controller to this observer. C) The simplest solution with the smallest "structure" is to simply drop your registration code at the end of your action methods that you are looking at.

Consider option number 2, violating the methods of MVC.

A) As you suggest, you could find means so that your Observer model has access to session data. You have tied your model to your business logic.

B) It is impossible to invent others :)

My personal inclination, not knowing more details about your project, is either 1A if I want to attach people to posts, or 1C if there are only a few places where I am interested in this. If you really want a reliable logging solution for all your controllers and actions, you can consider 1B.

If your model observer discovers that the session data is a little β€œsmelly” and is likely to break if you try to use your model in any other project / situation / context.

+3
source share

Germ, this is a sticky situation. You pretty much have to break MVC in order to make it work beautifully.

I would do something like this:

class MyObserverClass < ActiveRecord::Observer cattr_accessor :current_user # GLOBAL VARIABLE. RELIES ON RAILS BEING SINGLE THREADED # other logging code goes here end class ApplicationController before_filter :set_current_user_for_observer def set_current_user_for_observer MyObserverClass.current_user = session[:user] end end 

This is a bit hacky, but it is no more hacky than many other main rails that I have seen.

All you have to do to make it streamed (it only matters when running on jruby anyway) is to change cattr_accessor as a suitable method and store it in a local data store

+6
source share

You are right about this in violation of MVC. I would suggest using callbacks in your controllers, mainly because there are situations (for example, a model that is called but not checked) where you do not want the observer to register anything.

+1
source share

I found a clean way to do what suggested the answer I chose.

http://pjkh.com/articles/2009/02/02/creating-an-audit-log-in-rails

This solution uses the AuditLog model as well as the TrackChanges module to add tracking features to any model. You still need to add a row to the controller when updating or creating.

+1
source share

In the past, when I did something like this, I tended to extend the User model class to include the idea of ​​a "current user"

Looking at the previous answers, I see suggestions for keeping the actual active user of the record in the session. This has several disadvantages.

  • It stores a possibly large object in the session database
  • This means that the user's copy is "cached" for the entire time (or until logging out). This means that any changes in the status of this user will not be recognized until the user logs out and logs in. This means, for example, that an attempt to disconnect a user will wait for him to log out and back. This is probably not the behavior you want.

So, at the beginning of the request (in the filter), you take user_id from the session and read the user by setting User.current_user.

Something like that...

 class User
   cattr_accessor: current_user
 end

 class application
   before_filter: retrieve_user

   def retrieve_user
     if session [: user_id] .nil?
       User.current_user = nil
     else
       User.current_user = User.find (session [: user_id])
     end
   end
 end

From now on, it should be trivial.

0
source share

All Articles