FIX: post owner should be considered as any other invitable

FIX: post owner should be considered as any other invitable

diff --git a/app/controllers/discourse_post_event/invitees_controller.rb b/app/controllers/discourse_post_event/invitees_controller.rb
index 66b3266..26c2f82 100644
--- a/app/controllers/discourse_post_event/invitees_controller.rb
+++ b/app/controllers/discourse_post_event/invitees_controller.rb
@@ -17,24 +17,12 @@ module DiscoursePostEvent
     end
 
     def update
-      invitee = Invitee.find(params[:id])
-      guardian.ensure_can_act_on_invitee!(invitee)
-      status = Invitee.statuses[invitee_params[:status].to_sym]
-      invitee.update_attendance(status: status)
-      invitee.event.publish_update!
+      invitee = Invitee.upsert_attendance!(params[:id], invitee_params, guardian)
       render json: InviteeSerializer.new(invitee)
     end
 
     def create
-      status = Invitee.statuses[invitee_params[:status].to_sym]
-      event = Event.find(invitee_params[:post_id])
-      guardian.ensure_can_see!(event.post)
-      invitee = Invitee.create!(
-        status: status,
-        post_id: invitee_params[:post_id],
-        user_id: current_user.id,
-      )
-      invitee.event.publish_update!
+      invitee = Invitee.upsert_attendance!(current_user.id, invitee_params, guardian)
       render json: InviteeSerializer.new(invitee)
     end
 
diff --git a/app/models/discourse_post_event/event.rb b/app/models/discourse_post_event/event.rb
index f82ca7e..0c13b6f 100644
--- a/app/models/discourse_post_event/event.rb
+++ b/app/models/discourse_post_event/event.rb
@@ -109,26 +109,10 @@ module DiscoursePostEvent
       @statuses ||= Enum.new(standalone: 0, public: 1, private: 2)
     end
 
-    def most_likely_going(current_user, limit = SiteSetting.displayed_invitees_limit)
-      most_likely = []
-
-      if self.can_user_update_attendance(current_user)
-        most_likely << Invitee.find_or_initialize_by(
-          user_id: current_user.id,
-          post_id: self.id
-        )
-      end
-
-      most_likely << Invitee.new(
-        user_id: self.post.user_id,
-        status: Invitee.statuses[:going],
-        post_id: self.id
-      )
-
-      most_likely + self.invitees
+    def most_likely_going(limit = SiteSetting.displayed_invitees_limit)
+      self.invitees
         .order([:status, :user_id])
-        .where.not(user_id: current_user.id)
-        .limit(limit - most_likely.count)
+        .limit(limit)
     end
 
     def publish_update!
@@ -160,7 +144,6 @@ module DiscoursePostEvent
 
     def can_user_update_attendance(user)
       !self.is_expired? &&
