save method

Future<T?> save({
  1. bool autoTimestamps = true,
  2. bool autoId = true,
})

Save itself, auto-generates UUID if needed, returns fresh hydrated model.

Implementation

Future<T?> save({bool autoTimestamps = true, bool autoId = true}) async
{
  final map = toMap();

  // Apply pending changes!
  if (_pendingAttributes.isNotEmpty) {
    map.addAll(_pendingAttributes);
    _pendingAttributes.clear();
  }

  final pkName = primaryKey;
  var pkValue = map[pkName];

  // -----------------------------------------------------
  // AUTO GENERATE UUID FOR NON-AUTOINCREMENT MODELS
  // -----------------------------------------------------
  if (!autoIncrementPrimary) {
    final missing = pkValue == null || pkValue.toString().isEmpty;

    if (missing) {
      if (autoId) {
        // Generate UUID only when missing
        final newUuid = const Uuid().v4();
        map[pkName] = newUuid;
        pkValue = newUuid;
      } else {
        throw Exception(
          "Cannot save $table: primary key '$pkName' is missing and autoId=false.",
        );
      }
    }
  }

  // TIMESTAMPS
  if (timestamps) {
    if (autoTimestamps && map.containsKey('updated_at')) {
      map['updated_at'] = Helper.now(format: 'sql');
    }

    if (map.containsKey('created_at') && map['created_at'] == null) {
      map['created_at'] = Helper.now(format: 'sql');
    }
  }

  // DETERMINE INSERT vs UPDATE
  bool exists;

  if (autoIncrementPrimary) {
    exists = pkValue != null;
  } else {
    // For UUID primary keys
    exists = await find(pkValue) != null;
  }

  // INSERT / UPDATE
  dynamic finalPkValue;

  if (!exists) {
    if (autoIncrementPrimary) {
      finalPkValue = await dbService.insert(table, map);
    } else {
      await dbService.insert(table, map);
      finalPkValue = pkValue;
    }
  } else {
    finalPkValue = pkValue;

    await dbService.update(
      table,
      map,
      where: '$pkName = ?',
      params: [pkValue],
    );
  }

  final fresh = await find(finalPkValue, include: loadedIncludes);

  return fresh;
}