parse-stack 1.5.3 → 1.6.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/parse-ruby-sdk.png +0 -0
  3. data/Changes.md +25 -1
  4. data/Gemfile.lock +4 -4
  5. data/README.md +37 -31
  6. data/bin/console +3 -0
  7. data/lib/parse/api/all.rb +2 -1
  8. data/lib/parse/api/apps.rb +12 -0
  9. data/lib/parse/api/config.rb +5 -1
  10. data/lib/parse/api/files.rb +1 -0
  11. data/lib/parse/api/hooks.rb +1 -0
  12. data/lib/parse/api/objects.rb +4 -1
  13. data/lib/parse/api/push.rb +1 -0
  14. data/lib/parse/api/{schemas.rb → schema.rb} +7 -0
  15. data/lib/parse/api/server.rb +44 -0
  16. data/lib/parse/api/sessions.rb +1 -0
  17. data/lib/parse/api/users.rb +4 -1
  18. data/lib/parse/client.rb +109 -73
  19. data/lib/parse/client/authentication.rb +2 -1
  20. data/lib/parse/client/batch.rb +9 -1
  21. data/lib/parse/client/body_builder.rb +16 -1
  22. data/lib/parse/client/caching.rb +15 -13
  23. data/lib/parse/client/protocol.rb +27 -15
  24. data/lib/parse/client/response.rb +26 -8
  25. data/lib/parse/model/acl.rb +1 -1
  26. data/lib/parse/model/associations/belongs_to.rb +18 -19
  27. data/lib/parse/model/associations/collection_proxy.rb +6 -0
  28. data/lib/parse/model/associations/has_many.rb +5 -6
  29. data/lib/parse/model/bytes.rb +4 -1
  30. data/lib/parse/model/classes/user.rb +46 -44
  31. data/lib/parse/model/core/actions.rb +508 -460
  32. data/lib/parse/model/core/builder.rb +75 -0
  33. data/lib/parse/model/core/errors.rb +9 -0
  34. data/lib/parse/model/core/fetching.rb +42 -38
  35. data/lib/parse/model/core/properties.rb +46 -27
  36. data/lib/parse/model/core/querying.rb +231 -228
  37. data/lib/parse/model/core/schema.rb +76 -74
  38. data/lib/parse/model/date.rb +10 -2
  39. data/lib/parse/model/file.rb +16 -2
  40. data/lib/parse/model/geopoint.rb +9 -2
  41. data/lib/parse/model/model.rb +38 -7
  42. data/lib/parse/model/object.rb +60 -19
  43. data/lib/parse/model/pointer.rb +22 -1
  44. data/lib/parse/model/push.rb +6 -2
  45. data/lib/parse/query.rb +57 -11
  46. data/lib/parse/query/constraint.rb +5 -2
  47. data/lib/parse/query/constraints.rb +588 -589
  48. data/lib/parse/query/ordering.rb +2 -2
  49. data/lib/parse/stack.rb +1 -0
  50. data/lib/parse/stack/version.rb +1 -1
  51. data/lib/parse/webhooks.rb +30 -29
  52. data/lib/parse/webhooks/payload.rb +181 -168
  53. data/lib/parse/webhooks/registration.rb +1 -1
  54. data/parse-stack.gemspec +9 -9
  55. metadata +9 -12
@@ -4,90 +4,92 @@
4
4
  require_relative "properties"
5
5
 
6
6
  module Parse
7
- # Defines the Schema methods applied to a Parse::Object.
8
- module Schema
7
+ module Core
8
+ # Defines the Schema methods applied to a Parse::Object.
9
+ module Schema
9
10
 
