AshDispatch.Naming (AshDispatch v0.5.1)
View SourceCentral module for all AshDispatch naming conventions.
This module is the single source of truth for deriving names from resources, events, and channels. All other modules should delegate to these functions to ensure consistent naming across the library.
Resource & Event Naming
Derive identifiers and module names from Ash resources:
iex> Naming.event_id(MyApp.Orders.ProductOrder, :created)
"product_order.created"
iex> Naming.domain_name(MyApp.Orders.ProductOrder)
"orders"
iex> Naming.resource_name(MyApp.Orders.ProductOrder)
"product_order"
iex> Naming.data_key(MyApp.Orders.ProductOrder)
:product_order
iex> Naming.event_module(MyApp.Orders.ProductOrder, "orders", :created)
MyApp.Orders.Events.Created.EventChannel Naming (Filenames & Labels)
Handles the logic for combining transport, audience, and variant into:
- Filenames (e.g.,
email.user.html,email.admin.summary.txt) - Display labels (e.g., "email (user)", "email (admin, summary)")
Deduplication Rule
When variant equals audience (e.g., audience: :admin, variant: "admin"),
the variant is omitted to avoid redundant names like "email.admin.admin.html".
Examples
iex> Naming.filename("email", :user, nil, "html")
"email.user.html"
iex> Naming.filename("email", :admin, "admin", "html")
"email.admin.html" # variant omitted (matches audience)
iex> Naming.filename("email", :admin, "summary", "html")
"email.admin.summary.html"
iex> Naming.label(:email, :user, nil)
"email (user)"
iex> Naming.label(:email, :admin, "admin")
"email (admin)" # variant omitted (matches audience)
iex> Naming.label(:email, :admin, "summary")
"email (admin, summary)"
Summary
Functions
Extract the app module name from a resource.
Derive the data_key from a resource module.
Extract the domain name from a resource module.
Generate an event ID from a resource module and event name.
Derive the expected event module name from resource and event info.
Derive the event module from a resource (auto-deriving domain).
Derive the event module from otp_app and domain/event names.
Build a filename from channel properties.
Check if variant should be included (not redundant with audience).
Build a display label from channel properties.
Derive the module directory path from a module name.
Extract the resource name from a resource module.
Derive the template directory path from an event module.
Get the effective variant parts to display/include.
Derive the wire-name from an event_id by splitting on . and taking
the last segment. Used by the broadcast transport (and any future
transport that needs a Phoenix-channel-friendly event name).
Functions
Extract the app module name from a resource.
Takes the first module segment.
Examples
iex> Naming.app_module(MyApp.Orders.ProductOrder)
"MyApp"
Derive the data_key from a resource module.
Converts the resource name to a snake_case atom, used as the key in context.data for storing the primary resource.
Examples
iex> Naming.data_key(MyApp.Orders.ProductOrder)
:product_order
iex> Naming.data_key(MyApp.Accounts.User)
:user
Extract the domain name from a resource module.
Takes the second-to-last module segment and converts to snake_case.
Examples
iex> Naming.domain_name(MyApp.Orders.ProductOrder)
"orders"
iex> Naming.domain_name(MyApp.Accounts.User)
"accounts"
Generate an event ID from a resource module and event name.
Uses the resource name (last module segment) to avoid collisions when multiple resources in the same domain have common event names.
Examples
iex> Naming.event_id(MyApp.Orders.ProductOrder, :created)
"product_order.created"
iex> Naming.event_id(MyApp.Accounts.User, :password_reset)
"user.password_reset"
Derive the expected event module name from resource and event info.
Convention: {App}.{Domain}.Events.{EventName}.Event
Examples
iex> Naming.event_module(MyApp.Orders.ProductOrder, "orders", :created)
MyApp.Orders.Events.Created.Event
iex> Naming.event_module(MyApp.Accounts.User, "accounts", :password_reset)
MyApp.Accounts.Events.PasswordReset.Event
Derive the event module from a resource (auto-deriving domain).
Convenience function that combines domain_name/1 and event_module/3.
Examples
iex> Naming.event_module_for_resource(MyApp.Orders.ProductOrder, :created)
MyApp.Orders.Events.Created.Event
Derive the event module from otp_app and domain/event names.
Used when the app prefix should come from otp_app rather than a resource module. This is the preferred approach for generated modules since they should live in the user's app namespace.
Examples
iex> Naming.event_module_from_otp_app(:my_app, :orders, :created)
MyApp.Orders.Events.Created.Event
iex> Naming.event_module_from_otp_app(:acme_support, :tickets, :assigned)
AcmeSupport.Tickets.Events.Assigned.Event
Build a filename from channel properties.
Parameters
base- Base name, typically the transport (e.g., "email")audience- Target audience atom (e.g., :user, :admin)variant- Optional variant string or atom (e.g., "summary", :admin)extension- File extension without dot (e.g., "html", "txt")
Returns
Filename string like "email.user.html" or "email.admin.summary.txt"
Check if variant should be included (not redundant with audience).
Returns true if variant is present AND different from audience.
Build a display label from channel properties.
Parameters
transport- Transport type atom (e.g., :email, :sms)audience- Target audience atom (e.g., :user, :admin)variant- Optional variant string or atom
Returns
Label string like "email (user)" or "email (admin, summary)"
Derive the module directory path from a module name.
Used for locating template files relative to the event module.
Examples
iex> Naming.module_directory(MyApp.Orders.Events.Created.Event)
"lib/my_app/orders/events/created"
Extract the resource name from a resource module.
Takes the last module segment and converts to snake_case.
Examples
iex> Naming.resource_name(MyApp.Orders.ProductOrder)
"product_order"
iex> Naming.resource_name(MyApp.Accounts.User)
"user"
Derive the template directory path from an event module.
Examples
iex> Naming.template_directory(MyApp.Orders.Events.Created.Event)
"lib/my_app/orders/events/created/templates"
Get the effective variant parts to display/include.
Returns a list of parts after audience, excluding redundant variant.
Derive the wire-name from an event_id by splitting on . and taking
the last segment. Used by the broadcast transport (and any future
transport that needs a Phoenix-channel-friendly event name).
Per-event override is available via AshDispatch.Event.wire_event_name/0
(defaults to this string transform). F15 — review-deep 2026-05-15.
Examples
iex> AshDispatch.Naming.wire_event_name("pipeline_events.chat_chunk")
"chat_chunk"
iex> AshDispatch.Naming.wire_event_name(:report_resolved)
"report_resolved"
iex> AshDispatch.Naming.wire_event_name("orders.created")
"created"