Hello Friends,
Logging is a very important feature if you are creating an applicaton which will be accessed and edited by multiple users. Basically logging can be done in the following two ways:
- Log files
- Database Logging
Both of these mechanisms are supported by Rails. If you want to do logging using the first mechanism, you can simply use the Logger
class. Also this mechanism is quite easy to implement. As the details get stored in the default environment’s .log file. You can also change the file in which you want to store the logs. You can refer the documentation of the Logger
class.
Well anyways I am going to show you the other way around. Let’s see how do we log the changes made to the system in a database. First of all, we need a model, in which we will save the changes that take place in the system. You can create the model by using the command:
ruby script/generate model log_data
This will generate some files as below:
exists app/models/
exists test/unit/
exists test/fixtures/
create app/models/log_data.rb
create test/unit/log_data_test.rb
create test/fixtures/log_datas.yml
exists db/migrate
create db/migrate/20100819114624_create_log_datas.rb
As we need to log data for the complete application we need a polymorphic association between this model and all the rest of the models in the app directory. You can do this by taking the help of polymorphic associations. Now, as the final step of our preparation phase, we need to declare a method in the log_data model which will actually store the data in the database. Well, I have tracked the following things:
- user id
- action that is being performed
- new content in json format
- previous content in json format
You can also store the IP address of the machine from where the data is being altered, the time for which the user was logged in and many more as per your requirements. You can create the method as below:
class LogData < ActiveRecord::Base
def self.start_logging(current_user, data, action, new_content ={}, old_content ={})
# data => the model which is being created, updated or deleted
@log_data = data.log_datas.build(:user_id => user, :action => action, :new_content => new_content.to_json, : old_content => old_content.to_json)
@log_data.save
end
end
Now you just need to call this method. In each of your create, delete and update actions. In your book_controller.rb, create and destroy action you can use this piece of code:
class BooksController < ApplicationController
def create
@book = Book.new(params[:book])
if @book.save
LogData.start_logging(current_user,@book,params[:action],params[:book],"No previous content")
end
end
def destroy
@book = Book.find(params[:id])
LogData.start_logging(current_user,@book,params[:action],"Content Deleted",@book)
@book.destroy
end
end
And for the update action we might need the previous content as well as the new content. This can be done in the model by using the before_update callback like this in your book.rb.
class Book < ActiveRecord::Base
before_save :log_data
def log_data
book = self.class.find(:first, self.id)
if book.attributes != self.attributes
LogData.start_logging(User.current,self,"update",self.attributes,event.attributes)
end
end
end
You can get the User.current by using the Thread class provided by Rails. A detailed version of this is available here. And now you are all set to log your user activity in the database instead of using the primitive log files mechanism. If anyone has any suggestions, those people are heartly welcome.
Hope you found this article helpful.