10
- # Generate a Parse-server compatible schema hash for performing changes to the
11
- # structure of the remote collection.
12
- # @return [Hash] the schema for this Parse::Object subclass.
13
- def schema
14
- sch = { className: parse_class, fields: {} }
15
- #first go through all the attributes
16
- attributes.each do |k,v|
17
- # don't include the base Parse fields
18
- next if Parse::Properties::BASE.include?(k)
19
- next if v.nil?
20
- result = { type: v.to_s.camelize }
21
- # if it is a basic column property, find the right datatype
22
- case v
23
- when :integer, :float
24
- result[:type] = "Number"
25
- when :geopoint, :geo_point
26
- result[:type] = "GeoPoint"
27
- when :pointer
28
- result = { type: "Pointer", targetClass: references[k] }
29
- when :acl
30
- result[:type] = "ACL"
31
- else
32
- result[:type] = v.to_s.camelize
33
- end
11
+ # Generate a Parse-server compatible schema hash for performing changes to the
12
+ # structure of the remote collection.
13
+ # @return [Hash] the schema for this Parse::Object subclass.
14
+ def schema
15
+ sch = { className: parse_class, fields: {} }
16
+ #first go through all the attributes
17
+ attributes.each do |k,v|
18
+ # don't include the base Parse fields
19
+ next if Parse::Properties::BASE.include?(k)
20
+ next if v.nil?
21
+ result = { type: v.to_s.camelize }
22
+ # if it is a basic column property, find the right datatype
23
+ case v
24
+ when :integer, :float
25
+ result[:type] = Parse::Model::TYPE_NUMBER
26
+ when :geopoint, :geo_point
27
+ result[:type] = Parse::Model::TYPE_GEOPOINT
28
+ when :pointer
29
+ result = { type: Parse::Model::TYPE_POINTER, targetClass: references[k] }
30
+ when :acl
31
+ result[:type] = Parse::Model::ACL
32
+ else
33
+ result[:type] = v.to_s.camelize
34
+ end
34
35
 
35
- sch[:fields][k] = result
36
+ sch[:fields][k] = result
36
37
 
38
+ end
39
+ #then add all the relational column attributes
40
+ relations.each do |k,v|
41
+ sch[:fields][k] = { type: Parse::Model::TYPE_RELATION, targetClass: relations[k] }
42
+ end
43
+ sch
37
44
  end
38
- #then add all the relational column attributes
39
- relations.each do |k,v|
40
- sch[:fields][k] = { type: "Relation", targetClass: relations[k] }
41
- end
42
- sch
43
- end
44
45
 
45
- # Update the remote schema for this Parse collection.
46
- # @param schema_updates [Hash] the changes to be made to the schema.
47
- # @return [Parse::Response]
48
- def update_schema(schema_updates = nil)
49
- schema_updates ||= schema
50
- client.update_schema parse_class, schema_updates
51
- end
46
+ # Update the remote schema for this Parse collection.
47
+ # @param schema_updates [Hash] the changes to be made to the schema.
48
+ # @return [Parse::Response]
49
+ def update_schema(schema_updates = nil)
50
+ schema_updates ||= schema
51
+ client.update_schema parse_class, schema_updates
52
+ end
52
53
 
53
- # Create a new collection for this model with the schema defined by the local
54
- # model.
55
- # @return [Parse::Response]
56
- # @see Schema.schema
57
- def create_schema
58
- client.create_schema parse_class, schema
59
- end
54
+ # Create a new collection for this model with the schema defined by the local
55
+ # model.
56
+ # @return [Parse::Response]
57
+ # @see Schema.schema
58
+ def create_schema
59
+ client.create_schema parse_class, schema
60
+ end
60
61
 
61
- # Fetche the current schema for this collection from Parse server.
62
- # @return [Parse::Response]
63
- def fetch_schema
64
- client.schema parse_class
65
- end
62
+ # Fetche the current schema for this collection from Parse server.
63
+ # @return [Parse::Response]
64
+ def fetch_schema
65
+ client.schema parse_class
66
+ end
66
67
 
67
- # A class method for non-destructive auto upgrading a remote schema based
68
- # on the properties and relations you have defined in your local model. If
69
- # the collection doesn't exist, we create the schema. If the collection already
70
- # exists, the current schema is fetched, and only add the additional fields
71
- # that are missing.
72
- # @note No columns or fields are removed, this is a safe non-destructive upgrade.
73
- # @return [Parse::Response] if the remote schema was modified.
74
- # @return [Boolean] if no changes were made to the schema, it returns true.
75
- def auto_upgrade!
76
- response = fetch_schema
77
- if response.success?
78
- #let's figure out the diff fields
79
- remote_fields = response.result["fields"]
80
- current_schema = schema
81
- current_schema[:fields] = current_schema[:fields].reduce({}) do |h,(k,v)|
82
- #if the field does not exist in Parse, then add it to the update list
83
- h[k] = v if remote_fields[k.to_s].nil?
84
- h
68
+ # A class method for non-destructive auto upgrading a remote schema based
69
+ # on the properties and relations you have defined in your local model. If
70
+ # the collection doesn't exist, we create the schema. If the collection already
71
+ # exists, the current schema is fetched, and only add the additional fields
72
+ # that are missing.
73
+ # @note No columns or fields are removed, this is a safe non-destructive upgrade.
74
+ # @return [Parse::Response] if the remote schema was modified.
75
+ # @return [Boolean] if no changes were made to the schema, it returns true.
76
+ def auto_upgrade!
77
+ response = fetch_schema
78
+ if response.success?
79
+ #let's figure out the diff fields
80
+ remote_fields = response.result["fields"]
81
+ current_schema = schema
82
+ current_schema[:fields] = current_schema[:fields].reduce({}) do |h,(k,v)|
83
+ #if the field does not exist in Parse, then add it to the update list
84
+ h[k] = v if remote_fields[k.to_s].nil?
85
+ h
86
+ end
87
+ return true if current_schema[:fields].empty?
88
+ return update_schema( current_schema )
85
89
  end
