Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MultiEntity? #4

Closed
chikamichi opened this issue May 31, 2023 · 3 comments
Closed

MultiEntity? #4

chikamichi opened this issue May 31, 2023 · 3 comments
Labels
documentation Improvements or additions to documentation

Comments

@chikamichi
Copy link

chikamichi commented May 31, 2023

Hi! Thank you for creating this great library.

I wonder whether it’s possible, or could be made possible, creating a union of Entity modddels.

Currently the documentation only covers creating a union of ValueObject modddels:

class Weather extends MultiValueObject<InvalidWeather, ValidWeather> with _$Weather {

with the variants factories (Weather.sunny, Weather.rainy…) expected raw types (int, double, String, etc.) for the attributes.

I’d like to have the factories support Entity and/or ValueObject types, and the generated modddel behave as an Entity itself.

Rational

My use-case is as follow:

  • I’m modelling data layers for a map
    • there are multiple, specific layer types: raster, vector, geojson…
      • each with different attributes and behaviors
      • but with some shared attributes as well
  • "leaf" attributes are implemented as value objects: URI, VectorTilesStyle, GeoJSON, Percentage… each with its specific validation logic
  • for there are multiple layer types, and each type supports only so much of the possible "leaf" attributes, there’s need to be layer types variants: MapLayer ought to be the union of MapLayer.raster, MapLayer.vector, MapLayer.geojson… with some shared attributes (int position in the layer selector, URI uri to fetch the layer tiles from a remote source…), and some specific attributes depending on the variant (e.g., MapLayer.geojson requires GeoJSON geojsonText, whereas other variants don’t)

It could look like this (not using shared props, but could dry things up nicely):

// import "package:freezed_annotation/freezed_annotation.dart";
import "package:modddels_annotation_fpdart/modddels_annotation_fpdart.dart";

import "../../value_objects/geojson/geojson.dart";
import "../../value_objects/map_layer_position/map_layer_position.dart";
import "../../value_objects/vector_tiles_style/vector_tiles_style.dart";
import "../../value_objects/map_layer_type/map_layer_type.dart";
import "../../value_objects/percentage/percentage.dart";
import "../../value_objects/uri/uri.dart";

part "map_layer.modddel.dart";
// part "map_layer.freezed.dart";

@Modddel(
  validationSteps: [
    ValidationStep([
      contentValidation,
    ]),
    // [… some more validations …]
  ],
)
class MapLayer extends MultiEntity<InvalidMapLayer, ValidMapLayer>
    with _$MapLayer {
  MapLayer._();

  factory MapLayer.raster(
      {required MapLayerPosition position,
      required URI uri,
      @validParam bool loaded = false,
      @validParam bool enabled = false,
      Percentage opacity = 1}) {
    return _$MapLayer._createRaster(
      position: position,
      uri: uri,
    );
  }

  factory MapLayer.vector(
      {required MapLayerPosition position,
      required URI uri,
      @validParam bool loaded = false,
      @validParam bool enabled = false,
      Percentage opacity = 1,
      // MapLayel.vector’s specific attributes
      required VectorTilesStyle style,
      // [ … more specific attributes …]
    }) {
    return _$MapLayer._createVector(
      position: position,
      uri: uri,
      loaded: loaded,
      enabled: enabled,
      opacity: opacity,
      style: style,
    );
  }

 factory MapLayer.geojson(
      {required MapLayerPosition position,
      required URI uri,
      @validParam bool loaded = false,
      @validParam bool enabled = false,
      Percentage opacity = 1,
      // MapLayel.geojson’s specific attributes
      required GeoJSON geojsonText,
      // [ … more specific attributes …]
    }) {
    return _$MapLayer._createGeojson(
      position: position,
      uri: uri,
      loaded: loaded,
      enabled: enabled,
      opacity: opacity,
      geojsonText: geojsonText
    );
  }

  // [… validation methods …]
}

// [… ValueFailure implementation …]
@CodingSoot
Copy link
Owner

Hi there,

I think you're confusing MultiValueObject with union of ValueObjects. A MultiValueObject is simply a ValueObject that can have multiple member parameters (See this page of the docs).

You can create a union of any modddel kind, you just need to follow the same steps as for creating a modddel, then add multiple factory constructors. The Weather example you mentioned was for creating a union of MultiValueObjects, but you can do the same for all other modddel kinds (SingleValueObject, SimpleEntity...)

In your use-case, you want to create a union of SimpleEntity :

class MapLayer extends SimpleEntity<InvalidMapLayer, ValidMapLayer> with _$MapLayer {
  MapLayer._();

  /// ... your factory constructors
}

I will edit the docs to clear up the confusion.

Let me know if this helped !

@chikamichi
Copy link
Author

Oh, right! Let me try it out then.

@CodingSoot CodingSoot added the documentation Improvements or additions to documentation label May 31, 2023
@CodingSoot
Copy link
Owner

I've updated the docs.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

No branches or pull requests

2 participants