140 lines
3.2 KiB
Elixir
140 lines
3.2 KiB
Elixir
defmodule Core.Posts.Post do
|
|
@moduledoc false
|
|
|
|
import Ecto.Changeset
|
|
|
|
def content_changeset(%Schema.Post{} = post, attrs) do
|
|
changeset =
|
|
post
|
|
|> cast(attrs, [:tid, :kind, :slug, :title, :body])
|
|
|> validate_required([:kind], message: "must have a kind")
|
|
|> validate_required([:body], message: "must have a body")
|
|
|
|
changeset =
|
|
case get_field(changeset, :kind) do
|
|
:blog ->
|
|
changeset =
|
|
if not is_nil(get_field(changeset, :published_at)) and changed?(changeset, :slug) do
|
|
add_error(changeset, :slug, "cannot change slug of published post")
|
|
else
|
|
changeset
|
|
end
|
|
|
|
validate_required(changeset, [:title, :slug])
|
|
|
|
:status ->
|
|
changeset
|
|
|> put_change(:slug, nil)
|
|
|> put_change(:title, nil)
|
|
|
|
_ ->
|
|
changeset
|
|
end
|
|
|
|
changeset
|
|
|> validate_format(:slug, ~r/^[a-z](?:[a-z-]*[a-z])?$/)
|
|
|> unique_constraint([:slug])
|
|
end
|
|
|
|
def publish_changeset(%Schema.Post{} = post, published_at) do
|
|
changeset = change(post)
|
|
|
|
if is_nil(get_field(changeset, :published_at)) do
|
|
put_change(changeset, :published_at, published_at)
|
|
else
|
|
changeset
|
|
end
|
|
end
|
|
|
|
def delete_changeset(%Schema.Post{} = post, deleted_at) do
|
|
changeset = change(post)
|
|
|
|
if is_nil(get_field(changeset, :deleted_at)) do
|
|
put_change(changeset, :deleted_at, deleted_at)
|
|
else
|
|
changeset
|
|
end
|
|
end
|
|
|
|
def unpublish_changeset(%Schema.Post{} = post) do
|
|
post
|
|
|> change()
|
|
|> put_change(:published_at, nil)
|
|
end
|
|
|
|
def undelete_changeset(%Schema.Post{} = post) do
|
|
post
|
|
|> change()
|
|
|> put_change(:deleted_at, nil)
|
|
end
|
|
|
|
defmodule Query do
|
|
@moduledoc false
|
|
import Ecto.Query
|
|
|
|
def base do
|
|
from _ in Schema.Post, as: :posts
|
|
end
|
|
|
|
def current(query \\ base()) do
|
|
where(query, [posts: p], is_nil(p.deleted_at))
|
|
end
|
|
|
|
def default_order(query \\ base()) do
|
|
order_by(query, [posts: p], desc: :inserted_at, desc: :updated_at)
|
|
end
|
|
|
|
def where_kind(query \\ base(), kind) do
|
|
where(query, [posts: p], p.kind == ^kind)
|
|
end
|
|
|
|
def blogs(query \\ base()) do
|
|
where_kind(query, :blog)
|
|
end
|
|
|
|
def statuses(query \\ base()) do
|
|
where_kind(query, :status)
|
|
end
|
|
|
|
def recent_blogs(query \\ base(), count) do
|
|
query
|
|
|> blogs()
|
|
|> default_order()
|
|
|> limit(^count)
|
|
end
|
|
|
|
def recent_statuses(query \\ base(), count) do
|
|
query
|
|
|> statuses()
|
|
|> default_order()
|
|
|> limit(^count)
|
|
end
|
|
|
|
def recent_posts(query \\ base(), kind, count) do
|
|
query
|
|
|> where_kind(kind)
|
|
|> default_order()
|
|
|> limit(^count)
|
|
end
|
|
|
|
def where_publish_date_and_slug(query \\ current(), publish_date, slug) do
|
|
where(
|
|
query,
|
|
[posts: p],
|
|
p.slug == ^slug and
|
|
fragment("(? at time zone 'UTC' at time zone 'America/New_York')::date", p.published_at) ==
|
|
^publish_date
|
|
)
|
|
end
|
|
|
|
def published(query \\ base()) do
|
|
query
|
|
|> current()
|
|
|> where([posts: p], not is_nil(p.published_at))
|
|
end
|
|
|
|
def deleted(query \\ base()) do
|
|
where(query, [posts: p], not is_nil(p.deleted_at))
|
|
end
|
|
end
|
|
end
|