From dccde68649cb83e0a9bccb68b3dd7dd55f43e0c7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 5 Feb 2024 09:34:51 -0500 Subject: [PATCH 1/4] Add new `MarkerTimelinePresenter` class --- app/presenters/marker_timeline_presenter.rb | 23 +++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 app/presenters/marker_timeline_presenter.rb diff --git a/app/presenters/marker_timeline_presenter.rb b/app/presenters/marker_timeline_presenter.rb new file mode 100644 index 00000000000..dd80f18c390 --- /dev/null +++ b/app/presenters/marker_timeline_presenter.rb @@ -0,0 +1,23 @@ +# frozen_string_literal: true + +class MarkerTimelinePresenter + include ActiveModel::Model + + alias read_attribute_for_serialization send + + attr_reader :markers + + def initialize(markers) + @markers = markers + end + + Marker::TIMELINES.each do |timeline| + define_method timeline.to_sym do + markers.find { |marker| marker.timeline == timeline } + end + end + + def timeline_present?(value) + markers.map(&:timeline).include?(value) + end +end From 9d95ca7b0a4137d07789dcf717a2f7e2b8ca94c9 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 5 Feb 2024 09:35:02 -0500 Subject: [PATCH 2/4] Add new `MarkerTimelineSerializer` class --- app/serializers/rest/marker_timeline_serializer.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 app/serializers/rest/marker_timeline_serializer.rb diff --git a/app/serializers/rest/marker_timeline_serializer.rb b/app/serializers/rest/marker_timeline_serializer.rb new file mode 100644 index 00000000000..14d221b2900 --- /dev/null +++ b/app/serializers/rest/marker_timeline_serializer.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class REST::MarkerTimelineSerializer < ActiveModel::Serializer + Marker::TIMELINES.each do |timeline| + has_one timeline.to_sym, + if: -> { timeline_present?(timeline) }, + serializer: REST::MarkerSerializer + end + + delegate :timeline_present?, to: :object +end From 8b20eae8570f72eafcb94be9b166d0d2299cf8b7 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Mon, 5 Feb 2024 09:35:19 -0500 Subject: [PATCH 3/4] Use new marker timeline classes to generate markers API json response --- app/controllers/api/v1/markers_controller.rb | 42 ++++++++++---------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/app/controllers/api/v1/markers_controller.rb b/app/controllers/api/v1/markers_controller.rb index 8eaf7767df8..53d4b939af4 100644 --- a/app/controllers/api/v1/markers_controller.rb +++ b/app/controllers/api/v1/markers_controller.rb @@ -7,38 +7,40 @@ class Api::V1::MarkersController < Api::BaseController before_action :require_user! def index - with_read_replica do - @markers = current_user.markers.where(timeline: Array(params[:timeline])).index_by(&:timeline) - end - - render json: serialize_map(@markers) + @markers = current_user_markers + render json: marker_timeline_presenter, serializer: REST::MarkerTimelineSerializer end def create - Marker.transaction do - @markers = {} - - resource_params.each_pair do |timeline, timeline_params| - @markers[timeline] = current_user.markers.find_or_create_by(timeline: timeline) - @markers[timeline].update!(timeline_params) - end - end - - render json: serialize_map(@markers) + @markers = create_markers_from_params + render json: marker_timeline_presenter, serializer: REST::MarkerTimelineSerializer rescue ActiveRecord::StaleObjectError render json: { error: 'Conflict during update, please try again' }, status: 409 end private - def serialize_map(map) - serialized = {} + def marker_timeline_presenter + MarkerTimelinePresenter.new(@markers) + end - map.each_pair do |key, value| - serialized[key] = ActiveModelSerializers::SerializableResource.new(value, serializer: REST::MarkerSerializer).as_json + def current_user_markers + with_read_replica do + current_user.markers.where(timeline: Array(params[:timeline])) end + end - Oj.dump(serialized) + def create_markers_from_params + [].tap do |markers| + Marker.transaction do + resource_params.each_pair do |timeline, timeline_params| + current_user.markers.find_or_create_by(timeline: timeline).tap do |marker| + marker.update!(timeline_params) + markers << marker + end + end + end + end end def resource_params From a164025ecbeb376d5f1d12fff1bb540c392e9772 Mon Sep 17 00:00:00 2001 From: Matt Jankowski Date: Fri, 3 May 2024 09:22:59 -0400 Subject: [PATCH 4/4] Keep `with_read_replica` in main action --- app/controllers/api/v1/markers_controller.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/v1/markers_controller.rb b/app/controllers/api/v1/markers_controller.rb index 53d4b939af4..dac77fa14ff 100644 --- a/app/controllers/api/v1/markers_controller.rb +++ b/app/controllers/api/v1/markers_controller.rb @@ -7,7 +7,9 @@ class Api::V1::MarkersController < Api::BaseController before_action :require_user! def index - @markers = current_user_markers + with_read_replica do + @markers = current_user_markers + end render json: marker_timeline_presenter, serializer: REST::MarkerTimelineSerializer end @@ -25,9 +27,7 @@ class Api::V1::MarkersController < Api::BaseController end def current_user_markers - with_read_replica do - current_user.markers.where(timeline: Array(params[:timeline])) - end + current_user.markers.where(timeline: Array(params[:timeline])) end def create_markers_from_params