reface アプリ使い方

reface アプリ使い方

BABYFACEが誕生して30余年、幅広いお客様に愛され支持されて参りました。 BABYFACEは「食事+癒し」を重要なコンセプトとして「とにかくゆっくりしていただく」「毎日がハレの日、ご来店いただいた瞬間からハレになる」レストランを目指して参りました。

録音しながらワンタッチで見出しやタグを使えますので、使い方によってはかなり便利になりそうですね。, Recocoの設定画面から再生スピードを0.7倍、1倍、1.3倍、2倍から選択することができます。長い時間の録音ファイルだった場合、すべて聴くにはとても時間がかかります。ですので倍速にして聴きたい部分だけ聴けるのです。 Firebaseでは、バックエンドやインフラに精通したメンバーがいなくても、モバイルやWebフロントの開発に集中できます。Authentication、Firestore、Cloud Functions、さらにセキュリティルールまで、クックパッドの岸本卓(@_sgr_ksmt)さんが、実践的に解説します。, Firebaseをご存じでしょうか? Firebaseを利用したことはありますか? 今回は「Firebaseをこれから使ってみたい!」「絶賛使っているけど、初めてでどう開発したらいいかよく分からない……」という方を対象に、実践的な入門という形で説明していきます。, Firebaseは、2011年にFirebase社がサービスを開始し、2014年にGoogleが買収したMBaaS(Mobile Backend as a Service)です。, Firebaseでは、リアルタイムでデータを同期できるCloud FirestoreやRealtime Databaseといったデータベース、プッシュ通知を簡単に実装できるFirebase Cloud Messaging、サーバーレスに何かのイベントをトリガーに関数を実行するCloud Functions for Firebaseといった機能を利用できます。, Authentication、Hosting、Cloud Storage、Crashlytics、Performance Monitoring、Test Lab、Analytics、Predictions、A/B Testing、Remote Config、Dynamic Links、App Indexing、In App Messaging、ML Kit, サービスが開始された当初にはまだなかった機能やβ版だった機能も多かったのですが、今ではほとんどの機能がGA(Generally Available)となっており、Firebaseが使われるシーンも増えてきたように思えます。, Firebaseの良いところは、自分自身にバックエンドやインフラの知識がなかったり、精通したメンバーがいなかったりする中でサービスを開発することになっても、Firebaseがさまざまな機能をあらかじめ提供してくれているので、サーバーの構築やインスタンスの立ち上げなどを気にすることなく、モバイルやWebフロントの開発に集中できることです。, 自分でいちからサーバーを立ち上げたり、認証基盤を作成したり、プッシュ通知を配信する仕組みを作る手間と時間を短縮できることは、とても大きいと思います。, 実際に筆者が携わっているプロダクトでは、Firebaseを使って、iOSエンジニアのみでサービスの開発からローンチまで行うことができました(詳しくは次の記事を参照)。, また、Firebase自体の開発も盛んで、機能改善や新機能が次々と搭載されるため、Firebaseで実現できる開発の幅がどんどん広がっています。 今携わっているプロダクトでも、開発当初では機能上の制約や、そもそも提供されておらず実現できなかった機能が、今では当たり前のように実装できるようになった、ということも少なくありません。, さらに、Firebaseの利用を始めること自体は無料で、有料プランでも従量課金制のほか、毎月25ドルの定額プランも用意されています。, 「これから何かアプリケーションを開発したい!」という人には、筆者は強くFirebaseの利用をオススメします。 作成するアプリケーションの特性にもよりますが、以下の恩恵を受けることができます。, 個人開発をする人にとって、手間とコストを大幅に削減できるのはとても大きいと思います。, そして、Firebaseは無料で利用できる機能の範囲が広く、また従量課金プランに変更したとしても、そこまで料金がかかりません(規模によります)。, 一昔前のFirebaseでは、MVP(Minimum Viable Product)や検証目的で作るには適している一方で、プロダクション品質まで高めるのは難しいと言われることもありました。, しかし、ほとんどの機能がGAとなり、サービスの安定性も高くなったこともあり、採用しない手はないだろうと思います。, 途中からでは、Cloud Firestoreといったデータベースを導入することは難しいでしょうが、AnalyticsやPredictionsによる分析や、Cloud Messagingを用いたプッシュ通知の配信など、効果を発揮する機能があります。, また、Googleが買収したFabricのCrashlyticsがFirebaseに統合されたり、Performance Monitoringといった機能が用意されたりしたことで、クラッシュしている箇所やパフォーマンスに問題がある部分を特定し、改善していく手助けになります。, Firebaseを使った開発で特に重要となる3つの機能について、簡単に紹介します。 このAuthentication、Cloud Firestore、Cloud Functionsを組み合わせるだけでも、簡単にサービスを構築することが可能です(本記事の後半で紹介します)。, Firebaseには認証を行う機能が備わっており、認証自体を自分で実装しなくて済みます。, 認証方法としては、メールアドレス等を一切必要としない匿名認証から、メールアドレスでの認証、各種サービス(TwitterやFacebook)を使った認証などがあります。, 特に、次のCloud Firestoreなどを使うには、認証済みユーザーであるかどうかを検証することがベースとなるため、Authenticationの使用が必須となるでしょう。, Cloud Firestore(以下、Firestore)は、ドキュメント指向のNoSQLデータベースです。, Firestoreを理解する上で必要不可欠なのが、「コレクション」と「ドキュメント」です。 この関係についてはFirebaseの公式ガイドと図を参考にしてください。, また、リアルタイム性も兼ね備えており、ドキュメントに変更があった場合、クライアント側でリッスンしておくと、変更を即座に受け取ることも可能です。, なお、Realtime Databaseで特定のノードを取得する場合に子ノードも全て取得するため非効率になるケースがありますが、Firestoreでドキュメントを取得する際には配下のサブコレクションまで取得してしまうことはありません。, Cloud Functionsは、JavaScriptで記述された関数を実行する機能です。, ファンクションには、Firestoreにドキュメントが書き込まれた・更新されたといったイベントを元に実行されるもの、定期実行のもの、HTTPSリクエストで実行できるものがあります。, トリガーを起点にFirestoreのドキュメントに変更を加える、Cloud Messagingを用いてプッシュ通知を送る、外部サービスのAPIを叩くといったことが可能になります(CLoud FunctionsからFirebaseサービス外への通信が発生する場合、無料プランでは実行できず、有料プランへの切り替えが必要)。, ここからはサンプルアプリケーションを通して、Firebaseを使った開発の仕方や設計を説明していきます。 認証からデータベース、Cloud Functionsにセキュリティルールといった形で、実際にサービスを公開するまでに必須となる内容を、実践的に学ぶことができます。, 取り上げるサンプルは、とてもシンプルで簡素なフリーマーケット型のショッピングアプリです。, 筆者がiOS開発を得意としていることもあり、作成するサンプルはiOSアプリで開発言語はSwift、バックエンドはNode.jsでTypeScriptです。 使用した開発環境は、以下の通りです(できる限り執筆時点の最新バージョンを使用しています)。, 上記のリポジトリで公開しているサンプルを実際に動かすには、次のセクションから説明するように自身でFirebaseプロジェクトを作成することと、関連する設定ファイルが必要です。 iOSアプリ側の設定ファイルはGoogleService-Info.plistで、バックエンド側はadmin_sdk.jsonです。, まず、Firebaseのプロジェクトをセットアップしましょう。 Firebase consoleにアクセスして、「プロジェクトの追加」から新たにプロジェクトを作成します。, このウィンドウで、プロジェクト名、プロジェクトID、Firestoreとアナリティクスで使用されるロケーション(リージョン)を指定します。, プロジェクトIDとロケーションは後で変更できないので、注意が必要です。 また、今では東京リージョン(asia-northeast1)や大阪リージョン(asia-northeast2)を 選択できるので、国内に向けたサービスを作りたい場合は選ぶとよいでしょう。, iOSアプリに関しては、通常通りXcodeプロジェクトを作成したのち、FirebaseをCocoaPods経由でインストールすれば、おおむねセットアップは完了します。, 今回は、Firebase iOS SDKのうちCore Auth Firestore Functionsの4つを扱うので、次のようなPodfileを記述して、pod installを実行します。, CocoaPodsそのものの利用について知りたい方は、次のエントリーなどが参考になります。, 今回はCloud Functionsと、Firestoreのセキュリティルールをデプロイする必要があるので、バックエンド側のセットアップも行います。, まず、npmあるいはyarnで、firebase-toolsをインストールします(筆者はyarnを使います)。 firebase-toolsは、マシンのグローバル領域にインストールしてもよいですし、プロジェクトにインストールしてもかまいいません。, 筆者は、複数プロジェクトそれぞれで独立してバージョン管理ができるように、プロジェクト毎にインストールするようにしています。, firebaes-toolsがインストールできたら、セットアップを実施します。 以降はプロジェクトにfirebase-toolsをインストールした場合のコマンド例です (グローバルにインストールした場合、プレフィックスのyarnは不要)。, このように、まずFirebaseにログイン(firebase login)しないと、セットアップ(firebase init)やデプロイは実行できません。, Firebaseのセットアップは対話式に進みます。 セットアップしたいプロジェクトを選択し、以下のように答えていきます。, もしセットアップしたいプロジェクトが選択項目に現れないときは、firebase loginでログインしたアカウントに閲覧権限があるかどうか確認してください。, ここまでが済むと、指定したディレクトリに、functionsディレクトリができ、次のファイルが含まれていると思います。, という理由から、さらに少し手を加えます。 具体的には、次の3つのファイルを書き換え, package.jsonには、次のようにbuildとdeployのコマンドを記述しておきます。, buildは、functionsのソースコードをトランスパイルした.jsファイル、package.json、admin_sdk.jsonをdistディレクトリにコピーするコマンドになっています。 deployでは、firebase.jsonで指定したdistディレクトリの内容を元にデプロイを行います。, ここまでで、iOSアプリとバックエンドの両方で開発を進めるセットアップが一通り完了しました。 構成に迷ってしまった場合は、サンプルプロジェクトと照らし合わせて確認してみてください。, プロジェクトがセットアップできたら、Firebase consoleで「Authentication」を選び、「ログイン方法」の項目を開きます。 ここにはFirebaseで認証するためのログイン手段が並んでいます。, 今回は匿名認証を使用したいので、「匿名」の項目を有効にします。 これにより、アプリ側からメールアドレス等不要で認証させることが可能になります。, 以降、他の認証方法を使用する場合は、同様にこの画面から有効にする必要があります。 新規で認証方法を増やす場合にエラーが発生した場合には、設定を有効にしているかどうか見直しましょう。, なお、今回のサンプルでは使いませんが、TwitterやFacebookといった認証方法を使ってのログインも可能になっています。, 次に、データベースをセットアップをします。 Firebaseには、リアルタイムでデータを同期できるクラウドベースのデータベースが2つありますが、今回はRealtime Databaseではなく、Firestoreの方を使用します。, Firebase consoleで「Firestore」を選択するときに、セキュリティルールがどちらかを聞かれますが、ひとまず「テストモード」を選択します。 これにより、(一時的に)全てのドキュメントへのアクセスが可能になります。, ロックモードを選択すると、全てのドキュメントに対する操作は行えない状態になっているので、別途セキュリティルールを記述する必要があります (セキュリティルールに関しては後述)。, 登場するドキュメントは、User(ユーザー)、Product(商品)、CartItem(カート)、Order(注文情報)の4つで、構成は以下のようになっています。, また、Productドキュメントにはそのドキュメントの作成者(User)のドキュメントのパス(reference)を、CartItemドキュメントにはカートに入れた商品(Product)のドキュメントのパスを持たせるようにしています。, なお、今回はサンプルのため簡略化していますが、本格的にサービスを運用する場合は、次のような設計の追加が必要になるでしょう。, 決済に関わる部分の情報(カード情報等)は、適切にセキュリティルールで保護した上でFirestoreに持つのもよいですし、自社の決済基盤やStripeを活用するのもよいでしょう。, モデルの設計にあたっては、Firestoreのようなドキュメント指向のNoSQLとRDB(リレーショナルデータベース)との違いや、それぞれでできること・できないことを意識して設計する必要があります。, RDBでは、データを正規化し、JOINやGROUP BYといったSQLの操作で目的のデータを結合して取得することが定石となっています。 それに対して、Firestoreではデータを冗長化しておいたほうがよかったりします。, Firestoreのクエリにも絞り込みの機能が備わっているものの、RDBと違って結合や集計の操作を行うことが現状できないため、なるべく簡単なクエリ操作でデータを取得できる設計にしておくとよいでしょう。, また、結合などの操作が行えないため、「Aドキュメントを取得した後に、関係のあるBドキュメントをあらためて取得する」といった操作が発生するケースがあります(クライアントサイドジョインと呼ばれたりします)。 いわゆる「N+1問題」のような状況が発生するため、規模が大きくなるほど問題化することも考えられます。, クエリを活用し、適切な範囲を取得して読み込むようにロジックを調整すれば、大きな問題にはならないと筆者は思っていますが、読み込み回数の増加を少しでも防ぐため、あらかじめ「AのドキュメントにBのドキュメントの情報を書いて、冗長化する」といったデータ操作をすることもあります。, 具体的な例を挙げましょう。次のように参照を持たせる方法では、productドキュメントの一覧を取得した後に、それぞれのownerの参照を元にユーザーの情報を取得してUIに反映させるというように、N+1回の読み込みが必要になります。, 対して、次のように冗長化したデータを持たせた場合には、productドキュメントを取得した時点でユーザーの情報があるので、そのままUIに反映することができ、productの一覧を読み込むだけで済みます。, ただし、冗長化するデータの大元であるユーザーのドキュメントに更新があった場合は、冗長化した部分も更新する必要があり、読み込みは減るものの、書き込みは必然的に増えますし、更新を忘れるとデータの整合性が保てなくなります。, このような「冗長化したデータ構造を作る」ため、Firebaseにはバッチによる一括書き込み、トランザクションを用いた書き込み、Cloud FunctionsのFirestoreイベントトリガーといった機能が備わっています。 これらを活用することで、データの整合性を担保しつつ、データを冗長化して持たせることが可能になります。, 一方で、全てのデータを冗長化して持つべきかといえばそうではなく、データの読み込みの頻度、冗長化される元となるドキュメントの更新頻度によって、適切に判断する必要があります。 また、冗長化して配置する箇所が増えれば増えるほど、冗長化して配置・更新するための裏側の処理が複雑になるので、かえって設計が大変になってしまうこともあります。, 今までRDBを使ってきた人にとって、同じようなデータが冗長的に配置されることは、初めのうち違和感があると思います。 その違和感も、慣れてくるとなくなり、冗長化すべきかそうでないかも見極められるようになってくると思います。, Firestoreで実現できるモデルの構成に関しては、次の記事やスライドがとても参考になります。, Cloud Firestoreを実践投入するにあたって考えたこと#CloudFirestore データベース設計, ここから、Firebaseの機能を利用したコードの書き方を解説していきます。 まず、Authenticationを利用した認証について説明します。, より詳細な実装は、前述のリポジトリにあるFirestoreModel.swiftを参照してください。, AuthのaddStateDidChangeListenerを使って、ユーザーが認証済みであるかどうかを確認します。, このメソッドで、最初の呼び出し時と、以降の認証状態が変化したときに確認することができます。 これで、認証済みであれば認証後の画面を、そうでなければ認証前のサインアップ画面を出すことが可能になります。, はじめは認証情報がないため、次のようなサインアップ画面を準備します。 名前を入力してもらい、サインアップしてもらいます。, Result型を使いやすくするため、次のラッパーを用意しています(サンプルのResult+.swiftを参照)。, 認証ができたら、その認証情報を使ってUserドキュメントを作成します。 基本的には認証で得られたuidをそのままUserドキュメントのドキュメントIDとして用いるとよいでしょう。, Firestoreのドキュメントの取得や書き込みに関しては、SDKそのままのインターフェースではやや扱いづらいことがあります。, 今回のプロジェクトでは使用していませんが、Firestoreのモデルを扱いやすくするOSSが公開されているので紹介しておきます。, ユーザー(Userドキュメント)の処理に続いて、商品(Productドキュメント)とカート(CartItemドキュメント)の扱いを実装していきましょう。, 実際のショッピングサービスであれば、出品するユーザーがフォームに従って情報を入力し、商品を登録しますが、今回は簡易化のため既に商品情報は用意してあり、出品時にはランダムな商品情報に出品者自身のUserドキュメントのパスを付与し、Firestoreに保存します。, 次に、登録した商品の一覧を表示できるようにします。 ドキュメントの一覧を取得する方法には、一度だけ取得するgetと、変更をリッスンし続けるlistenがあります。 今回はlistenを用いて、変更があった場合に一覧を更新します。, ドキュメントの一覧を取得する際にはクエリを指定でき、対象のドキュメントを絞ったり、並び替えたりできます。 次のコードでは、クエリにpublishedTime(公開日時)で降順、さらに最大取得数が100という条件を付けて取得しています。, 常にリッスンしているので、商品を登録するとすぐさま変更を受け取り、商品の一覧を更新することができます。, 続いて、カートに商品を追加します。先程の商品の登録と同様に、ドキュメントを指定の場所に作り、保存する流れになります。, カートは、商品を購入するユーザーに紐付き、他のユーザーから干渉されるドキュメントにはならないため、Userドキュメントのサブコレクションとして実装するのがよいでしょう。 具体的には、users/{user_id}/cart_items/以下にドキュメントを作成します。, 既に同じ商品をカートに入れている場合は、既存のCartItemのquantityを更新します。, なお、数量を更新する際にはquantity + 1とするのではなく、FieldValue.increment()を使うとよいでしょう。 number型のフィールドを、安全に増減させることができます(減らすときは負数を代入)。 詳細は、公式ブログで次の記事を参照してください。, Incrementing Values Atomically with Cloud Firestore - The Firebase Blog, カートに入っている商品の一覧を表示するには、Userドキュメントのサブコレクションであるcart_itemsコレクションのドキュメントの一覧を取得します。, 取得したCartItemドキュメントには数量とProductドキュメントのパスがありますが、Product自体の情報は持っていないので、画面に商品画像や商品名を表示するには、CartItemドキュメント毎にProductドキュメントを取得する必要があります。, 今回のケースでは、Productドキュメントにある金額・名前・在庫数といった情報が変わる可能性があるため、CartItemドキュメントに情報を書き写すのではなく、Productドキュメントのパスを持っておいて、最新の情報をその都度、取得する方が適しています。, それぞれのユーザーがカートに入れる商品の数もたかだか数十個程度でしょうから、いわゆる「N+1問題」もそこまで大きな問題にならないのではと思います。, カートに入れた商品を削除するのはとても簡単で、cartItemドキュメントのパスに対して、.delete()を呼んでやるだけです。, 別の方法としては、ドキュメントにisActiveといったbool値のフィールドを持たせて、そのフラグを更新する方法もあります。, 物理的にデータベースから消去するのが好ましくなく、論理的に削除状態にしたい場合は、こちらを検討してみるとよいでしょう。, ここまでで商品を登録し、カートに入れたり外したりできるようになりました。次に、いよいよカートの商品を購入してみましょう。, 購入処理に関しては次のような要件が求められるため、Cloud Functionsの呼び出し可能なHTTPSファンクション(Callable HTTPS Functions)を利用します。, 呼び出し可能なHTTPSファンクション(functions.https.onCall)が、ただのHTTPSファンクション(functions.https.onRequest)と異なる点は、クライアントからリクエストを送信する際に、Firebaseの認証情報が自動的に付与されることです。 これによって、関数実行時に認証情報を検証できるため、より安全な呼び出しが可能です (呼び出し可能ファンクションが実装されるまでは、自前で認証情報を含めて呼び出す必要がありました)。, これはindex.tsに直接ではなく、purchase.tsという別ファイルに書くことにします。, 商品の在庫確認と在庫を減らす処理は、同時に複数のアプリから実行されても問題ないように、トランザクションを張る必要があります。 それによって、仮に同じ商品が同時に購入されようとしても整合性が担保でき、在庫切れになったのに購入できてしまったというケースを防ぐことができます。, トランザクションを張るには、FirestoreモジュールのrunTransactionを実行します。, また、最後に作成するOrderドキュメント(注文情報)は、次のようなデータになるため、, 購入当時のProductドキュメントの情報をSnapshotProductとして書き写します。, これは、先ほど説明したCartItemドキュメントが、書き写すのではなくパスを持っていたことと対照的です。, さらに、ファンクションの定義の最初にある.runWith()と.region()では、Cloud Functionsのトリガーに対して、実行時のメモリやタイムアウト、リージョンを指定できます。 ここではFirestoreのリージョンを東京で作成しているので、それに合わせています。, ファンクション内でAdmin SDKを使うため、最初にセットアップする必要があります。 詳細は公式のドキュメントを参考にしてください。, デプロイしたファンクションをiOSアプリから呼び出すには、次のようなコードを記述します(サンプルのPurchaseRequest.swiftを参照)。, ここまでで一通りの機能がそろったので、セットアップ時に「テストモード」で構築したCloud Firestoreのセキュリティルールを、強固なものに変更しましょう。, まず、データモデルの構成で説明したそれぞれのコレクション・ドキュメントに対して、必要なルールの条件をまとめてみます。, なお、ドキュメントのreadやwriteは、それぞれget list create update deleteといったオペレーションに分解でき、細かく設定できます。, Productドキュメント(/products/{product_id})の条件:, CartItemドキュメント(/users/{user_id}/cart_items/{cart_item_id})の条件:, Orderドキュメント(/users/{user_id}/orders/{order_id})の条件:, Firestoreのルールは原則として、記述のないドキュメント・コレクションに対するアクセス権は拒否されるようになっています。 この例では、Userドキュメントの削除や、全く関係のないcitiesコレクションに対するドキュメントの書き込みは拒否されます。, このため、今後新しいドキュメントを設計して読み書きする場合には、それに対応したルールを追加していく必要があります。, ここから骨組みに対してルールを構築していきますが、そのために便利な関数を定義します。, セキュリティルールでは独自に関数を組むことができ、関数を活用することで分かりやすく、後でメンテナンスのしやすいルールを構築できます。, また、updateの条件では、しばしば「変更前後でフィールドの値が変更されていないこと」を条件に書きたいケースがあります。 そういうときは、次のように書くとよいでしょう。 この例は、updateの操作のときに、Productドキュメントのパスが書き換わっていないことを確認するための条件です。, これを加えることで、意図しないProductドキュメントやその他のドキュメントのパスに書き換えられる問題を防ぐことができます。 update操作に対するルールを書くときには、どのフィールドが書き換え可能で、どのフィールドは書き換え不可なのか検討しておきましょう。, Cloud Firestoreのruleで`update`の条件を書く時に気をつけたいこと - Qiita, 上記の関数とテクニックを組み合わせて構築すると、最終的に次のような構成になります。, ルールが記述できたら、コマンドライン経由でFirebaseにデプロイします。 セキュリティルールのみをデプロイする場合は、--only firestore:rulesを付けます。, デプロイした後、1分ほどで設定が反映されるでしょう。 ルールをデプロイした後には、正しく動作するかを確認してみましょう。, ここで「どのくらいセキュリティルールを書けばいいの?」という疑問が出てくるかと思います。次の順で優先度を高くして、書くとよいでしょう。, 最も防ぐべきは、意図しないユーザーによる不正な読み取りや、意図しないデータへの書き換えです。, Firestoreのセキュリティルールに関してより詳しく学びたい方は、筆者の記事ですが、以下が参考になると思います。, Firestoreでセキュリティルールを書かないで、全てCloud FunctionsのHTTPSファンクション(ないしは呼び出し可能なHTTPSファンクション)でデータをやりとりすることもできます。それぞれ、次のようなPros/Consがあります。, 個人的には、次のような場合はルールを記述せず、閉じた状態にして、Cloud Functionsを活用するようにしています。, それ以外に関しては、適切なルールを敷いた上で、クライアントに提供されているSDKを介して読み書きを行うようにしています。 その方が読み書きの速度も早く、リッスンして変更を常に受け取るのも容易です。, Firebaseの紹介にはじまって、Authentication・Firestore・Cloud Functionsを組み合わせた実装をサンプルを通して説明し、セキュリティルールまで解説しました。, この記事が、まだ一度もFirebaseを試したことがない方や、どのように設計するか分からない方の手助けになればと思います。, 「更新通知を受け取る」をクリック!ブログの更新通知をメールやアプリで受け取ることができます。, 「エンジニアHub」は、「20代と30代の若手Webエンジニアを応援する」をテーマに、若手Webエンジニアの活躍の様子や、最新の技術情報/Tipsを広くお届けするためのWebメディアです。エン・ジャパン株式会社と株式会社はてなが共同で作った編集部にて運営しています。, Firebase入門 フリマアプリを作りながら、認証・Firestore・Cloud Functionsの使い方を学ぼう!, tsc && cp package.json ./dist && cp config/admin_sdk.json ./dist, [.quantity: FieldValue.increment(Int64(1))], // トランザクションを利用して、カートにいれた商品の在庫があり購入可能かを確認する, 'There is less stock than the quantity to buy'.