-      self.post.user != user &&
       (
         self.status == Event.statuses[:public] ||
         (
diff --git a/app/models/discourse_post_event/invitee.rb b/app/models/discourse_post_event/invitee.rb
index 8198679..872de57 100644
--- a/app/models/discourse_post_event/invitee.rb
+++ b/app/models/discourse_post_event/invitee.rb
@@ -19,6 +19,27 @@ module DiscoursePostEvent
       self.update!(params)
     end
 
+    def self.upsert_attendance!(user_id, params, guardian)
+      invitee = Invitee.find_by(id: user_id)
+      status = Invitee.statuses[params[:status].to_sym]
+
+      if invitee
+        guardian.ensure_can_act_on_invitee!(invitee)
+        invitee.update_attendance(status: status)
+      else
+        event = Event.find(params[:post_id])
+        guardian.ensure_can_see!(event.post)
+        invitee = Invitee.create!(
+          status: status,
+          post_id: params[:post_id],
+          user_id: user_id,
+        )
+      end
+
+      invitee.event.publish_update!
+      invitee
+    end
+
     def self.extract_uniq_usernames(groups)
       User.where(
         id: GroupUser.where(
diff --git a/app/serializers/discourse_post_event/event_serializer.rb b/app/serializers/discourse_post_event/event_serializer.rb
index 83fbe26..975af93 100644
--- a/app/serializers/discourse_post_event/event_serializer.rb
+++ b/app/serializers/discourse_post_event/event_serializer.rb
@@ -56,7 +56,7 @@ module DiscoursePostEvent
       counts = object.invitees.group(:status).count
 
       # event creator is always going so we add one
-      going = (counts[Invitee.statuses[:going]] || 0) + (object.is_expired? ? 0 : 1)
+      going = counts[Invitee.statuses[:going]] || 0
       interested = counts[Invitee.statuses[:interested]] || 0
       not_going = counts[Invitee.statuses[:not_going]] || 0
       unanswered = counts[nil] || 0
@@ -70,18 +70,10 @@ module DiscoursePostEvent
     end
 
     def watching_invitee
-      if scope.current_user === object.post.user
-        watching_invitee = Invitee.new(
-          user_id: object.post.user.id,
-          status: Invitee.statuses[:going],
-          post_id: object.id
-        )
-      else
-        watching_invitee = Invitee.find_by(
-          user_id: scope.current_user.id,
-          post_id: object.id
-        )
-      end
+      watching_invitee = Invitee.find_by(
+        user_id: scope.current_user.id,
+        post_id: object.id
+      )
 
       if watching_invitee
         InviteeSerializer.new(watching_invitee, root: false)
@@ -89,7 +81,7 @@ module DiscoursePostEvent
     end
 
     def sample_invitees
-      invitees = object.most_likely_going(scope.current_user)
+      invitees = object.most_likely_going
       ActiveModel::ArraySerializer.new(invitees, each_serializer: InviteeSerializer)
     end
 
diff --git a/assets/javascripts/discourse/widgets/discourse-post-event.js.es6 b/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
index 7e2ee9b..1464363 100644
--- a/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
+++ b/assets/javascripts/discourse/widgets/discourse-post-event.js.es6
@@ -57,7 +57,8 @@ export default createWidget("discourse-post-event", {
         "discourse-post-event-invitee",
         this.state.eventModel.watching_invitee.id,
         {
-          status
+          status,
+          post_id: this.state.eventModel.id
         }
       );
     } else {
diff --git a/spec/requests/invitees_controller_spec.rb b/spec/requests/invitees_controller_spec.rb
index c737909..e155a0c 100644
--- a/spec/requests/invitees_controller_spec.rb
+++ b/spec/requests/invitees_controller_spec.rb
@@ -63,6 +63,26 @@ module DiscoursePostEvent
             status: 2,
           )
         end
+
+        context 'when the invitee is the event owner' do
+          let(:post_event) { Fabricate(:event, post: post1) }
+
+          it 'creates an invitee' do
+            expect(post_event.invitees.length).to eq(0)
+
+            put "/discourse-post-event/invitees/#{post1.user.id}.json", params: {
+              invitee: {
+                post_id: post1.id,
+                status: "interested"
+              }
+            }
+
+            post_event.reload
+
+            invitee = post_event.invitees.first
+            expect(invitee.status).to eq(1)
+          end
+        end
       end
     end
   end
diff --git a/spec/requests/post_events_controller_spec.rb b/spec/requests/post_events_controller_spec.rb
index 879c44d..936be81 100644
--- a/spec/requests/post_events_controller_spec.rb
+++ b/spec/requests/post_events_controller_spec.rb
@@ -71,7 +71,7 @@ module DiscoursePostEvent
 
         expect(response.status).to eq(200)
         sample_invitees = response.parsed_body['event']['sample_invitees']
-        expect(sample_invitees.map { |i| i['user']['id'] }).to match_array([user.id] + group.group_users.map { |gu| gu.user.id })
+        expect(sample_invitees.map { |i| i['user']['id'] }).to match_array(group.group_users.map { |gu| gu.user.id })
         raw_invitees = response.parsed_body['event']['raw_invitees']
         expect(raw_invitees).to match_array(invitees)
       end
@@ -88,7 +88,7 @@ module DiscoursePostEvent
 
         expect(response.status).to eq(200)
         sample_invitees = response.parsed_body['event']['sample_invitees']
-        expect(sample_invitees.map { |i| i['user']['id'] }).to match_array([user.id])
+        expect(sample_invitees.length).to eq(0)
       end
 

[... diff too long, it was truncated ...]

GitHub sha: 166d5ff7

I am not sure if concurrency is an issue here, but one trick you can do here is the pattern of:

  • Assume it’s an update
    • Perform an update with a where clause
    • if the row_count was 0, it does not exist
      • create it

Might not apply here but something to consider.