Module: ActiveModel::Datastore::ClassMethods
- Defined in:
- lib/active_model/datastore.rb
Overview
Methods defined here will be class methods when ‘include ActiveModel::Datastore’.
Instance Method Summary collapse
-
#all(options = {}) ⇒ Array<Model>, String
Queries entities from Cloud Datastore by named kind and using the provided options.
- #build_model(entity) ⇒ Object
-
#build_query(options = {}) ⇒ Query
Constructs a Google::Cloud::Datastore::Query.
- #exclude_from_index(entity, boolean) ⇒ Object
-
#find(*ids, parent: nil) ⇒ Model, ...
Find entity by id - this can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]).
-
#find_all_entities(ids_or_names, parent) ⇒ Object
Finds entities by keys using the provided array items.
-
#find_by(args) ⇒ Model?
Finds the first entity matching the specified condition.
-
#find_entities(*ids_or_names, parent: nil) ⇒ Array<Entity>
Retrieves the entities for the provided ids by key and by an optional parent.
-
#find_entity(id_or_name, parent = nil) ⇒ Entity?
Retrieves an entity by id or name and by an optional parent.
-
#from_entities(entities) ⇒ Object
Translates an Enumerator of Datastore::Entity objects to ActiveModel::Model objects.
-
#from_entity(entity) ⇒ Model
Translates between Datastore::Entity objects and ActiveModel::Model objects.
- #log_google_cloud_error ⇒ Object
-
#parent_key(parent_id) ⇒ Object
A default parent key for specifying an ancestor path and creating an entity group.
-
#query_options(query, options) ⇒ Object
**************** private ****************.
-
#query_property_filter(query, options) ⇒ Object
Adds property filters to the query if included in the options.
-
#query_sort(query, options) ⇒ Object
Adds sorting to the results by a property name if included in the options.
- #retry_on_exception(max_retry_count = 5) ⇒ Object
- #retry_on_exception?(max_retry_count = 5) ⇒ Boolean
Instance Method Details
#all(options = {}) ⇒ Array<Model>, String
Queries entities from Cloud Datastore by named kind and using the provided options. When a limit option is provided queries up to the limit and returns results with a cursor.
This method may make several API calls until all query results are retrieved. The run method returns a QueryResults object, which is a special case Array with additional values. QueryResults are returned in batches, and the batch size is determined by the Datastore API. Batch size is not guaranteed. It will be affected by the size of the data being returned, and by other forces such as how distributed and/or consistent the data in Datastore is. Calling all on the QueryResults retrieves all results by repeatedly loading #next until #next? returns false. The all method returns an enumerator which from_entities iterates on.
Be sure to use as narrow a search criteria as possible. Please use with caution.
or if options was provided:
284 285 286 287 288 289 290 291 292 293 |
# File 'lib/active_model/datastore.rb', line 284 def all( = {}) next_cursor = nil query = build_query() query_results = retry_on_exception { CloudDatastore.dataset.run query } if [:limit] next_cursor = query_results.cursor if query_results.size == [:limit] return from_entities(query_results.all), next_cursor end from_entities(query_results.all) end |
#build_model(entity) ⇒ Object
491 492 493 494 495 496 497 |
# File 'lib/active_model/datastore.rb', line 491 def build_model(entity) model_entity = new model_entity.id = entity.key.id unless entity.key.id.nil? model_entity.id = entity.key.name unless entity.key.name.nil? model_entity.parent_key_id = entity.key.parent.id if entity.key.parent.present? model_entity end |
#build_query(options = {}) ⇒ Query
Constructs a Google::Cloud::Datastore::Query.
395 396 397 398 |
# File 'lib/active_model/datastore.rb', line 395 def build_query( = {}) query = CloudDatastore.dataset.query name (query, ) end |
#exclude_from_index(entity, boolean) ⇒ Object
373 374 375 376 377 |
# File 'lib/active_model/datastore.rb', line 373 def exclude_from_index(entity, boolean) entity.properties.to_h.keys.each do |value| entity.exclude_from_indexes! value, boolean end end |
#find(*ids, parent: nil) ⇒ Model, ...
Find entity by id - this can either be a specific id (1), a list of ids (1, 5, 6), or an array of ids ([5, 6, 10]). The parent key is optional.
305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 |
# File 'lib/active_model/datastore.rb', line 305 def find(*ids, parent: nil) expects_array = ids.first.is_a?(Array) ids = ids.flatten.compact.uniq.map(&:to_i) case ids.size when 0 raise EntityError, "Couldn't find #{name} without an ID" when 1 entity = find_entity(ids.first, parent) model_entity = from_entity(entity) expects_array ? [model_entity].compact : model_entity else lookup_results = find_all_entities(ids, parent) from_entities(lookup_results.all) end end |
#find_all_entities(ids_or_names, parent) ⇒ Object
Finds entities by keys using the provided array items. Results provided by the dataset find_all is a Dataset::LookupResults object.
485 486 487 488 489 |
# File 'lib/active_model/datastore.rb', line 485 def find_all_entities(ids_or_names, parent) keys = ids_or_names.map { |id| CloudDatastore.dataset.key name, id } keys.map { |key| key.parent = parent } if parent.present? retry_on_exception { CloudDatastore.dataset.find_all keys } end |
#find_by(args) ⇒ Model?
Finds the first entity matching the specified condition.
334 335 336 337 338 339 340 341 |
# File 'lib/active_model/datastore.rb', line 334 def find_by(args) query = CloudDatastore.dataset.query name query.ancestor(args[:ancestor]) if args[:ancestor] query.limit(1) query.where(args.keys[0].to_s, '=', args.values[0]) query_results = retry_on_exception { CloudDatastore.dataset.run query } from_entity(query_results.first) end |
#find_entities(*ids_or_names, parent: nil) ⇒ Array<Entity>
Retrieves the entities for the provided ids by key and by an optional parent. The find_all method returns LookupResults, which is a special case Array with additional values. LookupResults are returned in batches, and the batch size is determined by the Datastore API. Batch size is not guaranteed. It will be affected by the size of the data being returned, and by other forces such as how distributed and/or consistent the data in Datastore is. Calling all on the LookupResults retrieves all results by repeatedly loading #next until #next? returns false. The all method returns an enumerator unless passed a block. We iterate on the enumerator to return the model entity objects.
246 247 248 249 250 |
# File 'lib/active_model/datastore.rb', line 246 def find_entities(*ids_or_names, parent: nil) ids_or_names = ids_or_names.flatten.compact.uniq lookup_results = find_all_entities(ids_or_names, parent) lookup_results.all.collect { |x| x } end |
#find_entity(id_or_name, parent = nil) ⇒ Entity?
Retrieves an entity by id or name and by an optional parent.
224 225 226 227 228 |
# File 'lib/active_model/datastore.rb', line 224 def find_entity(id_or_name, parent = nil) key = CloudDatastore.dataset.key name, id_or_name key.parent = parent if parent.present? retry_on_exception { CloudDatastore.dataset.find key } end |
#from_entities(entities) ⇒ Object
Translates an Enumerator of Datastore::Entity objects to ActiveModel::Model objects.
Results provided by the dataset find_all or ‘run query` will be a Dataset::LookupResults or Dataset::QueryResults object. Invoking all on those objects returns an enumerator.
351 352 353 354 |
# File 'lib/active_model/datastore.rb', line 351 def from_entities(entities) raise ArgumentError, 'Entities param must be an Enumerator' unless entities.is_a? Enumerator entities.map { |entity| from_entity(entity) } end |
#from_entity(entity) ⇒ Model
Translates between Datastore::Entity objects and ActiveModel::Model objects.
362 363 364 365 366 367 368 369 370 371 |
# File 'lib/active_model/datastore.rb', line 362 def from_entity(entity) return if entity.nil? model_entity = build_model(entity) model_entity.entity_property_values = entity.properties.to_h entity.properties.to_h.each do |name, value| model_entity.send "#{name}=", value if model_entity.respond_to? "#{name}=" end model_entity.reload! model_entity end |
#log_google_cloud_error ⇒ Object
432 433 434 435 436 437 |
# File 'lib/active_model/datastore.rb', line 432 def log_google_cloud_error yield rescue Google::Cloud::Error => e puts "\e[33m[#{e..inspect}]\e[0m" raise e end |
#parent_key(parent_id) ⇒ Object
A default parent key for specifying an ancestor path and creating an entity group.
212 213 214 |
# File 'lib/active_model/datastore.rb', line 212 def parent_key(parent_id) CloudDatastore.dataset.key('Parent' + name, parent_id.to_i) end |
#query_options(query, options) ⇒ Object
**************** private ****************
441 442 443 444 445 446 447 448 |
# File 'lib/active_model/datastore.rb', line 441 def (query, ) query.ancestor([:ancestor]) if [:ancestor] query.cursor([:cursor]) if [:cursor] query.limit([:limit]) if [:limit] query_sort(query, ) query.select([:select]) if [:select] query_property_filter(query, ) end |
#query_property_filter(query, options) ⇒ Object
Adds property filters to the query if included in the options. Accepts individual or nested Arrays:
[['superseded', '=', false], ['email', '=', 'something']]
464 465 466 467 468 469 470 471 472 473 474 475 476 |
# File 'lib/active_model/datastore.rb', line 464 def query_property_filter(query, ) if [:where] opts = [:where] if opts[0].is_a?(Array) opts.each do |opt| query.where(opt[0], opt[1], opt[2]) unless opt.nil? end else query.where(opts[0], opts[1], opts[2]) end end query end |
#query_sort(query, options) ⇒ Object
Adds sorting to the results by a property name if included in the options.
453 454 455 456 457 |
# File 'lib/active_model/datastore.rb', line 453 def query_sort(query, ) query.order([:order]) if [:order] query.order([:desc_order], :desc) if [:desc_order] query end |
#retry_on_exception(max_retry_count = 5) ⇒ Object
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 |
# File 'lib/active_model/datastore.rb', line 416 def retry_on_exception(max_retry_count = 5) retries = 0 sleep_time = 0.25 begin yield rescue => e raise e if retries >= max_retry_count puts "\e[33mRescued exception #{e..inspect}, retrying in #{sleep_time}\e[0m" # 0.25, 0.5, 1, 2, and 4 second between retries. sleep sleep_time retries += 1 sleep_time *= 2 retry end end |
#retry_on_exception?(max_retry_count = 5) ⇒ Boolean
400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 |
# File 'lib/active_model/datastore.rb', line 400 def retry_on_exception?(max_retry_count = 5) retries = 0 sleep_time = 0.25 begin yield rescue => e return false if retries >= max_retry_count puts "\e[33mRescued exception #{e..inspect}, retrying in #{sleep_time}\e[0m" # 0.25, 0.5, 1, 2, and 4 second between retries. sleep sleep_time retries += 1 sleep_time *= 2 retry end end |