花瓶 おしゃれ 店舗, 松山千春 近況, ブルックス スニーカー メンズ, 強震モニタ Extension Twitter 認証できない, 広瀬香美 身長, ヤマダ 電機 名古屋 ソフトバンク, 南海トラフ地震 確率, オクトパストラベラー 奥義, グリーンブック 放送, 緊急速報 音 消す アンドロイド, ニトリ ソファベッド 口コミ, とくとくbb キャッシュバック メール 何日, 池袋ウエストゲートパーク ヒロト, 二ノ国クロスワールド 対応機種, Uqモバイル アマゾン かんたん決済できない, よく当たる宝くじ売り場 佐賀, S'accomodi ソファ, 女性歌手 歌唱力ランキング, アイドル歌手 一覧, 格安スマホ やめた, 成り上がり線 確率, 南海商事 宝くじ, グランドセフトオート 無料, ワールドポーターズ スーパー 閉店, Choose Ing形, 氷川きよしボヘミアンラプソディ Mステ, ゆうかん へずまりゅう, 木更津アウトレット プラダ, 三山ひろし カラオケ, バレンタインジャンボ 737, ドリームジャンボ Cm 女の子, パチスロ 負け まとめ, は に たぬき, ビッグローブ 問い合わせ つながらない, 一人暮らし 家電セット 中古, 18世紀イギリス女性 地位, サイバーパンク2077 めちゃくちゃ, くじの日 2019 みずほ銀行, 阪神 ファーム 成績 2020, パチンコ 歴代機種, ソファーカバー ボックスシーツ 代用, Amazon 携帯決済 危険, 駐 車場 月極 5,000円, 家具 リメイク あつ森, ねお 卒業, セイルー 神戸, 大塚家具 アウトレット オンライン, 壁掛けテレビ テレビボード バランス, 横浜 アンティーク 食器, 原田左之助 イケメン, 宝くじ 1000万, 丁寧な暮らし ユーチューバー, ギガ放題 比較 スマホ, オクトパス トラベラー キャラ テーマ, ヤマダ電機 株価 なぜ安い, サイバーパンク2077 車, 社交界 とは, 2ch 勢い 実況, エンヤ 夫, ダイニングチェア 失敗, 三山 ひろし, 地震アプリ ランキング, 東京 家具 おすすめ, ダイニングテーブル 高級感, 三越家具 ブルージュ 椅子, メンズ 夏服 通販, イオン 食器, ニトリ 顧客, カリモク キッチンボード, Gwent Steam 日本語, 甲斐野央 復帰, ダイニングテーブル シネマ3, ウィッチャー2 エンハンスドエディション, Iphone Se バッテリー交換 費用, ローソファー おしゃれ, シーリー 買取, インテリアショップ 神奈川, 匠大塚 現在, 宝くじ 一口だけ, へ ず ま りゅう 骨折, ヴィンテージソファ 北欧, ゲッターズ飯田 占い, サイバーパンク2077 三人称, Atpランキング 日本人, ニトリ ローテーブル クラウド, ソファーカバー 高級, グウェント 課金 値段, アーロンチェア 説明書, ウィッチャー3 ブログ, ファミリーテーブル コロナ, ぱちタウンエンジェルス さやか, 神戸 家具レンタル, 韓国アイドル 女性, Lol 5chまとめ, ジャンボ宝くじ Cm 嫌い,

コメントする

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

0

カート