Drops.Relation (drops_relation v0.1.0)

View Source

High-level API for defining database relations with automatic schema inference.

Drops.Relation automatically introspects database tables and generates Ecto schemas, providing a convenient query API that delegates to Ecto.Repo functions. Relations support composable queries, custom query definitions, and views.

Configuration

Relations can be configured at the application level:

config :my_app, :drops,
  relation: [
    repo: MyApp.Repo
  ]

Reading and Writing

defmodule MyApp.Users do
  use Drops.Relation, otp_app: :my_app

  schema("users", infer: true)
end

iex> {:ok, user} = MyApp.Users.insert(%{name: "Jane", email: "jane@doe.org", age: 42})
iex> user.name
"Jane"
iex> user.email
"jane@doe.org"
...>
iex> [user] = MyApp.Users.all()
iex> user.name
"Jane"
...>
iex> MyApp.Users.count()
1

Composable Queries

defmodule MyApp.Users do
  use Drops.Relation, otp_app: :my_app

  schema("users", infer: true)
end

iex> MyApp.Users.insert(%{name: "John", email: "john@doe.org", active: true})
iex> MyApp.Users.insert(%{name: "Jane", email: "jane@doe.org", active: true})
iex> MyApp.Users.insert(%{name: "Joe", email: "joe@doe.org", active: false})
...>
iex> query = MyApp.Users
...>          |> MyApp.Users.restrict(active: true)
...>          |> MyApp.Users.order(:name)
...>
iex> [jane, john] = Enum.to_list(query)
iex> jane.name
"Jane"
iex> john.name
"John"

Summary

Functions

Macro for creating delegation functions that automatically inject relation context.

Loads schema cache for all tables in a given repository.

Functions

delegate_to(fun, list)

(macro)

Macro for creating delegation functions that automatically inject relation context.

This macro generates functions that delegate to plugin modules while automatically injecting the current relation module as context. It's used by plugins to create clean APIs that don't require users to manually pass relation information.

Parameters

  • fun - The function call pattern to delegate (e.g., get(id), all())
  • target - The target module to delegate to (specified with to: keyword)

Behaviour

The macro automatically:

  1. Extracts the function name and arguments from the call pattern
  2. Adds [relation: __MODULE__] as the final argument to the delegation
  3. Generates a function definition that calls the target module

Examples

iex> defmodule TestPlugin do
...>   use Drops.Relation.Plugin
...>
...>   def on(:before_compile, _relation, _attributes) do
...>     quote do
...>       delegate_to(test_function(arg), to: unquote(__MODULE__))
...>     end
...>   end
...>
...>   def test_function(arg, opts) do
...>     {arg, opts[:relation]}
...>   end
...> end
...>
iex> defmodule MyApp.TestUsers do
...>   use Drops.Relation, otp_app: :my_app, plugins: [TestPlugin]
...>
...>   schema("users", infer: true)
...> end
...>
iex> MyApp.TestUsers.test_function("hello")
{"hello", Drops.RelationTest.MyApp.TestUsers}

load_cache(repo)

@spec load_cache(module()) :: :ok | {:error, term()}

Loads schema cache for all tables in a given repository.

This function provides a high-level API for loading cache that can be used in production environments without Mix. It introspects all tables in the database and warms up the cache with their schemas.

Parameters

  • repo - The Ecto repository module to load cache for

Returns

  • :ok - Successfully loaded cache for all tables
  • {:error, reason} - Error during cache loading

Examples

# Load cache for a repository
Drops.Relation.load_cache(MyApp.Repo)

# Use in release tasks
defmodule MyApp.Release do
  def load_schema_cache do
    for repo <- repos() do
      Drops.Relation.load_cache(repo)
    end
  end
end

Notes

  • This function requires the application to be started to access repository configuration
  • If no tables are found in the database, the function will still return :ok
  • Tables that don't exist or can't be introspected will be skipped with logging