Skip to content

Instantly share code, notes, and snippets.

View zachdaniel's full-sized avatar

Zach Daniel zachdaniel

View GitHub Profile
@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
)
```elixir
def macro uuidv7_primary(name , opts \\ []) do
quote do
attribute unquote(name), :uuid, Keyword.merge(unquote(opts), [...your_defaults])
end
end
```
@zachdaniel
zachdaniel / stream_distribute.ex
Last active June 15, 2024 14:06
A small demo to show how you might, given a stream, do a "fan out", processing different elements in separate streams. Powered by simple primitives like `Stream.resource` and `spawn_link`. Open in Livebook: https://livebook.dev/run?url=https%3A%2F%2Fgist.github.com%2Fzachdaniel%2Fd5ab06a9d2362fceeb6d27c37b206e28
<!-- livebook:{"persist_outputs":true} -->
# Distribute
## Section
A small toy to show how you might, given a stream, do a "fan out", processing different elements in separate streams. Powered by simple primitives like `Stream.resource` and `spawn_link`.
```elixir
defmodule Distribute do

What does "no lock-in" mean in the context of Ash

I think a reasonable definition of "no lock-in" is required. To me its the ability to “start making new choices”, not necessarily “you can push a button and remove your ash stuff”. But we'll get to ejecting at the end.

Ash is stateless. You call functions and it follows the instructions defined in the action. It supports "dropping the bottom" out of any given operation, by overriding whatever action Ash was going to take, And it will happily work along side ecto resources (or w/e) that modify the underlying data it works with.

Keeping in mind that Ash does significantly more than just simple data manipulation/crud, lets look at a simple example.

Comparing usage of Ash & Ecto

# https://gist.github.com/Gazler/b4e92e9ab7527c7e326f19856f8a974a

Application.put_env(:phoenix, :json_library, Jason)

Application.put_env(:sample, SamplePhoenix.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 5001],
  server: true,