dart-backend / angel

A polished, production-ready backend framework in Dart for the VM, AOT, and Flutter.
https://github.com/dukefirehawk/angel
BSD 3-Clause "New" or "Revised" License
171 stars 22 forks source link

Non-orm serializable jsonb column, can't run migration. #118

Open alguintu opened 5 months ago

alguintu commented 5 months ago

When using a non-orm serializable as a column, source_gen triggers a warning that leads to migration fail:

// simplified example
@orm
@serializable
abstract class _User extends Model {
  String get name;
  _Profile? get profile;
}

@serializable
abstract class _Profile {
  String get firstName;
  String get lastName;
}

Running build_runner succeeds with the following warning:

[INFO] ------------------------------------------------------------------------
[INFO] Starting Build
[INFO] Updating asset graph completed, took 2ms
[WARNING] angel3_orm_generator:angel3_orm on lib/src/models/models.dart:
Cannot generate ORM code for field profile of type _Profile?
[INFO] Running build completed, took 1.8s
[INFO] Caching finalized dependency graph completed, took 40ms
[INFO] Succeeded after 1.9s with 2 outputs (2 actions)

And then when I try to run dart bin/migrate.dart up I get the following error:

../core/lib/src/models/models.g.dart:1020:7: Error: The getter 'profile' isn't defined for the class 'UserQueryWhere'.
 - 'UserQueryWhere' is from 'package:core/src/models/models.dart' ('../core/lib/src/models/models.dart').
Try correcting the name to the name of an existing getter, or defining a getter or field named 'profile'.
      profile,
      ^^^^^^^

What am I missing here? The point is to use a serializable class for a jsonb column, but the generator seems to want to be able to query using that jsonb field. Any hints to what I'm doing wrong would be really appreciated. Thanks.

dukefirehawk commented 5 months ago

The jsonb data type can be done as follows. The @Column annotation is optional. Just added it for clarity. @serializable annotation is not designed to work with jsonb object. Check out the test case has_map_test.dart under angel_orm_test folder.

@orm
@serializable
abstract class _User extends Model {
  String get name;

  @Column(type: ColumnType.jsonb)
  Map<String, String>? profile = {};

  void updateProfile(Profile p) {
    profile = p.toMap();
  }

  Profile retrieveProfile() {
    return Profile()..fromMap(profile ?? {});
  }
}

class Profile {
  String firstName = '';
  String lastName = '';

  Map<String, String> toMap() {
    var result = <String, String>{};
    result['firstName'] = firstName;
    result['lastName'] = lastName;
    return result;
  }

  void fromMap(Map<String, String> m) {
    firstName = m['firstName'] ?? '';
    lastName = m['lastName'] ?? '';
  }
}