feat: EquatableConfig for global stringify configuration (#69)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4a390e6..1c1279b 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 1.2.0
+
+- Added `EquatableConfig` for global `stringify` configuration
+
# 1.1.1
- Updates to `EquatableUtils` documentation
diff --git a/README.md b/README.md
index 131b5a0..d9b1cb7 100644
--- a/README.md
+++ b/README.md
@@ -170,7 +170,9 @@
```
### `toString` Implementation
+
Equatable can implement `toString` method including all the given props. If you want that behaviour, just include the following:
+
```dart
@override
bool get stringify => true;
@@ -188,19 +190,30 @@
@override
List<Object> get props => [name];
-
+
@override
bool get stringify => true;
}
```
-For the name `Bob`, the outuput will be:
-```
-Person(Bob)
-```
+
+For the name `Bob`, the output will be:
+
+`Person(Bob)`
+
This flag by default is false and `toString` will return just the type:
+
+`Person`
+
+#### EquatableConfig
+
+`stringify` can also be configured globally for all `Equatable` instances via `EquatableConfig`
+
+```dart
+EquatableConfig.stringify = true;
```
-Person
-```
+
+If `stringify` is overridden for a specific `Equatable` class, then the value of `EquatableConfig.stringify` is ignored.
+In other words, the local configuration always takes precedence over the global configuration.
## Recap
diff --git a/lib/equatable.dart b/lib/equatable.dart
index 5e54832..3dc9fb0 100644
--- a/lib/equatable.dart
+++ b/lib/equatable.dart
@@ -1,4 +1,5 @@
library equatable;
export './src/equatable.dart';
+export './src/equatable_config.dart';
export './src/equatable_mixin.dart';
diff --git a/lib/src/equatable.dart b/lib/src/equatable.dart
index aa0735c..ed85511 100644
--- a/lib/src/equatable.dart
+++ b/lib/src/equatable.dart
@@ -1,5 +1,6 @@
import 'package:meta/meta.dart';
+import './equatable_config.dart';
import './equatable_utils.dart';
/// A base class to facilitate [operator==] and [hashCode] overrides.
@@ -22,7 +23,8 @@
/// If the value is [true], the `toString` method will be overrided to print
/// the equatable `props`.
- bool get stringify => false;
+ // ignore: avoid_returning_null
+ bool get stringify => null;
/// A class that helps implement equality
/// without needing to explicitly override == and [hashCode].
@@ -41,6 +43,16 @@
int get hashCode => runtimeType.hashCode ^ mapPropsToHashCode(props);
@override
- String toString() =>
- stringify ? mapPropsToString(runtimeType, props) : '$runtimeType';
+ String toString() {
+ switch (stringify) {
+ case true:
+ return mapPropsToString(runtimeType, props);
+ case false:
+ return '$runtimeType';
+ default:
+ return EquatableConfig.stringify == true
+ ? mapPropsToString(runtimeType, props)
+ : '$runtimeType';
+ }
+ }
}
diff --git a/lib/src/equatable_config.dart b/lib/src/equatable_config.dart
new file mode 100644
index 0000000..17c823c
--- /dev/null
+++ b/lib/src/equatable_config.dart
@@ -0,0 +1,10 @@
+// ignore: avoid_classes_with_only_static_members
+/// Global [Equatable] configuration settings
+class EquatableConfig {
+ /// Global [stringify] setting for all [Equatable] instances.
+ /// If [stringify] is overridden for a particular [Equatable] instance,
+ /// then the local [stringify] value takes precendence
+ /// over `EquatableConfig.stringify`.
+ /// This value defaults to false.
+ static bool stringify = false;
+}
diff --git a/lib/src/equatable_mixin.dart b/lib/src/equatable_mixin.dart
index c4850dd..55c1d44 100644
--- a/lib/src/equatable_mixin.dart
+++ b/lib/src/equatable_mixin.dart
@@ -1,4 +1,5 @@
-import './equatable_utils.dart';
+import 'equatable_config.dart';
+import 'equatable_utils.dart';
/// You must define the [EquatableMixin] on the class
/// which you want to make Equatable.
@@ -26,6 +27,16 @@
int get hashCode => runtimeType.hashCode ^ mapPropsToHashCode(props);
@override
- String toString() =>
- stringify ? mapPropsToString(runtimeType, props) : '$runtimeType';
+ String toString() {
+ switch (stringify) {
+ case true:
+ return mapPropsToString(runtimeType, props);
+ case false:
+ return '$runtimeType';
+ default:
+ return EquatableConfig.stringify == true
+ ? mapPropsToString(runtimeType, props)
+ : '$runtimeType';
+ }
+ }
}
diff --git a/pubspec.yaml b/pubspec.yaml
index e2475e3..70b9b9b 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,6 +1,6 @@
name: equatable
description: An abstract class that helps to implement equality without needing to explicitly override == and hashCode.
-version: 1.1.1
+version: 1.2.0
homepage: https://github.com/felangel/equatable
environment:
diff --git a/test/equatable_config_test.dart b/test/equatable_config_test.dart
new file mode 100644
index 0000000..961e84f
--- /dev/null
+++ b/test/equatable_config_test.dart
@@ -0,0 +1,114 @@
+import 'package:equatable/equatable.dart';
+import 'package:test/test.dart';
+
+class Credentials extends Equatable {
+ final String username;
+ final String password;
+ final bool shouldStringify;
+
+ const Credentials({this.username, this.password, this.shouldStringify});
+
+ @override
+ List<Object> get props => [username, password];
+
+ @override
+ bool get stringify => shouldStringify;
+}
+
+abstract class EquatableBase with EquatableMixin {}
+
+class CredentialsMixin extends EquatableBase {
+ final String username;
+ final String password;
+ final bool shouldStringify;
+
+ CredentialsMixin({this.username, this.password, this.shouldStringify});
+
+ @override
+ List get props => [username, password];
+
+ @override
+ bool get stringify => shouldStringify;
+}
+
+void main() {
+ group('EquatableConfig', () {
+ tearDown(() {
+ EquatableConfig.stringify = false;
+ });
+
+ group('stringify', () {
+ test('defaults to false', () {
+ expect(EquatableConfig.stringify, isFalse);
+ });
+
+ test('is used when stringify is not overridden at the instance (false)',
+ () {
+ EquatableConfig.stringify = false;
+ expect(
+ Credentials(username: 'joe', password: 'pass').toString(),
+ 'Credentials',
+ );
+ expect(
+ CredentialsMixin(username: 'joe', password: 'pass').toString(),
+ 'CredentialsMixin',
+ );
+ });
+
+ test('is not used when stringify is overridden at the instance (true)',
+ () {
+ EquatableConfig.stringify = false;
+ expect(
+ Credentials(
+ username: 'joe',
+ password: 'pass',
+ shouldStringify: true,
+ ).toString(),
+ 'Credentials(joe, pass)',
+ );
+ expect(
+ CredentialsMixin(
+ username: 'joe',
+ password: 'pass',
+ shouldStringify: true,
+ ).toString(),
+ 'CredentialsMixin(joe, pass)',
+ );
+ });
+
+ test('is used when stringify is not overridden at the instance (true)',
+ () {
+ EquatableConfig.stringify = true;
+ expect(
+ Credentials(username: 'joe', password: 'pass').toString(),
+ 'Credentials(joe, pass)',
+ );
+ expect(
+ CredentialsMixin(username: 'joe', password: 'pass').toString(),
+ 'CredentialsMixin(joe, pass)',
+ );
+ });
+
+ test('is not used when stringify is overridden at the instance (true)',
+ () {
+ EquatableConfig.stringify = true;
+ expect(
+ Credentials(
+ username: 'joe',
+ password: 'pass',
+ shouldStringify: false,
+ ).toString(),
+ 'Credentials',
+ );
+ expect(
+ CredentialsMixin(
+ username: 'joe',
+ password: 'pass',
+ shouldStringify: false,
+ ).toString(),
+ 'CredentialsMixin',
+ );
+ });
+ });
+ });
+}
diff --git a/test/equatable_mixin_test.dart b/test/equatable_mixin_test.dart
index b7873b1..67ae5c2 100644
--- a/test/equatable_mixin_test.dart
+++ b/test/equatable_mixin_test.dart
@@ -103,6 +103,20 @@
bool get stringify => true;
}
+class ExplicitStringifyFalse extends ComplexEquatable {
+ final String name;
+ final int age;
+ final Color hairColor;
+
+ ExplicitStringifyFalse({this.name, this.age, this.hairColor});
+
+ @override
+ List get props => [name, age, hairColor];
+
+ @override
+ bool get stringify => false;
+}
+
class NullProps extends Equatable {
NullProps();
@@ -114,6 +128,7 @@
}
void main() {
+ EquatableConfig.stringify = false;
group('Empty Equatable', () {
test('should correct toString', () {
final instance = EmptyEquatable();
@@ -581,6 +596,17 @@
expect(instanceB.toString(), 'ComplexStringify(Bob, , Color.black)');
expect(instanceC.toString(), 'ComplexStringify(Joe, 50, Color.blonde)');
});
+
+ test('with ExplicitStringifyFalse stringify', () {
+ final instanceA = ExplicitStringifyFalse();
+ final instanceB =
+ ExplicitStringifyFalse(name: "Bob", hairColor: Color.black);
+ final instanceC =
+ ExplicitStringifyFalse(name: "Joe", age: 50, hairColor: Color.blonde);
+ expect(instanceA.toString(), 'ExplicitStringifyFalse');
+ expect(instanceB.toString(), 'ExplicitStringifyFalse');
+ expect(instanceC.toString(), 'ExplicitStringifyFalse');
+ });
});
group('Null props Equatable', () {
diff --git a/test/equatable_test.dart b/test/equatable_test.dart
index b43aac9..0b874b8 100644
--- a/test/equatable_test.dart
+++ b/test/equatable_test.dart
@@ -105,6 +105,20 @@
bool get stringify => true;
}
+class ExplicitStringifyFalse extends Equatable {
+ final String name;
+ final int age;
+ final Color hairColor;
+
+ ExplicitStringifyFalse({this.name, this.age, this.hairColor});
+
+ @override
+ List get props => [name, age, hairColor];
+
+ @override
+ bool get stringify => false;
+}
+
class NullProps extends Equatable {
NullProps();
@@ -116,6 +130,7 @@
}
void main() {
+ EquatableConfig.stringify = false;
group('Empty Equatable', () {
test('should correct toString', () {
final instance = EmptyEquatable();
@@ -764,6 +779,17 @@
expect(instanceB.toString(), 'ComplexStringify(Bob, , Color.black)');
expect(instanceC.toString(), 'ComplexStringify(Joe, 50, Color.blonde)');
});
+
+ test('with ExplicitStringifyFalse stringify', () {
+ final instanceA = ExplicitStringifyFalse();
+ final instanceB =
+ ExplicitStringifyFalse(name: "Bob", hairColor: Color.black);
+ final instanceC =
+ ExplicitStringifyFalse(name: "Joe", age: 50, hairColor: Color.blonde);
+ expect(instanceA.toString(), 'ExplicitStringifyFalse');
+ expect(instanceB.toString(), 'ExplicitStringifyFalse');
+ expect(instanceC.toString(), 'ExplicitStringifyFalse');
+ });
});
group('Null props Equatable', () {