đ Gen Model Command
Individual model class generation commandāĨ¤
đ¯ Overviewâ
flx gen model
command āĻŦā§āϝāĻŦāĻšāĻžāϰ āĻāϰ⧠āĻāĻĒāύāĻŋ standalone model class āϤā§āϰāĻŋ āĻāϰāϤ⧠āĻĒāĻžāϰāĻŦā§āύāĨ¤ āĻāĻāĻŋ āĻŦāĻŋāĻļā§āώāĻāĻžāĻŦā§ useful āϝāĻāύ āĻāĻĒāύāĻžāϰ āĻļā§āϧ⧠āĻāĻāĻāĻŋ model class āĻĻāϰāĻāĻžāϰāĨ¤
đ Basic Usageâ
# Basic model generation
flx gen model User
# Model with specific location
flx gen model Product --path lib/models
# Model with custom properties
flx gen model Order --props id,userId,total
âī¸ Command Optionsâ
Basic Optionsâ
flx gen model <name> [options]
Options:
--path, -p Output directory path
--props Comma-separated properties
--extends Parent class to extend
--implements Interfaces to implement
--freezed Generate with Freezed annotations
--json Add JSON serialization
--equatable Add Equatable support
--help, -h Show help
Property Typesâ
# String properties
flx gen model User --props "name:String,email:String"
# Mixed types
flx gen model Product --props "id:String,price:double,isActive:bool"
# Optional properties
flx gen model Profile --props "name:String,bio:String?,avatar:String?"
# List properties
flx gen model Order --props "id:String,items:List<OrderItem>"
# DateTime properties
flx gen model Event --props "title:String,date:DateTime,endDate:DateTime?"
đ Generated Filesâ
Basic Modelâ
flx gen model User --props "id:String,name:String,email:String"
Generated file: lib/models/user_model.dart
class UserModel {
final String id;
final String name;
final String email;
const UserModel({
required this.id,
required this.name,
required this.email,
});
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'name': name,
'email': email,
};
}
UserModel copyWith({
String? id,
String? name,
String? email,
}) {
return UserModel(
id: id ?? this.id,
name: name ?? this.name,
email: email ?? this.email,
);
}
bool operator ==(Object other) {
if (identical(this, other)) return true;
return other is UserModel &&
other.id == id &&
other.name == name &&
other.email == email;
}
int get hashCode {
return id.hashCode ^ name.hashCode ^ email.hashCode;
}
String toString() {
return 'UserModel(id: $id, name: $name, email: $email)';
}
}
Model with Freezedâ
flx gen model Product --props "id:String,name:String,price:double" --freezed
Generated file: lib/models/product_model.dart
import 'package:freezed_annotation/freezed_annotation.dart';
part 'product_model.freezed.dart';
part 'product_model.g.dart';
class ProductModel with _$ProductModel {
const factory ProductModel({
required String id,
required String name,
required double price,
}) = _ProductModel;
factory ProductModel.fromJson(Map<String, dynamic> json) =>
_$ProductModelFromJson(json);
}
Model with Entity Extensionâ
flx gen model UserModel --extends UserEntity --props "accessToken:String"
Generated file: lib/models/user_model.dart
import '../entities/user_entity.dart';
class UserModel extends UserEntity {
final String accessToken;
const UserModel({
required super.id,
required super.name,
required super.email,
required this.accessToken,
});
factory UserModel.fromJson(Map<String, dynamic> json) {
return UserModel(
id: json['id'] as String,
name: json['name'] as String,
email: json['email'] as String,
accessToken: json['access_token'] as String,
);
}
Map<String, dynamic> toJson() {
final json = super.toJson();
json['access_token'] = accessToken;
return json;
}
UserModel copyWith({
String? id,
String? name,
String? email,
String? accessToken,
}) {
return UserModel(
id: id ?? this.id,
name: name ?? this.name,
email: email ?? this.email,
accessToken: accessToken ?? this.accessToken,
);
}
}
đ§ Advanced Examplesâ
Complex Model with Nested Objectsâ
flx gen model Order --props "id:String,customer:Customer,items:List<OrderItem>,totalAmount:double,status:OrderStatus,createdAt:DateTime"
import 'customer.dart';
import 'order_item.dart';
import 'order_status.dart';
class OrderModel {
final String id;
final Customer customer;
final List<OrderItem> items;
final double totalAmount;
final OrderStatus status;
final DateTime createdAt;
const OrderModel({
required this.id,
required this.customer,
required this.items,
required this.totalAmount,
required this.status,
required this.createdAt,
});
factory OrderModel.fromJson(Map<String, dynamic> json) {
return OrderModel(
id: json['id'] as String,
customer: Customer.fromJson(json['customer'] as Map<String, dynamic>),
items: (json['items'] as List)
.map((item) => OrderItem.fromJson(item as Map<String, dynamic>))
.toList(),
totalAmount: (json['total_amount'] as num).toDouble(),
status: OrderStatus.values.firstWhere(
(status) => status.name == json['status'],
),
createdAt: DateTime.parse(json['created_at'] as String),
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'customer': customer.toJson(),
'items': items.map((item) => item.toJson()).toList(),
'total_amount': totalAmount,
'status': status.name,
'created_at': createdAt.toIso8601String(),
};
}
// ... copyWith, equality, toString methods
}
Model with Validationâ
flx gen model RegistrationModel --props "name:String,email:String,password:String,age:int" --validate
class RegistrationModel {
final String name;
final String email;
final String password;
final int age;
const RegistrationModel({
required this.name,
required this.email,
required this.password,
required this.age,
});
factory RegistrationModel.fromJson(Map<String, dynamic> json) {
final model = RegistrationModel(
name: json['name'] as String,
email: json['email'] as String,
password: json['password'] as String,
age: json['age'] as int,
);
model.validate();
return model;
}
Map<String, dynamic> toJson() {
return {
'name': name,
'email': email,
'password': password,
'age': age,
};
}
void validate() {
final errors = <String>[];
if (name.trim().isEmpty) {
errors.add('Name is required');
}
if (!_isValidEmail(email)) {
errors.add('Invalid email format');
}
if (password.length < 8) {
errors.add('Password must be at least 8 characters');
}
if (age < 18) {
errors.add('Age must be at least 18');
}
if (errors.isNotEmpty) {
throw ValidationException(errors);
}
}
bool _isValidEmail(String email) {
return RegExp(r'^[\w-\.]+@([\w-]+\.)+[\w-]{2,4}$').hasMatch(email);
}
// ... rest of the methods
}
class ValidationException implements Exception {
final List<String> errors;
ValidationException(this.errors);
String toString() => 'Validation failed: ${errors.join(', ')}';
}
Model with Equatableâ
flx gen model TaskModel --props "id:String,title:String,completed:bool" --equatable
import 'package:equatable/equatable.dart';
class TaskModel extends Equatable {
final String id;
final String title;
final bool completed;
const TaskModel({
required this.id,
required this.title,
required this.completed,
});
factory TaskModel.fromJson(Map<String, dynamic> json) {
return TaskModel(
id: json['id'] as String,
title: json['title'] as String,
completed: json['completed'] as bool,
);
}
Map<String, dynamic> toJson() {
return {
'id': id,
'title': title,
'completed': completed,
};
}
TaskModel copyWith({
String? id,
String? title,
bool? completed,
}) {
return TaskModel(
id: id ?? this.id,
title: title ?? this.title,
completed: completed ?? this.completed,
);
}
List<Object?> get props => [id, title, completed];
String toString() {
return 'TaskModel(id: $id, title: $title, completed: $completed)';
}
}
đ Property Type Mappingâ
Input Type | Dart Type | JSON Handling |
---|---|---|
String | String | json['key'] as String |
String? | String? | json['key'] as String? |
int | int | json['key'] as int |
double | double | (json['key'] as num).toDouble() |
bool | bool | json['key'] as bool |
DateTime | DateTime | DateTime.parse(json['key']) |
DateTime? | DateTime? | json['key'] != null ? DateTime.parse(json['key']) : null |
List<String> | List<String> | List<String>.from(json['key']) |
List<Model> | List<Model> | (json['key'] as List).map((e) => Model.fromJson(e)).toList() |
Map | Map<String, dynamic> | json['key'] as Map<String, dynamic> |
đ¯ Real-World Examplesâ
E-commerce Product Modelâ
flx gen model ProductModel --props "id:String,name:String,description:String,price:double,discountPrice:double?,category:Category,images:List<String>,inStock:bool,tags:List<String>,createdAt:DateTime,updatedAt:DateTime"
User Profile Modelâ
flx gen model UserProfileModel --props "id:String,firstName:String,lastName:String,email:String,phoneNumber:String?,dateOfBirth:DateTime?,avatar:String?,address:Address?,preferences:Map<String,dynamic>,isVerified:bool,createdAt:DateTime"
API Response Modelâ
flx gen model ApiResponseModel --props "success:bool,message:String,data:Map<String,dynamic>?,errors:List<String>?,timestamp:DateTime" --generic
đ Model Templatesâ
Custom Templatesâ
Create custom model templates in templates/model/
:
// templates/model/base_model.dart.mustache
class {{className}} {
{{#properties}}
final {{type}} {{name}};
{{/properties}}
const {{className}}({
{{#properties}}
{{#required}}required {{/required}}this.{{name}},
{{/properties}}
});
// Custom business logic methods
{{#hasBusinessMethods}}
{{#businessMethods}}
{{method}}
{{/businessMethods}}
{{/hasBusinessMethods}}
// Standard methods
factory {{className}}.fromJson(Map<String, dynamic> json) {
return {{className}}(
{{#properties}}
{{name}}: {{jsonParsing}},
{{/properties}}
);
}
Map<String, dynamic> toJson() {
return {
{{#properties}}
'{{jsonKey}}': {{jsonSerialization}},
{{/properties}}
};
}
}
Use Custom Templateâ
flx gen model CustomModel --template base_model --props "id:String,value:double"
đ§Ē Testing Integrationâ
Generate with Testsâ
flx gen model UserModel --props "id:String,name:String" --with-tests
Generated test file: test/models/user_model_test.dart
import 'package:flutter_test/flutter_test.dart';
import 'package:myapp/models/user_model.dart';
void main() {
group('UserModel', () {
test('should create instance from JSON', () {
// Arrange
final json = {
'id': '123',
'name': 'John Doe',
};
// Act
final user = UserModel.fromJson(json);
// Assert
expect(user.id, '123');
expect(user.name, 'John Doe');
});
test('should convert to JSON', () {
// Arrange
const user = UserModel(
id: '123',
name: 'John Doe',
);
// Act
final json = user.toJson();
// Assert
expect(json['id'], '123');
expect(json['name'], 'John Doe');
});
test('should create copy with updated fields', () {
// Arrange
const user = UserModel(
id: '123',
name: 'John Doe',
);
// Act
final updatedUser = user.copyWith(name: 'Jane Doe');
// Assert
expect(updatedUser.id, '123');
expect(updatedUser.name, 'Jane Doe');
});
test('should implement equality correctly', () {
// Arrange
const user1 = UserModel(id: '123', name: 'John');
const user2 = UserModel(id: '123', name: 'John');
const user3 = UserModel(id: '456', name: 'Jane');
// Assert
expect(user1, equals(user2));
expect(user1, isNot(equals(user3)));
});
});
}
â Best Practicesâ
- Naming Convention: Use
Model
suffix for model classes - Property Types: Be specific with property types
- Null Safety: Use nullable types appropriately
- JSON Keys: Follow API naming conventions
- Validation: Add validation for critical models
- Documentation: Document complex properties
- Testing: Generate tests for important models
- Immutability: Keep models immutable
đ Troubleshootingâ
Common Issuesâ
# Invalid property syntax
flx gen model User --props "name,email"
Error: Property 'name' missing type. Use 'name:String'
# Invalid type
flx gen model User --props "name:InvalidType"
Error: Unknown type 'InvalidType'
# Missing required arguments
flx gen model
Error: Model name is required
Debug Modeâ
# Show what will be generated
flx gen model User --props "name:String" --dry-run
# Verbose output
flx gen model User --props "name:String" --verbose
Individual models āϤā§āϰāĻŋ āĻāϰāĻžāϰ āĻāύā§āϝ: flx gen model
command perfect tool! đ