Skip to main content

Quellinformationen

Repository
diegosouzapw/awesome-omni-skill
Letzte Quellaktivität
2. März 2026 um 12:15
Erkannte Sprache von SKILL.md
Englisch
Sterne
62
Forks
20

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
2 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
ash-postgres
description
Rules for working with AshPostgres
<!-- SPDX-FileCopyrightText: 2020 Zach Daniel SPDX-License-Identifier: MIT --> # Rules for working with AshPostgres ## Understanding AshPostgres AshPostgres is the PostgreSQL data layer for Ash Framework. It's the most fully-featured Ash data layer and should be your default choice unless you have specific requirements for another data layer. Any PostgreSQL version higher than 13 is fully supported. ## Basic Configuration To use AshPostgres, add the data layer to your resource: ```elixir defmodule MyApp.Tweet do use Ash.Resource, data_layer: AshPostgres.DataLayer attributes do integer_primary_key :id attribute :text, :string end relationships do belongs_to :author, MyApp.User end postgres do table "tweets" repo MyApp.Repo end end ``` ## PostgreSQL Configuration ### Table & Schema Configuration ```elixir postgres do # Required: Define the table name for this resource table "users" # Optional: Define the PostgreSQL schema schema "public" # Required: Define the Ecto repo to use repo MyApp.Repo # Optional: Control whether migrations are generated for this resource migrate? true end ``` ## Foreign Key References Use the `references` section to configure foreign key behavior: ```elixir postgres do table "comments" repo MyApp.Repo references do # Simple reference with defaults reference :post # Fully configured reference reference :user, on_delete: :delete, # What happens when referenced row is deleted on_update: :update, # What happens when referenced row is updated name: "comments_to_users_fkey", # Custom constraint name deferrable: true, # Make constraint deferrable initially_deferred: false # Defer constraint check to end of transaction end end ``` ### Foreign Key Actions For `on_delete` and `on_update` options: - `:nothing` or `:restrict` - Prevent the change to the referenced row - `:delete` - Delete the row when the referenced row is deleted (for `on_delete` only) - `:update` - Update the row according to changes in the referenced row (for `on_update` only) - `:nilify` - Set all foreign key columns to NULL - `{:nilify, columns}` - Set specific columns to NULL (Postgres 15.0+ only) > **Warning**: These operations happen directly at the database level. No resource logic, authorization rules, validations, or notifications are triggered. ## Check Constraints Define database check constraints: ```elixir postgres do check_constraints do check_constraint :positive_amount, check: "amount > 0", name: "positive_amount_check", message: "Amount must be positive" check_constraint :status_valid, check: "status IN ('pending', 'active', 'completed')" end end ``` ## Custom Indexes Define custom indexes beyond those automatically created for identities and relationships: ```elixir postgres do custom_indexes do index [:first_name, :last_name] index :email, unique: true, name: "users_email_index", where: "email IS NOT NULL", using: :gin index [:status, :created_at], concurrently: true, include: [:user_id] end end ``` ## Custom SQL Statements Include custom SQL in migrations: ```elixir postgres do custom_statements do statement "CREATE EXTENSION IF NOT EXISTS \"uuid-ossp\"" statement """ CREATE TRIGGER update_updated_at BEFORE UPDATE ON posts FOR EACH ROW EXECUTE FUNCTION trigger_set_timestamp(); """ statement "DROP INDEX IF EXISTS posts_title_index", on_destroy: true # Only run when resource is destroyed/dropped end end ``` ## Migrations and Codegen ### Development Migration Workflow (Recommended) For development iterations, use the dev workflow to avoid naming migrations prematurely: 1. Make resource changes 2. Run `mix ash.codegen --dev` to generate and run dev migrations 3. Review the migrations and run `mix ash.migrate` to run them 4. Continue making changes and running `mix ash.codegen --dev` as needed 5. When your feature is complete, run `mix ash.codegen add_feature_name` to generate final named migrations (this will rollback dev migrations and squash them) 3. Review the migrations and run `mix ash.migrate` to run them ### Traditional Migration Generation For single-step changes or when you know the final feature name: 1. Run `mix ash.codegen add_feature_name` to generate migrations 2. Review the generated migrations in `priv/repo/migrations` 3. Run `mix ash.migrate` to apply the migrations > **Tip**: The dev workflow (`--dev` flag) is preferred during development as it allows you to iterate without thinking of migration names and provides better development ergonomics. > **Warning**: Always review migrations before applying them to ensure they are correct and safe. ## Multitenancy AshPostgres supports schema-based multitenancy: ```elixir defmodule MyApp.Tenant do use Ash.Resource, data_layer: AshPostgres.DataLayer # Resource definition... postgres do table "tenants" repo MyApp.Repo # Automatically create/manage tenant schemas manage_tenant do template ["tenant_", :id] end end end ``` ### Setting Up Multitenancy 1. Configure your repo to support multitenancy: ```elixir defmodule MyApp.Repo do use AshPostgres.Repo, otp_app: :my_app # Return all tenant schemas for migrations def all_tenants do import Ecto.Query, only: [from: 2] all(from(t in "tenants", select: fragment("? || ?", "tenant_", t.id))) end end ``` 2. Mark resources that should be multi-tenant: ```elixir defmodule MyApp.Post do use Ash.Resource, data_layer: AshPostgres.DataLayer multitenancy do strategy :context attribute :tenant end # Resource definition... end ``` 3. When tenant migrations are generated, they'll be in `priv/repo/tenant_migrations` 4. Run tenant migrations in addition to regular migrations: ```bash # Run regular migrations mix ash.migrate # Run tenant migrations mix ash_postgres.migrate --tenants ``` ## Advanced Features ### Manual Relationships For complex relationships that can't be expressed with standard relationship types: ```elixir defmodule MyApp.Post.Relationships.HighlyRatedComments do use Ash.Resource.ManualRelationship use AshPostgres.ManualRelationship def load(posts, _opts, context) do post_ids = Enum.map(posts, & &1.id) {:ok, MyApp.Comment |> Ash.Query.filter(post_id in ^post_ids) |> Ash.Query.filter(rating > 4) |> MyApp.read!() |> Enum.group_by(& &1.post_id)} end def ash_postgres_join(query, _opts, current_binding, as_binding, :inner, destination_query) do {:ok, Ecto.Query.from(_ in query, join: dest in ^destination_query, as: ^as_binding, on: dest.post_id == as(^current_binding).id, on: dest.rating > 4 )} end # Other required callbacks... end # In your resource: relationships do has_many :highly_rated_comments, MyApp.Comment do manual MyApp.Post.Relationships.HighlyRatedComments end end ``` ### Using Multiple Repos (Read Replicas) Configure different repos for reads vs mutations: ```elixir postgres do repo fn resource, type -> case type do :read -> MyApp.ReadReplicaRepo :mutate -> MyApp.WriteRepo end end end ``` ## Best Practices 1. **Organize migrations**: Run `mix ash.codegen` after each meaningful set of resource changes with a descriptive name: ```bash mix ash.codegen --name add_user_roles mix ash.codegen --name implement_post_tagging ``` 2. **Use check constraints for domain invariants**: Enforce data integrity at the database level: ```elixir check_constraints do check_constraint :valid_status, check: "status IN ('pending', 'active', 'completed')" check_constraint :positive_balance, check: "balance >= 0" end ``` 3. **Use custom statements for schema-only changes**: If you need to add database objects not directly tied to resources: ```elixir custom_statements do statement "CREATE EXTENSION IF NOT EXISTS \"pgcrypto\"" statement "CREATE INDEX users_search_idx ON users USING gin(search_vector)" end ``` Remember that using AshPostgres provides a full-featured PostgreSQL data layer for your Ash application, giving you both the structure and declarative approach of Ash along with the power and flexibility of PostgreSQL.
Auf GitHub ansehen