From 1d24d8471ef3cad7df341468a1e5ba14c1761460 Mon Sep 17 00:00:00 2001 From: riking <rikingcoding@gmail.com> Date: Fri, 23 Jan 2015 21:04:14 -0800 Subject: [PATCH] FEATURE: Latest posts endpoint at /posts.json --- app/controllers/posts_controller.rb | 23 +++++++++++++++++++- app/serializers/post_serializer.rb | 33 +++++++++++++++++++++++------ config/routes.rb | 1 + 3 files changed, 50 insertions(+), 7 deletions(-) diff --git a/app/controllers/posts_controller.rb b/app/controllers/posts_controller.rb index 2d0b936d0..26c190087 100644 --- a/app/controllers/posts_controller.rb +++ b/app/controllers/posts_controller.rb @@ -5,7 +5,7 @@ require_dependency 'distributed_memoizer' class PostsController < ApplicationController # Need to be logged in for all actions here - before_filter :ensure_logged_in, except: [:show, :replies, :by_number, :short_link, :reply_history, :revisions, :latest_revision, :expand_embed, :markdown, :raw, :cooked] + before_filter :ensure_logged_in, except: [:show, :replies, :by_number, :short_link, :reply_history, :revisions, :latest_revision, :expand_embed, :markdown_id, :markdown_num, :cooked, :latest] skip_before_filter :check_xhr, only: [:markdown_id, :markdown_num, :short_link] @@ -25,6 +25,27 @@ class PostsController < ApplicationController end end + def latest + posts = Post.order(created_at: :desc) + .where('posts.id > ?', Post.last.id - 50) # last 50 post IDs only, to avoid counting deleted posts in security check + .includes(topic: :category) + .includes(:user) + .limit(50) + # Remove posts the user doesn't have permission to see + # This isn't leaking any information we weren't already through the post ID numbers + posts = posts.reject { |post| !guardian.can_see?(post) } + + counts = PostAction.counts_for(posts, current_user) + + render_json_dump(serialize_data(posts, + PostSerializer, + scope: guardian, + root: 'latest_posts', + add_raw: true, + all_post_actions: counts) + ) + end + def cooked post = find_post_from_params render json: {cooked: post.cooked} diff --git a/app/serializers/post_serializer.rb b/app/serializers/post_serializer.rb index b6ca0ba92..bb99bfd85 100644 --- a/app/serializers/post_serializer.rb +++ b/app/serializers/post_serializer.rb @@ -1,12 +1,17 @@ class PostSerializer < BasicPostSerializer # To pass in additional information we might need - attr_accessor :topic_view, + INSTANCE_VARS = [:topic_view, :parent_post, :add_raw, :single_post_link_counts, :draft_sequence, - :post_actions + :post_actions, + :all_post_actions] + + INSTANCE_VARS.each do |v| + self.send(:attr_accessor, v) + end attributes :post_number, :post_type, @@ -53,6 +58,15 @@ class PostSerializer < BasicPostSerializer :static_doc, :via_email + def initialize(object, opts) + super(object, opts) + PostSerializer::INSTANCE_VARS.each do |name| + if opts.include? name + self.send("#{name}=", opts[name]) + end + end + end + def topic_slug object.try(:topic).try(:slug) end @@ -154,6 +168,13 @@ class PostSerializer < BasicPostSerializer scope.is_staff? && object.deleted_by.present? end + # Helper function to decide between #post_actions and @all_post_actions + def actions + return post_actions if post_actions.present? + return all_post_actions[object.id] if all_post_actions.present? + nil + end + # Summary of the actions taken on this post def actions_summary result = [] @@ -167,7 +188,7 @@ class PostSerializer < BasicPostSerializer id: id, count: count, hidden: (sym == :vote), - can_act: scope.post_can_act?(object, sym, taken_actions: post_actions) + can_act: scope.post_can_act?(object, sym, taken_actions: actions) } if sym == :notify_user && scope.current_user.present? && scope.current_user == object.user @@ -182,9 +203,9 @@ class PostSerializer < BasicPostSerializer active_flags[id].count > 0 end - if post_actions.present? && post_actions.has_key?(id) + if actions.present? && actions.has_key?(id) action_summary[:acted] = true - action_summary[:can_undo] = scope.can_delete?(post_actions[id]) + action_summary[:can_undo] = scope.can_delete?(actions[id]) end # only show public data @@ -225,7 +246,7 @@ class PostSerializer < BasicPostSerializer end def include_bookmarked? - post_actions.present? && post_actions.keys.include?(PostActionType.types[:bookmark]) + actions.present? && actions.keys.include?(PostActionType.types[:bookmark]) end def include_display_username? diff --git a/config/routes.rb b/config/routes.rb index 3c288b57d..8a41b8be1 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -269,6 +269,7 @@ Discourse::Application.routes.draw do get "uploads/:site/:sha" => "uploads#show", constraints: { site: /\w+/, sha: /[a-z0-9]{40}/} post "uploads" => "uploads#create" + get "posts" => "posts#latest" get "posts/by_number/:topic_id/:post_number" => "posts#by_number" get "posts/:id/reply-history" => "posts#reply_history" get "posts/:username/deleted" => "posts#deleted_posts", constraints: {username: USERNAME_ROUTE_FORMAT}