Created
April 15, 2025 20:14
-
-
Save pinetops/e4859594d66e6830c15f0c276900aca8 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Remember that in addition to the prior instructions, when writing queries and code examples, please adhere to the following guidelines: | |
General: | |
- Database access is done using Ash 3.0/AshPostgres resources | |
- Don't use Ash resources for in memory data structures unless specified | |
- Only implement coding standards for new/modified code unless explicitly specified | |
- Minimal comments (only notable/counter-intuitive), no module level or function level docs | |
- Always Remove any unused aliases | |
IMPORTANT - MIGRATIONS: | |
- NEVER generate migration files or migration code | |
- DO NOT create files with timestamps like "20240322123456_add_field.exs" | |
- DO NOT attempt to write migration code in any form | |
- When schema changes are needed, simply note: "These changes will require running `mix ash_postgres.generate_migrations`" | |
- Ash handles migrations differently from Ecto - they are automatically generated with the command above | |
Ash coding standards: | |
When writing Ash code: | |
- Use domain functions when accessing data that's primarily in a different domain (don't go through contortions though) or from non domain modules | |
- Domain functions should be implemented using resource/define in the domain module and calling an action (created as needed) on the resource (Domain module is usually the parent module, but always contains 'use Ash.Domain) | |
- When implementing queries with Ash.Query, you must 'require Ash.Query' in any module in which you use Ash's query syntax, and then use the Ash 3.0 interface (Ash.read(), Ash.read_one!(), Ash.create() etc. and ! versions) | |
- When doing individual creates/updates, prefer the following syntax (optionally Ash.update!()/Ash.create!()): | |
- For updates: `entity |> Ash.Changeset.for_update(:action, %{prop1: value1, prop2: value2}) |> Ash.update()` | |
- For creates: `Resource |> Ash.Changeset.for_create(:action, %{prop1: value1, prop2: value2}) |> Ash.create()` | |
- Alternatively, for attribute-by-attribute updates: `Ash.Changeset.for_update(entity, :action) |> Ash.Changeset.set_attribute(:prop, value) |> Ash.update!()` | |
- Do NOT use the pattern: `entity |> Ash.Changeset.for_update(:action, %{prop1: value1})` as this is not the preferred approach | |
- in general ash data operations without ! return tuple with status :ok/:error with ! returns entity directly | |
- For bulk operations, use Ash 3.0 syntax (! optional): | |
- Ash.bulk_destroy(records, :destroy, %{}) - do NOT add atomic: true as a separate parameter | |
- Ash.bulk_create(records, Resource, :create, return_errors?: true) - action options go directly in the function call, not in a separate map | |
- When building an Ash Query set_argument should be called before for_read (etc.) | |
- When using Ash.filter(...) queries do not need to be wrapped in expr(), but when using filter in a resource declaration you do need to wrap in expr() When using a select operation, any fields not selected or relationships not loaded will return %Ash.NotLoaded{} instead of nil | |
- NEVER generate database migrations | |
- NEVER include migration code in your response | |
- When adding/changing database fields, simply state: "Run `mix ash_postgres.generate_migrations` to create the necessary migrations for these changes" | |
Generic Actions and Action Modules: | |
- When creating generic actions, always use `Ash.ActionInput.get_argument/2` consistently to access input arguments | |
- For action modules that implement `run/3`: | |
- Return `{:ok, result}` or `{:error, reason}` consistently | |
- Place them in a dedicated directory (e.g., `lib/domain/actions/`) | |
- Keep them focused on a single responsibility | |
- For domain functions that delegate to actions: | |
- when using 'args: [:arg1, :arg2], remember these translate into positional function arguments:with' | |
General Elixir: | |
- no @doc for private functions |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment