- Actually use preloaded bookmarks in views
authorrinpatch <rinpatch@sdf.org>
Sat, 4 May 2019 10:42:54 +0000 (13:42 +0300)
committerWilliam Pitcock <nenolod@dereferenced.org>
Tue, 7 May 2019 19:33:22 +0000 (19:33 +0000)
- Preload bookmarks in bookmark timeline
- Rework bookmark preload tests

lib/pleroma/activity.ex
lib/pleroma/bookmark.ex
lib/pleroma/web/mastodon_api/mastodon_api_controller.ex
lib/pleroma/web/mastodon_api/views/status_view.ex
test/activity_test.exs
test/web/mastodon_api/status_view_test.exs

index 7845c264a22a1255d634fea1510b055775d5fe51..e432fcb0738c9a333a068a6f8035e4c332c8a4e1 100644 (file)
@@ -73,6 +73,11 @@ defmodule Pleroma.Activity do
         )
     )
     |> preload([activity, object], object: object)
+    |> with_preloaded_bookmarks()
+  end
+
+  def with_preloaded_bookmarks(query) do
+    query
     |> preload(:bookmarks)
   end
 
@@ -105,9 +110,9 @@ defmodule Pleroma.Activity do
             activity.data,
             activity.data
           ),
-        preload: [object: o],
-        preload: :bookmarks
+        preload: [object: o]
       )
+      |> with_preloaded_bookmarks()
     )
   end
 
@@ -126,9 +131,9 @@ defmodule Pleroma.Activity do
           activity.data,
           activity.data
         ),
-      preload: [object: o],
-      preload: :bookmarks
+      preload: [object: o]
     )
+    |> with_preloaded_bookmarks()
     |> Repo.one()
   end
 
index 7f8fd43b6f174f2367022727f6292956396f1d9c..bbb51c22cf3fcf9724e1c2352a627ef89df6f33f 100644 (file)
@@ -38,7 +38,8 @@ defmodule Pleroma.Bookmark do
     Bookmark
     |> where(user_id: ^user_id)
     |> join(:inner, [b], activity in assoc(b, :activity))
-    |> preload([b, a], activity: a)
+    |> join(:inner, [_b, a], bookmarks in assoc(a, :bookmarks))
+    |> preload([b, a, b2], activity: {a, bookmarks: b2})
   end
 
   def get(user_id, activity_id) do
index 2a3d58592de1a1a05ee7124766c57f31c01207aa..451fc85ce574d578acda54965fe9bcb1a5555c23 100644 (file)
@@ -563,7 +563,9 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
     with %Activity{} = activity <- Activity.get_by_id_with_object(id),
          %User{} = user <- User.get_cached_by_nickname(user.nickname),
          true <- Visibility.visible_for_user?(activity, user),
-         {:ok, _bookmark} <- Bookmark.create(user.id, activity.id) do
+         {:ok, bookmark} <- Bookmark.create(user.id, activity.id) do
+      activity = %{activity | bookmarks: [bookmark | activity.bookmarks]}
+
       conn
       |> put_view(StatusView)
       |> try_render("status.json", %{activity: activity, for: user, as: :activity})
@@ -575,6 +577,11 @@ defmodule Pleroma.Web.MastodonAPI.MastodonAPIController do
          %User{} = user <- User.get_cached_by_nickname(user.nickname),
          true <- Visibility.visible_for_user?(activity, user),
          {:ok, _bookmark} <- Bookmark.destroy(user.id, activity.id) do
+      bookmarks =
+        Enum.filter(activity.bookmarks, fn %{user_id: user_id} -> user_id != user.id end)
+
+      activity = %{activity | bookmarks: bookmarks}
+
       conn
       |> put_view(StatusView)
       |> try_render("status.json", %{activity: activity, for: user, as: :activity})
index 62d064d717f1d5a4d2c0f2fcbb50cfdae82a3e35..c5a7bcbab692bec7b4af5c9e88430aa49808b8d8 100644 (file)
@@ -80,13 +80,21 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
     user = get_user(activity.data["actor"])
     created_at = Utils.to_masto_date(activity.data["published"])
 
-    reblogged_activity = Activity.get_create_by_object_ap_id(object)
+    reblogged_activity =
+      Activity.create_by_object_ap_id(object)
+      |> Activity.with_preloaded_bookmarks()
+      |> Repo.one()
+
     reblogged = render("status.json", Map.put(opts, :activity, reblogged_activity))
 
     activity_object = Object.normalize(activity)
     favorited = opts[:for] && opts[:for].ap_id in (activity_object.data["likes"] || [])
 
