lib/google/cloud/firestore/document_snapshot.rb in google-cloud-firestore-0.22.0 vs lib/google/cloud/firestore/document_snapshot.rb in google-cloud-firestore-0.23.0

- old
+ new

@@ -15,10 +15,11 @@ require "google/cloud/firestore/v1beta1" require "google/cloud/firestore/document_reference" require "google/cloud/firestore/collection_reference" require "google/cloud/firestore/convert" +require "google/cloud/firestore/watch/order" module Google module Cloud module Firestore ## @@ -27,10 +28,13 @@ # A document snapshot object is an immutable representation for a # document in a Cloud Firestore database. # # The snapshot can reference a non-existing document. # + # See {DocumentReference#get}, {DocumentReference#listen}, + # {Query#get}, {Query#listen}, and {QuerySnapshot#docs}. + # # @example # require "google/cloud/firestore" # # firestore = Google::Cloud::Firestore.new # @@ -38,10 +42,26 @@ # nyc_snap = firestore.doc("cities/NYC").get # # # Get the document data # nyc_snap[:population] #=> 1000000 # + # @example Listen to a document reference for changes: + # require "google/cloud/firestore" + # + # firestore = Google::Cloud::Firestore.new + # + # # Get a document reference + # nyc_ref = firestore.doc "cities/NYC" + # + # listener = nyc_ref.listen do |snapshot| + # puts "The population of #{snapshot[:name]} " + # puts "is #{snapshot[:population]}." + # end + # + # # When ready, stop the listen operation and close the stream. + # listener.stop + # class DocumentSnapshot ## # @private The Google::Firestore::V1beta1::Document object. attr_accessor :grpc @@ -116,13 +136,15 @@ # @!endgroup # @!group Data ## - # Retrieves the document data. + # Retrieves the document data. When the document exists the data hash is + # frozen and will not allow any changes. When the document does not + # exist `nil` will be returned. # - # @return [Hash] The document data. + # @return [Hash, nil] The document data. # # @example # require "google/cloud/firestore" # # firestore = Google::Cloud::Firestore.new @@ -132,11 +154,11 @@ # # Get the document data # nyc_snap.data[:population] #=> 1000000 # def data return nil if missing? - Convert.fields_to_hash grpc.fields, ref.client + @data ||= Convert.fields_to_hash(grpc.fields, ref.client).freeze end alias fields data ## # Retrieves the document data. @@ -190,12 +212,13 @@ unless field_path.is_a? FieldPath field_path = FieldPath.parse field_path end nodes = field_path.fields.map(&:to_sym) - selected_data = data + return ref if nodes == [:__name__] + selected_data = data nodes.each do |node| unless selected_data.is_a? Hash err_msg = "#{field_path.formatted_string} is not " \ "contained in the data" raise ArgumentError, err_msg @@ -284,14 +307,49 @@ def missing? grpc.nil? end ## + # @private + def <=> other + return nil unless other.is_a? DocumentSnapshot + return data <=> other.data if path == other.path + path <=> other.path + end + + ## + # @private + def eql? other + return nil unless other.is_a? DocumentSnapshot + return data.eql? other.data if path == other.path + path.eql? other.path + end + + ## + # @private + def hash + @hash ||= [path, data].hash + end + + ## + # @private + def query_comparisons_for query_grpc + @memoized_comps ||= {} + if @memoized_comps.key? query_grpc.hash + return @memoized_comps[query_grpc.hash] + end + + @memoized_comps[query_grpc.hash] = query_grpc.order_by.map do |order| + Watch::Order.field_comparison get(order.field.field_path) + end + end + + ## # @private New DocumentSnapshot from a # Google::Firestore::V1beta1::RunQueryResponse object. - def self.from_query_result result, context - ref = DocumentReference.from_path result.document.name, context + def self.from_query_result result, client + ref = DocumentReference.from_path result.document.name, client read_at = Convert.timestamp_to_time result.read_time new.tap do |s| s.grpc = result.document s.instance_variable_set :@ref, ref @@ -299,24 +357,48 @@ end end ## # @private New DocumentSnapshot from a + # Google::Firestore::V1beta1::DocumentChange object. + def self.from_document document, client, read_at: nil + ref = DocumentReference.from_path document.name, client + + new.tap do |s| + s.grpc = document + s.instance_variable_set :@ref, ref + s.instance_variable_set :@read_at, read_at + end + end + + ## + # @private New DocumentSnapshot from a # Google::Firestore::V1beta1::BatchGetDocumentsResponse object. - def self.from_batch_result result, context + def self.from_batch_result result, client ref = nil grpc = nil if result.result == :found grpc = result.found - ref = DocumentReference.from_path grpc.name, context + ref = DocumentReference.from_path grpc.name, client else - ref = DocumentReference.from_path result.missing, context + ref = DocumentReference.from_path result.missing, client end read_at = Convert.timestamp_to_time result.read_time new.tap do |s| s.grpc = grpc s.instance_variable_set :@ref, ref + s.instance_variable_set :@read_at, read_at + end + end + + ## + # @private New non-existant DocumentSnapshot from a + # DocumentReference object. + def self.missing doc_ref, read_at: nil + new.tap do |s| + s.grpc = nil + s.instance_variable_set :@ref, doc_ref s.instance_variable_set :@read_at, read_at end end end end