diff --git a/Changelog.md b/Changelog.md
index 15eef00615918fd7f84e5450c6a3992fab4d5e6a..bfe7235c20d52f98fe057e2bd665f263cff55e25 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -76,6 +76,7 @@ With the port to Bootstrap 3, app/views/terms/default.haml has a new structure.
 * Refactor HomeController#toggle\_mobile [#6260](https://github.com/diaspora/diaspora/pull/6260)
 * Extract CommentService from CommentsController [#6307](https://github.com/diaspora/diaspora/pull/6307)
 * Extract user/profile discovery into the diaspora\_federation-rails gem [#6310](https://github.com/diaspora/diaspora/pull/6310)
+* Refactor PostPresenter [#6315](https://github.com/diaspora/diaspora/pull/6315)
 
 ## Bug fixes
 * Fix indentation and a link title on the default home page [#6212](https://github.com/diaspora/diaspora/pull/6212)
diff --git a/app/presenters/post_interaction_presenter.rb b/app/presenters/post_interaction_presenter.rb
index 2616b0f76e77ff1fc3c71c2133891a104fadd962..12c999febb57bd0da85d16e30fe51625bc66d350 100644
--- a/app/presenters/post_interaction_presenter.rb
+++ b/app/presenters/post_interaction_presenter.rb
@@ -7,7 +7,7 @@ class PostInteractionPresenter
   def as_json(_options={})
     {
       likes:          as_api(@post.likes),
-      reshares:       PostPresenter.collection_json(@post.reshares, @current_user),
+      reshares:       PostPresenter.as_collection(@post.reshares, :as_json, @current_user),
       comments:       CommentPresenter.as_collection(@post.comments.order("created_at ASC")),
       participations: as_api(participations),
       comments_count: @post.comments_count,
diff --git a/app/presenters/post_presenter.rb b/app/presenters/post_presenter.rb
index f17e6bb8c33a3e1fd74a94c419c3eb28de01559f..b1df1a917aaec83c3effcee867f6ea6a960cfcc7 100644
--- a/app/presenters/post_presenter.rb
+++ b/app/presenters/post_presenter.rb
@@ -1,84 +1,91 @@
-class PostPresenter
+class PostPresenter < BasePresenter
   include PostsHelper
 
-  attr_accessor :post, :current_user
+  attr_accessor :post
 
-  def initialize(post, current_user = nil)
+  def initialize(post, current_user=nil)
     @post = post
     @current_user = current_user
   end
 
-  def self.collection_json(collection, current_user)
-    collection.map {|post| PostPresenter.new(post, current_user)}
+  def as_json(_options={})
+    @post.include_root_in_json = false
+    @post.as_json(only: directly_retrieved_attributes).merge(non_directly_retrieved_attributes)
   end
 
-  def as_json(options={})
-    text = if @post.message
+  private
+
+  def directly_retrieved_attributes
+    %i(id guid public created_at interacted_at provider_display_name image_url object_url)
+  end
+
+  def non_directly_retrieved_attributes
+    {
+      text:                         build_text,
+      post_type:                    @post.post_type,
+      nsfw:                         @post.nsfw,
+      author:                       @post.author.as_api_response(:backbone),
+      o_embed_cache:                @post.o_embed_cache.try(:as_api_response, :backbone),
+      open_graph_cache:             build_open_graph_cache,
+      mentioned_people:             build_mentioned_people_json,
+      photos:                       build_photos_json,
+      root:                         root,
+      title:                        title,
+      address:                      @post.address,
+      poll:                         @post.poll,
+      already_participated_in_poll: already_participated_in_poll,
+      participation:                participate?,
+      interactions:                 build_interactions_json
+    }
+  end
+
+  def build_text
+    if @post.message
       @post.message.plain_text_for_json
     else
       @post.raw_message
     end
-    {
-        :id => @post.id,
-        :guid => @post.guid,
-        :text => text,
-        :public => @post.public,
-        :created_at => @post.created_at,
-        :interacted_at => @post.interacted_at,
-        :provider_display_name => @post.provider_display_name,
-        :post_type => @post.post_type,
-        :image_url => @post.image_url,
-        :object_url => @post.object_url,
-        :nsfw => @post.nsfw,
-        :author => @post.author.as_api_response(:backbone),
-        :o_embed_cache => @post.o_embed_cache.try(:as_api_response, :backbone),
-        :open_graph_cache => @post.open_graph_cache.try(:as_api_response, :backbone),
-        :mentioned_people => @post.mentioned_people.as_api_response(:backbone),
-        :photos => @post.photos.map {|p| p.as_api_response(:backbone)},
-        :root => root,
-        :title => title,
-        :address => @post.address,
-        :poll => @post.poll(),
-        :already_participated_in_poll => already_participated_in_poll,
-        :participation => participate?,
-
-        :interactions => {
-            :likes => [user_like].compact,
-            :reshares => [user_reshare].compact,
-            :comments_count => @post.comments_count,
-            :likes_count => @post.likes_count,
-            :reshares_count => @post.reshares_count
-        }
-    }
   end
 
-  def title
-    @post.message.present? ? @post.message.title : I18n.t('posts.presenter.title', name: @post.author_name)
+  def build_open_graph_cache
+    @post.open_graph_cache.try(:as_api_response, :backbone)
   end
 
-  def root
-    PostPresenter.new(@post.absolute_root, current_user).as_json if @post.respond_to?(:absolute_root) && @post.absolute_root.present?
+  def build_mentioned_people_json
+    @post.mentioned_people.as_api_response(:backbone)
   end
 
-  def user_like
-    @post.like_for(@current_user).try(:as_api_response, :backbone)
+  def build_photos_json
+    @post.photos.map {|p| p.as_api_response(:backbone) }
   end
 
-  def user_reshare
-    @post.reshare_for(@current_user)
+  def title
+    @post.message.present? ? @post.message.title : I18n.t("posts.presenter.title", name: @post.author_name)
   end
 
-  protected
+  def root
+    if @post.respond_to?(:absolute_root) && @post.absolute_root.present?
+      PostPresenter.new(@post.absolute_root, current_user).as_json
+    end
+  end
 
-  def person
-    @current_user.person
+  def build_interactions_json
+    {
+      likes:          [user_like].compact,
+      reshares:       [user_reshare].compact,
+      comments_count: @post.comments_count,
+      likes_count:    @post.likes_count,
+      reshares_count: @post.reshares_count
+    }
   end
 
-  def user_signed_in?
-    @current_user.present?
+  def user_like
+    @post.like_for(current_user).try(:as_api_response, :backbone)
   end
 
-  private
+  def user_reshare
+    @post.reshare_for(current_user)
+  end
 
   def already_participated_in_poll
     if @post.poll && user_signed_in?
@@ -87,7 +94,14 @@ class PostPresenter
   end
 
   def participate?
-    user_signed_in? && @current_user.participations.where(:target_id => @post).exists?
+    user_signed_in? && current_user.participations.where(target_id: @post).exists?
   end
 
+  def user_signed_in?
+    current_user.present?
+  end
+
+  def person
+    current_user.person
+  end
 end
diff --git a/spec/presenters/post_presenter_spec.rb b/spec/presenters/post_presenter_spec.rb
index 293f0337c545bb250c75f9a1aa3d61b4ed297065..07a4b2d8411407fda7cac100c946f9b968954e56 100644
--- a/spec/presenters/post_presenter_spec.rb
+++ b/spec/presenters/post_presenter_spec.rb
@@ -1,90 +1,90 @@
-require 'spec_helper'
+require "spec_helper"
 
 describe PostPresenter do
   before do
-    @sm = FactoryGirl.create(:status_message, :public => true)
+    @sm = FactoryGirl.create(:status_message, public: true)
     @sm_with_poll = FactoryGirl.create(:status_message_with_poll, public: true)
     @presenter = PostPresenter.new(@sm, bob)
     @unauthenticated_presenter = PostPresenter.new(@sm)
   end
 
-  it 'takes a post and an optional user' do
+  it "takes a post and an optional user" do
     expect(@presenter).not_to be_nil
   end
 
-  describe '#as_json' do
-    it 'works with a user' do
+  describe "#as_json" do
+    it "works with a user" do
       expect(@presenter.as_json).to be_a Hash
     end
 
-    it 'works without a user' do
+    it "works without a user" do
       expect(@unauthenticated_presenter.as_json).to be_a Hash
     end
   end
 
-  describe '#user_like' do
-    it 'includes the users like' do
+  describe "#user_like" do
+    it "includes the users like" do
       bob.like!(@sm)
-      expect(@presenter.user_like).to be_present
+      expect(@presenter.send(:user_like)).to be_present
     end
 
-    it 'is nil if the user is not authenticated' do
-      expect(@unauthenticated_presenter.user_like).to be_nil
+    it "is nil if the user is not authenticated" do
+      expect(@unauthenticated_presenter.send(:user_like)).to be_nil
     end
   end
 
-  describe '#user_reshare' do
-    it 'includes the users reshare' do
+  describe "#user_reshare" do
+    it "includes the users reshare" do
       bob.reshare!(@sm)
-      expect(@presenter.user_reshare).to be_present
+      expect(@presenter.send(:user_reshare)).to be_present
     end
 
-    it 'is nil if the user is not authenticated' do
-      expect(@unauthenticated_presenter.user_reshare).to be_nil
+    it "is nil if the user is not authenticated" do
+      expect(@unauthenticated_presenter.send(:user_reshare)).to be_nil
     end
   end
 
-  describe '#root' do
-    it 'does not raise if the absolute_root does not exists' do
+  describe "#root" do
+    it "does not raise if the absolute_root does not exists" do
       first_reshare = FactoryGirl.create :reshare
       first_reshare.root = nil
-      reshare = FactoryGirl.create :reshare, :root => first_reshare
+      reshare = FactoryGirl.create :reshare, root: first_reshare
 
       expect {
-        PostPresenter.new(reshare).root
+        PostPresenter.new(reshare).send(:root)
       }.to_not raise_error
     end
 
-    it 'does not raise if the root does not exists' do
-      reshare = FactoryGirl.create:reshare
+    it "does not raise if the root does not exists" do
+      reshare = FactoryGirl.create :reshare
       reshare.root = nil
       expect {
-        PostPresenter.new(reshare).root
+        PostPresenter.new(reshare).send(:root)
       }.to_not raise_error
     end
   end
 
-  describe '#title' do
-    context 'with posts with text' do
+  describe "#title" do
+    context "with posts with text" do
       it "delegates to message.title" do
         message = double(present?: true)
         expect(message).to receive(:title)
         @presenter.post = double(message: message)
-        @presenter.title
+        @presenter.send(:title)
       end
     end
 
-    context 'with posts without text' do
-      it ' displays a messaage with the post class' do
+    context "with posts without text" do
+      it " displays a messaage with the post class" do
         @sm = double(message: double(present?: false), author: bob.person, author_name: bob.person.name)
         @presenter.post = @sm
-        expect(@presenter.title).to eq("A post from #{@sm.author.name}")
+        expect(@presenter.send(:title)).to eq("A post from #{@sm.author.name}")
       end
     end
   end
 
-  describe '#poll' do
-    it 'works without a user' do
+  describe "#poll" do
+    it "works without a user" do
       presenter = PostPresenter.new(@sm_with_poll)
       expect(presenter.as_json).to be_a(Hash)
     end