Manages blog post comments in the MishkaBlog plugin with full versioning support.
This resource represents comments on blog posts with support for nested threading through parent-child relationships. Each comment belongs to a specific site (via site_id) and a blog post, and can have replies, creating conversation threads. Comments support multiple statuses for moderation workflows (pending, approved, flagged, spam).
Comments feature full version control through PaperTrail integration, tracking all changes with snapshot-based history including content edits, status changes, and moderation actions. The resource implements soft deletion via archival and provides comprehensive metadata tracking including sender information (IP address, user agent) for moderation and security purposes.
Comments can be pinned to highlight important discussions, and the threading system enables rich conversation structures. This resource uses multi-tenancy with site_id as the tenant attribute, ensuring comments are scoped to their respective sites.
Multi-Tenancy
Comments are site-specific and use attribute-based multi-tenancy:
- Tenant actions require a site_id context
- Master actions (master_read, master_permanent_destroy) can bypass tenant filtering
- Public actions (public_list, public_get) show only approved comments
Public Access
public_list- Lists all approved comments (paginated)public_get- Gets a single approved comment by IDapproved_by_post- Lists approved comments for a specific post
Summary
Functions
Apply the full GuardedStruct pipeline (sanitize → validate → derive →
main_validator) to attrs and return either {:ok, transformed_attrs}
or {:error, errors}. Wire this into an Ash.Resource.Change to plug
guardedstruct rules into Ash's changeset pipeline.
O(1) lookup of a field's compile-time metadata by name. Returns
nil for unknown fields.
Compile-time-baked MapSet of every field name owned by the
guardedstruct block. Used by GuardedStruct.AshResource.Change
to decide, in O(1), whether a key in changeset.atomics
belongs to the pipeline.
Validates that the keys in the provided input are valid for at least one action on the resource.
Same as input/1, except restricts the keys to values accepted by the action provided.
Types
@type t() :: %MishkaBlog.Comment{ __lateral_join_source__: term(), __meta__: term(), __metadata__: term(), __order__: term(), aggregates: term(), archived_at: term(), author: term(), author_id: term(), author_master?: term(), author_profile: term(), calculations: term(), content: term(), downvote_count: term(), effective_permissions: term(), id: term(), inserted_at: term(), is_pinned: term(), locked_collections: term(), locked_posts: term(), locks_apply?: term(), master_post: term(), parent_comment: term(), parent_comment_id: term(), post: term(), post_id: term(), rendered_content: term(), replies: term(), sender_data: term(), site: term(), site_id: term(), status: term(), updated_at: term(), upvote_count: term(), votes: term() }
Functions
Apply the full GuardedStruct pipeline (sanitize → validate → derive →
main_validator) to attrs and return either {:ok, transformed_attrs}
or {:error, errors}. Wire this into an Ash.Resource.Change to plug
guardedstruct rules into Ash's changeset pipeline.
The function is named __guarded_change__ because it does more than
validate — it can also transform values (trim, downcase, slugify,
auto-fill, etc.) before they reach the data layer.
O(1) lookup of a field's compile-time metadata by name. Returns
nil for unknown fields.
Compile-time-baked MapSet of every field name owned by the
guardedstruct block. Used by GuardedStruct.AshResource.Change
to decide, in O(1), whether a key in changeset.atomics
belongs to the pipeline.
Validates that the keys in the provided input are valid for at least one action on the resource.
Raises a KeyError error at compile time if not. This exists because generally a struct should only ever
be created by Ash as a result of a successful action. You should not be creating records manually in code,
e.g %MyResource{value: 1, value: 2}. Generally that is fine, but often with embedded resources it is nice
to be able to validate the keys that are being provided, e.g
Resource
|> Ash.Changeset.for_create(:create, %{embedded: EmbeddedResource.input(foo: 1, bar: 2)})
|> Ash.create()
Same as input/1, except restricts the keys to values accepted by the action provided.