This may come in handy if you want to keep a track on what happened to your database records over time. As you know database is where the Active Record objects go to sleep. Why would you not want to know the activities that when on on each object.
Say you have a bicycle record in the bicycles. And a you painted one bike from blue to bright yellow. So you updated the bicycles colour as yellow. You may never know that it was once blue. If you have a change log, it would say back in the day this bikes colour was changed to yellow from blue. Also you can keep a track on who updated the records in your database as the object changes its state.
It is best to keep the changes in a separate table. So lets call that table "happenings" or "activities"
Here is happening migration file and 'description' is where the changes hash goes in.
class CreateHappenings < ActiveRecord::Migration
def change
create_table :happenings do |t|
t.text :description
t.integer :user_id
t.string :happenable_type
t.integer :happenable_id
t.timestamps
end
end
end
This is that 'happenings.rb' table
class Happening < ActiveRecord::Base
belongs_to :happenable, :polymorphic => true
belongs_to :user
serialize :description, Hash
def self.create_from_action(info )
happening = Happening.new
happening.user_id = info[:current_user]
happening.happenable_type = info[:happenable_type]
happening.happenable_id = info[:happenable_id]
happening.description = info[:updatings]
happening.save
end
def parse_the_hash
itm = self.description
unless itm.empty?
hello = []
itm.each do |k, v|
unless k == "updated_at" || k == "created_at" || v.all?(&:blank?)
if v.first.present? && v.first.length == 0
hello << "#{k} updated to #{v.last}"
else
hello << "#{k} changed from #{v.first} to #{v.last}"
end
end
end
hello.join(", ")
end
end
end
def obj_before_after_difference(before, after)
((before.keys - ["updated_at"]) + (after.keys - ["updated_at"])).uniq.inject({}) do |memo, key|
unless before.key?(key) && after.key?(key) && before[key] == after[key]
memo[key] = [before.key?(key) ? before[key] : :_no_key, after.key?(key) ? after[key] : :_no_key]
end
memo
end
end
So now you can put this method in your update method.
def update
@pricing = Pricing.find(params[:id])
before = @pricing.attributes
respond_to do |format|
if @pricing.update(pricing_params)
format.html { redirect_to :back }
format.json { render :show, status: :ok, location: @pricing }
after = @pricing.attributes
Happening.create_from_action(:current_user => current_user.id, :happenable_type => "Pricing",:happenable_id => @pricing.id, :updatings => obj_before_after_difference(before, after) )
else
format.html { render :edit }
format.json { render json: @pricing.errors, status: :unprocessable_entity }
end
end
end
Now to see all the changes. In your "show.html.erb" file you could add a activity list.
Activity list
<%the_obj.happenings.order("created_at DESC").each do |happ|%>
<% unless happ.description.empty? %>
-<%=happ.parse_the_hash %> (on: <%=happ.created_at.strftime("%d-%m-%Y - %l:%M %p")%> by <%= happ.user.name if happ.user %>)
<%end%>
<%end%>