Skip to content

Spurious "Field '<col>' not found in schema of collection '<Model>'" WARN during schema generation for has_many :through walking a has_one with custom foreign_key #370

Description

@jreed-mt

Summary

Schema generation logs a misleading WARN when a datasource is added with an include: list, and the AR model graph contains a has_many :through (or has_one :through) where:

  • the through leg is polymorphic (has_many ..., as: :something), and
  • the source is a has_one on the through model with a custom foreign_key:.

The schema is still generated correctly; only the log is wrong.

Environment

  • Ruby 3.4 (>= 3.0)
  • Rails 8.1
  • forest_admin_agent 1.27.0
  • forest_admin_datasource_active_record 1.35.2
  • forest_admin_datasource_customizer 1.35.2
  • PostgreSQL

Minimal reproduction

Three models. Parent (published), Child (unpublished, polymorphic belongs_to), and Leaf (unpublished) whose FK column uses a name that doesn't follow the AR default:

class Parent < ApplicationRecord
  has_many :children, as: :owner
  has_many :leaves, through: :children
end

class Child < ApplicationRecord
  belongs_to :owner, polymorphic: true

  has_one :leaf,
    foreign_key: :custom_child_id,   # ← custom FK; column lives on `leaves`
    inverse_of: :child,
    class_name: "Leaf"
end

class Leaf < ApplicationRecord
  belongs_to :child, class_name: "Child", foreign_key: :custom_child_id, inverse_of: :leaf
end

Schema (Postgres):

parents(id)
children(id, owner_type, owner_id)          -- no custom_child_id here
leaves(id, custom_child_id references children(id))

Agent setup uses an include: list that excludes Child and Leaf:

add_datasource(
  ForestAdminDatasourceActiveRecord::Datasource.new(db_config),
  { include: %w[Parent] }
)

Run:

$ bin/rails forest_admin:schema:generate
[ForestAdmin] Starting schema generation...
W, ... WARN -- : Field 'custom_child_id' not found in schema of collection 'Child'
[ForestAdmin] Schema generated successfully at .../.forestadmin-schema.json

custom_child_id is a column on leaves, not on children.

Likely cause

forest_admin_datasource_active_record/lib/.../collection.rb — the :has_many + through_reflection? branch (around line 189) constructs the ManyToManySchema for Parent#leaves as:

ManyToManySchema.new(
  foreign_collection: format_model_name(association.klass.name),         # \"Leaf\"
  origin_key: through_reflection.foreign_key,                            # \"owner_id\" (polymorphic FK on Child — fine)
  origin_key_target: through_reflection.join_foreign_key,
  foreign_key: association.join_foreign_key,                             # \"custom_child_id\" (on `leaves`, NOT on through!)
  foreign_key_target: association.association_primary_key,
  through_collection: format_model_name(through_reflection.klass.name),  # \"Child\"
  ...
)

Then in forest_admin_datasource_customizer/lib/.../publication/publication_collection_decorator.rb#published? (ManyToMany branch, ~line 88):

if field.type == 'ManyToMany'
  return (
    datasource.published?(field.through_collection) &&
    datasource.published?(field.foreign_collection) &&
    datasource.get_collection(field.through_collection).published?(field.foreign_key) &&  # ← asks Child for a column that's on leaves
    datasource.get_collection(field.through_collection).published?(field.origin_key) &&
    published?(field.origin_key_target) &&
    datasource.get_collection(field.foreign_collection).published?(field.foreign_key_target)
  )
end

Line 92 asks the through collection (Child) whether it publishes foreign_key (custom_child_id), but for a has_many :through where the source is a has_one, that column lives on the target table (leaves), not the through table (children). The published? on Child then falls into the field.nil? branch at line 66:

message = \"Field '#{name}' not found in schema of collection '#{self.name}'\"
ForestAdminAgent::Facades::Container.logger.log('Warn', message)

producing the observed WARN.

Expected

No WARN. Either:

  1. The publication check should validate foreign_key against datasource.get_collection(field.foreign_collection) (the target), not field.through_collection, or
  2. The AR datasource should populate foreign_key/foreign_key_target such that they refer to columns on the through collection.

Impact

Cosmetic — schema still generates correctly. But when many such associations exist (or repeat per-schema-refresh), the warnings drown out real diagnostics in dev/CI tooling.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions