myexperiment-hackers
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[myexperiment-hackers] [2033] branches/event_logging/app/helpers/applica


From: noreply
Subject: [myexperiment-hackers] [2033] branches/event_logging/app/helpers/application_helper.rb: News generation.
Date: Fri, 5 Dec 2008 07:37:35 -0500 (EST)

Revision
2033
Author
alekses6
Date
2008-12-05 07:37:35 -0500 (Fri, 05 Dec 2008)

Log Message

News generation. Work on news entry grouping.

Code still more refactored - now all decision-making about grouping of events is done is one place.

Bookmarks now grouped: "User X added File1, File2, Workflow3 to their favourites."

Modified Paths

Diff

Modified: branches/event_logging/app/helpers/application_helper.rb (2032 => 2033)


--- branches/event_logging/app/helpers/application_helper.rb	2008-12-04 18:09:51 UTC (rev 2032)
+++ branches/event_logging/app/helpers/application_helper.rb	2008-12-05 12:37:35 UTC (rev 2033)
@@ -1747,7 +1747,7 @@
     puts "=============== GROUPING ================="
     # END DEBUG
     
-    related_activity_loggable_ids = []
+    related_objects = []
     array_ids_to_delete = []
     grouping_happened = false
     
@@ -1767,9 +1767,9 @@
       new_event = events_unique[i]
       reset_required = true
       
-      # check if grouping will happen
+      
+      # DEBUG
       if (new_event.created_at - base_event.created_at <= EVENT_GROUPING_TIMEFRAME)
-        # DEBUG
         puts "timeframe match: seq_start(#{seq_start_idx}) -> current(#{i})"
         puts "new: " + new_event.action + " base: " + base_event.action + " #{ new_event.action == base_event.action}"
         puts "new: " + new_event.activity_loggable_type + " base: " + base_event.activity_loggable_type + " #{ new_event.activity_loggable_type == base_event.activity_loggable_type}"
@@ -1781,31 +1781,25 @@
         puts "-- first condition of further check: #{["Tagging"].include? new_event.activity_loggable_type}"
         puts "-- second condition of further check: #{new_event.action == "create"}"
         puts "\n"
+      end  
+      # END DEBUG
+      
+      
+      # check if grouping will happen
+      grouping_allowed, related_object = group_event_with_base?(new_event, base_event)
+      if grouping_allowed
+        # events are within the correct timeframe and potentially can be grouped
         
+        # DEBUG
+        puts "grouping should happen"
         # END DEBUG
         
-        # events are within the correct timeframe, potentially can be grouped
-        if group_event_with_base?(true, new_event, base_event)
-          
-          # DEBUG
-          puts "grouping should happen"
-          # END DEBUG
-          
-          seq_timestamp = [new_event.created_at, new_event.updated_at]
-          related_activity_loggable_ids << new_event.activity_loggable_id
-          array_ids_to_delete << i
-          
-          grouping_happened = true
-          reset_required = false
-
-        elsif group_event_with_base?(false, new_event, base_event)
-           
-           seq_timestamp = [new_event.created_at, new_event.updated_at]
-           array_ids_to_delete << i
-           
-           grouping_happened = true
-           reset_required = false
-        end
+        seq_timestamp = [new_event.created_at, new_event.updated_at]
+        related_objects << related_object
+        array_ids_to_delete << i
+        
+        grouping_happened = true
+        reset_required = false
       end
       
       if reset_required
@@ -1818,7 +1812,7 @@
           
           events_unique[seq_start_idx].created_at = seq_timestamp[0]
           events_unique[seq_start_idx].updated_at = seq_timestamp[1]
-          events_unique[seq_start_idx] = [events_unique[seq_start_idx], related_activity_loggable_ids]
+          events_unique[seq_start_idx] = [events_unique[seq_start_idx], related_objects]
           # delete all (now) redundant elements
           array_ids_to_delete.each do |del_idx|
             events_unique.delete_at(del_idx)
@@ -1829,7 +1823,7 @@
         seq_start_idx = i # current element becomes the start of the sequence
         base_event = events_unique[seq_start_idx]
         seq_timestamp = nil
-        related_activity_loggable_ids = []
+        related_objects = []
         array_ids_to_delete = []
         grouping_happened = false
       end
@@ -1846,7 +1840,7 @@
       
       events_unique[seq_start_idx].created_at = seq_timestamp[0]
       events_unique[seq_start_idx].updated_at = seq_timestamp[1]
-      events_unique[seq_start_idx] = [events_unique[seq_start_idx], related_activity_loggable_ids]
+      events_unique[seq_start_idx] = [events_unique[seq_start_idx], related_objects]
       # delete all (now) redundant elements
       array_ids_to_delete.each do |del_idx|
         events_unique.delete_at(del_idx)
@@ -1904,11 +1898,11 @@
     if log_entry_container.class.name == "Array"
       # if log_entry_container holds an array, the zeroth element is the actual log_entry object!
       log_entry = log_entry_container[0]
-      extra_ids = log_entry_container[1]
+      extra_objects = log_entry_container[1]
     else
       # the log entry container should be the log_entry itself
       log_entry = log_entry_container
-      extra_ids = []
+      extra_objects = []
     end
     
     rtn = [] # despite this, NIL will be returned on errors / when news entry not to be shown for current user
@@ -2275,18 +2269,42 @@
       when "Bookmark"
         if action == "create"
           begin
-            # information from the actual bookmark instance is not used directly, however this check is required to ensure that - 
-            # RecordNotFound exception will be thrown and the news item won't appear if the bookmark was subsequently removed after creation
-            bookmark = Bookmark.find(log_entry.activity_loggable_id)
-            object, object_path = evaluate_object_instance_and_path(log_entry.referenced_type, log_entry.referenced_id)
-            object_visible_name = contributable_name_from_instance(object)
+            # process potentially multiple bookmarks
+            all_bookmark_ids = [log_entry.activity_loggable_id]
+            extra_objects.each do |extra_bookmark|
+              # all of the "extra objects" will be bookmarks, no need to check the type
+              all_bookmark_ids << extra_bookmark[1]
+            end
+            not_found_bookmark_count = 0
+            bookmarked_items_strings = []
             
-            # the news item to be displayed if the current viewer is allowed to see the affected contributable
-            authorized = ( my_event || object.authorized?("view", current_viewer) )
+            all_bookmark_ids.each do |bookmark_id|
+              # protected block required to ensure that if several - not all bookmarks are missing, remaining still get displayed
+              begin
+                bookmark = Bookmark.find(bookmark_id)
+                
+                object, object_path = evaluate_object_instance_and_path(bookmark.bookmarkable_type, bookmark.bookmarkable_id)
+                object_visible_name = contributable_name_from_instance(object)
+                
+                # the news item to be displayed if the current viewer is allowed to see the affected contributable(s)
+                authorized = ( my_event || object.authorized?("view", current_viewer) )
+                
+                if authorized
+                  bookmarked_items_strings << [link_to(object_visible_name, object_path) + " " + model_visible_name(object.class.name, true, object)]
+                end
+              rescue ActiveRecord::RecordNotFound
+                not_found_bookmark_count += 1
+              end
+            end
             
-            if authorized
-              rtn << [timestamp, "#{culprit_link} <span class='news_feed_action'>added</span> #{link_to object_visible_name, object_path} #{model_visible_name(log_entry.referenced_type.to_s, true, object)} to their #{link_to "favourites", user_path(log_entry.culprit_id) + "/favourites"}.", "Favourites"]
+            if not_found_bookmark_count == all_bookmark_ids.length
+              raise ActiveRecord::RecordNotFound, "None of the bookmarks found"
             end
+            
+            # authorization was done when this array was filled up - if it's empty, nothing to display (potentially because of the authorization)
+            unless bookmarked_items_strings.empty?
+              rtn << [timestamp, "#{culprit_link} <span class='news_feed_action'>added</span> #{bookmarked_items_strings.join(", ")} to their #{link_to "favourites", user_path(log_entry.culprit_id) + "/favourites"}.", "Favourites"]
+            end
           rescue ActiveRecord::RecordNotFound
             # do nothing, but don't display the news entry for missing bookmark / object
           end
@@ -2403,35 +2421,40 @@
       when "Tagging"
         if action == "create"
           begin
-            # process potentially multiple tags
-            all_tagging_ids = [log_entry.activity_loggable_id]
-            all_tagging_ids.concat(extra_ids)
-            not_found_tag_count = 0
-            tag_strings = []
-            
-            all_tagging_ids.each do |tagging_id|
-              # protected block required to ensure that if several - not all tags are missing, remaining still get displayed
-              begin
-                tagging = Tagging.find(tagging_id)
-                tag = Tag.find(tagging.tag_id)
-                tag_strings << ["\"" + link_to(tag.name, tag_path(tag.id)) + "\""]
-              rescue ActiveRecord::RecordNotFound
-                not_found_tag_count += 1
-              end
-            end
-            
-            if not_found_tag_count == all_tagging_ids.length
-              raise ActiveRecord::RecordNotFound, "None of the tags found"
-            end
-            
-            
             object, object_path = evaluate_object_instance_and_path(log_entry.referenced_type, log_entry.referenced_id)
             object_visible_name = contributable_name_from_instance(object)
             
             # the news item to be displayed if the current viewer is allowed to see the affected contributable
+            # (it's fine to do authorization only once, because all tags refer to the same object)
             authorized = ( my_event || object.authorized?("view", current_viewer) )
             
+            # multiple tag processing is quite DB intensive, so if the object not authorized for 
+            # current viewer, no need to do anything further
             if authorized
+              # process potentially multiple tags
+              all_tagging_ids = [log_entry.activity_loggable_id]
+              extra_objects.each do |extra_tagging|
+                # all of the "extra objects" will be taggings, no need to check the type
+                all_tagging_ids << extra_tagging[1]
+              end
+              not_found_tag_count = 0
+              tag_strings = []
+              
+              all_tagging_ids.each do |tagging_id|
+                # protected block required to ensure that if several - not all tags are missing, remaining still get displayed
+                begin
+                  tagging = Tagging.find(tagging_id)
+                  tag = Tag.find(tagging.tag_id)
+                  tag_strings << ["\"" + link_to(tag.name, tag_path(tag.id)) + "\""]
+                rescue ActiveRecord::RecordNotFound
+                  not_found_tag_count += 1
+                end
+              end
+              
+              if not_found_tag_count == all_tagging_ids.length
+                raise ActiveRecord::RecordNotFound, "None of the tags found"
+              end
+            
               rtn << [timestamp, "#{culprit_link} <span class='news_feed_action'>tagged</span> #{link_to object_visible_name, object_path} #{model_visible_name(log_entry.referenced_type.to_s, true, object)} with #{tag_strings.join(", ")}.", "Tags"]
             end
           rescue ActiveRecord::RecordNotFound
@@ -2540,28 +2563,36 @@
   end
   
   
-  # this method assumes that the two events are within a certain timeframe and decides if
-  # these can be grouped or not;
-  # "should_have_accummulated_ids" parameter chooses between two types of grouping behaviour:
-  # -- one option is to pick the latest of all events (because they don't add any new information) (false)
-  # -- another option is to accummulate the items the news entries are pointing to and present them as one (true)
-  def group_event_with_base?(should_have_accummulated_ids, new_event, base_event)
+  # This method decides whether the "new_event" can be grouped with "base_event";
+  # (Assumption is made that the two events are within a certain timeframe to allow grouping)
+  #
+  # Two types of grouping behaviour is possible:
+  # -- one option is to pick the latest of all events (because they don't add any new information) (like for "Profile" updates)
+  # -- another option is to accummulate the items the news entries are pointing to and present them as one (like for "Tagging" - "X tagged with A,B,C")
+  #
+  # Method returns an array in the form: [allow_grouping, [related_object_type, related_object_id]]
+  # * allow_grouping - boolean value; "true" when the events should be grouped;
+  # * related_object_type/ID - related object (like tag "B") which should be grouped with the object in the base event (like tag "A")
+  def group_event_with_base?(new_event, base_event)
     ans = false
+    related_object = []
     
-    if should_have_accummulated_ids
+    if (new_event.created_at - base_event.created_at <= EVENT_GROUPING_TIMEFRAME)
       # action "create" && "Tagging" && ActivityLoggableType match (IDs can vary) && CulpritType/CulpritID match && ReferencedType/ReferencedID match
       if ((["Tagging"].include? new_event.activity_loggable_type) && new_event.action == "create" &&
           new_event.action == base_event.action && new_event.activity_loggable_type == base_event.activity_loggable_type &&
           new_event.culprit_type == base_event.culprit_type && new_event.culprit_id == base_event.culprit_id &&
           new_event.referenced_type == base_event.referenced_type && new_event.referenced_id == base_event.referenced_id)
         ans = true
+        related_object = ["Tagging", new_event.activity_loggable_id]
       
       # action "create" && "Bookmark" && ActivityLoggableType match (IDs can vary) && CulpritType/CulpritID match --> Referenced :: Any type / ID
       elsif ((["Bookmark"].include? new_event.activity_loggable_type) && new_event.action == "create" &&
              new_event.action == base_event.action && new_event.activity_loggable_type == base_event.activity_loggable_type &&
              new_event.culprit_type == base_event.culprit_type && new_event.culprit_id == base_event.culprit_id)
         ans = true
-        
+        related_object = ["Bookmark", new_event.activity_loggable_id]
+      
       # action "create" && "Creditation|Attribution" && ActivityLoggableType match (IDs can vary) && CulpritType/CulpritID match --> Referenced :: Any type / ID
       # but need to add more strict check on the timestamp - will attempt to group only creditations / attributions at exact same date / time
       elsif ((["Creditation", "Attribution"].include? new_event.activity_loggable_type) && new_event.action == "create" &&
@@ -2569,18 +2600,20 @@
              new_event.culprit_type == base_event.culprit_type && new_event.culprit_id == base_event.culprit_id &&
              new_event.created_at == base_event.created_at && new_event.updated_at == base_event.updated_at)
         ans = true
-      end
-    else
+        related_object = [new_event.activity_loggable_type, new_event.activity_loggable_id]
+      
       # action "update" && "Profile" && ActivityLoggableType match && CulpritType/CulpritID match && ReferencedType/ReferencedID match
-      if ((["Profile"].include? new_event.activity_loggable_type) && new_event.action == "update" &&
+      elsif ((["Profile"].include? new_event.activity_loggable_type) && new_event.action == "update" &&
           new_event.action == base_event.action && new_event.activity_loggable_type == base_event.activity_loggable_type &&
           new_event.culprit_type == base_event.culprit_type && new_event.culprit_id == base_event.culprit_id &&
           new_event.referenced_type == base_event.referenced_type && new_event.referenced_id == base_event.referenced_id)
-        ans = true 
+        ans = true
+        # related_object not required in this case
       end
+      
     end
     
-    return ans
+    return [ans, related_object]
   end
   
   ######################################################  

reply via email to

[Prev in Thread] Current Thread [Next in Thread]