Submit Search
Upload
cloud_firestore_schema_code_generation_for_flutter.pdf
•
0 likes
•
739 views
K
Kosuke Saigusa
Follow
GDG DevFest Tokyo 2023 において「Cloud Firestore のスキーマ定義の Flutter 向けコード生成について」のテーマで発表したスライドです。
Read less
Read more
Engineering
Slideshow view
Report
Share
Slideshow view
Report
Share
1 of 17
Download now
Download to read offline
Recommended
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
Fujio Kojima
Dart のコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について
Dart のコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について
Kosuke Saigusa
Apache Torqueについて
Apache Torqueについて
tako pons
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Shotaro Suzuki
Twitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hack
kimukou_26 Kimukou
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programming
takesako
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
takezoe
Java EE8 Report
Java EE8 Report
Norito Agetsuma
Recommended
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
「Windows 8 ストア アプリ開発 tips」 hokuriku.net vol.11 (2013年1月26日)
Fujio Kojima
Dart のコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について
Dart のコード自動生成の仕組みと、コード自動生成のパッケージを自作する方法について
Kosuke Saigusa
Apache Torqueについて
Apache Torqueについて
tako pons
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Let's build a simple app with .net 6 asp.net core web api, react, and elasti...
Shotaro Suzuki
Twitter sphere of #twitter4j #twtr_hack
Twitter sphere of #twitter4j #twtr_hack
kimukou_26 Kimukou
Node.js - JavaScript Thread Programming
Node.js - JavaScript Thread Programming
takesako
Seasarプロジェクト徹底攻略
Seasarプロジェクト徹底攻略
takezoe
Java EE8 Report
Java EE8 Report
Norito Agetsuma
Sc2009autumn s2robot
Sc2009autumn s2robot
Shinsuke Sugaya
ASP.NETを利用したAJAX開発の応用
ASP.NETを利用したAJAX開発の応用
Sho Okada
第2回デザインパターン資料
第2回デザインパターン資料
gaaupp
JSがちょい好きになるプレゼン
JSがちょい好きになるプレゼン
James Kirk
Spark Streaming Snippets
Spark Streaming Snippets
Koji Agawa
GoF デザインパターン 2009
GoF デザインパターン 2009
miwarin
OpenGLプログラミング
OpenGLプログラミング
幸雄 村上
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Preferred Networks
Grafana Dashboards as Code
Grafana Dashboards as Code
Takuhiro Yoshida
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
Satoshi Nagayasu
Let's begin WebRTC
Let's begin WebRTC
yoshikawa_t
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration
Kazuki Nakajima
Real world android akka
Real world android akka
Taisuke Oe
Xamarinで作る「オリジナルタイル地図」アプリ
Xamarinで作る「オリジナルタイル地図」アプリ
Kohei Otsuka
C#勉強会 ~ C#9の新機能 ~
C#勉強会 ~ C#9の新機能 ~
Fujio Kojima
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
文樹 高橋
Infrastructure as code for azure
Infrastructure as code for azure
Keiji Kamebuchi
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
Yatabe Terumasa
More Related Content
Similar to cloud_firestore_schema_code_generation_for_flutter.pdf
Sc2009autumn s2robot
Sc2009autumn s2robot
Shinsuke Sugaya
ASP.NETを利用したAJAX開発の応用
ASP.NETを利用したAJAX開発の応用
Sho Okada
第2回デザインパターン資料
第2回デザインパターン資料
gaaupp
JSがちょい好きになるプレゼン
JSがちょい好きになるプレゼン
James Kirk
Spark Streaming Snippets
Spark Streaming Snippets
Koji Agawa
GoF デザインパターン 2009
GoF デザインパターン 2009
miwarin
OpenGLプログラミング
OpenGLプログラミング
幸雄 村上
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Preferred Networks
Grafana Dashboards as Code
Grafana Dashboards as Code
Takuhiro Yoshida
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
Satoshi Nagayasu
Let's begin WebRTC
Let's begin WebRTC
yoshikawa_t
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration
Kazuki Nakajima
Real world android akka
Real world android akka
Taisuke Oe
Xamarinで作る「オリジナルタイル地図」アプリ
Xamarinで作る「オリジナルタイル地図」アプリ
Kohei Otsuka
C#勉強会 ~ C#9の新機能 ~
C#勉強会 ~ C#9の新機能 ~
Fujio Kojima
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
Akio Katayama
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
文樹 高橋
Infrastructure as code for azure
Infrastructure as code for azure
Keiji Kamebuchi
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
Yatabe Terumasa
Similar to cloud_firestore_schema_code_generation_for_flutter.pdf
(20)
Sc2009autumn s2robot
Sc2009autumn s2robot
ASP.NETを利用したAJAX開発の応用
ASP.NETを利用したAJAX開発の応用
第2回デザインパターン資料
第2回デザインパターン資料
JSがちょい好きになるプレゼン
JSがちょい好きになるプレゼン
Spark Streaming Snippets
Spark Streaming Snippets
GoF デザインパターン 2009
GoF デザインパターン 2009
OpenGLプログラミング
OpenGLプログラミング
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
Grafana Dashboards as Code
Grafana Dashboards as Code
PostgreSQL - C言語によるユーザ定義関数の作り方
PostgreSQL - C言語によるユーザ定義関数の作り方
Let's begin WebRTC
Let's begin WebRTC
勉強会force#4 Chatter Integration
勉強会force#4 Chatter Integration
Real world android akka
Real world android akka
Xamarinで作る「オリジナルタイル地図」アプリ
Xamarinで作る「オリジナルタイル地図」アプリ
C#勉強会 ~ C#9の新機能 ~
C#勉強会 ~ C#9の新機能 ~
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
FxUG in Toyama - ASphalt2 container -
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
WPD-Fes #3 2015年のサバイバル学習術 Web開発技術の税引後利益 を最大化しよう!
Infrastructure as code for azure
Infrastructure as code for azure
ソーシャルアプリ勉強会(第一回資料)配布用
ソーシャルアプリ勉強会(第一回資料)配布用
cloud_firestore_schema_code_generation_for_flutter.pdf
1.
GDG DevFest Tokyo
2023 2023/12/09 Cloud Firestore のスキーマ定義の Flutter 向けコード生成について @kosukesaigusa
2.
株式会社SODA ○ 2023年8月〜 ○ Flutter
エンジニア ○ 趣味としても Flutter, Dart の OSS の開発など ⇧⇧⇧ atama plus株式会社 ○ Web エンジニア ○ Django, Angular, React など Kosuke Saigusa- @kosukesaigusa @kosukesaigusa
3.
Flutter x Cloud
Firestore で Todo アプリを作ろうとすると... ちょっとまじめに
4.
仕様 Todo 一覧を一括取得またはリアルタイム更新を取得できる ● タイトル、完了済みかどうか、作成日時、更新日時をもつ ●
fromJson 時にドキュメント ID も取り出してインスタンスに含める Todo を作成できる ● 作成日時は自動で FieldValue.serverTimestamp() が適用される Todo を更新できる ● 指定したフィールドだけを更新できる(例:完了済みかどうかフィールドのみ) ● 作成日時・更新日時は自動で FieldValue.serverTimestamp() が適用される 読み書き処理はすべて型安全に行う ● withConverter を適用する
5.
class ReadTodo { const
ReadTodo({ required this.todoId, required this.title, required this.isCompleted, required this.createdAt, required this.updatedAt, }); final String todoId; final String title; final bool isCompleted; final DateTime? createdAt; final DateTime? updatedAt; } factory ReadTodo.fromDocumentSnapshot(DocumentSnapshot ds) { final data = ds.data()! as Map<String, dynamic>; return ReadTodo.fromJson(<String, dynamic>{ 'todoId': ds.id, ...data, }); } factory ReadTodo.fromJson(Map<String, dynamic> json) { return ReadTodo( todoId: json['todoId'] as String, title: json['title'] as String, isCompleted: json['isCompleted'] as bool? ?? false, createdAt: (json['createdAt'] as Timestamp?)?.toDate(), updatedAt: (json['updatedAt'] as Timestamp?)?.toDate(), ); } DocumentSnapshot からドキュメント ID を取得してインスタンスに含める
6.
class ReadTodo { const
ReadTodo({ required this.todoId, required this.title, required this.isCompleted, required this.createdAt, required this.updatedAt, }); final String todoId; final String title; final bool isCompleted; final DateTime? createdAt; final DateTime? updatedAt; } factory ReadTodo.fromDocumentSnapshot(DocumentSnapshot ds) { final data = ds.data()! as Map<String, dynamic>; return ReadTodo.fromJson(<String, dynamic>{ 'todoId': ds.id, ...data, }); } factory ReadTodo.fromJson(Map<String, dynamic> json) { return ReadTodo( todoId: json['todoId'] as String, title: json['title'] as String, isCompleted: json['isCompleted'] as bool? ?? false, createdAt: (json['createdAt'] as Timestamp?)?.toDate(), updatedAt: (json['updatedAt'] as Timestamp?)?.toDate(), ); } isCompleted の読み取り時のデフォルト値として false を与える
7.
class ReadTodo { const
ReadTodo({ required this.todoId, required this.title, required this.isCompleted, required this.createdAt, required this.updatedAt, }); final String todoId; final String title; final bool isCompleted; final DateTime? createdAt; final DateTime? updatedAt; } factory ReadTodo.fromDocumentSnapshot(DocumentSnapshot ds) { final data = ds.data()! as Map<String, dynamic>; return ReadTodo.fromJson(<String, dynamic>{ 'todoId': ds.id, ...data, }); } factory ReadTodo.fromJson(Map<String, dynamic> json) { return ReadTodo( todoId: json['todoId'] as String, title: json['title'] as String, isCompleted: json['isCompleted'] as bool? ?? false, createdAt: (json['createdAt'] as Timestamp?)?.toDate(), updatedAt: (json['updatedAt'] as Timestamp?)?.toDate(), ); } Cloud Firestore の Timestamp を Dart の DateTime に変換する
8.
Future<List<ReadTodo>> fetchTodos() async
{ final querySnapshot = await FirebaseFirestore.instance .collection('todos') .withConverter<ReadTodo>( fromFirestore: (ds, _) => ReadTodo.fromDocumentSnapshot(ds), toFirestore: (_, __) => throw UnimplementedError(), ) .get(); return querySnapshot.docs .map((queryDocumentSnapshot) => queryDocumentSnapshot.data()) .toList(); } withConverter を用いて型安全に一括取得する
9.
Stream<List<ReadTodo>> subscribeTodos() { final
streamQuerySnapshot = FirebaseFirestore.instance .collection('todos') .withConverter<ReadTodo>( fromFirestore: (ds, _) => ReadTodo.fromDocumentSnapshot(ds), toFirestore: (_, __) => throw UnimplementedError(), ) .snapshots(); return streamQuerySnapshot.map( (querySnapshot) => querySnapshot.docs .map((queryDocumentSnapshot) => queryDocumentSnapshot.data()) .toList(), ); } withConverter を用いて型安全にリアルタイム更新を取得する
10.
class CreateTodo { const
CreateTodo({ required this.title, this.isCompleted, }); final String title; final bool? isCompleted; Map<String, dynamic> toJson() { return <String, dynamic>{ 'title': title, 'isCompleted': isCompleted ?? false, 'createdAt': FieldValue.serverTimestamp(), 'updatedAt': FieldValue.serverTimestamp(), }; } } Future<DocumentReference<CreateTodo>> createTodo({ required String title, bool? isCompleted, }) { return FirebaseFirestore.instance .collection('todos') .withConverter<CreateTodo>( fromFirestore: (_, __) => throw UnimplementedError(), toFirestore: (obj, _) => obj.toJson(), ) .add(CreateTodo(title: title, isCompleted: isCompleted)); } title は必須、isCompleted は任意かつデフォルト値 false で作成する
11.
class CreateTodo { const
CreateTodo({ required this.title, this.isCompleted, }); final String title; final bool? isCompleted; Map<String, dynamic> toJson() { return <String, dynamic>{ 'title': title, 'isCompleted': isCompleted ?? false, 'createdAt': FieldValue.serverTimestamp(), 'updatedAt': FieldValue.serverTimestamp(), }; } } Future<DocumentReference<CreateTodo>> createTodo({ required String title, bool? isCompleted, }) { return FirebaseFirestore.instance .collection('todos') .withConverter<CreateTodo>( fromFirestore: (_, __) => throw UnimplementedError(), toFirestore: (obj, _) => obj.toJson(), ) .add(CreateTodo(title: title, isCompleted: isCompleted)); } createdAt, updatedAt には自動で FieldValue.serverTimestamp() を適用する
12.
Future<void> updateTodo({ required String
todoId, String? title, bool? isCompleted, DateTime? createdAt, }) { return FirebaseFirestore.instance .collection('todos') .doc(todoId) .update(<String, dynamic>{ if (title != null) 'title': title, if (isCompleted != null) 'isCompleted': isCompleted, if (createdAt != null) 'createdAt': Timestamp.fromDate(createdAt), 'updatedAt': FieldValue.serverTimestamp(), }); } すべて任意で、非 null な値が与えられたフィールドのみを更新する
13.
Future<void> updateTodo({ required String
todoId, String? title, bool? isCompleted, DateTime? createdAt, }) { return FirebaseFirestore.instance .collection('todos') .doc(todoId) .update(<String, dynamic>{ if (title != null) 'title': title, if (isCompleted != null) 'isCompleted': isCompleted, if (createdAt != null) 'createdAt': Timestamp.fromDate(createdAt), 'updatedAt': FieldValue.serverTimestamp(), }); } updatedAt には自動で FieldValue.serverTimestamp() を適用する
14.
@FirestoreDocument(path: 'todos', documentName:
'todo') class Todo { const Todo({ required this.title, required this.isCompleted, required this.createdAt, required this.updatedAt, }); final String title; @ReadDefault(false) @CreateDefault(false) final bool isCompleted; @AlwaysUseFieldValueServerTimestampWhenCreating() final DateTime? createdAt; @AlwaysUseFieldValueServerTimestampWhenCreating() @AlwaysUseFieldValueServerTimestampWhenUpdating() final DateTime? updatedAt; } これまでに取り上げたコードがすべて build_runner により自動で生成できる! その他にも... ネストされたサブコレクションのドキュメントのスキーマ定義にも対応 取得時のクエリ条件(where 句や orderBy 句など)も通常通り適用可能 FieldValue の指定も可能対応 ● FieldValue.increment(), arrayUnion(), arrayRemove() など 基本的な読み書きメソッドも一通り自動生成 ● 指定した 1 件を取得 ● 指定した 1 件を購読 ● 複数件を取得 ● 複数件を購読 ● ドキュメントの作成 (add, set) ● ドキュメントの更新 (update) ● ドキュメントの削除 (delete) ...など
15.
@riverpod TodoQuery todoQuery(TodoQueryRef _)
=> TodoQuery(); @riverpod class TodoList extends _$TodoList { @override Future<List<ReadTodo>> build() => ref.watch(todoQueryProvider).fetchDocuments(); Future<DocumentReference<CreateTodo>> addTodo(String title) { return ref .read(todoQueryProvider) .add(createTodo: CreateTodo(title: title)); } Future<void> updateCompletionStatus({ required String todoId, required bool isCompleted, }) { return ref.read(todoQueryProvider).update( todoId: todoId, updateTodo: UpdateTodo(isCompleted: isCompleted), ); } } @FirestoreDocument(path: 'todos', documentName: 'todo') class Todo { const Todo({ required this.title, required this.isCompleted, required this.createdAt, required this.updatedAt, }); final String title; @ReadDefault(false) @CreateDefault(false) final bool isCompleted; @AlwaysUseFieldValueServerTimestampWhenCreating() final DateTime? createdAt; @AlwaysUseFieldValueServerTimestampWhenCreating() @AlwaysUseFieldValueServerTimestampWhenUpdating() final DateTime? updatedAt; } 例:riverpod_generator と組み合わせてみると、こんなに簡潔にすべてを書ける!
16.
flutterfire_gen: Cloud Firestore
のスキーマ定義の Flutter 向けコード生成パッケージ kosukesaigusa/flutterfire_gen 鋭意開発中です!(機能自体はほぼできています) ユニットテストやドキュメントを整備して近日中のリリースを目指し ています。 一緒に作ってみたい方、完成したらフィードバックをくれる方、使っ てみたい方...お知らせください or 続報をお待ちください! https://github.com/kosukesaigusa/flutterfire_gen
17.
GDG DevFest Tokyo
2023 2023/12/09 Cloud Firestore のスキーマ定義の Flutter 向けコード生成について @kosukesaigusa
Download now