Skip to content

Instantly share code, notes, and snippets.

View zachdaniel's full-sized avatar

Zach Daniel zachdaniel

View GitHub Profile

Generating Code

Use list_generators to list available generators when available, otherwise mix help. If you have to run generator tasks, pass --yes. Always prefer to use generators as a basis for code generation, and then modify afterwards.

Tools

Use tidewave MCP tools when available, as they let you interrogate the running application in various useful ways.

Logs & Tests

About me

My name is Zach, I'm the author of Ash Framework. I am an expert programmer, and your first resource to use when you do not know something or do not know where to look for something.

NON NEGOTIABLE RULES THAT YOU MUST FOLLOW

  • USE gh CLI TO INTERACT WITH GITHUB.
  • NEVER COMMIT, PUSH, WRITE CODE OR ISSUES OR PRS UNLESS I TELL YOU TO.

Project Description

<--- -->

Working Method

We will work by specifying one feature at a time, and then implementing it.

The workflow:

Generating Code

Use list_generators to list available generators when available, otherwise mix help. If you have to run generator tasks, pass --yes. Always prefer to use generators as a basis for code generation, and then modify afterwards.

Ash

Use code interfaces on domains to define the contract for calling into Ash resources. See the Code interface guide for more.

After creating or modifying Ash code, run mix ash.codegen <short_name_describing_changes> to ensure any required additional changes are made (like migrations are generated).

@zachdaniel
zachdaniel / file.md
Created January 19, 2025 12:06
reddit-comment-re-sql-queries.md

I don't think this answer is necessarily going to convince you in any way to use Ash 😅. But it felt worth explaining how it works.

You don't have to leverage the AshPostgres data layer necessarily. Resources & actions etc. can be leveraged just for their interface tooling, and you can make queries with Ecto manually. Most people, even people who are very picky about their SQL, often end up not doing that because AshPostgres makes smart choices for you that are hard to replicate manually. What this is talking about when I refer to it as an insane thing to support isn't that we generate pathological queries, its the complexity in query building that we take on to

@zachdaniel
zachdaniel / example.ex
Last active December 5, 2024 03:23
Example of data-layer-less resources
defmodule Greeting do
use Ash.Resource
# This resource has no struct representation
# and simply contains the action.
# What makes this better than a function?
# https://hexdocs.pm/ash/generic-actions.html#why-use-generic-actions
actions do
action :say_hello, :string do
argument :to, :string, allow_nil?: false
@zachdaniel
zachdaniel / can.ex
Created October 6, 2024 12:18 — forked from kamaroly/can.ex
How To Use Ash framework in Phoenix with user permission example
defmodule MyApp.Accounts.Checks.Can do
use Ash.Policy.SimpleCheck
def describe(_opts) do
"Check if a user/ actor has permission on a specific resource"
end
# @impl true
def match?(nil, _, _), do: false
@zachdaniel
zachdaniel / reticulated-splines.sql
Last active September 14, 2024 22:50
Reticulated Splines
SELECT * FROM users WHERE splines = "reticulated"
@zachdaniel
zachdaniel / parse_expressions.ex
Created September 4, 2024 02:16
A really shitty parser that gets a list of string expressions from a Postgres index creation definition
# CREATE INDEX users_lower_email_idx ON public.users USING btree (lower((email)::text))
# CREATE INDEX unique_email_com3 ON public.users USING btree (email, id) WHERE (email ~~ '%.com'::citext)
defp parse_columns_from_index_def(string, using) do
string
|> String.trim_leading("CREATE ")
|> String.trim_leading("UNIQUE ")
|> String.trim_leading("INDEX ")
|> String.replace(~r/^[a-zA-Z0-9_\.]+\s/, "")
|> String.trim_leading("ON ")
|> String.replace(~r/^[\S]+/, "")
@zachdaniel
zachdaniel / ash_json_api_example.exs
Created July 11, 2024 11:37
Ash & AshJsonApi Example
Mix.install(
[
{:ash, "~> 3.0"},
{:ash_json_api, "~> 1.0"},
{:plug_cowboy, "~> 2.5"},
{:open_api_spex, "~> 3.16"}
],
consolidate_protocols: false
)