diff --git a/app/models/collection.rb b/app/models/collection.rb
index a03bcbadb6067cfe24d141e06ddfb9dfc34e1fed..632f2179105d5b251b5c79986c978475df9afd0c 100644
--- a/app/models/collection.rb
+++ b/app/models/collection.rb
@@ -119,4 +119,8 @@ class Collection < ApplicationRecord
   def download_link
     '/'+PackageService.link(self)
   end
+
+  def ignore_changes
+    super + %w(score views_count downloads_count likes_count shares_count follows_count)
+  end
 end
diff --git a/app/models/concerns/trackable.rb b/app/models/concerns/trackable.rb
index a8da93f4f48c87701517dfcfef7be35c2164abd5..8b773ce9eff8d5b9f4b6e2d69ea650821748627b 100644
--- a/app/models/concerns/trackable.rb
+++ b/app/models/concerns/trackable.rb
@@ -1,12 +1,53 @@
 module Trackable
   extend ActiveSupport::Concern
-  include PublicActivity::Model
+  include PublicActivity::Common
   include ActivitiesFilterService
 
   included do
-    tracked owner: proc { |controller, model| model.try(:user) || model.try(:owner) || controller.try(:current_user) }
-    tracked recipient: proc { |_controller, model| model.try(:recipient) || model }
-    tracked privacy: proc { |_controller, model| model.try(:privacy) || "public" }
+    after_create :new_create_activity
+    after_destroy :new_destroy_activity
+    after_update :new_update_activity
+  end
+
+  private
+
+  def new_update_activity
+    return nil if changed.blank?
+    return new_activity(:update) if ignore_changes == %w(updated_at)
+    filtered = changed.reject { |x| ignore_changes.include?(x) }
+    new_activity(:update) unless filtered.empty?
+  end
+
+  def new_create_activity
+    new_activity(:create)
+  end
+
+  def new_destroy_activity
+    new_activity(:destroy)
+  end
+
+  def new_activity(action)
+    create_activity(
+      action,
+      owner: activity_owner,
+      recipient: activity_recipient,
+      privacy: activity_privacy
+    )
+  end
+
+  def ignore_changes
+    %w(updated_at)
+  end
+
+  def activity_owner
+    proc { |controller, model| model.try(:user) || model.try(:owner) || controller.try(:current_user) }
+  end
+
+  def activity_recipient
+    proc { |_controller, model| model.try(:recipient) || model }
+  end
 
+  def activity_privacy
+    proc { |_controller, model| model.try(:privacy) || 'public' }
   end
 end
diff --git a/app/models/learning_object.rb b/app/models/learning_object.rb
index b3df1847119e84a9d013d838e9dc3f35ab3f7a96..dee6c17462c6d9b7a1ff8bfbe3529ccf0b69ac49 100644
--- a/app/models/learning_object.rb
+++ b/app/models/learning_object.rb
@@ -61,7 +61,7 @@ class LearningObject < ApplicationRecord
   belongs_to :object_type
   belongs_to :attachment, class_name: 'LearningObject::Attachment'
 
-  validates_presence_of :name, :publisher, :object_type, :language, :author, unless: :draft?
+  validates :name, :publisher, :object_type, :language, :author, unless: :draft?, presence: true
   validates :id_dspace, presence: true, uniqueness: true, unless: :published?
 
   default_scope { includes(:object_type, :attachment, :attachments) }
@@ -111,7 +111,7 @@ class LearningObject < ApplicationRecord
 
   # If a LO has more than one object, this gives the location of the main one
   def default_attachment_location
-    object_type.try(:name) == ("Vídeo" || "Áudio") ? default_attachment.try(:retrieve_cache_link) : default_attachment.try(:retrieve_url)
+    object_type.try(:name) == ('Vídeo' || 'Áudio') ? default_attachment.try(:retrieve_cache_link) : default_attachment.try(:retrieve_url)
   end
 
   def default_thumbnail
@@ -135,6 +135,10 @@ class LearningObject < ApplicationRecord
     default_attachment_location
   end
 
+  def ignore_changes
+    super + %w(score views_count downloads_count likes_count shares_count)
+  end
+
   ## score methods
   def normalized_collected
     max = CollectionItem.where(collectionable_type: 'LearningObject').group(:collectionable_id).order('count_all DESC').count
diff --git a/app/models/user.rb b/app/models/user.rb
index 41cf256fb701fd2f6ff2b7c15b362e1399e3b484..a68598c89afae37d02363749e9d3cf099514464c 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -41,12 +41,9 @@ class User < ApplicationRecord
   include Tagger
   include Complainable
   include Publisher
-  include PublicActivity::Common
+  include Trackable
   include ActivitiesFilterService
 
-  after_create -> { new_activity("create") }
-  after_update -> { new_activity("update") }
-
   # Include default devise modules. Others available are:
   # :confirmable, :lockable, :timeoutable and :omniauthable
   devise :database_authenticatable, :registerable,
@@ -79,7 +76,7 @@ class User < ApplicationRecord
 
   has_attached_file :cover, styles: { medium: '800x300>', thumb: '160x60>' }, default_url: ''
   validates_attachment_content_type :cover, content_type: ['image/jpg', 'image/jpeg', 'image/png', 'image/gif']
-  
+
   validates :terms_of_service, acceptance: true
 
   searchkick language: 'brazilian', match: :word_start, searchable: [:name], callbacks: :async
@@ -207,13 +204,11 @@ class User < ApplicationRecord
     )
   end
 
-  def new_activity(type)
-    should_create = true
-    if type == "update"
-      ignore = ["tokens", "sign_in_count", "current_sign_in_at", "last_sign_in_at", "updated_at"]
-      filtered = changed.reject { |x| ignore.include?(x) }
-      should_create = !filtered.empty?
-    end
-    self.create_activity key: 'user.'+type, trackable: self, owner: self, recipient: self, privacy: "public" if should_create
+  def activity_owner
+    self
+  end
+
+  def ignore_changes
+    super + %w(tokens sign_in_count current_sign_in_at last_sign_in_at current_sign_in_ip last_sign_in_ip score follows_count confirmation_token confirmed_at confirmation_sent_at)
   end
 end