Class: DynamicActiveModel::Associations

Inherits:
Object
  • Object
show all
Defined in:
lib/dynamic-active-model/associations.rb

Overview

The Associations class is responsible for automatically detecting and setting up ActiveRecord relationships between models based on database schema analysis. It supports the following relationship types:

  • belongs_to

  • has_many

  • has_one (automatically detected from unique constraints)

  • has_and_belongs_to_many (automatically detected from join tables)

Examples:

Basic Usage

db = DynamicActiveModel::Database.new(DB, database_config)
db.create_models!
associations = DynamicActiveModel::Associations.new(db)
associations.build!

Custom Foreign Key

associations.add_foreign_key('users', 'manager_id', 'manager')

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(database) ⇒ Associations

Initializes a new Associations instance

Parameters:

  • database (Database)

    The database instance containing the models



32
33
34
35
36
37
38
39
40
41
42
# File 'lib/dynamic-active-model/associations.rb', line 32

def initialize(database)
  @database = database
  @table_indexes = {}
  @join_tables = []
  @foreign_keys = {}
  database.models.each do |model|
    @foreign_keys[model.table_name] = ForeignKey.new(model)
    @table_indexes[model.table_name] = model.connection.indexes(model.table_name)
    @join_tables << model if join_table?(model)
  end
end

Instance Attribute Details

#databaseDatabase (readonly)

Returns The database instance containing the models.

Returns:

  • (Database)

    The database instance containing the models



22
23
24
# File 'lib/dynamic-active-model/associations.rb', line 22

def database
  @database
end

#join_tablesArray (readonly)

Returns List of detected join tables.

Returns:

  • (Array)

    List of detected join tables



28
29
30
# File 'lib/dynamic-active-model/associations.rb', line 28

def join_tables
  @join_tables
end

#table_indexesHash (readonly)

Returns Mapping of table names to their indexes.

Returns:

  • (Hash)

    Mapping of table names to their indexes



25
26
27
# File 'lib/dynamic-active-model/associations.rb', line 25

def table_indexes
  @table_indexes
end

Instance Method Details

#add_foreign_key(table_name, foreign_key, relationship_name = nil) ⇒ Object

Adds a custom foreign key relationship

Parameters:

  • table_name (String)

    Name of the table with the foreign key

  • foreign_key (String)

    Name of the foreign key column

  • relationship_name (String, nil) (defaults to: nil)

    Custom name for the relationship



48
49
50
# File 'lib/dynamic-active-model/associations.rb', line 48

def add_foreign_key(table_name, foreign_key, relationship_name = nil)
  @foreign_keys[table_name].add(foreign_key, relationship_name)
end

#build!void

This method returns an undefined value.

Builds all relationships between models based on foreign keys and constraints This method:

  1. Maps foreign keys to their corresponding models

  2. Adds belongs_to relationships

  3. Adds has_many or has_one relationships based on unique constraints

  4. Sets up has_and_belongs_to_many relationships for join tables



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/dynamic-active-model/associations.rb', line 59

def build!
  foreign_key_to_models = create_foreign_key_to_model_map

  @database.models.each do |model|
    model.column_names.each do |column_name|
      next unless foreign_key_to_models[column_name.downcase]

      foreign_key_to_models[column_name.downcase].each do |foreign_model, relationship_name|
        next if foreign_model == model

        add_relationships(relationship_name, model, foreign_model, column_name)
      end
    end
  end

  @join_tables.each do |join_table_model|
    models = join_table_model.column_names.map { |column_name| foreign_key_to_models[column_name.downcase]&.first&.first }.compact
    if models.size == 2
      add_has_and_belongs_to_many(join_table_model, models)
    end
  end
end