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 -> 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_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