Class: IronAdmin::FieldInferrer

Inherits:
Object
  • Object
show all
Defined in:
lib/iron_admin/field_inferrer.rb

Overview

Infers field configurations from an ActiveRecord model's database schema.

This is the core of IronAdmin's convention-over-configuration approach. It analyzes the model's columns and associations to automatically generate appropriate field configurations without requiring explicit definitions.

The inferrer handles:

  • Column type to field type mapping
  • Enum column detection (generates select fields)
  • belongs_to association detection (generates association fields)
  • has_many/has_one shadowing (excludes columns named after associations)

Examples:

Basic usage

fields = IronAdmin::FieldInferrer.call(User)
fields.map(&:name)  #=> [:id, :name, :email, :role, :organization, :created_at, ...]

See Also:

Constant Summary collapse

URL_PATTERN =

Column name patterns that indicate a URL field.

Returns:

  • (Regexp)
/\A(website|homepage|.*_url|.*_link)\z/
EMAIL_PATTERN =

Column name patterns that indicate an email field.

Returns:

  • (Regexp)
/\A(email|.*_email)\z/
TYPE_MAP =

Maps database column types to field types.

Returns:

  • (Hash{Symbol => Symbol})
{
  string: :text,
  text: :textarea,
  integer: :number,
  float: :number,
  decimal: :number,
  boolean: :boolean,
  date: :date,
  datetime: :datetime,
  time: :time,
  json: :json,
  jsonb: :json,
}.freeze

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(adapter) ⇒ FieldInferrer

Creates a new FieldInferrer for the given adapter.

Parameters:



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/iron_admin/field_inferrer.rb', line 69

def initialize(adapter)
  @adapter = adapter
  @polymorphic_map = adapter.associations(:belongs_to)
    .select(&:polymorphic?)
    .index_by { |a| a.name.to_s }
  @polymorphic_columns = @polymorphic_map.values
    .flat_map { |a| [a.foreign_type, a.foreign_key.to_s] }.to_set
  @belongs_to_map = adapter.associations(:belongs_to)
    .reject(&:polymorphic?)
    .index_by { |a| a.foreign_key.to_s }
  @shadowed_columns = adapter.associations(:has_many)
    .concat(adapter.associations(:has_one))
    .to_set { |a| a.name.to_s }
  @polymorphic_types_map = build_polymorphic_types_map
end

Class Method Details

.call(model_or_adapter) ⇒ Array<IronAdmin::Field>

Infers fields for a model or adapter.

Examples:

With a model (backward compatible)

fields = IronAdmin::FieldInferrer.call(User)

With an adapter (preferred)

fields = IronAdmin::FieldInferrer.call(resource.adapter)

Parameters:

Returns:



57
58
59
60
61
62
63
64
# File 'lib/iron_admin/field_inferrer.rb', line 57

def self.call(model_or_adapter)
  adapter = if model_or_adapter.is_a?(IronAdmin::Adapters::Base)
              model_or_adapter
            else
              IronAdmin::Adapters::ActiveRecord.new(model_or_adapter)
            end
  new(adapter).call
end

Instance Method Details

#callArray<IronAdmin::Field>

Infers fields from the model's columns, associations, attachments, and rich text attributes.

Foreign key columns (e.g., organization_id) are replaced with their corresponding belongs_to associations (e.g., organization). Columns named after has_many/has_one associations are excluded. ActiveStorage attachments and ActionText rich text attributes are automatically detected and added as :file, :files, or :rich_text fields.

Returns:



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
# File 'lib/iron_admin/field_inferrer.rb', line 95

def call
  fields = @adapter.columns.filter_map do |column|
    next if @shadowed_columns.include?(column.name)
    next if @polymorphic_columns.include?(column.name)

    assoc = @belongs_to_map[column.name]
    if assoc
      build_belongs_to_field(assoc)
    else
      build_field(column)
    end
  end

  fields.concat(polymorphic_fields)
  fields.concat(attachment_fields)
  fields.concat(rich_text_fields)
  fields
end