86
- return true if current_schema[:fields].empty?
87
- return update_schema( current_schema )
90
+ create_schema
88
91
  end
89
- create_schema
90
- end
91
92
 
93
+ end
92
94
  end
93
95
  end
@@ -23,6 +23,7 @@ module Parse
23
23
  # the Parse ISO hash format for these fields instead, set
24
24
  # `Parse::Object.disable_serialized_string_date = true`.
25
25
  class Date < ::DateTime
26
+ # The default attributes in a Parse Date hash.
26
27
  ATTRIBUTES = { __type: :string, iso: :string }.freeze
27
28
  include ::ActiveModel::Model
28
29
  include ::ActiveModel::Serializers::JSON
@@ -43,10 +44,15 @@ module Parse
43
44
  to_time.utc.iso8601(3)
44
45
  end
45
46
 
47
+ # @return (see #iso)
48
+ def to_s(*args)
49
+ args.empty? ? iso : super(*args)
50
+ end
51
+
46
52
  end
47
53
  end
48
54
 
49
-
55
+ # Adds extensions to Time class to be compatible with {Parse::Date}.
50
56
  class Time
51
57
  # @return [Parse::Date] Converts object to Parse::Date
52
58
  def parse_date
@@ -54,7 +60,7 @@ class Time
54
60
  end
55
61
 
56
62
  end
57
-
63
+ # Adds extensions to DateTime class to be compatible with {Parse::Date}.
58
64
  class DateTime
59
65
  # @return [Parse::Date] Converts object to Parse::Date
60
66
  def parse_date
@@ -62,7 +68,9 @@ class DateTime
62
68
  end
63
69
  end
64
70
 
71
+ # Adds extensions to ActiveSupport class to be compatible with {Parse::Date}.
65
72
  module ActiveSupport
73
+ # Adds extensions to ActiveSupport::TimeWithZone class to be compatible with {Parse::Date}.
66
74
  class TimeWithZone
67
75
  # @return [Parse::Date] Converts object to Parse::Date
68
76
  def parse_date
@@ -26,13 +26,16 @@ module Parse
26
26
  # @note The default MIME type for all files is _image/jpeg_. This can be default
27
27
  # can be changed by setting a value to `Parse::File.default_mime_type`.
28
28
  class File < Model
29
+ # Regular expression that matches the old legacy Parse hosted file name
30
+ LEGACY_FILE_RX = /^tfss-[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}-/
31
+ # The default attributes in a Parse File hash.
29
32
  ATTRIBUTES = { __type: :string, name: :string, url: :string }.freeze
30
33
  # @return [String] the name of the file including extension (if any)
31
34
  attr_accessor :name
32
35
  # @return [String] the url resource of the file.
33
36
  attr_accessor :url
34
37
 
35
- # You may set the contents of the file.
38
+ # @return [Object] the contents of the file.
36
39
  attr_accessor :contents
37
40
 
38
41
  # @return [String] the mime-type of the file whe
@@ -42,12 +45,16 @@ module Parse
42
45
  # @return [Model::TYPE_FILE]
43
46
  def parse_class; self.class.parse_class; end;
44
47
  alias_method :__type, :parse_class
48
+ # @!visibility private
45
49
  FIELD_NAME = "name"
50
+ # @!visibility private
46
51
  FIELD_URL = "url"
47
52
  class << self
48
53
 
54
+ # @return [String] the default mime-type
49
55
  attr_accessor :default_mime_type
50
56
 
