Skip to content

Commit

Permalink
Add ability to watch a thread
Browse files Browse the repository at this point in the history
  • Loading branch information
knewter committed Jun 19, 2017
1 parent eef311c commit 65cabe7
Show file tree
Hide file tree
Showing 5 changed files with 95 additions and 2 deletions.
57 changes: 56 additions & 1 deletion lib/firestorm_web/forums/forums.ex
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ defmodule FirestormWeb.Forums do
import Ecto.{Query, Changeset}, warn: false
alias FirestormWeb.{Repo, Notifications}
alias Ecto.Multi
alias FirestormWeb.Forums.{User, Category, Thread, Post}
alias FirestormWeb.Forums.{User, Category, Thread, Post, Watch}

@doc """
Returns the list of users.
Expand Down Expand Up @@ -412,4 +412,59 @@ defmodule FirestormWeb.Forums do
|> preload([p], [thread: [:category]])
|> Repo.paginate(page: page)
end

@doc """
Have a user watch a thread:
iex> %User{} |> watch(%Thread{})
{:ok, %Watch{}}
"""
def watch(%User{} = user, %Thread{} = thread) do
thread
|> Ecto.build_assoc(:watches, %{user_id: user.id})
|> watch_changeset(%{})
|> Repo.insert()
end

@doc """
Determine if a user is watching a given watchable (Thread, etc):
iex> %Thread{} |> watched_by?(%User{})
false
"""
def watched_by?(watchable, user = %User{}) do
watch_count(watchable, user) > 0
end

def watcher_ids(watchable) do
watchable
|> watches()
|> select([f], f.user_id)
|> Repo.all
end

def watch_count(watchable) do
watchable
|> watches()
|> Repo.aggregate(:count, :id)
end
defp watch_count(watchable, user = %User{}) do
watchable
|> watches()
|> where([f], f.user_id == ^user.id)
|> Repo.aggregate(:count, :id)
end

defp watches(watchable) do
watchable
|> Ecto.assoc(:watches)
end

defp watch_changeset(%Watch{} = watch, attrs) do
watch
|> cast(attrs, [:assoc_id, :user_id])
|> validate_required([:assoc_id, :user_id])
end
end
4 changes: 3 additions & 1 deletion lib/firestorm_web/forums/thread.ex
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
defmodule FirestormWeb.Forums.Thread do
use Ecto.Schema

alias FirestormWeb.Forums.{Category, Post}
alias FirestormWeb.Forums.{Category, Post, Watch, User}
alias FirestormWeb.Forums.Slugs.ThreadTitleSlug

schema "forums_threads" do
field :title, :string
field :slug, ThreadTitleSlug.Type
belongs_to :category, Category
has_many :posts, Post
has_many :watches, {"forums_threads_watches", Watch}, foreign_key: :assoc_id
many_to_many :watchers, User, join_through: "forums_threads_watches", join_keys: [assoc_id: :id, user_id: :id]

timestamps()
end
Expand Down
16 changes: 16 additions & 0 deletions lib/firestorm_web/forums/watch.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
defmodule FirestormWeb.Forums.Watch do
@moduledoc """
A `Watch` is a polymorphic representation that a user is watching a thing in our system.
"""

use Ecto.Schema
import Ecto.Changeset

schema "abstract table: watches" do
# This will be used by associations on each "concrete" table
field :assoc_id, :integer
field :user_id, :integer

timestamps()
end
end
11 changes: 11 additions & 0 deletions priv/repo/migrations/20170619194021_add_forums_threads_watches.exs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
defmodule FirestormWeb.Repo.Migrations.AddForumsThreadsWatches do
use Ecto.Migration

def change do
create table(:forums_threads_watches) do
add :assoc_id, references(:forums_threads)
add :user_id, references(:forums_users)
timestamps()
end
end
end
9 changes: 9 additions & 0 deletions test/forums_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,15 @@ defmodule FirestormWeb.ForumsTest do
end
end

describe "watching a thread" do
setup [:create_user, :create_category, :create_thread]

test "watching a thread", %{thread: thread, user: user} do
{:ok, _watch} = user |> Forums.watch(thread)
assert thread |> Forums.watched_by?(user)
end
end

def create_category(_) do
category = fixture(:category, @create_category_attrs)
{:ok, category: category}
Expand Down

0 comments on commit 65cabe7

Please sign in to comment.