Class: Parse::Installation
- Defined in:
- lib/parse/model/classes/installation.rb,
lib/parse/stack/generators/templates/model_installation.rb
Overview
This class represents the data and columns contained in the standard Parse
_Installation collection. This class is also responsible for managing the
device tokens for mobile devices in order to use push notifications. All queries done
to send pushes using Parse::Push are performed against the Installation collection.
An installation object represents an instance of your app being installed
on a device. These objects are used to store subscription data for
installations which have subscribed to one or more push notification channels.
The default schema for Installation is as follows:
class Parse::Installation < Parse::Object # See Parse::Object for inherited properties...
property :gcm_sender_id, field: :GCMSenderId
property :app_identifier
property :app_name
property :app_version
property :app_build_number
property :badge, :integer
property :channels, :array
property :device_token
property :device_token_last_modified, :integer
property :device_type, enum: [:ios, :android, :osx, :tvos, :watchos, :web, :expo, :win, :other, :unknown, :unsupported]
property :installation_id
property :locale_identifier
property :parse_version
property :push_type
property :time_zone, :timezone
has_one :session, ->{ where(installation_id: i.installation_id) }, scope_only: true
end
Class-Level Permissions on _Installation
_Installation is special-cased inside Parse Server. Some operations are
hardcoded at the REST layer and CANNOT be relaxed via CLP — calling
Object.set_clp for them has no effect on the server's actual
behavior, regardless of what you pass. Other operations work the way
CLP normally does. The matrix:
| Operation | Behavior |
|---|---|
find |
Master key only. Hardcoded. set_clp :find, ... is effectively ignored by the server. |
delete |
Master key only. Hardcoded. set_clp :delete, ... is effectively ignored by the server. |
create |
Open to anonymous clients (the X-Parse-Installation-Id header is the credential). Locking via CLP breaks first-launch device registration. |
update |
Open to clients whose installationId matches the record; else master key. Locking via CLP breaks silent device-token refresh and channel subscribe/unsubscribe before login. |
get |
CLP applies normally. Safe to tighten — SDKs don't usually GET their own installation from the server. |
count |
CLP applies normally. Safe to tighten to master-only (the push flow doesn't need it). |
addField |
CLP applies normally. Safe to tighten to master-only as a hardening default. |
What you can safely do with set_clp on _Installation
set_clp :get, requires_authentication: true(or{}for master-only)set_clp :count(master-only)set_clp :addField(master-only)- Object.protect_fields to hide
device_token,gcm_sender_id,push_type, etc. from non-master reads — these are write-only from the client's perspective in normal SDK flows.
What you should NOT do with set_clp on _Installation
set_clp :create, requires_authentication: true— breaks device registration for users who haven't logged in yet.set_clp :update, requires_authentication: true— breaks background device-token refresh and pre-login channel subscribe/unsubscribe.- Pointer-based
set_read_user_fields/set_write_user_fields— an installation has no stable owning user (a device can outlive a user session and change users), so user-pointer ACLing is unreliable here. set_clp :find, public: true(or any other:findconfig) — has no effect; the server enforces master-only at the REST layer.
If your app actually does require login before any installation write,
put that policy in a beforeSave('_Installation') Cloud Code trigger
rather than in CLP — the trigger fires under master-key context and can
inspect request.user directly without breaking the SDK's anonymous
registration handshake.
Constant Summary
Constants inherited from Object
Object::BUILTIN_PARSE_CLASS_NAMES, Object::IDENTIFICATION_FIELDS, Object::VALID_ACL_POLICIES
Constants included from Core::Schema
Core::Schema::DEFAULT_PUBLIC_CLP, Core::Schema::SCHEMA_READONLY_CLASSES
Constants included from Core::Describe
Core::Describe::ALL_SECTIONS, Core::Describe::CORE_FIELD_KEYS, Core::Describe::LOCAL_SECTIONS, Core::Describe::NETWORK_SECTIONS
Constants included from Core::Indexing
Core::Indexing::MAX_INDEXES_PER_COLLECTION, Core::Indexing::PARSE_MANAGED_ARRAY_FIELDS, Core::Indexing::SENSITIVE_FIELDS
Constants included from Core::SearchIndexing
Core::SearchIndexing::ALLOWED_INDEX_TYPES, Core::SearchIndexing::INDEX_NAME_PATTERN
Constants included from Core::Fetching
Core::Fetching::NON_SERIALIZABLE_IVARS
Constants included from Core::EmbedManaged
Core::EmbedManaged::WRITER_KEY
Constants included from Core::ParseReference
Core::ParseReference::OBJECT_ID_LENGTH, Core::ParseReference::SEPARATOR
Constants included from Core::FieldGuards
Core::FieldGuards::GUARD_MODES
Constants included from Properties
Properties::BASE, Properties::BASE_FIELD_MAP, Properties::BASE_KEYS, Properties::CORE_FIELDS, Properties::DELETE_OP, Properties::PROTECTED_INITIALIZE_KEYS, Properties::PROTECTED_MASS_ASSIGNMENT_KEYS, Properties::TYPES
Constants inherited from Pointer
Pointer::ATTRIBUTES, Pointer::OBJECT_ID_FORMAT
Constants inherited from Model
Model::CLASS_AUDIENCE, Model::CLASS_INSTALLATION, Model::CLASS_JOB_SCHEDULE, Model::CLASS_JOB_STATUS, Model::CLASS_PRODUCT, Model::CLASS_PUSH_STATUS, Model::CLASS_ROLE, Model::CLASS_SCHEMA, Model::CLASS_SESSION, Model::CLASS_USER, Model::ID, Model::KEY_CLASS_NAME, Model::KEY_CREATED_AT, Model::KEY_OBJECT_ID, Model::KEY_UPDATED_AT, Model::OBJECT_ID, Model::TYPE_ACL, Model::TYPE_BYTES, Model::TYPE_DATE, Model::TYPE_FIELD, Model::TYPE_FILE, Model::TYPE_GEOPOINT, Model::TYPE_NUMBER, Model::TYPE_OBJECT, Model::TYPE_POINTER, Model::TYPE_POLYGON, Model::TYPE_RELATION
Instance Attribute Summary collapse
-
#app_build_number ⇒ String
The build number of the client application to which this installation belongs.
-
#app_identifier ⇒ String
A unique identifier for this installation’s client application.
-
#app_name ⇒ String
The display name of the client application to which this installation belongs.
-
#app_version ⇒ String
The version string of the client application to which this installation belongs.
-
#badge ⇒ Integer
A number field representing the last known application badge for iOS installations.
-
#channels ⇒ Array
An array of the channels to which a device is currently subscribed.
-
#device_token ⇒ String
The Apple or Google generated token used to deliver messages to the APNs or GCM push networks respectively.
-
#device_token_last_modified ⇒ Integer
Number of seconds since token modified.
-
#device_type ⇒ String
The type of device: "ios", "android", "osx", "tvos", "watchos", "web", "expo", "win", "other", "unknown", or "unsupported".
-
#gcm_sender_id ⇒ String
This field only has meaning for Android installations that use the GCM push type.
-
#installation_id ⇒ String
Universally Unique Identifier (UUID) for the device used by Parse.
-
#locale_identifier ⇒ String
The locale for this device.
-
#parse_version ⇒ String
The version of the Parse SDK which this installation uses.
-
#push_type ⇒ String
This field is reserved for directing Parse to the push delivery network to be used.
-
#session ⇒ Parse::Session
Returns the corresponding Session associated with this installation, if any exists.
-
#time_zone ⇒ Parse::TimeZone
The current time zone where the target device is located.
-
#user ⇒ Parse::User
The User associated with this installation.
Attributes inherited from Object
#acl, #created_at, #id, #updated_at
Attributes inherited from Pointer
Class Method Summary collapse
-
.all_channels ⇒ Array<String>
List all unique channel names across all installations.
-
.by_device_type(type) ⇒ Parse::Query
Query scope for a specific device type.
-
.cleanup_stale_tokens!(days: 90) ⇒ Integer
Delete all installations with stale tokens.
-
.protect_fields(pattern, fields) ⇒ Object
protect_fieldson_Installationis a documented-legitimate use (e.g. hidingdevice_token/gcm_sender_id/push_typefrom non-master reads), so we deliberately do NOT fire the find/delete-are-hardcoded advisory here. -
.reset_all_badges(type = :ios) ⇒ Integer
Reset badge count for all installations of a specific device type.
-
.reset_badges_for_channel(channel) ⇒ Integer
Reset badge count for all installations in a channel.
-
.set_class_access(**ops_to_access) ⇒ Object
Same advisory for the bulk-config DSL.
-
.set_clp(operation, **opts) ⇒ Object
Override Object.set_clp on
_Installationso that any attempt to change CLP from the SDK emits a one-time advisory. -
.set_read_user_fields(*fields) ⇒ Object
Pointer-permission helpers on
_Installationare a mistake in practice (devices have no stable owning user); warn loudly. - .set_write_user_fields(*fields) ⇒ Object
-
.stale_count(days: 90) ⇒ Integer
Count installations with stale tokens.
-
.stale_tokens(days: 90) ⇒ Parse::Query
Query for installations with stale (old) device tokens.
-
.subscribers(channel) ⇒ Parse::Query
Get a query for installations subscribed to a specific channel.
-
.subscribers_count(channel) ⇒ Integer
Count the number of installations subscribed to a specific channel.
Instance Method Summary collapse
-
#days_since_update ⇒ Integer?
Get the number of days since this installation was last updated.
-
#increment_badge!(amount = 1) ⇒ Boolean
Increment the badge count and save.
-
#reset_badge! ⇒ Boolean
Reset the badge count to 0 and save.
-
#stale?(days: 90) ⇒ Boolean
Check if this installation's token is considered stale.
-
#subscribe(*channel_names) ⇒ Boolean
Subscribe this installation to one or more channels.
-
#subscribed_to?(channel) ⇒ Boolean
Check if this installation is subscribed to a specific channel.
-
#unsubscribe(*channel_names) ⇒ Boolean
Unsubscribe this installation from one or more channels.
Methods inherited from Object
#[], #[]=, #__type, #_resolve_acl_owner_id, #_resolve_default_acl, #acl_changed?, acl_owner_field, acl_policy, acl_policy_setting, #acl_was, #acl_will_change!, #after_create, #after_destroy, #after_save, #after_update, #after_validation, #apply_defaults!, #around_create, #around_destroy, #around_save, #around_update, #around_validation, #as_json, #autofetch_disabled?, #before_create, #before_destroy, #before_save, #before_update, #before_validation, build, #changed, #changed?, class_permissions, #clear_attribute_change!, #clear_changes!, #clear_partial_fetch_state!, default_acls, describe_access, #disable_autofetch!, #enable_autofetch!, #existed?, fetch_clp, #fetched?, #fetched_keys, #fetched_keys=, #field_was_fetched?, #filter_for_user, filter_results_for_user, #fully_fetched?, #has?, #has_selective_keys?, #initialize, #keys, master_only_class!, #nested_fetched_keys, #nested_fetched_keys=, #nested_keys_for, #new?, #parse_class, #partially_fetched?, #persisted?, pointer, #pretty, private_acl!, #reload!, roles_for_user, #rollback!, #run_after_create_callbacks, #run_after_delete_callbacks, #run_after_save_callbacks, #schema, #search_highlights, #search_score, set_default_acl, set_default_clp, #twin, unlistable_class!, update_clp!, #updates, #valid?, #validate!, #vector_score, wait_for, watch, webhook, webhook_function
Methods included from Core::Querying
#all, #all_as, #count, #count_distinct, #cursor, #distinct, #each, #find, #find_cached, #first, #first_as, #last_updated, #latest, #literal_where, #newest, #oldest, #query, #scope
Methods included from Core::Schema
#_default_class_level_permissions_for_upgrade, #auto_upgrade!, #create_schema, #fetch_schema, #reset_clp!, #schema, #update_schema
Methods included from Core::Describe
Methods included from Core::Indexing
#apply_indexes!, #indexes_plan, #mongo_geo_index, #mongo_index, #mongo_index_declarations, #mongo_relation_index
Methods included from Core::SearchIndexing
#apply_search_indexes!, #mongo_search_index, #mongo_search_index_declarations, #search_indexes_plan
Methods included from Core::VectorSearchable
Methods included from Agent::MetadataDSL
#agent_description, #agent_methods, #property_descriptions, #property_enum_descriptions
Methods included from Core::Actions
#_deleted?, #change_requests, #changes_applied!, #changes_payload, #create, #destroy, #destroy_request, #op_add!, #op_add_relation!, #op_add_unique!, #op_destroy!, #op_increment!, #op_remove!, #op_remove_relation!, #operate_field!, #prepare_save!, #relation_change_operations, #save, #save!, #set_attributes!, #update, #update!, #update_relations, #uri_path
Methods included from Core::Fetching
#autofetch!, #fetch, #fetch!, #fetch_cache!, #fetch_json, #fetch_object, #prepare_for_dirty_tracking!
Methods included from Associations::HasMany
has_many, #relation_changes?, #relation_updates, #relations
Methods included from Associations::BelongsTo
Methods included from Associations::HasOne
Methods included from Core::ParseReference
format, generate_object_id, parse
Methods included from Core::FieldGuards
Methods included from Properties
#apply_attributes!, #attribute_changes?, #attribute_updates, #attributes, #attributes=, #field_map, #fields, #format_operation, #format_value
Methods inherited from Pointer
#==, #[], #[]=, #__type, #attributes, #className, #fetch, #fetch_cache!, #fetch_json, #fetch_object, #fetched?, #hash, #initialize, #json_hash, #method_missing, #pointer, #pointer?, #present?, #respond_to_missing?, #search_highlights, #search_score, #sig, #vector_score
Methods inherited from Model
Methods included from Client::Connectable
Constructor Details
This class inherits a constructor from Parse::Object
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Parse::Pointer
Instance Attribute Details
#app_build_number ⇒ String
The build number of the client application to which this installation belongs.
177 |
# File 'lib/parse/model/classes/installation.rb', line 177 property :app_build_number |
#app_identifier ⇒ String
A unique identifier for this installation’s client application. In iOS, this is the Bundle Identifier.
162 |
# File 'lib/parse/model/classes/installation.rb', line 162 property :app_identifier |
#app_name ⇒ String
The display name of the client application to which this installation belongs.
167 |
# File 'lib/parse/model/classes/installation.rb', line 167 property :app_name |
#app_version ⇒ String
The version string of the client application to which this installation belongs.
172 |
# File 'lib/parse/model/classes/installation.rb', line 172 property :app_version |
#badge ⇒ Integer
A number field representing the last known application badge for iOS installations.
182 |
# File 'lib/parse/model/classes/installation.rb', line 182 property :badge, :integer |
#channels ⇒ Array
An array of the channels to which a device is currently subscribed. Note that channelUris (the Microsoft-generated push URIs for Windows devices) is not supported at this time.
189 |
# File 'lib/parse/model/classes/installation.rb', line 189 property :channels, :array |
#device_token ⇒ String
The Apple or Google generated token used to deliver messages to the APNs or GCM push networks respectively.
195 |
# File 'lib/parse/model/classes/installation.rb', line 195 property :device_token |
#device_token_last_modified ⇒ Integer
Returns number of seconds since token modified.
199 |
# File 'lib/parse/model/classes/installation.rb', line 199 property :device_token_last_modified, :integer |
#device_type ⇒ String
The type of device: "ios", "android", "osx", "tvos", "watchos", "web", "expo", "win", "other", "unknown", or "unsupported". This property is implemented as a Parse::Stack enumeration.
206 |
# File 'lib/parse/model/classes/installation.rb', line 206 property :device_type, enum: [:ios, :android, :osx, :tvos, :watchos, :web, :expo, :win, :other, :unknown, :unsupported] |
#gcm_sender_id ⇒ String
This field only has meaning for Android installations that use the GCM push type. It is reserved for directing Parse to send pushes to this installation with an alternate GCM sender ID. This field should generally not be set unless you are uploading installation data from another push provider. If you set this field, then you must set the GCM API key corresponding to this GCM sender ID in your Parse application’s push settings.
157 |
# File 'lib/parse/model/classes/installation.rb', line 157 property :gcm_sender_id, field: :GCMSenderId |
#installation_id ⇒ String
Universally Unique Identifier (UUID) for the device used by Parse. It must be unique across all of an app’s installations. (readonly).
212 |
# File 'lib/parse/model/classes/installation.rb', line 212 property :installation_id |
#locale_identifier ⇒ String
The locale for this device.
217 |
# File 'lib/parse/model/classes/installation.rb', line 217 property :locale_identifier |
#parse_version ⇒ String
The version of the Parse SDK which this installation uses.
222 |
# File 'lib/parse/model/classes/installation.rb', line 222 property :parse_version |
#push_type ⇒ String
This field is reserved for directing Parse to the push delivery network to be used. If the device is registered to receive pushes via GCM, this field will be marked “gcm”. If this device is not using GCM, and is using Parse’s push notification service, it will be blank (readonly).
230 |
# File 'lib/parse/model/classes/installation.rb', line 230 property :push_type |
#session ⇒ Parse::Session
Returns the corresponding Session associated with this installation, if any exists. This is implemented as a has_one association to the Session class using the #installation_id.
243 |
# File 'lib/parse/model/classes/installation.rb', line 243 has_one :session, -> { where(installation_id: i.installation_id) }, scope_only: true |
#time_zone ⇒ Parse::TimeZone
The current time zone where the target device is located. This should be an IANA time zone identifier or a TimeZone instance.
236 |
# File 'lib/parse/model/classes/installation.rb', line 236 property :time_zone, :timezone |
#user ⇒ Parse::User
The User associated with this installation. Parse Server populates this pointer when the installation is created or updated by an authenticated client (the session-token holder on the request). It is useful for targeted push delivery — finding all installations belonging to a given user.
Caveat — do not use for ACL or CLP scoping. Devices outlive
sessions and can change users (account switch, sign-out, shared
device), so the user pointer on _Installation is not a
reliable owner identity. See the "What you should NOT do with
set_clp" notes above for the broader context.
258 |
# File 'lib/parse/model/classes/installation.rb', line 258 belongs_to :user |
Class Method Details
.all_channels ⇒ Array<String>
List all unique channel names across all installations.
270 271 272 |
# File 'lib/parse/model/classes/installation.rb', line 270 def all_channels distinct(:channels) end |
.by_device_type(type) ⇒ Parse::Query
Query scope for a specific device type.
308 309 310 |
# File 'lib/parse/model/classes/installation.rb', line 308 def by_device_type(type) query(device_type: type.to_s) end |
.cleanup_stale_tokens!(days: 90) ⇒ Integer
Delete all installations with stale tokens. Use with caution - this permanently removes installation records.
380 381 382 383 384 |
# File 'lib/parse/model/classes/installation.rb', line 380 def cleanup_stale_tokens!(days: 90) installations = stale_tokens(days: days).all installations.each(&:destroy) installations.count end |
.protect_fields(pattern, fields) ⇒ Object
protect_fields on _Installation is a documented-legitimate use
(e.g. hiding device_token / gcm_sender_id / push_type from
non-master reads), so we deliberately do NOT fire the
find/delete-are-hardcoded advisory here. The advisory exists to
nudge callers away from CLP changes that the server ignores;
protectedFields is one of the four operations on _Installation
that CLP actually controls.
114 115 116 |
# File 'lib/parse/model/classes/installation.rb', line 114 def protect_fields(pattern, fields) super end |
.reset_all_badges(type = :ios) ⇒ Integer
Reset badge count for all installations of a specific device type.
336 337 338 339 340 341 342 343 |
# File 'lib/parse/model/classes/installation.rb', line 336 def reset_all_badges(type = :ios) installations = by_device_type(type).where(:badge.gt => 0).all installations.each do |installation| installation.badge = 0 installation.save end installations.count end |
.reset_badges_for_channel(channel) ⇒ Integer
Reset badge count for all installations in a channel.
321 322 323 324 325 326 327 328 |
# File 'lib/parse/model/classes/installation.rb', line 321 def reset_badges_for_channel(channel) installations = subscribers(channel).where(:badge.gt => 0).all installations.each do |installation| installation.badge = 0 installation.save end installations.count end |
.set_class_access(**ops_to_access) ⇒ Object
Same advisory for the bulk-config DSL.
102 103 104 105 |
# File 'lib/parse/model/classes/installation.rb', line 102 def set_class_access(**ops_to_access) _warn_about_installation_clp!(:set_class_access, ops_to_access.keys) super end |
.set_clp(operation, **opts) ⇒ Object
Override Object.set_clp on _Installation so that any
attempt to change CLP from the SDK emits a one-time advisory.
Parse Server hardcodes find and delete on _Installation to
master-key-only at the REST layer, and gates create/update
on the X-Parse-Installation-Id header rather than CLP — so
most CLP changes here either do nothing or break the SDK's
device-registration flow. Behavior is otherwise unchanged.
96 97 98 99 |
# File 'lib/parse/model/classes/installation.rb', line 96 def set_clp(operation, **opts) _warn_about_installation_clp!(:set_clp, operation) super end |
.set_read_user_fields(*fields) ⇒ Object
Pointer-permission helpers on _Installation are a mistake in
practice (devices have no stable owning user); warn loudly.
120 121 122 123 |
# File 'lib/parse/model/classes/installation.rb', line 120 def set_read_user_fields(*fields) _warn_about_installation_clp!(:set_read_user_fields, fields) super end |
.set_write_user_fields(*fields) ⇒ Object
125 126 127 128 |
# File 'lib/parse/model/classes/installation.rb', line 125 def set_write_user_fields(*fields) _warn_about_installation_clp!(:set_write_user_fields, fields) super end |
.stale_count(days: 90) ⇒ Integer
Count installations with stale tokens.
369 370 371 |
# File 'lib/parse/model/classes/installation.rb', line 369 def stale_count(days: 90) stale_tokens(days: days).count end |
.stale_tokens(days: 90) ⇒ Parse::Query
Query for installations with stale (old) device tokens. Useful for cleaning up installations that are likely no longer active.
359 360 361 362 |
# File 'lib/parse/model/classes/installation.rb', line 359 def stale_tokens(days: 90) cutoff = Time.now - (days * 24 * 60 * 60) query(:updated_at.lt => cutoff) end |
.subscribers(channel) ⇒ Parse::Query
Get a query for installations subscribed to a specific channel.
292 293 294 |
# File 'lib/parse/model/classes/installation.rb', line 292 def subscribers(channel) query(:channels.in => [channel]) end |
.subscribers_count(channel) ⇒ Integer
Count the number of installations subscribed to a specific channel.
280 281 282 |
# File 'lib/parse/model/classes/installation.rb', line 280 def subscribers_count(channel) query(:channels.in => [channel]).count end |
Instance Method Details
#days_since_update ⇒ Integer?
Get the number of days since this installation was last updated.
473 474 475 476 |
# File 'lib/parse/model/classes/installation.rb', line 473 def days_since_update return nil if updated_at.nil? ((Time.now - updated_at.to_time) / (24 * 60 * 60)).to_i end |
#increment_badge!(amount = 1) ⇒ Boolean
Increment the badge count and save.
447 448 449 450 |
# File 'lib/parse/model/classes/installation.rb', line 447 def increment_badge!(amount = 1) self.badge = (badge || 0) + amount save end |
#reset_badge! ⇒ Boolean
Reset the badge count to 0 and save.
436 437 438 439 |
# File 'lib/parse/model/classes/installation.rb', line 436 def reset_badge! self.badge = 0 save end |
#stale?(days: 90) ⇒ Boolean
Check if this installation's token is considered stale.
463 464 465 466 467 |
# File 'lib/parse/model/classes/installation.rb', line 463 def stale?(days: 90) return false if updated_at.nil? cutoff = Time.now - (days * 24 * 60 * 60) updated_at < cutoff end |
#subscribe(*channel_names) ⇒ Boolean
Subscribe this installation to one or more channels. The changes are automatically saved to the server.
398 399 400 401 402 |
# File 'lib/parse/model/classes/installation.rb', line 398 def subscribe(*channel_names) self.channels ||= [] self.channels = (self.channels + channel_names.flatten.map(&:to_s)).uniq save end |
#subscribed_to?(channel) ⇒ Boolean
Check if this installation is subscribed to a specific channel.
424 425 426 |
# File 'lib/parse/model/classes/installation.rb', line 424 def subscribed_to?(channel) channels&.include?(channel.to_s) || false end |
#unsubscribe(*channel_names) ⇒ Boolean
Unsubscribe this installation from one or more channels. The changes are automatically saved to the server.
411 412 413 414 415 |
# File 'lib/parse/model/classes/installation.rb', line 411 def unsubscribe(*channel_names) return true unless channels.present? self.channels = channels - channel_names.flatten.map(&:to_s) save end |