57
+ # @return [Boolean] whether to force all urls to be https.
51
58
  attr_accessor :force_ssl
52
59
 
53
60
  # @return [String] The default mime type for created instances. Default: _'image/jpeg'_
@@ -135,6 +142,7 @@ module Parse
135
142
  @url == u.url
136
143
  end
137
144
 
145
+ # Allows mass assignment from a Parse JSON hash.
138
146
  def attributes=(h)
139
147
  if h.is_a?(String)
140
148
  @url = h
@@ -172,6 +180,12 @@ module Parse
172
180
  saved?
173
181
  end
174
182
 
183
+ # @return [Boolean] true if this file is hosted by Parse's servers.
184
+ def parse_hosted_file?
185
+ return false if @url.blank?
186
+ ::File.basename(@url).starts_with?('tfss-') || @url.starts_with?('http://files.parsetfss.com')
187
+ end
188
+
175
189
  # @!visibility private
176
190
  def inspect
177
191
  "<Parse::File @name='#{@name}' @mime_type='#{@mime_type}' @contents=#{@contents.nil?} @url='#{@url}'>"
@@ -187,7 +201,7 @@ module Parse
187
201
 
188
202
  end
189
203
 
190
-
204
+ # Adds extensions to Hash class.
191
205
  class Hash
192
206
  # Determines if the hash contains Parse File json metadata fields. This is determined whether
193
207
  # the key `__type` exists and is of type `__File` and whether the `name` field matches the File.basename
@@ -23,18 +23,25 @@ module Parse
23
23
  # place.save
24
24
  #
25
25
  class GeoPoint < Model
26
+ # The default attributes in a Parse GeoPoint hash.
26
27
  ATTRIBUTES = { __type: :string, latitude: :float, longitude: :float }.freeze
27
28
 
28
29
  # @return [Float] latitude value between -90.0 and 90.0
29
30
  attr_accessor :latitude
30
31
  # @return [Float] longitude value between -180.0 and 180.0
31
32
  attr_accessor :longitude
32
- FIELD_LAT = "latitude"
33
- FIELD_LNG = "longitude"
33
+ # The key field for latitude
34
+ FIELD_LAT = "latitude".freeze
35
+ # The key field for longitude
36
+ FIELD_LNG = "longitude".freeze
34
37
 
38
+ # The minimum latitude value.
35
39
  LAT_MIN = -90.0
40
+ # The maximum latitude value.
36
41
  LAT_MAX = 90.0
42
+ # The minimum longitude value.
37
43
  LNG_MIN = -180.0
44
+ # The maximum longitude value.
38
45
  LNG_MAX = 180.0
39
46
 
40
47
  alias_method :lat, :latitude
@@ -30,24 +30,50 @@ module Parse
30
30
  extend ::ActiveModel::Callbacks # callback support on save, update, delete, etc.
31
31
  extend ::ActiveModel::Naming # provides the methods for getting class names from Model classes
32
32
 
33
- ID = "id".freeze
33
+ # The name of the field in a hash that contains information about the type
34
+ # of data the hash represents.
35
+ TYPE_FIELD = '__type'.freeze
36
+
37
+ # The objectId field in Parse Objects.
34
38
  OBJECT_ID = 'objectId'.freeze
39
+ # @see OBJECT_ID
40
+ ID = "id".freeze
41
+
42
+ # The key field for getting class information.
35
43
  KEY_CLASS_NAME = 'className'.freeze
44
+ # @deprecated Use OBJECT_ID instead.
36
45
  KEY_OBJECT_ID = 'objectId'.freeze
46
+ # The key field for getting the created at date of an object hash.
37
47
  KEY_CREATED_AT = 'createdAt'
48
+ # The key field for getting the updated at date of an object hash.
38
49
  KEY_UPDATED_AT = 'updatedAt'
50
+ # The collection for Users in Parse. Used by Parse::User.
39
51
  CLASS_USER = '_User'
52
+ # The collection for Installations in Parse. Used by Parse::Installation.
40
53
  CLASS_INSTALLATION = '_Installation'
54
+ # The collection for revocable Sessions in Parse. Used by Parse::Session.
41
55
  CLASS_SESSION = '_Session'
56
+ # The collection for revocable Roles in Parse. Used by Parse::Role.
42
57
  CLASS_ROLE = '_Role'
58
+ # The type label for hashes containing file data. Used by Parse::File.
43
59
  TYPE_FILE = 'File'
