Ash FrameworkAF
Ash Framework7mo ago
12 replies
Oliver

Using no attributes to use a parent_type / parent_id style table as a join table

I have this table:
attributes do
    integer_primary_key :id

    attribute :target_type, Safari.Types.LithostratTargetType, public?: true, allow_nil?: false
    attribute :target_id, :integer, public?: true, allow_nil?: false
    create_timestamp :inserted_at, public?: true
    update_timestamp :updated_at, public?: true
  end

  relationships do
    belongs_to :parent, Safari.Outcrop.Outcrop, public?: true, allow_nil?: false

    has_one :group, Safari.Wiki.Group,
      source_attribute: :target_id,
      destination_attribute: :id,
      filter: expr(parent(target_type) == :group)

    has_one :formation, Safari.Wiki.Formation,
      source_attribute: :target_id,
      destination_attribute: :id,
      filter: expr(parent(target_type) == :formation)

    has_one :member, Safari.Wiki.Member,
      source_attribute: :target_id,
      destination_attribute: :id,
      filter: expr(parent(target_type) == :member)
  end


And in Group I want to query all Outcrop through this table..

I thought I had done this before and I am currently stuck here (in relationships of Group):
has_many :outcrops, Outcrop do
      no_attributes? true
      filter expr(what_to_put_here.target_id == parent(id) and target_type == :group)
    end
Solution
Ok for anyone else coming across this post because they want to use no_attributes? true to do some complex mapping, here is the gist of it:

- You can do a has_many or has_one to any App.Domain.Resource with some prereqs:
- There must be a tangible path mapped up back to what you want
- In my case I had
- Outcrop
- LithostratOutcropLink (with parent_id == outcrop, target_type == group|member|formation and target_id == the id of the group etc)
- Group
Solution to put on Group:
has_many :outcrops, Safari.Outcrop.Outcrop do
      no_attributes? true

      filter expr(
               lithostrat_outcrop_links.target_id == parent(id) and
                 lithostrat_outcrop_links.target_type == :group
             )
    end


This works because outcrop has:

has_many :lithostrat_outcrop_links, LithostratOutcropLink,
      public?: true,
      destination_attribute: :parent_id


And that lets the filter traverse this relation and relate the ids etc with the source resource, using this middle table as an impromptu jointable.
Was this page helpful?