sloanelybutsurely.com/lib/core/posts/post.ex

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