|
- class PostVersionsController < ApplicationController
- def index
- post_id = params[:post].presence
- tag_id = params[:tag].presence
- page = (params[:page].presence || 1).to_i
- limit = (params[:limit].presence || 20).to_i
-
- page = 1 if page < 1
- limit = 1 if limit < 1
-
- offset = (page - 1) * limit
-
- tag_name =
- if tag_id
- TagName.joins(:tag).find_by(tag: { id: tag_id })
- end
- return render json: { versions: [], count: 0 } if tag_id && tag_name.blank?
-
- q = PostVersion.joins(<<~SQL.squish)
- LEFT JOIN
- post_versions prev
- ON
- prev.post_id = post_versions.post_id
- AND prev.version_no = post_versions.version_no - 1
- SQL
- .select('post_versions.*', 'prev.title AS prev_title', 'prev.url AS prev_url',
- 'prev.thumbnail_base AS prev_thumbnail_base', 'prev.tags AS prev_tags',
- 'prev.original_created_from AS prev_original_created_from',
- 'prev.original_created_before AS prev_original_created_before')
- q = q.where('post_versions.post_id = ?', post_id) if post_id
- if tag_name
- escaped = ActiveRecord::Base.sanitize_sql_like(tag_name.name)
- q = q.where("CONCAT(' ', post_versions.tags, ' ') LIKE ?", "% #{ escaped } %")
- end
-
- count = q.except(:select, :order, :limit, :offset).count
-
- versions = q.order(Arel.sql('post_versions.created_at DESC, post_versions.id DESC'))
- .limit(limit)
- .offset(offset)
-
- render json: { versions: serialise_versions(versions), count: }
- end
-
- private
-
- def serialise_versions rows
- user_ids = rows.map(&:created_by_user_id).compact.uniq
- users_by_id = User.where(id: user_ids).pluck(:id, :name).to_h
-
- rows.map do |row|
- cur_tags = split_tags(row.tags)
- prev_tags = split_tags(row.attributes['prev_tags'])
-
- {
- post_id: row.post_id,
- version_no: row.version_no,
- event_type: row.event_type,
- title: {
- current: row.title,
- prev: row.attributes['prev_title']
- },
- url: {
- current: row.url,
- prev: row.attributes['prev_url']
- },
- thumbnail: {
- current: nil,
- prev: nil
- },
- thumbnail_base: {
- current: row.thumbnail_base,
- prev: row.attributes['prev_thumbnail_base']
- },
- tags: build_version_tags(cur_tags, prev_tags),
- original_created_from: {
- current: row.original_created_from&.iso8601,
- prev: row.attributes['prev_original_created_from']&.iso8601
- },
- original_created_before: {
- current: row.original_created_before&.iso8601,
- prev: row.attributes['prev_original_created_before']&.iso8601
- },
- created_at: row.created_at.iso8601,
- created_by_user:
- if row.created_by_user_id
- {
- id: row.created_by_user_id,
- name: users_by_id[row.created_by_user_id]
- }
- end
- }
- end
- end
-
- def build_version_tags(cur_tags, prev_tags)
- (cur_tags | prev_tags).map do |name|
- type =
- if cur_tags.include?(name) && prev_tags.include?(name)
- 'context'
- elsif cur_tags.include?(name)
- 'added'
- else
- 'removed'
- end
-
- {
- name:,
- type:
- }
- end
- end
-
- def split_tags(tags)
- tags.to_s.split(/\s+/).reject(&:blank?)
- end
- end
|