60
+ # The type label for hashes containing geopoints. Used by Parse::GeoPoint.
44
61
  TYPE_GEOPOINT = 'GeoPoint'
62
+ # The type label for hashes containing a Parse object. Used by Parse::Object and subclasses.
45
63
  TYPE_OBJECT = 'Object'
64
+ # The type label for hashes containing a Parse date object. Used by Parse::Date.
46
65
  TYPE_DATE = 'Date'
66
+ # The type label for hashes containing 'byte' data. Used by Parse::Bytes.
47
67
  TYPE_BYTES = 'Bytes'
68
+ # The type label for hashes containing ACL data. Used by Parse::ACL
69
+ TYPE_ACL = 'ACL'
70
+ # The type label for hashes storing numeric data.
71
+ TYPE_NUMBER = 'Number'
72
+ # The type label for hashes containing a Parse pointer.
48
73
  TYPE_POINTER = 'Pointer'
74
+ # The type label for hashes representing relational data.
49
75
  TYPE_RELATION = 'Relation'
50
- TYPE_FIELD = '__type'
76
+
51
77
 
52
78
  # To support being able to have different ruby class names from the 'table'
53
79
  # names used in Parse, we will need to have a dynamic lookup system where
@@ -58,21 +84,25 @@ module Parse
58
84
  # @!visibility private
59
85
  @@model_cache = {}
60
86
 
61
- # If set to true, a call to first_or_create will automatically save the object.
87
+ # @!attribute self.autosave_on_create
88
+ # If set to true, a call to {Parse::Object.first_or_create} will automatically save the object.
89
+ # Default is false.
62
90
  # @return [Boolean]
63
91
  def self.autosave_on_create
64
92
  @@autosave_on_create ||= false
65
93
  end
66
94
 
95
+ # @!visibility private
67
96
  def self.autosave_on_create=(bool)
68
97
  @@autosave_on_create = bool
69
98
  end
70
99
 
71
100
  class << self
101
+ # @!attribute self.raise_on_save_failure
72
102
  # By default, we return `true` or `false` for save and destroy operations.
73
103
  # If you prefer to have `Parse::Object` raise an exception instead, you
74
104
  # can tell to do so either globally or on a per-model basis. When a save
75
- # fails, it will raise a `Parse::SaveFailureError`.
105
+ # fails, it will raise a `Parse::RecordNotSaved`.
76
106
  #
77
107
  # @example
78
108
  # Parse::Model.raise_on_save_failure = true # globally across all models
@@ -84,15 +114,15 @@ module Parse
84
114
  # When enabled, if an error is returned by Parse due to saving or
85
115
  # destroying a record, due to your `before_save` or `before_delete`
86
116
  # validation cloud code triggers, `Parse::Object` will return the a
87
- # `Parse::SaveFailureError` exception type. This exception has an
117
+ # `Parse::RecordNotSaved` exception type. This exception has an
88
118
  # instance method of `#object` which contains the object that failed to save.
89
119
  #
90
120
  # @return [Boolean]
91
- attr_accessor :raise_on_save_failure
92
121
 
93
122
  def raise_on_save_failure
94
123
  @global_raise_on_save_failure ||= false
95
124
  end
125
+
96
126
  def raise_on_save_failure=(bool)
97
127
  @global_raise_on_save_failure = bool
98
128
  end
@@ -137,7 +167,7 @@ module Parse
137
167
 
138
168
  end
139
169
 
140
-
170
+ # Add extensions to the String class.
141
171
  class String
142
172
  # This method returns a camel-cased version of the string with the first letter
143
173
  # of the string in lower case. This is the standard naming convention for Parse columns
@@ -181,6 +211,7 @@ class String
181
211
  end
182
212
  end
183
213
 
214
+ # Add extensions to the Symbol class.
184
215
  class Symbol
185
216
  # @return [String] a lower-first-camelcased version of the symbol
186
217
  # @see String#columnize
@@ -11,23 +11,25 @@ require 'active_model_serializers'
11
11
  require 'time'
12
12
  require 'open-uri'
13
13
 
