ash-project / ash-project/ash

Code Interface: Allow defining `?` functions that return the unwrapped boolean result

Open
#1,696 1 comment 0 reactions 0 assignees View on GitHub
enhancement
Dominant language
Elixir
Stars
2.5k
Forks
426
Avg merge
23h 26m
Merged PRs (30d)
46

Description

**Is your feature request related to a problem? Please describe.**

There isn't a way to define a question mark function on code interfaces that return a boolean. All code interface functions auto-generate the non-bang (tuple wrapped result) and bang (unwrapped result) versions today.

If you want to define a resource action that returns a boolean typically suffixed with a question mark, you end up with a non-bang and bang-version of it.

For example

```elixir
define :user_exists?

# Generates
user_exists?(...) -> {:ok, boolean()}
user_exists?! -> boolean()
```

Question mark functions aren't written this way by convention since they operate like the bang version.

**Describe the solution you'd like**
A clear and concise description of what you want to happen.

When a code interface function has a question mark suffix, generate one function that works like the bang version, returning only the result.

```elixir
define :user_exists?

# Generates only
user_exists?(...) -> boolean()
```

**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.

**Express the feature either with a change to resource syntax, or with a change to the resource interface**

The current alternative is not to use the code interface to define the function; instead, the question mark function is created in the domain directly.

```elixir
def user_exists?(user_id, opts \\ []) do
MyApp.Accounts.User
|> Ash.Query.for_read(:read, opts)
|> Ash.Query.filter(id == ^user_id)
|> Ash.exists?()
end
```

Or

Combine with a generic action in the resource.

```elixir
def user_exists?(user_id, opts) do
MyApp.Accounts.User
|> Ash.ActionInput.for_action(:user_exists?, opts)
|> Ash.run_action!()
end
```

This is a simple example of checking where a record exists but applies to any action that returns a boolean, which should be suffixed with a question mark.

**Additional context**
This isn't a critical issue and has an easy workaround with defining functions inside the domain. However, this helps keep the resource's actions inside the resource and the use of the domain to expose them.

Contributor guide

Open the contributing guide

Research direction

Trace how code interface functions are generated from resource actions, focusing on the handling of bang and question-mark suffixes. Review existing tests for generated interfaces and add coverage for a question-mark action returning a boolean. Done means the question-mark interface returns the unwrapped boolean without generating a separate bang variant, while existing conventions remain unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
elixir
Domain
backend-api-design
Issue type
Feature
Difficulty
3/5
Estimated time
1-2 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.