google-cloud-firestore 2.3.0 → 2.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/CHANGELOG.md +35 -0
 - data/CONTRIBUTING.md +4 -5
 - data/LOGGING.md +1 -1
 - data/lib/google/cloud/firestore/batch.rb +3 -4
 - data/lib/google/cloud/firestore/client.rb +17 -23
 - data/lib/google/cloud/firestore/collection_group.rb +136 -0
 - data/lib/google/cloud/firestore/collection_reference.rb +9 -6
 - data/lib/google/cloud/firestore/collection_reference_list.rb +3 -3
 - data/lib/google/cloud/firestore/convert.rb +151 -173
 - data/lib/google/cloud/firestore/document_reference.rb +9 -2
 - data/lib/google/cloud/firestore/document_reference/list.rb +5 -6
 - data/lib/google/cloud/firestore/field_path.rb +2 -2
 - data/lib/google/cloud/firestore/field_value.rb +7 -2
 - data/lib/google/cloud/firestore/query.rb +99 -29
 - data/lib/google/cloud/firestore/query_partition.rb +80 -0
 - data/lib/google/cloud/firestore/resource_path.rb +58 -0
 - data/lib/google/cloud/firestore/service.rb +18 -1
 - data/lib/google/cloud/firestore/transaction.rb +5 -5
 - data/lib/google/cloud/firestore/version.rb +1 -1
 - data/lib/google/cloud/firestore/watch/inventory.rb +9 -8
 - data/lib/google/cloud/firestore/watch/listener.rb +3 -4
 - metadata +9 -6
 
    
        checksums.yaml
    CHANGED
    
    | 
         @@ -1,7 +1,7 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            ---
         
     | 
| 
       2 
2 
     | 
    
         
             
            SHA256:
         
     | 
| 
       3 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       4 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 3 
     | 
    
         
            +
              metadata.gz: 3141b004673c1db562f162d9218ac680c0693e4d91a8eb48b7d17f444646e74a
         
     | 
| 
      
 4 
     | 
    
         
            +
              data.tar.gz: 4ab2bb6f69da5f8ad2e53464ae3712647b3642d49a465dc5f75d1dbc923979f5
         
     | 
| 
       5 
5 
     | 
    
         
             
            SHA512:
         
     | 
| 
       6 
     | 
    
         
            -
              metadata.gz:  
     | 
| 
       7 
     | 
    
         
            -
              data.tar.gz:  
     | 
| 
      
 6 
     | 
    
         
            +
              metadata.gz: fd5dccbe067d6fea81556aae40b9fc9de2ca75fc389c919335217371d84578b68ad7c9854c84831bb368dd58982849c06f044cef0c864be586cdace0ea48994a
         
     | 
| 
      
 7 
     | 
    
         
            +
              data.tar.gz: 7a7f0ee2a3259f2a65119b0b31dbf781d7336f7c530301f4c7f0a7fdf95fea8a7773caa4ed172c9ce8c5ff9f9fe80dab830f37ef1e6d204ae7d770fdf9c066c0
         
     | 
    
        data/CHANGELOG.md
    CHANGED
    
    | 
         @@ -1,5 +1,40 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            # Release History
         
     | 
| 
       2 
2 
     | 
    
         | 
| 
      
 3 
     | 
    
         
            +
            ### 2.6.0 / 2021-06-15
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            #### Features
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            * Add support for Query Partitions
         
     | 
| 
      
 8 
     | 
    
         
            +
              * Add CollectionGroup
         
     | 
| 
      
 9 
     | 
    
         
            +
              * Update Client#col_group to return CollectionGroup (subclass of Query)
         
     | 
| 
      
 10 
     | 
    
         
            +
              * Add QueryPartition
         
     | 
| 
      
 11 
     | 
    
         
            +
              * Add QueryPartition::List
         
     | 
| 
      
 12 
     | 
    
         
            +
              * Add Query#to_json and Query.from_json
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
            ### 2.5.1 / 2021-04-19
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            #### Bug Fixes
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
            * Add GRPC::Unknown to retryable errors in Watch::Listener
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            ### 2.5.0 / 2021-03-10
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            #### Features
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            * Drop support for Ruby 2.4 and add support for Ruby 3.0
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
            ### 2.4.1 / 2021-01-06
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
            #### Bug Fixes
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            * Replace usage of Write.transform with Write.update_transforms
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
            ### 2.4.0 / 2020-11-19
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
            #### Features
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
            * add support for != and NOT_IN queries
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
       3 
38 
     | 
    
         
             
            ### 2.3.0 / 2020-09-30
         
     | 
| 
       4 
39 
     | 
    
         | 
| 
       5 
40 
     | 
    
         
             
            #### Features
         
     | 
    
        data/CONTRIBUTING.md
    CHANGED
    
    | 
         @@ -24,7 +24,7 @@ be able to accept your pull requests. 
     | 
|
| 
       24 
24 
     | 
    
         
             
            In order to use the google-cloud-firestore console and run the project's tests,
         
     | 
| 
       25 
25 
     | 
    
         
             
            there is a small amount of setup:
         
     | 
| 
       26 
26 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
            1. Install Ruby. google-cloud-firestore requires Ruby 2. 
     | 
| 
      
 27 
     | 
    
         
            +
            1. Install Ruby. google-cloud-firestore requires Ruby 2.5+. You may choose to
         
     | 
| 
       28 
28 
     | 
    
         
             
               manage your Ruby and gem installations with [RVM](https://rvm.io/),
         
     | 
| 
       29 
29 
     | 
    
         
             
               [rbenv](https://github.com/rbenv/rbenv), or
         
     | 
| 
       30 
30 
     | 
    
         
             
               [chruby](https://github.com/postmodern/chruby).
         
     | 
| 
         @@ -45,7 +45,7 @@ there is a small amount of setup: 
     | 
|
| 
       45 
45 
     | 
    
         | 
| 
       46 
46 
     | 
    
         
             
               ```sh
         
     | 
| 
       47 
47 
     | 
    
         
             
               $ cd google-cloud-firestore/
         
     | 
| 
       48 
     | 
    
         
            -
               $ bundle  
     | 
| 
      
 48 
     | 
    
         
            +
               $ bundle install
         
     | 
| 
       49 
49 
     | 
    
         
             
               ```
         
     | 
| 
       50 
50 
     | 
    
         | 
| 
       51 
51 
     | 
    
         
             
            ## Console
         
     | 
| 
         @@ -119,15 +119,14 @@ If you alter an example's title, you may encounter breaking tests. 
     | 
|
| 
       119 
119 
     | 
    
         
             
            ### Firestore Acceptance Tests
         
     | 
| 
       120 
120 
     | 
    
         | 
| 
       121 
121 
     | 
    
         
             
            The Firestore acceptance tests interact with the live service API. Follow the
         
     | 
| 
       122 
     | 
    
         
            -
            instructions in the {file:AUTHENTICATION.md Authentication  
     | 
| 
      
 122 
     | 
    
         
            +
            instructions in the {file:AUTHENTICATION.md Authentication Guide} for enabling
         
     | 
| 
       123 
123 
     | 
    
         
             
            the Firestore API. Occasionally, some API features may not yet be generally
         
     | 
| 
       124 
124 
     | 
    
         
             
            available, making it difficult for some contributors to successfully run the
         
     | 
| 
       125 
125 
     | 
    
         
             
            entire acceptance test suite. However, please ensure that you do successfully
         
     | 
| 
       126 
126 
     | 
    
         
             
            run acceptance tests for any code areas covered by your pull request.
         
     | 
| 
       127 
127 
     | 
    
         | 
| 
       128 
128 
     | 
    
         
             
            To run the acceptance tests, first create and configure a project in the Google
         
     | 
| 
       129 
     | 
    
         
            -
            Developers Console, as described in the {file:AUTHENTICATION.md Authentication
         
     | 
| 
       130 
     | 
    
         
            -
            guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
         
     | 
| 
      
 129 
     | 
    
         
            +
            Developers Console, as described in the {file:AUTHENTICATION.md Authentication Guide}. Be sure to download the JSON KEY file. Make note of the PROJECT_ID and
         
     | 
| 
       131 
130 
     | 
    
         
             
            the KEYFILE location on your system.
         
     | 
| 
       132 
131 
     | 
    
         | 
| 
       133 
132 
     | 
    
         
             
            Before you can run the Firestore acceptance tests, you must first create indexes
         
     | 
    
        data/LOGGING.md
    CHANGED
    
    | 
         @@ -3,7 +3,7 @@ 
     | 
|
| 
       3 
3 
     | 
    
         
             
            To enable logging for this library, set the logger for the underlying
         
     | 
| 
       4 
4 
     | 
    
         
             
            [gRPC](https://github.com/grpc/grpc/tree/master/src/ruby) library. The logger
         
     | 
| 
       5 
5 
     | 
    
         
             
            that you set may be a Ruby stdlib
         
     | 
| 
       6 
     | 
    
         
            -
            [`Logger`](https://ruby-doc.org/stdlib 
     | 
| 
      
 6 
     | 
    
         
            +
            [`Logger`](https://ruby-doc.org/stdlib/libdoc/logger/rdoc/Logger.html) as
         
     | 
| 
       7 
7 
     | 
    
         
             
            shown below, or a
         
     | 
| 
       8 
8 
     | 
    
         
             
            [`Google::Cloud::Logging::Logger`](https://googleapis.dev/ruby/google-cloud-logging/latest)
         
     | 
| 
       9 
9 
     | 
    
         
             
            that will write logs to [Stackdriver
         
     | 
| 
         @@ -119,7 +119,7 @@ module Google 
     | 
|
| 
       119 
119 
     | 
    
         | 
| 
       120 
120 
     | 
    
         
             
                      doc_path = coalesce_doc_path_argument doc
         
     | 
| 
       121 
121 
     | 
    
         | 
| 
       122 
     | 
    
         
            -
                      @writes << Convert. 
     | 
| 
      
 122 
     | 
    
         
            +
                      @writes << Convert.write_for_create(doc_path, data)
         
     | 
| 
       123 
123 
     | 
    
         | 
| 
       124 
124 
     | 
    
         
             
                      nil
         
     | 
| 
       125 
125 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -218,7 +218,7 @@ module Google 
     | 
|
| 
       218 
218 
     | 
    
         | 
| 
       219 
219 
     | 
    
         
             
                      doc_path = coalesce_doc_path_argument doc
         
     | 
| 
       220 
220 
     | 
    
         | 
| 
       221 
     | 
    
         
            -
                      @writes << Convert. 
     | 
| 
      
 221 
     | 
    
         
            +
                      @writes << Convert.write_for_set(doc_path, data, merge: merge)
         
     | 
| 
       222 
222 
     | 
    
         | 
| 
       223 
223 
     | 
    
         
             
                      nil
         
     | 
| 
       224 
224 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -322,8 +322,7 @@ module Google 
     | 
|
| 
       322 
322 
     | 
    
         | 
| 
       323 
323 
     | 
    
         
             
                      doc_path = coalesce_doc_path_argument doc
         
     | 
| 
       324 
324 
     | 
    
         | 
| 
       325 
     | 
    
         
            -
                      @writes << Convert. 
     | 
| 
       326 
     | 
    
         
            -
                                                           update_time: update_time)
         
     | 
| 
      
 325 
     | 
    
         
            +
                      @writes << Convert.write_for_update(doc_path, data, update_time: update_time)
         
     | 
| 
       327 
326 
     | 
    
         | 
| 
       328 
327 
     | 
    
         
             
                      nil
         
     | 
| 
       329 
328 
     | 
    
         
             
                    end
         
     | 
| 
         @@ -20,6 +20,7 @@ require "google/cloud/firestore/field_value" 
     | 
|
| 
       20 
20 
     | 
    
         
             
            require "google/cloud/firestore/collection_reference"
         
     | 
| 
       21 
21 
     | 
    
         
             
            require "google/cloud/firestore/document_reference"
         
     | 
| 
       22 
22 
     | 
    
         
             
            require "google/cloud/firestore/document_snapshot"
         
     | 
| 
      
 23 
     | 
    
         
            +
            require "google/cloud/firestore/collection_group"
         
     | 
| 
       23 
24 
     | 
    
         
             
            require "google/cloud/firestore/batch"
         
     | 
| 
       24 
25 
     | 
    
         
             
            require "google/cloud/firestore/transaction"
         
     | 
| 
       25 
26 
     | 
    
         | 
| 
         @@ -100,11 +101,11 @@ module Google 
     | 
|
| 
       100 
101 
     | 
    
         
             
                    #     puts col.collection_id
         
     | 
| 
       101 
102 
     | 
    
         
             
                    #   end
         
     | 
| 
       102 
103 
     | 
    
         
             
                    #
         
     | 
| 
       103 
     | 
    
         
            -
                    def cols
         
     | 
| 
      
 104 
     | 
    
         
            +
                    def cols &block
         
     | 
| 
       104 
105 
     | 
    
         
             
                      ensure_service!
         
     | 
| 
       105 
106 
     | 
    
         
             
                      grpc = service.list_collections "#{path}/documents"
         
     | 
| 
       106 
107 
     | 
    
         
             
                      cols_enum = CollectionReferenceList.from_grpc(grpc, self, "#{path}/documents").all
         
     | 
| 
       107 
     | 
    
         
            -
                      cols_enum.each  
     | 
| 
      
 108 
     | 
    
         
            +
                      cols_enum.each(&block) if block_given?
         
     | 
| 
       108 
109 
     | 
    
         
             
                      cols_enum
         
     | 
| 
       109 
110 
     | 
    
         
             
                    end
         
     | 
| 
       110 
111 
     | 
    
         
             
                    alias collections cols
         
     | 
| 
         @@ -139,7 +140,7 @@ module Google 
     | 
|
| 
       139 
140 
     | 
    
         
             
                    alias collection col
         
     | 
| 
       140 
141 
     | 
    
         | 
| 
       141 
142 
     | 
    
         
             
                    ##
         
     | 
| 
       142 
     | 
    
         
            -
                    # Creates and returns a new  
     | 
| 
      
 143 
     | 
    
         
            +
                    # Creates and returns a new collection group that includes all documents in the
         
     | 
| 
       143 
144 
     | 
    
         
             
                    # database that are contained in a collection or subcollection with the
         
     | 
| 
       144 
145 
     | 
    
         
             
                    # given collection_id.
         
     | 
| 
       145 
146 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -147,7 +148,7 @@ module Google 
     | 
|
| 
       147 
148 
     | 
    
         
             
                    #   over. Every collection or subcollection with this ID as the last
         
     | 
| 
       148 
149 
     | 
    
         
             
                    #   segment of its path will be included. Cannot contain a slash (`/`).
         
     | 
| 
       149 
150 
     | 
    
         
             
                    #
         
     | 
| 
       150 
     | 
    
         
            -
                    # @return [ 
     | 
| 
      
 151 
     | 
    
         
            +
                    # @return [CollectionGroup] The created collection group.
         
     | 
| 
       151 
152 
     | 
    
         
             
                    #
         
     | 
| 
       152 
153 
     | 
    
         
             
                    # @example
         
     | 
| 
       153 
154 
     | 
    
         
             
                    #   require "google/cloud/firestore"
         
     | 
| 
         @@ -155,9 +156,9 @@ module Google 
     | 
|
| 
       155 
156 
     | 
    
         
             
                    #   firestore = Google::Cloud::Firestore.new
         
     | 
| 
       156 
157 
     | 
    
         
             
                    #
         
     | 
| 
       157 
158 
     | 
    
         
             
                    #   # Get the cities collection group query
         
     | 
| 
       158 
     | 
    
         
            -
                    #    
     | 
| 
      
 159 
     | 
    
         
            +
                    #   col_group = firestore.col_group "cities"
         
     | 
| 
       159 
160 
     | 
    
         
             
                    #
         
     | 
| 
       160 
     | 
    
         
            -
                    #    
     | 
| 
      
 161 
     | 
    
         
            +
                    #   col_group.get do |city|
         
     | 
| 
       161 
162 
     | 
    
         
             
                    #     puts "#{city.document_id} has #{city[:population]} residents."
         
     | 
| 
       162 
163 
     | 
    
         
             
                    #   end
         
     | 
| 
       163 
164 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -166,15 +167,8 @@ module Google 
     | 
|
| 
       166 
167 
     | 
    
         
             
                        raise ArgumentError, "Invalid collection_id: '#{collection_id}', " \
         
     | 
| 
       167 
168 
     | 
    
         
             
                          "must not contain '/'."
         
     | 
| 
       168 
169 
     | 
    
         
             
                      end
         
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                          Google::Cloud::Firestore::V1::StructuredQuery::CollectionSelector.new(
         
     | 
| 
       172 
     | 
    
         
            -
                            collection_id: collection_id, all_descendants: true
         
     | 
| 
       173 
     | 
    
         
            -
                          )
         
     | 
| 
       174 
     | 
    
         
            -
                        ]
         
     | 
| 
       175 
     | 
    
         
            -
                      )
         
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
       177 
     | 
    
         
            -
                      Query.start query, service.documents_path, self
         
     | 
| 
      
 170 
     | 
    
         
            +
             
     | 
| 
      
 171 
     | 
    
         
            +
                      CollectionGroup.from_collection_id service.documents_path, collection_id, self
         
     | 
| 
       178 
172 
     | 
    
         
             
                    end
         
     | 
| 
       179 
173 
     | 
    
         
             
                    alias collection_group col_group
         
     | 
| 
       180 
174 
     | 
    
         | 
| 
         @@ -256,7 +250,7 @@ module Google 
     | 
|
| 
       256 
250 
     | 
    
         
             
                      ensure_service!
         
     | 
| 
       257 
251 
     | 
    
         | 
| 
       258 
252 
     | 
    
         
             
                      unless block_given?
         
     | 
| 
       259 
     | 
    
         
            -
                        return enum_for :get_all, docs, field_mask: field_mask
         
     | 
| 
      
 253 
     | 
    
         
            +
                        return enum_for :get_all, *docs, field_mask: field_mask
         
     | 
| 
       260 
254 
     | 
    
         
             
                      end
         
     | 
| 
       261 
255 
     | 
    
         | 
| 
       262 
256 
     | 
    
         
             
                      doc_paths = Array(docs).flatten.map do |doc_path|
         
     | 
| 
         @@ -634,9 +628,9 @@ module Google 
     | 
|
| 
       634 
628 
     | 
    
         
             
                        commit_return = transaction.commit
         
     | 
| 
       635 
629 
     | 
    
         
             
                        # Conditional return value, depending on truthy commit_response
         
     | 
| 
       636 
630 
     | 
    
         
             
                        commit_response ? commit_return : transaction_return
         
     | 
| 
       637 
     | 
    
         
            -
                      rescue Google::Cloud::UnavailableError =>  
     | 
| 
      
 631 
     | 
    
         
            +
                      rescue Google::Cloud::UnavailableError => e
         
     | 
| 
       638 
632 
     | 
    
         
             
                        # Re-raise if retried more than the max
         
     | 
| 
       639 
     | 
    
         
            -
                        raise  
     | 
| 
      
 633 
     | 
    
         
            +
                        raise e if backoff[:current] > backoff[:max]
         
     | 
| 
       640 
634 
     | 
    
         | 
| 
       641 
635 
     | 
    
         
             
                        # Sleep with incremental backoff before restarting
         
     | 
| 
       642 
636 
     | 
    
         
             
                        sleep backoff[:delay]
         
     | 
| 
         @@ -649,18 +643,18 @@ module Google 
     | 
|
| 
       649 
643 
     | 
    
         
             
                        transaction = Transaction.from_client \
         
     | 
| 
       650 
644 
     | 
    
         
             
                          self, previous_transaction: transaction.transaction_id
         
     | 
| 
       651 
645 
     | 
    
         
             
                        retry
         
     | 
| 
       652 
     | 
    
         
            -
                      rescue Google::Cloud::InvalidArgumentError =>  
     | 
| 
      
 646 
     | 
    
         
            +
                      rescue Google::Cloud::InvalidArgumentError => e
         
     | 
| 
       653 
647 
     | 
    
         
             
                        # Return if a previous call was retried but ultimately succeeded
         
     | 
| 
       654 
     | 
    
         
            -
                        return nil if backoff[:current] 
     | 
| 
      
 648 
     | 
    
         
            +
                        return nil if backoff[:current].positive?
         
     | 
| 
       655 
649 
     | 
    
         | 
| 
       656 
650 
     | 
    
         
             
                        # Re-raise error.
         
     | 
| 
       657 
     | 
    
         
            -
                        raise  
     | 
| 
       658 
     | 
    
         
            -
                      rescue StandardError =>  
     | 
| 
      
 651 
     | 
    
         
            +
                        raise e
         
     | 
| 
      
 652 
     | 
    
         
            +
                      rescue StandardError => e
         
     | 
| 
       659 
653 
     | 
    
         
             
                        # Rollback transaction when handling unexpected error
         
     | 
| 
       660 
654 
     | 
    
         
             
                        transaction.rollback rescue nil
         
     | 
| 
       661 
655 
     | 
    
         | 
| 
       662 
656 
     | 
    
         
             
                        # Re-raise error.
         
     | 
| 
       663 
     | 
    
         
            -
                        raise  
     | 
| 
      
 657 
     | 
    
         
            +
                        raise e
         
     | 
| 
       664 
658 
     | 
    
         
             
                      end
         
     | 
| 
       665 
659 
     | 
    
         
             
                    end
         
     | 
| 
       666 
660 
     | 
    
         | 
| 
         @@ -0,0 +1,136 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Copyright 2021 Google LLC
         
     | 
| 
      
 2 
     | 
    
         
            +
            #
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Licensed under the Apache License, Version 2.0 (the "License");
         
     | 
| 
      
 4 
     | 
    
         
            +
            # you may not use this file except in compliance with the License.
         
     | 
| 
      
 5 
     | 
    
         
            +
            # You may obtain a copy of the License at
         
     | 
| 
      
 6 
     | 
    
         
            +
            #
         
     | 
| 
      
 7 
     | 
    
         
            +
            #     https://www.apache.org/licenses/LICENSE-2.0
         
     | 
| 
      
 8 
     | 
    
         
            +
            #
         
     | 
| 
      
 9 
     | 
    
         
            +
            # Unless required by applicable law or agreed to in writing, software
         
     | 
| 
      
 10 
     | 
    
         
            +
            # distributed under the License is distributed on an "AS IS" BASIS,
         
     | 
| 
      
 11 
     | 
    
         
            +
            # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
         
     | 
| 
      
 12 
     | 
    
         
            +
            # See the License for the specific language governing permissions and
         
     | 
| 
      
 13 
     | 
    
         
            +
            # limitations under the License.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
      
 16 
     | 
    
         
            +
            require "google/cloud/firestore/v1"
         
     | 
| 
      
 17 
     | 
    
         
            +
            require "google/cloud/firestore/query"
         
     | 
| 
      
 18 
     | 
    
         
            +
            require "google/cloud/firestore/query_partition"
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
            module Google
         
     | 
| 
      
 21 
     | 
    
         
            +
              module Cloud
         
     | 
| 
      
 22 
     | 
    
         
            +
                module Firestore
         
     | 
| 
      
 23 
     | 
    
         
            +
                  ##
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # # CollectionGroup
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  # A collection group object is used for adding documents, getting
         
     | 
| 
      
 27 
     | 
    
         
            +
                  # document references, and querying for documents, including with partitions.
         
     | 
| 
      
 28 
     | 
    
         
            +
                  #
         
     | 
| 
      
 29 
     | 
    
         
            +
                  # See {Client#col_group} and {Query}.
         
     | 
| 
      
 30 
     | 
    
         
            +
                  #
         
     | 
| 
      
 31 
     | 
    
         
            +
                  # @example
         
     | 
| 
      
 32 
     | 
    
         
            +
                  #   require "google/cloud/firestore"
         
     | 
| 
      
 33 
     | 
    
         
            +
                  #
         
     | 
| 
      
 34 
     | 
    
         
            +
                  #   firestore = Google::Cloud::Firestore.new
         
     | 
| 
      
 35 
     | 
    
         
            +
                  #
         
     | 
| 
      
 36 
     | 
    
         
            +
                  #   # Get a collection group
         
     | 
| 
      
 37 
     | 
    
         
            +
                  #   col_group = firestore.col_group "cities"
         
     | 
| 
      
 38 
     | 
    
         
            +
                  #
         
     | 
| 
      
 39 
     | 
    
         
            +
                  #   # Get and print all city documents
         
     | 
| 
      
 40 
     | 
    
         
            +
                  #   col_group.get do |city|
         
     | 
| 
      
 41 
     | 
    
         
            +
                  #     puts "#{city.document_id} has #{city[:population]} residents."
         
     | 
| 
      
 42 
     | 
    
         
            +
                  #   end
         
     | 
| 
      
 43 
     | 
    
         
            +
                  #
         
     | 
| 
      
 44 
     | 
    
         
            +
                  class CollectionGroup < Query
         
     | 
| 
      
 45 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 46 
     | 
    
         
            +
                    # Partitions a query by returning partition cursors that can be used to run the query in parallel. The returned
         
     | 
| 
      
 47 
     | 
    
         
            +
                    # partition cursors are split points that can be used as starting/end points for the query results.
         
     | 
| 
      
 48 
     | 
    
         
            +
                    #
         
     | 
| 
      
 49 
     | 
    
         
            +
                    # @param [Integer] partition_count The desired maximum number of partition points. The number must be strictly
         
     | 
| 
      
 50 
     | 
    
         
            +
                    #   positive. The actual number of partitions returned may be fewer.
         
     | 
| 
      
 51 
     | 
    
         
            +
                    #
         
     | 
| 
      
 52 
     | 
    
         
            +
                    # @return [Array<QueryPartition>] An ordered array of query partitions.
         
     | 
| 
      
 53 
     | 
    
         
            +
                    #
         
     | 
| 
      
 54 
     | 
    
         
            +
                    # @example
         
     | 
| 
      
 55 
     | 
    
         
            +
                    #   require "google/cloud/firestore"
         
     | 
| 
      
 56 
     | 
    
         
            +
                    #
         
     | 
| 
      
 57 
     | 
    
         
            +
                    #   firestore = Google::Cloud::Firestore.new
         
     | 
| 
      
 58 
     | 
    
         
            +
                    #
         
     | 
| 
      
 59 
     | 
    
         
            +
                    #   col_group = firestore.col_group "cities"
         
     | 
| 
      
 60 
     | 
    
         
            +
                    #
         
     | 
| 
      
 61 
     | 
    
         
            +
                    #   partitions = col_group.partitions 3
         
     | 
| 
      
 62 
     | 
    
         
            +
                    #
         
     | 
| 
      
 63 
     | 
    
         
            +
                    #   queries = partitions.map(&:to_query)
         
     | 
| 
      
 64 
     | 
    
         
            +
                    #
         
     | 
| 
      
 65 
     | 
    
         
            +
                    def partitions partition_count
         
     | 
| 
      
 66 
     | 
    
         
            +
                      ensure_service!
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                      raise ArgumentError, "partition_count must be > 0" unless partition_count.positive?
         
     | 
| 
      
 69 
     | 
    
         
            +
             
     | 
| 
      
 70 
     | 
    
         
            +
                      # Partition queries require explicit ordering by __name__.
         
     | 
| 
      
 71 
     | 
    
         
            +
                      query_with_default_order = order "__name__"
         
     | 
| 
      
 72 
     | 
    
         
            +
                      # Since we are always returning an extra partition (with en empty endBefore cursor), we reduce the desired
         
     | 
| 
      
 73 
     | 
    
         
            +
                      # partition count by one.
         
     | 
| 
      
 74 
     | 
    
         
            +
                      partition_count -= 1
         
     | 
| 
      
 75 
     | 
    
         
            +
             
     | 
| 
      
 76 
     | 
    
         
            +
                      grpc_partitions = if partition_count.positive?
         
     | 
| 
      
 77 
     | 
    
         
            +
                                          # Retrieve all pages, since cursor order is not guaranteed and they must be sorted.
         
     | 
| 
      
 78 
     | 
    
         
            +
                                          list_all partition_count, query_with_default_order
         
     | 
| 
      
 79 
     | 
    
         
            +
                                        else
         
     | 
| 
      
 80 
     | 
    
         
            +
                                          [] # Ensure that a single, empty QueryPartition is returned.
         
     | 
| 
      
 81 
     | 
    
         
            +
                                        end
         
     | 
| 
      
 82 
     | 
    
         
            +
                      cursor_values = grpc_partitions.map do |cursor|
         
     | 
| 
      
 83 
     | 
    
         
            +
                        # Convert each cursor to a (single-element) array of Google::Cloud::Firestore::DocumentReference.
         
     | 
| 
      
 84 
     | 
    
         
            +
                        cursor.values.map do |value|
         
     | 
| 
      
 85 
     | 
    
         
            +
                          Convert.value_to_raw value, client
         
     | 
| 
      
 86 
     | 
    
         
            +
                        end
         
     | 
| 
      
 87 
     | 
    
         
            +
                      end
         
     | 
| 
      
 88 
     | 
    
         
            +
                      # Sort the values of the returned cursor, which right now should only contain a single reference value (which
         
     | 
| 
      
 89 
     | 
    
         
            +
                      # needs to be sorted one component at a time).
         
     | 
| 
      
 90 
     | 
    
         
            +
                      cursor_values.sort! do |a, b|
         
     | 
| 
      
 91 
     | 
    
         
            +
                        a.first <=> b.first
         
     | 
| 
      
 92 
     | 
    
         
            +
                      end
         
     | 
| 
      
 93 
     | 
    
         
            +
             
     | 
| 
      
 94 
     | 
    
         
            +
                      start_at = nil
         
     | 
| 
      
 95 
     | 
    
         
            +
                      results = cursor_values.map do |end_before|
         
     | 
| 
      
 96 
     | 
    
         
            +
                        partition = QueryPartition.new query_with_default_order, start_at, end_before
         
     | 
| 
      
 97 
     | 
    
         
            +
                        start_at = end_before
         
     | 
| 
      
 98 
     | 
    
         
            +
                        partition
         
     | 
| 
      
 99 
     | 
    
         
            +
                      end
         
     | 
| 
      
 100 
     | 
    
         
            +
                      # Always add a final QueryPartition with an empty end_before value.
         
     | 
| 
      
 101 
     | 
    
         
            +
                      results << QueryPartition.new(query_with_default_order, start_at, nil)
         
     | 
| 
      
 102 
     | 
    
         
            +
                      results
         
     | 
| 
      
 103 
     | 
    
         
            +
                    end
         
     | 
| 
      
 104 
     | 
    
         
            +
             
     | 
| 
      
 105 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 106 
     | 
    
         
            +
                    # @private New Collection group object from a path.
         
     | 
| 
      
 107 
     | 
    
         
            +
                    def self.from_collection_id parent_path, collection_id, client
         
     | 
| 
      
 108 
     | 
    
         
            +
                      query = Google::Cloud::Firestore::V1::StructuredQuery.new(
         
     | 
| 
      
 109 
     | 
    
         
            +
                        from: [
         
     | 
| 
      
 110 
     | 
    
         
            +
                          Google::Cloud::Firestore::V1::StructuredQuery::CollectionSelector.new(
         
     | 
| 
      
 111 
     | 
    
         
            +
                            collection_id: collection_id,
         
     | 
| 
      
 112 
     | 
    
         
            +
                            all_descendants: true
         
     | 
| 
      
 113 
     | 
    
         
            +
                          )
         
     | 
| 
      
 114 
     | 
    
         
            +
                        ]
         
     | 
| 
      
 115 
     | 
    
         
            +
                      )
         
     | 
| 
      
 116 
     | 
    
         
            +
                      CollectionGroup.new query, parent_path, client
         
     | 
| 
      
 117 
     | 
    
         
            +
                    end
         
     | 
| 
      
 118 
     | 
    
         
            +
             
     | 
| 
      
 119 
     | 
    
         
            +
                    protected
         
     | 
| 
      
 120 
     | 
    
         
            +
             
     | 
| 
      
 121 
     | 
    
         
            +
                    def list_all partition_count, query_with_default_order
         
     | 
| 
      
 122 
     | 
    
         
            +
                      grpc_partitions = []
         
     | 
| 
      
 123 
     | 
    
         
            +
                      token = nil
         
     | 
| 
      
 124 
     | 
    
         
            +
                      loop do
         
     | 
| 
      
 125 
     | 
    
         
            +
                        grpc = service.partition_query parent_path, query_with_default_order.query, partition_count, token: token
         
     | 
| 
      
 126 
     | 
    
         
            +
                        grpc_partitions += Array(grpc.partitions)
         
     | 
| 
      
 127 
     | 
    
         
            +
                        token = grpc.next_page_token
         
     | 
| 
      
 128 
     | 
    
         
            +
                        token = nil if token == ""
         
     | 
| 
      
 129 
     | 
    
         
            +
                        break unless token
         
     | 
| 
      
 130 
     | 
    
         
            +
                      end
         
     | 
| 
      
 131 
     | 
    
         
            +
                      grpc_partitions
         
     | 
| 
      
 132 
     | 
    
         
            +
                    end
         
     | 
| 
      
 133 
     | 
    
         
            +
                  end
         
     | 
| 
      
 134 
     | 
    
         
            +
                end
         
     | 
| 
      
 135 
     | 
    
         
            +
              end
         
     | 
| 
      
 136 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -14,9 +14,9 @@ 
     | 
|
| 
       14 
14 
     | 
    
         | 
| 
       15 
15 
     | 
    
         | 
| 
       16 
16 
     | 
    
         
             
            require "google/cloud/firestore/v1"
         
     | 
| 
      
 17 
     | 
    
         
            +
            require "google/cloud/firestore/query"
         
     | 
| 
       17 
18 
     | 
    
         
             
            require "google/cloud/firestore/document_reference"
         
     | 
| 
       18 
19 
     | 
    
         
             
            require "google/cloud/firestore/document_snapshot"
         
     | 
| 
       19 
     | 
    
         
            -
            require "google/cloud/firestore/query"
         
     | 
| 
       20 
20 
     | 
    
         
             
            require "google/cloud/firestore/generate"
         
     | 
| 
       21 
21 
     | 
    
         
             
            require "google/cloud/firestore/collection_reference_list"
         
     | 
| 
       22 
22 
     | 
    
         | 
| 
         @@ -47,6 +47,13 @@ module Google 
     | 
|
| 
       47 
47 
     | 
    
         
             
                    # @private The firestore client object.
         
     | 
| 
       48 
48 
     | 
    
         
             
                    attr_accessor :client
         
     | 
| 
       49 
49 
     | 
    
         | 
| 
      
 50 
     | 
    
         
            +
                    ##
         
     | 
| 
      
 51 
     | 
    
         
            +
                    # @private Creates a new CollectionReference.
         
     | 
| 
      
 52 
     | 
    
         
            +
                    def initialize query, path, client
         
     | 
| 
      
 53 
     | 
    
         
            +
                      super query, nil, client # Pass nil parent_path arg since this class implements #parent_path
         
     | 
| 
      
 54 
     | 
    
         
            +
                      @path = path
         
     | 
| 
      
 55 
     | 
    
         
            +
                    end
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
       50 
57 
     | 
    
         
             
                    ##
         
     | 
| 
       51 
58 
     | 
    
         
             
                    # The collection identifier for the collection resource.
         
     | 
| 
       52 
59 
     | 
    
         
             
                    #
         
     | 
| 
         @@ -257,11 +264,7 @@ module Google 
     | 
|
| 
       257 
264 
     | 
    
         
             
                        ]
         
     | 
| 
       258 
265 
     | 
    
         
             
                      )
         
     | 
| 
       259 
266 
     | 
    
         | 
| 
       260 
     | 
    
         
            -
                      new 
     | 
| 
       261 
     | 
    
         
            -
                        c.client = client
         
     | 
| 
       262 
     | 
    
         
            -
                        c.instance_variable_set :@path, path
         
     | 
| 
       263 
     | 
    
         
            -
                        c.instance_variable_set :@query, query
         
     | 
| 
       264 
     | 
    
         
            -
                      end
         
     | 
| 
      
 267 
     | 
    
         
            +
                      CollectionReference.new query, path, client
         
     | 
| 
       265 
268 
     | 
    
         
             
                    end
         
     | 
| 
       266 
269 
     | 
    
         | 
| 
       267 
270 
     | 
    
         
             
                    protected
         
     | 
| 
         @@ -90,17 +90,17 @@ module Google 
     | 
|
| 
       90 
90 
     | 
    
         
             
                    #     collection_reference.collection_id
         
     | 
| 
       91 
91 
     | 
    
         
             
                    #   end
         
     | 
| 
       92 
92 
     | 
    
         
             
                    #
         
     | 
| 
       93 
     | 
    
         
            -
                    def all request_limit: nil
         
     | 
| 
      
 93 
     | 
    
         
            +
                    def all request_limit: nil, &block
         
     | 
| 
       94 
94 
     | 
    
         
             
                      request_limit = request_limit.to_i if request_limit
         
     | 
| 
       95 
95 
     | 
    
         
             
                      unless block_given?
         
     | 
| 
       96 
96 
     | 
    
         
             
                        return enum_for :all, request_limit: request_limit
         
     | 
| 
       97 
97 
     | 
    
         
             
                      end
         
     | 
| 
       98 
98 
     | 
    
         
             
                      results = self
         
     | 
| 
       99 
99 
     | 
    
         
             
                      loop do
         
     | 
| 
       100 
     | 
    
         
            -
                        results.each 
     | 
| 
      
 100 
     | 
    
         
            +
                        results.each(&block)
         
     | 
| 
       101 
101 
     | 
    
         
             
                        if request_limit
         
     | 
| 
       102 
102 
     | 
    
         
             
                          request_limit -= 1
         
     | 
| 
       103 
     | 
    
         
            -
                          break if request_limit 
     | 
| 
      
 103 
     | 
    
         
            +
                          break if request_limit.negative?
         
     | 
| 
       104 
104 
     | 
    
         
             
                        end
         
     | 
| 
       105 
105 
     | 
    
         
             
                        break unless results.next?
         
     | 
| 
       106 
106 
     | 
    
         
             
                        results = results.next
         
     | 
| 
         @@ -24,7 +24,12 @@ module Google 
     | 
|
| 
       24 
24 
     | 
    
         
             
                  ##
         
     | 
| 
       25 
25 
     | 
    
         
             
                  # @private Helper module for converting Protobuf values.
         
     | 
| 
       26 
26 
     | 
    
         
             
                  module Convert
         
     | 
| 
       27 
     | 
    
         
            -
                    # rubocop:disable  
     | 
| 
      
 27 
     | 
    
         
            +
                    # rubocop:disable Metrics/AbcSize
         
     | 
| 
      
 28 
     | 
    
         
            +
                    # rubocop:disable Metrics/BlockLength
         
     | 
| 
      
 29 
     | 
    
         
            +
                    # rubocop:disable Metrics/CyclomaticComplexity
         
     | 
| 
      
 30 
     | 
    
         
            +
                    # rubocop:disable Metrics/MethodLength
         
     | 
| 
      
 31 
     | 
    
         
            +
                    # rubocop:disable Metrics/ModuleLength
         
     | 
| 
      
 32 
     | 
    
         
            +
                    # rubocop:disable Metrics/PerceivedComplexity
         
     | 
| 
       28 
33 
     | 
    
         
             
                    module ClassMethods
         
     | 
| 
       29 
34 
     | 
    
         
             
                      def time_to_timestamp time
         
     | 
| 
       30 
35 
     | 
    
         
             
                        return nil if time.nil?
         
     | 
| 
         @@ -32,9 +37,10 @@ module Google 
     | 
|
| 
       32 
37 
     | 
    
         
             
                        # Force the object to be a Time object.
         
     | 
| 
       33 
38 
     | 
    
         
             
                        time = time.to_time
         
     | 
| 
       34 
39 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
                        Google::Protobuf::Timestamp.new 
     | 
| 
      
 40 
     | 
    
         
            +
                        Google::Protobuf::Timestamp.new(
         
     | 
| 
       36 
41 
     | 
    
         
             
                          seconds: time.to_i,
         
     | 
| 
       37 
     | 
    
         
            -
                          nanos: 
     | 
| 
      
 42 
     | 
    
         
            +
                          nanos:   time.nsec
         
     | 
| 
      
 43 
     | 
    
         
            +
                        )
         
     | 
| 
       38 
44 
     | 
    
         
             
                      end
         
     | 
| 
       39 
45 
     | 
    
         | 
| 
       40 
46 
     | 
    
         
             
                      def timestamp_to_time timestamp
         
     | 
| 
         @@ -100,9 +106,10 @@ module Google 
     | 
|
| 
       100 
106 
     | 
    
         
             
                        elsif Google::Cloud::Firestore::DocumentReference === obj
         
     | 
| 
       101 
107 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::Value.new reference_value: obj.path
         
     | 
| 
       102 
108 
     | 
    
         
             
                        elsif Array === obj
         
     | 
| 
       103 
     | 
    
         
            -
                          values = obj.map { |o| raw_to_value 
     | 
| 
       104 
     | 
    
         
            -
                          Google::Cloud::Firestore::V1::Value.new( 
     | 
| 
       105 
     | 
    
         
            -
                            Google::Cloud::Firestore::V1::ArrayValue.new(values: values) 
     | 
| 
      
 109 
     | 
    
         
            +
                          values = obj.map { |o| raw_to_value o }
         
     | 
| 
      
 110 
     | 
    
         
            +
                          Google::Cloud::Firestore::V1::Value.new(
         
     | 
| 
      
 111 
     | 
    
         
            +
                            array_value: Google::Cloud::Firestore::V1::ArrayValue.new(values: values)
         
     | 
| 
      
 112 
     | 
    
         
            +
                          )
         
     | 
| 
       106 
113 
     | 
    
         
             
                        elsif Hash === obj
         
     | 
| 
       107 
114 
     | 
    
         
             
                          # keys have been changed to strings before the hash gets here
         
     | 
| 
       108 
115 
     | 
    
         
             
                          geo_pairs = hash_is_geo_point? obj
         
     | 
| 
         @@ -112,8 +119,9 @@ module Google 
     | 
|
| 
       112 
119 
     | 
    
         
             
                            )
         
     | 
| 
       113 
120 
     | 
    
         
             
                          else
         
     | 
| 
       114 
121 
     | 
    
         
             
                            fields = hash_to_fields obj
         
     | 
| 
       115 
     | 
    
         
            -
                            Google::Cloud::Firestore::V1::Value.new( 
     | 
| 
       116 
     | 
    
         
            -
                              Google::Cloud::Firestore::V1::MapValue.new(fields: fields) 
     | 
| 
      
 122 
     | 
    
         
            +
                            Google::Cloud::Firestore::V1::Value.new(
         
     | 
| 
      
 123 
     | 
    
         
            +
                              map_value: Google::Cloud::Firestore::V1::MapValue.new(fields: fields)
         
     | 
| 
      
 124 
     | 
    
         
            +
                            )
         
     | 
| 
       117 
125 
     | 
    
         
             
                          end
         
     | 
| 
       118 
126 
     | 
    
         
             
                        elsif obj.respond_to?(:read) && obj.respond_to?(:rewind)
         
     | 
| 
       119 
127 
     | 
    
         
             
                          obj.rewind
         
     | 
| 
         @@ -129,9 +137,7 @@ module Google 
     | 
|
| 
       129 
137 
     | 
    
         
             
                        return false unless hash.keys.count == 2
         
     | 
| 
       130 
138 
     | 
    
         | 
| 
       131 
139 
     | 
    
         
             
                        pairs = hash.map { |k, v| [String(k), v] }.sort
         
     | 
| 
       132 
     | 
    
         
            -
                        if pairs.map(&:first) == ["latitude", "longitude"]
         
     | 
| 
       133 
     | 
    
         
            -
                          pairs
         
     | 
| 
       134 
     | 
    
         
            -
                        end
         
     | 
| 
      
 140 
     | 
    
         
            +
                        pairs if pairs.map(&:first) == ["latitude", "longitude"]
         
     | 
| 
       135 
141 
     | 
    
         
             
                      end
         
     | 
| 
       136 
142 
     | 
    
         | 
| 
       137 
143 
     | 
    
         
             
                      def hash_to_geo_point hash, pairs = nil
         
     | 
| 
         @@ -140,47 +146,39 @@ module Google 
     | 
|
| 
       140 
146 
     | 
    
         
             
                        raise ArgumentError, "value is not a geo point" unless pairs
         
     | 
| 
       141 
147 
     | 
    
         | 
| 
       142 
148 
     | 
    
         
             
                        Google::Type::LatLng.new(
         
     | 
| 
       143 
     | 
    
         
            -
                          latitude: 
     | 
| 
       144 
     | 
    
         
            -
                          longitude: pairs.last.last 
     | 
| 
      
 149 
     | 
    
         
            +
                          latitude:  pairs.first.last,
         
     | 
| 
      
 150 
     | 
    
         
            +
                          longitude: pairs.last.last
         
     | 
| 
       145 
151 
     | 
    
         
             
                        )
         
     | 
| 
       146 
152 
     | 
    
         
             
                      end
         
     | 
| 
       147 
153 
     | 
    
         | 
| 
       148 
     | 
    
         
            -
                      def  
     | 
| 
       149 
     | 
    
         
            -
                         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                        if is_field_value_nested data, :delete
         
     | 
| 
      
 154 
     | 
    
         
            +
                      def write_for_create doc_path, data
         
     | 
| 
      
 155 
     | 
    
         
            +
                        if field_value_nested? data, :delete
         
     | 
| 
       152 
156 
     | 
    
         
             
                          raise ArgumentError, "DELETE not allowed on create"
         
     | 
| 
       153 
157 
     | 
    
         
             
                        end
         
     | 
| 
       154 
158 
     | 
    
         
             
                        raise ArgumentError, "data is required" unless data.is_a? Hash
         
     | 
| 
       155 
159 
     | 
    
         | 
| 
       156 
160 
     | 
    
         
             
                        data, field_paths_and_values = remove_field_value_from data
         
     | 
| 
       157 
161 
     | 
    
         | 
| 
       158 
     | 
    
         
            -
                         
     | 
| 
       159 
     | 
    
         
            -
                           
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
             
     | 
| 
       162 
     | 
    
         
            -
             
     | 
| 
       163 
     | 
    
         
            -
             
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                           
     | 
| 
       166 
     | 
    
         
            -
                           
     | 
| 
       167 
     | 
    
         
            -
                         
     | 
| 
       168 
     | 
    
         
            -
             
     | 
| 
       169 
     | 
    
         
            -
                        if field_paths_and_values.any?
         
     | 
| 
       170 
     | 
    
         
            -
                          transform_write = transform_write doc_path, field_paths_and_values
         
     | 
| 
       171 
     | 
    
         
            -
             
     | 
| 
       172 
     | 
    
         
            -
                          if data.empty?
         
     | 
| 
       173 
     | 
    
         
            -
                            transform_write.current_document = \
         
     | 
| 
       174 
     | 
    
         
            -
                              Google::Cloud::Firestore::V1::Precondition.new(exists: false)
         
     | 
| 
       175 
     | 
    
         
            -
                          end
         
     | 
| 
       176 
     | 
    
         
            -
             
     | 
| 
       177 
     | 
    
         
            -
                          writes << transform_write
         
     | 
| 
       178 
     | 
    
         
            -
                        end
         
     | 
| 
      
 162 
     | 
    
         
            +
                        doc = Google::Cloud::Firestore::V1::Document.new(
         
     | 
| 
      
 163 
     | 
    
         
            +
                          name:   doc_path,
         
     | 
| 
      
 164 
     | 
    
         
            +
                          fields: hash_to_fields(data)
         
     | 
| 
      
 165 
     | 
    
         
            +
                        )
         
     | 
| 
      
 166 
     | 
    
         
            +
                        precondition = Google::Cloud::Firestore::V1::Precondition.new exists: false
         
     | 
| 
      
 167 
     | 
    
         
            +
                        Google::Cloud::Firestore::V1::Write.new(
         
     | 
| 
      
 168 
     | 
    
         
            +
                          update:            doc,
         
     | 
| 
      
 169 
     | 
    
         
            +
                          current_document:  precondition,
         
     | 
| 
      
 170 
     | 
    
         
            +
                          update_transforms: field_transforms(field_paths_and_values)
         
     | 
| 
      
 171 
     | 
    
         
            +
                        )
         
     | 
| 
      
 172 
     | 
    
         
            +
                      end
         
     | 
| 
       179 
173 
     | 
    
         | 
| 
       180 
     | 
    
         
            -
             
     | 
| 
      
 174 
     | 
    
         
            +
                      def field_transforms paths
         
     | 
| 
      
 175 
     | 
    
         
            +
                        return nil if paths.empty?
         
     | 
| 
      
 176 
     | 
    
         
            +
                        paths.map do |field_path, field_value|
         
     | 
| 
      
 177 
     | 
    
         
            +
                          to_field_transform field_path, field_value
         
     | 
| 
      
 178 
     | 
    
         
            +
                        end.to_a
         
     | 
| 
       181 
179 
     | 
    
         
             
                      end
         
     | 
| 
       182 
180 
     | 
    
         | 
| 
       183 
     | 
    
         
            -
                      def  
     | 
| 
      
 181 
     | 
    
         
            +
                      def write_for_set doc_path, data, merge: nil
         
     | 
| 
       184 
182 
     | 
    
         
             
                        raise ArgumentError, "data is required" unless data.is_a? Hash
         
     | 
| 
       185 
183 
     | 
    
         | 
| 
       186 
184 
     | 
    
         
             
                        if merge
         
     | 
| 
         @@ -195,11 +193,9 @@ module Google 
     | 
|
| 
       195 
193 
     | 
    
         
             
                            end
         
     | 
| 
       196 
194 
     | 
    
         
             
                            allow_empty = false
         
     | 
| 
       197 
195 
     | 
    
         
             
                          end
         
     | 
| 
       198 
     | 
    
         
            -
                          return  
     | 
| 
      
 196 
     | 
    
         
            +
                          return write_for_set_merge doc_path, data, field_paths, allow_empty
         
     | 
| 
       199 
197 
     | 
    
         
             
                        end
         
     | 
| 
       200 
198 
     | 
    
         | 
| 
       201 
     | 
    
         
            -
                        writes = []
         
     | 
| 
       202 
     | 
    
         
            -
             
     | 
| 
       203 
199 
     | 
    
         
             
                        data, delete_paths = remove_field_value_from data, :delete
         
     | 
| 
       204 
200 
     | 
    
         
             
                        if delete_paths.any?
         
     | 
| 
       205 
201 
     | 
    
         
             
                          raise ArgumentError, "DELETE not allowed on set"
         
     | 
| 
         @@ -207,30 +203,25 @@ module Google 
     | 
|
| 
       207 
203 
     | 
    
         | 
| 
       208 
204 
     | 
    
         
             
                        data, field_paths_and_values = remove_field_value_from data
         
     | 
| 
       209 
205 
     | 
    
         | 
| 
       210 
     | 
    
         
            -
                         
     | 
| 
       211 
     | 
    
         
            -
                           
     | 
| 
       212 
     | 
    
         
            -
             
     | 
| 
       213 
     | 
    
         
            -
             
     | 
| 
      
 206 
     | 
    
         
            +
                        doc = Google::Cloud::Firestore::V1::Document.new(
         
     | 
| 
      
 207 
     | 
    
         
            +
                          name:   doc_path,
         
     | 
| 
      
 208 
     | 
    
         
            +
                          fields: hash_to_fields(data)
         
     | 
| 
      
 209 
     | 
    
         
            +
                        )
         
     | 
| 
      
 210 
     | 
    
         
            +
                        Google::Cloud::Firestore::V1::Write.new(
         
     | 
| 
      
 211 
     | 
    
         
            +
                          update:            doc,
         
     | 
| 
      
 212 
     | 
    
         
            +
                          update_transforms: field_transforms(field_paths_and_values)
         
     | 
| 
       214 
213 
     | 
    
         
             
                        )
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
                        if field_paths_and_values.any?
         
     | 
| 
       217 
     | 
    
         
            -
                          writes << transform_write(doc_path, field_paths_and_values)
         
     | 
| 
       218 
     | 
    
         
            -
                        end
         
     | 
| 
       219 
     | 
    
         
            -
             
     | 
| 
       220 
     | 
    
         
            -
                        writes
         
     | 
| 
       221 
214 
     | 
    
         
             
                      end
         
     | 
| 
       222 
215 
     | 
    
         | 
| 
       223 
     | 
    
         
            -
                      def  
     | 
| 
      
 216 
     | 
    
         
            +
                      def write_for_set_merge doc_path, data, field_paths, allow_empty
         
     | 
| 
       224 
217 
     | 
    
         
             
                        raise ArgumentError, "data is required" unless data.is_a? Hash
         
     | 
| 
       225 
218 
     | 
    
         | 
| 
       226 
219 
     | 
    
         
             
                        validate_field_paths! field_paths
         
     | 
| 
       227 
220 
     | 
    
         | 
| 
       228 
     | 
    
         
            -
                        writes = []
         
     | 
| 
       229 
     | 
    
         
            -
             
     | 
| 
       230 
221 
     | 
    
         
             
                        # Ensure provided field paths are valid.
         
     | 
| 
       231 
222 
     | 
    
         
             
                        all_valid = identify_leaf_nodes data
         
     | 
| 
       232 
223 
     | 
    
         
             
                        all_valid_check = field_paths.map do |verify_path|
         
     | 
| 
       233 
     | 
    
         
            -
                          if all_valid.include? 
     | 
| 
      
 224 
     | 
    
         
            +
                          if all_valid.include? verify_path
         
     | 
| 
       234 
225 
     | 
    
         
             
                            true
         
     | 
| 
       235 
226 
     | 
    
         
             
                          else
         
     | 
| 
       236 
227 
     | 
    
         
             
                            found_in_all_valid = all_valid.select do |fp|
         
     | 
| 
         @@ -271,32 +262,25 @@ module Google 
     | 
|
| 
       271 
262 
     | 
    
         
             
                        # Restore delete paths
         
     | 
| 
       272 
263 
     | 
    
         
             
                        field_paths += delete_field_paths_and_values.keys
         
     | 
| 
       273 
264 
     | 
    
         | 
| 
       274 
     | 
    
         
            -
                        if data.empty? && !allow_empty
         
     | 
| 
       275 
     | 
    
         
            -
                           
     | 
| 
       276 
     | 
    
         
            -
                            raise ArgumentError, "data required for set with merge"
         
     | 
| 
       277 
     | 
    
         
            -
                          end
         
     | 
| 
      
 265 
     | 
    
         
            +
                        if data.empty? && !allow_empty && field_paths_and_values.empty? && delete_field_paths_and_values.empty?
         
     | 
| 
      
 266 
     | 
    
         
            +
                          raise ArgumentError, "data required for set with merge"
         
     | 
| 
       278 
267 
     | 
    
         
             
                        end
         
     | 
| 
       279 
268 
     | 
    
         | 
| 
       280 
     | 
    
         
            -
                         
     | 
| 
       281 
     | 
    
         
            -
                           
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
             
     | 
| 
       284 
     | 
    
         
            -
             
     | 
| 
       285 
     | 
    
         
            -
             
     | 
| 
       286 
     | 
    
         
            -
             
     | 
| 
       287 
     | 
    
         
            -
             
     | 
| 
       288 
     | 
    
         
            -
                         
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
             
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
       292 
     | 
    
         
            -
                        end
         
     | 
| 
       293 
     | 
    
         
            -
             
     | 
| 
       294 
     | 
    
         
            -
                        writes
         
     | 
| 
      
 269 
     | 
    
         
            +
                        doc = Google::Cloud::Firestore::V1::Document.new(
         
     | 
| 
      
 270 
     | 
    
         
            +
                          name:   doc_path,
         
     | 
| 
      
 271 
     | 
    
         
            +
                          fields: hash_to_fields(data)
         
     | 
| 
      
 272 
     | 
    
         
            +
                        )
         
     | 
| 
      
 273 
     | 
    
         
            +
                        doc_mask = Google::Cloud::Firestore::V1::DocumentMask.new(
         
     | 
| 
      
 274 
     | 
    
         
            +
                          field_paths: field_paths.map(&:formatted_string).sort
         
     | 
| 
      
 275 
     | 
    
         
            +
                        )
         
     | 
| 
      
 276 
     | 
    
         
            +
                        Google::Cloud::Firestore::V1::Write.new(
         
     | 
| 
      
 277 
     | 
    
         
            +
                          update:            doc,
         
     | 
| 
      
 278 
     | 
    
         
            +
                          update_mask:       doc_mask,
         
     | 
| 
      
 279 
     | 
    
         
            +
                          update_transforms: field_transforms(field_paths_and_values)
         
     | 
| 
      
 280 
     | 
    
         
            +
                        )
         
     | 
| 
       295 
281 
     | 
    
         
             
                      end
         
     | 
| 
       296 
282 
     | 
    
         | 
| 
       297 
     | 
    
         
            -
                      def  
     | 
| 
       298 
     | 
    
         
            -
                        writes = []
         
     | 
| 
       299 
     | 
    
         
            -
             
     | 
| 
      
 283 
     | 
    
         
            +
                      def write_for_update doc_path, data, update_time: nil
         
     | 
| 
       300 
284 
     | 
    
         
             
                        raise ArgumentError, "data is required" unless data.is_a? Hash
         
     | 
| 
       301 
285 
     | 
    
         | 
| 
       302 
286 
     | 
    
         
             
                        # Convert data to use FieldPath
         
     | 
| 
         @@ -308,11 +292,11 @@ module Google 
     | 
|
| 
       308 
292 
     | 
    
         
             
                        # Duplicate field paths check
         
     | 
| 
       309 
293 
     | 
    
         
             
                        validate_field_paths! new_data_pairs.map(&:first)
         
     | 
| 
       310 
294 
     | 
    
         | 
| 
       311 
     | 
    
         
            -
                        delete_paths, new_data_pairs = new_data_pairs.partition do | 
     | 
| 
      
 295 
     | 
    
         
            +
                        delete_paths, new_data_pairs = new_data_pairs.partition do |_field_path, value|
         
     | 
| 
       312 
296 
     | 
    
         
             
                          value.is_a?(FieldValue) && value.type == :delete
         
     | 
| 
       313 
297 
     | 
    
         
             
                        end
         
     | 
| 
       314 
298 
     | 
    
         | 
| 
       315 
     | 
    
         
            -
                        root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do | 
     | 
| 
      
 299 
     | 
    
         
            +
                        root_field_paths_and_values, new_data_pairs = new_data_pairs.partition do |_field_path, value|
         
     | 
| 
       316 
300 
     | 
    
         
             
                          value.is_a? FieldValue
         
     | 
| 
       317 
301 
     | 
    
         
             
                        end
         
     | 
| 
       318 
302 
     | 
    
         | 
| 
         @@ -325,7 +309,7 @@ module Google 
     | 
|
| 
       325 
309 
     | 
    
         
             
                        data, nested_deletes = remove_field_value_from data, :delete
         
     | 
| 
       326 
310 
     | 
    
         
             
                        raise ArgumentError, "DELETE cannot be nested" if nested_deletes.any?
         
     | 
| 
       327 
311 
     | 
    
         | 
| 
       328 
     | 
    
         
            -
                        data, nested_field_paths_and_values 
     | 
| 
      
 312 
     | 
    
         
            +
                        data, nested_field_paths_and_values = remove_field_value_from data
         
     | 
| 
       329 
313 
     | 
    
         | 
| 
       330 
314 
     | 
    
         
             
                        field_paths_and_values = root_field_paths_and_values.merge nested_field_paths_and_values
         
     | 
| 
       331 
315 
     | 
    
         | 
| 
         @@ -338,34 +322,31 @@ module Google 
     | 
|
| 
       338 
322 
     | 
    
         
             
                          raise ArgumentError, "data is required"
         
     | 
| 
       339 
323 
     | 
    
         
             
                        end
         
     | 
| 
       340 
324 
     | 
    
         | 
| 
      
 325 
     | 
    
         
            +
                        write = Google::Cloud::Firestore::V1::Write.new(
         
     | 
| 
      
 326 
     | 
    
         
            +
                          update:           Google::Cloud::Firestore::V1::Document.new(name: doc_path),
         
     | 
| 
      
 327 
     | 
    
         
            +
                          update_mask:      Google::Cloud::Firestore::V1::DocumentMask.new,
         
     | 
| 
      
 328 
     | 
    
         
            +
                          current_document: Google::Cloud::Firestore::V1::Precondition.new(exists: true)
         
     | 
| 
      
 329 
     | 
    
         
            +
                        )
         
     | 
| 
      
 330 
     | 
    
         
            +
             
     | 
| 
       341 
331 
     | 
    
         
             
                        if data.any? || delete_paths.any?
         
     | 
| 
       342 
     | 
    
         
            -
                           
     | 
| 
       343 
     | 
    
         
            -
             
     | 
| 
       344 
     | 
    
         
            -
             
     | 
| 
       345 
     | 
    
         
            -
             
     | 
| 
       346 
     | 
    
         
            -
             
     | 
| 
       347 
     | 
    
         
            -
             
     | 
| 
       348 
     | 
    
         
            -
                            current_document: Google::Cloud::Firestore::V1::Precondition.new(
         
     | 
| 
       349 
     | 
    
         
            -
                              exists: true)
         
     | 
| 
       350 
     | 
    
         
            -
                          )
         
     | 
| 
      
 332 
     | 
    
         
            +
                          htf = hash_to_fields data
         
     | 
| 
      
 333 
     | 
    
         
            +
                          htf.each_pair do |k, v|
         
     | 
| 
      
 334 
     | 
    
         
            +
                            write.update.fields[k] = v
         
     | 
| 
      
 335 
     | 
    
         
            +
                          end
         
     | 
| 
      
 336 
     | 
    
         
            +
                          write.update_mask.field_paths += field_paths.map(&:formatted_string).sort
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
       351 
338 
     | 
    
         
             
                          if update_time
         
     | 
| 
       352 
     | 
    
         
            -
                            write.current_document =  
     | 
| 
       353 
     | 
    
         
            -
                               
     | 
| 
       354 
     | 
    
         
            -
             
     | 
| 
      
 339 
     | 
    
         
            +
                            write.current_document = Google::Cloud::Firestore::V1::Precondition.new(
         
     | 
| 
      
 340 
     | 
    
         
            +
                              update_time: time_to_timestamp(update_time)
         
     | 
| 
      
 341 
     | 
    
         
            +
                            )
         
     | 
| 
       355 
342 
     | 
    
         
             
                          end
         
     | 
| 
       356 
     | 
    
         
            -
                          writes << write
         
     | 
| 
       357 
343 
     | 
    
         
             
                        end
         
     | 
| 
       358 
344 
     | 
    
         | 
| 
       359 
345 
     | 
    
         
             
                        if field_paths_and_values.any?
         
     | 
| 
       360 
     | 
    
         
            -
                           
     | 
| 
       361 
     | 
    
         
            -
                          if data.empty?
         
     | 
| 
       362 
     | 
    
         
            -
                            transform_write.current_document = \
         
     | 
| 
       363 
     | 
    
         
            -
                              Google::Cloud::Firestore::V1::Precondition.new(exists: true)
         
     | 
| 
       364 
     | 
    
         
            -
                          end
         
     | 
| 
       365 
     | 
    
         
            -
                          writes << transform_write
         
     | 
| 
      
 346 
     | 
    
         
            +
                          write.update_transforms += field_transforms field_paths_and_values
         
     | 
| 
       366 
347 
     | 
    
         
             
                        end
         
     | 
| 
       367 
348 
     | 
    
         | 
| 
       368 
     | 
    
         
            -
                         
     | 
| 
      
 349 
     | 
    
         
            +
                        write
         
     | 
| 
       369 
350 
     | 
    
         
             
                      end
         
     | 
| 
       370 
351 
     | 
    
         | 
| 
       371 
352 
     | 
    
         
             
                      def write_for_delete doc_path, exists: nil, update_time: nil
         
     | 
| 
         @@ -387,13 +368,20 @@ module Google 
     | 
|
| 
       387 
368 
     | 
    
         
             
                        write
         
     | 
| 
       388 
369 
     | 
    
         
             
                      end
         
     | 
| 
       389 
370 
     | 
    
         | 
| 
       390 
     | 
    
         
            -
                      def  
     | 
| 
      
 371 
     | 
    
         
            +
                      def field_value_nested? obj, field_value_type = nil
         
     | 
| 
       391 
372 
     | 
    
         
             
                        return obj if obj.is_a?(FieldValue) && (field_value_type.nil? || obj.type == field_value_type)
         
     | 
| 
       392 
373 
     | 
    
         | 
| 
       393 
     | 
    
         
            -
                         
     | 
| 
       394 
     | 
    
         
            -
             
     | 
| 
       395 
     | 
    
         
            -
             
     | 
| 
       396 
     | 
    
         
            -
             
     | 
| 
      
 374 
     | 
    
         
            +
                        case obj
         
     | 
| 
      
 375 
     | 
    
         
            +
                        when Array
         
     | 
| 
      
 376 
     | 
    
         
            +
                          obj.each do |o|
         
     | 
| 
      
 377 
     | 
    
         
            +
                            val = field_value_nested? o, field_value_type
         
     | 
| 
      
 378 
     | 
    
         
            +
                            return val if val
         
     | 
| 
      
 379 
     | 
    
         
            +
                          end
         
     | 
| 
      
 380 
     | 
    
         
            +
                        when Hash
         
     | 
| 
      
 381 
     | 
    
         
            +
                          obj.each do |_k, v|
         
     | 
| 
      
 382 
     | 
    
         
            +
                            val = field_value_nested? v, field_value_type
         
     | 
| 
      
 383 
     | 
    
         
            +
                            return val if val
         
     | 
| 
      
 384 
     | 
    
         
            +
                          end
         
     | 
| 
       397 
385 
     | 
    
         
             
                        end
         
     | 
| 
       398 
386 
     | 
    
         
             
                        nil
         
     | 
| 
       399 
387 
     | 
    
         
             
                      end
         
     | 
| 
         @@ -406,35 +394,33 @@ module Google 
     | 
|
| 
       406 
394 
     | 
    
         
             
                          if value.is_a?(FieldValue) && (field_value_type.nil? || value.type == field_value_type)
         
     | 
| 
       407 
395 
     | 
    
         
             
                            paths << [FieldPath.new(*key), value]
         
     | 
| 
       408 
396 
     | 
    
         
             
                            nil # will be removed by calling compact
         
     | 
| 
       409 
     | 
    
         
            -
                           
     | 
| 
       410 
     | 
    
         
            -
                            if value. 
     | 
| 
       411 
     | 
    
         
            -
                               
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
     | 
    
         
            -
             
     | 
| 
       414 
     | 
    
         
            -
             
     | 
| 
       415 
     | 
    
         
            -
             
     | 
| 
       416 
     | 
    
         
            -
             
     | 
| 
       417 
     | 
    
         
            -
             
     | 
| 
       418 
     | 
    
         
            -
                                   
     | 
| 
       419 
     | 
    
         
            -
                                end
         
     | 
| 
       420 
     | 
    
         
            -
                                if nested_hash.empty?
         
     | 
| 
       421 
     | 
    
         
            -
                                  nil # will be removed by calling compact
         
     | 
| 
       422 
     | 
    
         
            -
                                else
         
     | 
| 
       423 
     | 
    
         
            -
                                  [String(key), nested_hash]
         
     | 
| 
      
 397 
     | 
    
         
            +
                          elsif value.is_a? Hash
         
     | 
| 
      
 398 
     | 
    
         
            +
                            if value.empty?
         
     | 
| 
      
 399 
     | 
    
         
            +
                              [String(key), value]
         
     | 
| 
      
 400 
     | 
    
         
            +
                            else
         
     | 
| 
      
 401 
     | 
    
         
            +
                              nested_hash, nested_paths = remove_field_value_from value, field_value_type
         
     | 
| 
      
 402 
     | 
    
         
            +
                              if nested_paths.any?
         
     | 
| 
      
 403 
     | 
    
         
            +
                                nested_paths.each do |nested_field_path, nested_field_value|
         
     | 
| 
      
 404 
     | 
    
         
            +
                                  updated_field_paths = ([key] + nested_field_path.fields).flatten
         
     | 
| 
      
 405 
     | 
    
         
            +
                                  updated_field_path = FieldPath.new(*updated_field_paths)
         
     | 
| 
      
 406 
     | 
    
         
            +
                                  paths << [updated_field_path, nested_field_value]
         
     | 
| 
       424 
407 
     | 
    
         
             
                                end
         
     | 
| 
      
 408 
     | 
    
         
            +
                              end
         
     | 
| 
      
 409 
     | 
    
         
            +
                              if nested_hash.empty?
         
     | 
| 
      
 410 
     | 
    
         
            +
                                nil # will be removed by calling compact
         
     | 
| 
       425 
411 
     | 
    
         
             
                              else
         
     | 
| 
       426 
     | 
    
         
            -
                                [String(key),  
     | 
| 
      
 412 
     | 
    
         
            +
                                [String(key), nested_hash]
         
     | 
| 
       427 
413 
     | 
    
         
             
                              end
         
     | 
| 
       428 
     | 
    
         
            -
                             
     | 
| 
       429 
     | 
    
         
            -
             
     | 
| 
       430 
     | 
    
         
            -
             
     | 
| 
       431 
     | 
    
         
            -
             
     | 
| 
       432 
     | 
    
         
            -
             
     | 
| 
       433 
     | 
    
         
            -
                                 
     | 
| 
      
 414 
     | 
    
         
            +
                            end
         
     | 
| 
      
 415 
     | 
    
         
            +
                          else
         
     | 
| 
      
 416 
     | 
    
         
            +
                            if value.is_a? Array
         
     | 
| 
      
 417 
     | 
    
         
            +
                              nested_field_value = field_value_nested? value, field_value_type
         
     | 
| 
      
 418 
     | 
    
         
            +
                              if nested_field_value
         
     | 
| 
      
 419 
     | 
    
         
            +
                                raise ArgumentError, "cannot nest #{nested_field_value.type} under arrays"
         
     | 
| 
       434 
420 
     | 
    
         
             
                              end
         
     | 
| 
       435 
     | 
    
         
            -
             
     | 
| 
       436 
     | 
    
         
            -
                              [String(key), value]
         
     | 
| 
       437 
421 
     | 
    
         
             
                            end
         
     | 
| 
      
 422 
     | 
    
         
            +
             
     | 
| 
      
 423 
     | 
    
         
            +
                            [String(key), value]
         
     | 
| 
       438 
424 
     | 
    
         
             
                          end
         
     | 
| 
       439 
425 
     | 
    
         
             
                        end
         
     | 
| 
       440 
426 
     | 
    
         | 
| 
         @@ -449,14 +435,14 @@ module Google 
     | 
|
| 
       449 
435 
     | 
    
         
             
                          if value.is_a? Hash
         
     | 
| 
       450 
436 
     | 
    
         
             
                            nested_paths = identify_leaf_nodes value
         
     | 
| 
       451 
437 
     | 
    
         
             
                            nested_paths.each do |nested_path|
         
     | 
| 
       452 
     | 
    
         
            -
                              paths << ( 
     | 
| 
      
 438 
     | 
    
         
            +
                              paths << ([key] + nested_path.fields).flatten
         
     | 
| 
       453 
439 
     | 
    
         
             
                            end
         
     | 
| 
       454 
440 
     | 
    
         
             
                          else
         
     | 
| 
       455 
441 
     | 
    
         
             
                            paths << [key]
         
     | 
| 
       456 
442 
     | 
    
         
             
                          end
         
     | 
| 
       457 
443 
     | 
    
         
             
                        end
         
     | 
| 
       458 
444 
     | 
    
         | 
| 
       459 
     | 
    
         
            -
                        paths.map { |path| FieldPath.new 
     | 
| 
      
 445 
     | 
    
         
            +
                        paths.map { |path| FieldPath.new(*path) }
         
     | 
| 
       460 
446 
     | 
    
         
             
                      end
         
     | 
| 
       461 
447 
     | 
    
         | 
| 
       462 
448 
     | 
    
         
             
                      def identify_all_file_paths hash
         
     | 
| 
         @@ -465,15 +451,14 @@ module Google 
     | 
|
| 
       465 
451 
     | 
    
         
             
                        hash.map do |key, value|
         
     | 
| 
       466 
452 
     | 
    
         
             
                          paths << [key]
         
     | 
| 
       467 
453 
     | 
    
         | 
| 
       468 
     | 
    
         
            -
                           
     | 
| 
       469 
     | 
    
         
            -
             
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
             
     | 
| 
       472 
     | 
    
         
            -
                            end
         
     | 
| 
      
 454 
     | 
    
         
            +
                          next unless value.is_a? Hash
         
     | 
| 
      
 455 
     | 
    
         
            +
                          nested_paths = identify_all_file_paths value
         
     | 
| 
      
 456 
     | 
    
         
            +
                          nested_paths.each do |nested_path|
         
     | 
| 
      
 457 
     | 
    
         
            +
                            paths << ([key] + nested_path.fields).flatten
         
     | 
| 
       473 
458 
     | 
    
         
             
                          end
         
     | 
| 
       474 
459 
     | 
    
         
             
                        end
         
     | 
| 
       475 
460 
     | 
    
         | 
| 
       476 
     | 
    
         
            -
                        paths.map { |path| FieldPath.new 
     | 
| 
      
 461 
     | 
    
         
            +
                        paths.map { |path| FieldPath.new(*path) }
         
     | 
| 
       477 
462 
     | 
    
         
             
                      end
         
     | 
| 
       478 
463 
     | 
    
         | 
| 
       479 
464 
     | 
    
         
             
                      def select_by_field_paths hash, field_paths
         
     | 
| 
         @@ -533,19 +518,19 @@ module Google 
     | 
|
| 
       533 
518 
     | 
    
         
             
                        right_hash.each_pair do |key, right_value|
         
     | 
| 
       534 
519 
     | 
    
         
             
                          left_value = left_hash[key]
         
     | 
| 
       535 
520 
     | 
    
         | 
| 
       536 
     | 
    
         
            -
                          if left_value.is_a?(Hash) && right_value.is_a?(Hash)
         
     | 
| 
       537 
     | 
    
         
            -
             
     | 
| 
       538 
     | 
    
         
            -
             
     | 
| 
       539 
     | 
    
         
            -
             
     | 
| 
       540 
     | 
    
         
            -
             
     | 
| 
      
 521 
     | 
    
         
            +
                          left_hash[key] = if left_value.is_a?(Hash) && right_value.is_a?(Hash)
         
     | 
| 
      
 522 
     | 
    
         
            +
                                             deep_merge_hashes left_value, right_value
         
     | 
| 
      
 523 
     | 
    
         
            +
                                           else
         
     | 
| 
      
 524 
     | 
    
         
            +
                                             right_value
         
     | 
| 
      
 525 
     | 
    
         
            +
                                           end
         
     | 
| 
       541 
526 
     | 
    
         
             
                        end
         
     | 
| 
       542 
527 
     | 
    
         | 
| 
       543 
528 
     | 
    
         
             
                        left_hash
         
     | 
| 
       544 
529 
     | 
    
         
             
                      end
         
     | 
| 
       545 
530 
     | 
    
         | 
| 
       546 
     | 
    
         
            -
                      START_FIELD_PATH_CHARS = /\A[a-zA-Z_] 
     | 
| 
       547 
     | 
    
         
            -
                      INVALID_FIELD_PATH_CHARS =  
     | 
| 
       548 
     | 
    
         
            -
                      ESCAPED_FIELD_PATH = /\A 
     | 
| 
      
 531 
     | 
    
         
            +
                      START_FIELD_PATH_CHARS = /\A[a-zA-Z_]/.freeze
         
     | 
| 
      
 532 
     | 
    
         
            +
                      INVALID_FIELD_PATH_CHARS = %r{[~*/\[\]]}.freeze
         
     | 
| 
      
 533 
     | 
    
         
            +
                      ESCAPED_FIELD_PATH = /\A`(.*)`\z/.freeze
         
     | 
| 
       549 
534 
     | 
    
         | 
| 
       550 
535 
     | 
    
         
             
                      def build_hash_from_field_paths_and_values pairs
         
     | 
| 
       551 
536 
     | 
    
         
             
                        pairs.each do |field_path, _value|
         
     | 
| 
         @@ -579,59 +564,52 @@ module Google 
     | 
|
| 
       579 
564 
     | 
    
         
             
                        "`#{str}`"
         
     | 
| 
       580 
565 
     | 
    
         
             
                      end
         
     | 
| 
       581 
566 
     | 
    
         | 
| 
       582 
     | 
    
         
            -
                      def transform_write doc_path, paths
         
     | 
| 
       583 
     | 
    
         
            -
                        field_transforms = paths.map do |field_path, field_value|
         
     | 
| 
       584 
     | 
    
         
            -
                          to_field_transform field_path, field_value
         
     | 
| 
       585 
     | 
    
         
            -
                        end
         
     | 
| 
       586 
     | 
    
         
            -
             
     | 
| 
       587 
     | 
    
         
            -
                        Google::Cloud::Firestore::V1::Write.new(
         
     | 
| 
       588 
     | 
    
         
            -
                          transform: Google::Cloud::Firestore::V1::DocumentTransform.new(
         
     | 
| 
       589 
     | 
    
         
            -
                            document: doc_path,
         
     | 
| 
       590 
     | 
    
         
            -
                            field_transforms: field_transforms
         
     | 
| 
       591 
     | 
    
         
            -
                          )
         
     | 
| 
       592 
     | 
    
         
            -
                        )
         
     | 
| 
       593 
     | 
    
         
            -
                      end
         
     | 
| 
       594 
     | 
    
         
            -
             
     | 
| 
       595 
567 
     | 
    
         
             
                      def to_field_transform field_path, field_value
         
     | 
| 
       596 
     | 
    
         
            -
                         
     | 
| 
      
 568 
     | 
    
         
            +
                        case field_value.type
         
     | 
| 
      
 569 
     | 
    
         
            +
                        when :server_time
         
     | 
| 
       597 
570 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       598 
     | 
    
         
            -
                            field_path: 
     | 
| 
      
 571 
     | 
    
         
            +
                            field_path:          field_path.formatted_string,
         
     | 
| 
       599 
572 
     | 
    
         
             
                            set_to_server_value: :REQUEST_TIME
         
     | 
| 
       600 
573 
     | 
    
         
             
                          )
         
     | 
| 
       601 
     | 
    
         
            -
                         
     | 
| 
      
 574 
     | 
    
         
            +
                        when :array_union
         
     | 
| 
       602 
575 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       603 
     | 
    
         
            -
                            field_path: 
     | 
| 
      
 576 
     | 
    
         
            +
                            field_path:              field_path.formatted_string,
         
     | 
| 
       604 
577 
     | 
    
         
             
                            append_missing_elements: raw_to_value(Array(field_value.value)).array_value
         
     | 
| 
       605 
578 
     | 
    
         
             
                          )
         
     | 
| 
       606 
     | 
    
         
            -
                         
     | 
| 
      
 579 
     | 
    
         
            +
                        when :array_delete
         
     | 
| 
       607 
580 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       608 
     | 
    
         
            -
                            field_path: 
     | 
| 
      
 581 
     | 
    
         
            +
                            field_path:            field_path.formatted_string,
         
     | 
| 
       609 
582 
     | 
    
         
             
                            remove_all_from_array: raw_to_value(Array(field_value.value)).array_value
         
     | 
| 
       610 
583 
     | 
    
         
             
                          )
         
     | 
| 
       611 
     | 
    
         
            -
                         
     | 
| 
      
 584 
     | 
    
         
            +
                        when :increment
         
     | 
| 
       612 
585 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       613 
586 
     | 
    
         
             
                            field_path: field_path.formatted_string,
         
     | 
| 
       614 
     | 
    
         
            -
                            increment: 
     | 
| 
      
 587 
     | 
    
         
            +
                            increment:  raw_to_value(field_value.value)
         
     | 
| 
       615 
588 
     | 
    
         
             
                          )
         
     | 
| 
       616 
     | 
    
         
            -
                         
     | 
| 
      
 589 
     | 
    
         
            +
                        when :maximum
         
     | 
| 
       617 
590 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       618 
591 
     | 
    
         
             
                            field_path: field_path.formatted_string,
         
     | 
| 
       619 
     | 
    
         
            -
                            maximum: 
     | 
| 
      
 592 
     | 
    
         
            +
                            maximum:    raw_to_value(field_value.value)
         
     | 
| 
       620 
593 
     | 
    
         
             
                          )
         
     | 
| 
       621 
     | 
    
         
            -
                         
     | 
| 
      
 594 
     | 
    
         
            +
                        when :minimum
         
     | 
| 
       622 
595 
     | 
    
         
             
                          Google::Cloud::Firestore::V1::DocumentTransform::FieldTransform.new(
         
     | 
| 
       623 
596 
     | 
    
         
             
                            field_path: field_path.formatted_string,
         
     | 
| 
       624 
     | 
    
         
            -
                            minimum: 
     | 
| 
      
 597 
     | 
    
         
            +
                            minimum:    raw_to_value(field_value.value)
         
     | 
| 
       625 
598 
     | 
    
         
             
                          )
         
     | 
| 
       626 
599 
     | 
    
         
             
                        else
         
     | 
| 
       627 
600 
     | 
    
         
             
                          raise ArgumentError, "unknown field transform #{field_value.type}"
         
     | 
| 
       628 
601 
     | 
    
         
             
                        end
         
     | 
| 
       629 
602 
     | 
    
         
             
                      end
         
     | 
| 
       630 
603 
     | 
    
         
             
                    end
         
     | 
| 
       631 
     | 
    
         
            -
                    # rubocop:enable all
         
     | 
| 
       632 
604 
     | 
    
         | 
| 
       633 
605 
     | 
    
         
             
                    extend ClassMethods
         
     | 
| 
       634 
606 
     | 
    
         
             
                  end
         
     | 
| 
      
 607 
     | 
    
         
            +
                  # rubocop:enable Metrics/AbcSize
         
     | 
| 
      
 608 
     | 
    
         
            +
                  # rubocop:enable Metrics/BlockLength
         
     | 
| 
      
 609 
     | 
    
         
            +
                  # rubocop:enable Metrics/CyclomaticComplexity
         
     | 
| 
      
 610 
     | 
    
         
            +
                  # rubocop:enable Metrics/MethodLength
         
     | 
| 
      
 611 
     | 
    
         
            +
                  # rubocop:enable Metrics/ModuleLength
         
     | 
| 
      
 612 
     | 
    
         
            +
                  # rubocop:enable Metrics/PerceivedComplexity
         
     | 
| 
       635 
613 
     | 
    
         
             
                end
         
     | 
| 
       636 
614 
     | 
    
         
             
              end
         
     | 
| 
       637 
615 
     | 
    
         
             
            end
         
     |