14
- require_relative "../client"
15
- require_relative "model"
16
- require_relative "pointer"
17
- require_relative "geopoint"
18
- require_relative "file"
19
- require_relative "bytes"
20
- require_relative "date"
21
- require_relative "acl"
22
- require_relative "push"
14
+ require_relative '../client'
15
+ require_relative 'model'
16
+ require_relative 'pointer'
17
+ require_relative 'geopoint'
18
+ require_relative 'file'
19
+ require_relative 'bytes'
20
+ require_relative 'date'
21
+ require_relative 'acl'
22
+ require_relative 'push'
23
23
  require_relative 'core/actions'
24
24
  require_relative 'core/fetching'
25
25
  require_relative 'core/querying'
26
- require_relative "core/schema"
27
- require_relative "core/properties"
28
- require_relative "associations/has_one"
29
- require_relative "associations/belongs_to"
30
- require_relative "associations/has_many"
26
+ require_relative 'core/schema'
27
+ require_relative 'core/properties'
28
+ require_relative 'core/errors'
29
+ require_relative 'core/builder'
30
+ require_relative 'associations/has_one'
31
+ require_relative 'associations/belongs_to'
32
+ require_relative 'associations/has_many'
31
33
 
32
34
 
33
35
  module Parse
@@ -36,6 +38,19 @@ module Parse
36
38
  Parse::Object.descendants.map(&:parse_class).uniq
37
39
  end
38
40
 
41
+ # @return [Array<Hash>] the list of all schemas for this application.
42
+ def self.schemas
43
+ client.schemas.results
44
+ end
45
+
46
+ # Fetch the schema for a specific collection name.
47
+ # @param className [String] the name collection
48
+ # @return [Hash] the schema document of this collection.
49
+ # @see Parse::Core::ClassBuilder.build!
50
+ def self.schema(className)
51
+ client.schema(className).result
52
+ end
53
+
39
54
  # Perform a non-destructive upgrade of all your Parse schemas in the backend
40
55
  # based on the property definitions of your local {Parse::Object} subclasses.
41
56
  def self.auto_upgrade!
@@ -91,10 +106,11 @@ module Parse
91
106
  include Associations::HasOne
92
107
  include Associations::BelongsTo
93
108
  include Associations::HasMany
94
- extend Querying
95
- extend Schema
96
- include Fetching
97
- include Actions
109
+ extend Core::Querying
110
+ extend Core::Schema
111
+ include Core::Fetching
112
+ include Core::Actions
113
+ # @!visibility private
98
114
  BASE_OBJECT_CLASS = "Parse::Object".freeze
99
115
 
100
116
  # @return [Model::TYPE_OBJECT]
@@ -192,7 +208,7 @@ module Parse
192
208
  alias_method :className, :parse_class
193
209
 
194
210
  # @return [Hash] the schema structure for this Parse collection from the server.
195
- # @see Parse::Schema
211
+ # @see Parse::Core::Schema
196
212
  def schema
197
213
  self.class.schema
198
214
  end
@@ -426,16 +442,41 @@ module Parse
426
442
  property :updated_at, :date
427
443
  property :acl, :acl, field: :ACL
428
444
 
445
+ # Alias to {created_at}
446
+ # @return (see #created_at)
429
447
  def createdAt
430
448
  return @created_at if Parse::Object.disable_serialized_string_date.present?
431
449
  @created_at.to_time.utc.iso8601(3) if @created_at.present?
432
450
  end
433
451
 
452
+ # Alias to {updated_at}
453
+ # @return (see #updated_at)
434
454
  def updatedAt
435
455
  return @updated_at if Parse::Object.disable_serialized_string_date.present?
436
456
  @updated_at.to_time.utc.iso8601(3) if @updated_at.present?
437
457
  end
438
458
 
459
+ # Access the value for a defined property through hash accessor. This method
460
+ # returns nil if the key is not one of the defined properties for this Parse::Object
461
+ # subclass.
462
+ # @param key [String] the name of the property. This key must be in the {fields} hash.
463
+ # @return [Object] the value for this key.
464
+ def [](key)
465
+ return nil unless self.class.fields[key.to_sym].present?
466
+ send(key)
467
+ end
468
+
469
+ # Set the value for a specific property through a hash accessor. This method
470
+ # does nothing if key is not one of the defined properties for this Parse::Object
471
+ # subclass.
472
+ # @param key (see Parse::Object#[])
473
+ # @param value [Object] the value to set this property.
474
+ # @return [Object] the value passed in.
475
+ def []=(key,value)
476
+ return unless self.class.fields[key.to_sym].present?
477
+ send("#{key}=",value)
478
+ end
479
+
439
480
  end
440
481
 
441
482