-    bookmarked = opts[:for] && CommonAPI.bookmarked?(opts[:for], reblogged_activity)
+    bookmarked =
+      opts[:for] && Ecto.assoc_loaded?(reblogged_activity.bookmarks) &&
+        Enum.any?(reblogged_activity.bookmarks, fn %{user_id: user_id} ->
+          user_id == opts[:for].id
+        end)
 
     mentions =
       activity.recipients
@@ -149,7 +157,11 @@ defmodule Pleroma.Web.MastodonAPI.StatusView do
 
     favorited = opts[:for] && opts[:for].ap_id in (object.data["likes"] || [])
 
-    bookmarked = opts[:for] && CommonAPI.bookmarked?(opts[:for], activity)
+    bookmarked =
+      opts[:for] && Ecto.assoc_loaded?(activity.bookmarks) &&
+        Enum.any?(activity.bookmarks, fn %{user_id: user_id} ->
+          user_id == opts[:for].id
+        end)
 
     attachment_data = object.data["attachment"] || []
     attachments = render_many(attachment_data, StatusView, "attachment.json", as: :attachment)
index e2a8baada672a8a1be45d5bf1a663b7735ce8daa..dd149543cd09e20952f67e547b612d81d39a309c 100644 (file)
@@ -31,30 +31,52 @@ defmodule Pleroma.ActivityTest do
     assert activity == found_activity
   end
 
-  test "preloading object preloads bookmarks" do
-    user1 = insert(:user)
-    user2 = insert(:user)
-    activity = insert(:note_activity)
-    {:ok, bookmark1} = Bookmark.create(user1.id, activity.id)
-    {:ok, bookmark2} = Bookmark.create(user2.id, activity.id)
-    bookmarks = Enum.sort([bookmark1, bookmark2])
+  describe "preloading bookmarks" do
+    setup do
+      user1 = insert(:user)
+      user2 = insert(:user)
+      activity = insert(:note_activity)
+      {:ok, bookmark1} = Bookmark.create(user1.id, activity.id)
+      {:ok, bookmark2} = Bookmark.create(user2.id, activity.id)
+      [activity: activity, bookmarks: Enum.sort([bookmark1, bookmark2])]
+    end
+
+    test "using with_preloaded_bookmarks", %{activity: activity, bookmarks: bookmarks} do
+      queried_activity =
+        Ecto.Query.from(a in Activity, where: a.id == ^activity.id)
+        |> Activity.with_preloaded_bookmarks()
+        |> Repo.one()
+
+      assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    end
 
-    queried_activity =
-      Ecto.Query.from(a in Activity, where: a.id == ^activity.id)
-      |> Activity.with_preloaded_object()
-      |> Repo.one()
+    test "using with_preloaded_object", %{activity: activity, bookmarks: bookmarks} do
+      queried_activity =
+        Ecto.Query.from(a in Activity, where: a.id == ^activity.id)
+        |> Activity.with_preloaded_object()
+        |> Repo.one()
 
-    assert Enum.sort(queried_activity.bookmarks) == bookmarks
+      assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    end
 
-    queried_activity = Activity.get_by_ap_id_with_object(activity.data["id"])
-    assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    test "using get_by_ap_id_with_object", %{activity: activity, bookmarks: bookmarks} do
+      queried_activity = Activity.get_by_ap_id_with_object(activity.data["id"])
+      assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    end
 
-    queried_activity = Activity.get_by_id_with_object(activity.id)
-    assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    test "using get_by_id_with_object", %{activity: activity, bookmarks: bookmarks} do
+      queried_activity = Activity.get_by_id_with_object(activity.id)
+      assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    end
 
-    queried_activity =
-      Activity.get_create_by_object_ap_id_with_object(Object.normalize(activity).data["id"])
+    test "using get_create_by_object_ap_id_with_object", %{
+      activity: activity,
+      bookmarks: bookmarks
+    } do
+      queried_activity =
+        Activity.get_create_by_object_ap_id_with_object(Object.normalize(activity).data["id"])
 
-    assert Enum.sort(queried_activity.bookmarks) == bookmarks
+      assert Enum.sort(queried_activity.bookmarks) == bookmarks
+    end
   end
 end
index 5fddc6c58bbcad6cc44e70addfbd701965f3d670..d7c800e83a54d04a210d7f8894a6583af74bb66e 100644 (file)
@@ -168,6 +168,8 @@ defmodule Pleroma.Web.MastodonAPI.StatusViewTest do
 
     {:ok, _bookmark} = Bookmark.create(user.id, activity.id)
 
+    activity = Activity.get_by_id_with_object(activity.id)
+
     status = StatusView.render("status.json", %{activity: activity, for: user})
 
     assert status.bookmarked == true