repository patterns

Repository Interface (Domain Layer)

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "repository patterns" with this command: npx skills add kaakati/rails-enterprise-dev/kaakati-rails-enterprise-dev-repository-patterns

Repository Patterns

Repository Interface (Domain Layer)

// lib/domain/repositories/user_repository.dart import 'package:dartz/dartz.dart'; import '../../core/errors/failures.dart'; import '../entities/user.dart';

abstract class UserRepository { Future<Either<Failure, User>> getUser(String id); Future<Either<Failure, List<User>>> getAllUsers(); Future<Either<Failure, User>> createUser(User user); Future<Either<Failure, User>> updateUser(User user); Future<Either<Failure, void>> deleteUser(String id); }

Repository Implementation (Data Layer)

Basic Implementation

// lib/data/repositories/user_repository_impl.dart import 'package:dartz/dartz.dart'; import '../../core/errors/failures.dart'; import '../../core/errors/exceptions.dart'; import '../../domain/entities/user.dart'; import '../../domain/repositories/user_repository.dart'; import '../providers/user_provider.dart';

class UserRepositoryImpl implements UserRepository { final UserProvider _provider;

UserRepositoryImpl(this._provider);

@override Future<Either<Failure, User>> getUser(String id) async { try { final model = await _provider.fetchUser(id); return Right(model.toEntity()); } on ServerException catch (e) { return Left(ServerFailure(e.message)); } on NetworkException { return Left(NetworkFailure()); } catch (e) { return Left(ServerFailure('Unexpected error: $e')); } } }

Offline-First Implementation

class UserRepositoryImpl implements UserRepository { final UserProvider _remoteSource; final UserLocalSource _localSource; final NetworkInfo _networkInfo;

UserRepositoryImpl( this._remoteSource, this._localSource, this._networkInfo, );

@override Future<Either<Failure, User>> getUser(String id) async { if (await _networkInfo.isConnected) { // Try remote first try { final model = await _remoteSource.fetchUser(id); // Cache for offline use await _localSource.cacheUser(model); return Right(model.toEntity()); } on ServerException catch (e) { // Fallback to cache on server error return _getCachedUser(id); } } else { // Use cache when offline return _getCachedUser(id); } }

Future<Either<Failure, User>> _getCachedUser(String id) async { try { final cached = await _localSource.getCachedUser(id); if (cached != null) { return Right(cached.toEntity()); } else { return Left(CacheFailure('No cached data available')); } } on CacheException catch (e) { return Left(CacheFailure(e.message)); } }

@override Future<Either<Failure, List<User>>> getAllUsers() async { if (await _networkInfo.isConnected) { try { final models = await _remoteSource.fetchAllUsers(); await _localSource.cacheUsers(models); return Right(models.map((m) => m.toEntity()).toList()); } on ServerException { return _getCachedUsers(); } } else { return _getCachedUsers(); } }

Future<Either<Failure, List<User>>> _getCachedUsers() async { try { final cached = await _localSource.getCachedUsers(); if (cached != null && cached.isNotEmpty) { return Right(cached.map((m) => m.toEntity()).toList()); } else { return Left(CacheFailure('No cached users')); } } on CacheException catch (e) { return Left(CacheFailure(e.message)); } } }

Caching Strategies

  1. Cache-First (Offline-First)

// Try cache first, then network Future<Either<Failure, User>> getUser(String id) async { // Check cache first final cached = await _localSource.getCachedUser(id); if (cached != null) { // Return cached data immediately _refreshInBackground(id); // Update in background return Right(cached.toEntity()); }

// Cache miss - fetch from network return _fetchFromNetwork(id); }

  1. Network-First (Fresh Data Priority)

// Try network first, fallback to cache Future<Either<Failure, User>> getUser(String id) async { if (await _networkInfo.isConnected) { try { final model = await _remoteSource.fetchUser(id); await _localSource.cacheUser(model); return Right(model.toEntity()); } catch (e) { return _getCachedUser(id); // Fallback } } else { return _getCachedUser(id); } }

  1. Cache-Then-Network

// Return cache immediately, then update with network data Stream<Either<Failure, User>> getUserStream(String id) async* { // Emit cached data first final cached = await _localSource.getCachedUser(id); if (cached != null) { yield Right(cached.toEntity()); }

// Then fetch from network if (await _networkInfo.isConnected) { try { final model = await _remoteSource.fetchUser(id); await _localSource.cacheUser(model); yield Right(model.toEntity()); } on ServerException catch (e) { yield Left(ServerFailure(e.message)); } } }

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

Coding

flutter conventions & best practices

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

getx state management patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

ruby oop patterns

No summary provided by upstream source.

Repository SourceNeeds Review
Coding

rails localization (i18n) - english & arabic

No summary provided by upstream source.

Repository SourceNeeds Review