parse-stack 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +4 -4
  2. data/Changes.md +15 -1
  3. data/Gemfile.lock +10 -10
  4. data/README.md +23 -9
  5. data/bin/console +3 -0
  6. data/lib/parse/api/analytics.rb +1 -1
  7. data/lib/parse/api/objects.rb +1 -1
  8. data/lib/parse/api/users.rb +1 -1
  9. data/lib/parse/client.rb +77 -40
  10. data/lib/parse/client/caching.rb +9 -5
  11. data/lib/parse/client/protocol.rb +47 -0
  12. data/lib/parse/client/request.rb +66 -37
  13. data/lib/parse/client/response.rb +39 -21
  14. data/lib/parse/model/acl.rb +4 -9
  15. data/lib/parse/model/associations/belongs_to.rb +97 -9
  16. data/lib/parse/model/associations/collection_proxy.rb +89 -29
  17. data/lib/parse/model/associations/has_many.rb +301 -28
  18. data/lib/parse/model/associations/has_one.rb +98 -4
  19. data/lib/parse/model/associations/pointer_collection_proxy.rb +48 -16
  20. data/lib/parse/model/associations/relation_collection_proxy.rb +61 -36
  21. data/lib/parse/model/bytes.rb +11 -5
  22. data/lib/parse/model/classes/installation.rb +50 -3
  23. data/lib/parse/model/classes/role.rb +7 -2
  24. data/lib/parse/model/classes/session.rb +21 -4
  25. data/lib/parse/model/classes/user.rb +122 -22
  26. data/lib/parse/model/core/actions.rb +7 -3
  27. data/lib/parse/model/core/properties.rb +14 -13
  28. data/lib/parse/model/core/querying.rb +16 -10
  29. data/lib/parse/model/core/schema.rb +2 -3
  30. data/lib/parse/model/date.rb +18 -12
  31. data/lib/parse/model/file.rb +77 -19
  32. data/lib/parse/model/geopoint.rb +70 -12
  33. data/lib/parse/model/model.rb +84 -8
  34. data/lib/parse/model/object.rb +225 -94
  35. data/lib/parse/model/pointer.rb +94 -13
  36. data/lib/parse/model/push.rb +76 -4
  37. data/lib/parse/query.rb +356 -41
  38. data/lib/parse/query/constraints.rb +399 -29
  39. data/lib/parse/query/ordering.rb +21 -8
  40. data/lib/parse/stack.rb +1 -0
  41. data/lib/parse/stack/version.rb +2 -1
  42. data/lib/parse/webhooks.rb +0 -24
  43. data/lib/parse/webhooks/payload.rb +54 -1
  44. data/lib/parse/webhooks/registration.rb +13 -2
  45. metadata +2 -2
@@ -2,10 +2,9 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  require_relative "properties"
5
- # This class adds methods to Parse::Objects in order to create a JSON Parse schema
6
- # in order to support table creation and table alterations.
7
- module Parse
8
5
 
6
+ module Parse
7
+ # Upgrade all
9
8
  def self.auto_upgrade!
10
9
  klassModels = Parse::Object.descendants
11
10
  klassModels.sort_by { |c| c.parse_class }.each do |klass|
@@ -13,38 +13,42 @@ require 'active_support/core_ext/time/calculations'
13
13
  require 'active_model_serializers'
14
14
  require_relative 'model'
15
15
 
16
- # Parse has a specific date format. One of the supported types is a date string in
17
- # ISO 8601 format (including milliseconds). The other is a hash object that contains
18
- # the similar information. When sending data to Parse, we need to use the hash object,
19
- # but when receiving data from Parse, we may either get the string version or the hash version.
20
- # To make things easier to use in ruby, th Parse::Date class inherits from the DateTime class.
21
- # This will allow us to use all the great ActiveSupport methods for date (ex. 3.days.ago) while
22
- # providing our own encoding for sending to Parse.
23
16
  module Parse
17
+ # This class manages dates in the special JSON format it requires for
18
+ # properties of type _:date_. One important note with dates, is that 'created_at' and 'updated_at'
19
+ # columns do not follow this convention all the time. Depending on the
20
+ # Cloud Code SDK, they can be the Parse ISO hash date format or the `iso8601`
21
+ # string format. By default, these are serialized as `iso8601` when sent as
22
+ # responses to Parse for backwards compatibility with some clients. To use
23
+ # the Parse ISO hash format for these fields instead, set
24
+ # `Parse::Object.disable_serialized_string_date = true`.
24
25
  class Date < ::DateTime
25
26
  ATTRIBUTES = { __type: :string, iso: :string }.freeze
26
27
  include ::ActiveModel::Model
27
28
  include ::ActiveModel::Serializers::JSON
29
+
30
+ # @return [Parse::Model::TYPE_DATE]
28
31
  def self.parse_class; Parse::Model::TYPE_DATE; end;
32
+ # @return [Parse::Model::TYPE_DATE]
29
33
  def parse_class; self.class.parse_class; end;
30
34
  alias_method :__type, :parse_class
31
35
 
32
- # called when encoding to JSON.
36
+ # @return [Hash]
33
37
  def attributes
34
38
  ATTRIBUTES
35
39
  end
36
40
 
37
- # this method is defined because it is used by JSON encoding
41
+ # @return [String] the ISO8601 time string including milliseconds
38
42
  def iso
39
- to_time.utc.iso8601(3) #include milliseconds
43
+ to_time.utc.iso8601(3)
40
44
  end
41
45
 
42
46
  end
43
47
  end
44
48
 
45
- # To enable conversion of other date class objects, we will add a mixin to turn
46
- # Time and DateTime objects to Parse::Date objects
49
+
47
50
  class Time
51
+ # @return [Parse::Date] Converts object to Parse::Date
48
52
  def parse_date
49
53
  Parse::Date.parse iso8601(3)
50
54
  end
@@ -52,6 +56,7 @@ class Time
52
56
  end
53
57
 
54
58
  class DateTime
59
+ # @return [Parse::Date] Converts object to Parse::Date
55
60
  def parse_date
56
61
  Parse::Date.parse iso8601(3)
57
62
  end
@@ -59,6 +64,7 @@ end
59
64
 
60
65
  module ActiveSupport
61
66
  class TimeWithZone
67
+ # @return [Parse::Date] Converts object to Parse::Date
62
68
  def parse_date
63
69
  Parse::Date.parse iso8601(3)
64
70
  end
@@ -5,30 +5,61 @@ require 'active_support'
5
5
  require 'active_support/core_ext/object'
6
6
  require_relative "model"
7
7
  require 'open-uri'
8
- # Parse File objects are the only non Parse::Object subclass that has a save method.
9
- # In general, a Parse File needs content and a specific mime-type to be created. When it is saved, it
10
- # is sent to AWS/S3 to be saved (by Parse), and the result is a new URL pointing to that file.
11
- # This however is return as a type of File pointer object (hash format)
12
- # It only has two fields, the absolute URL of the file and the basename of the file.
13
- # The contents and mime_type are only present when creating a new file locally and are not
14
- # stored as part of the parse pointer.
15
- module Parse
16
8
 
9
+ module Parse
10
+ # This class represents a Parse file pointer. `Parse::File` has helper
11
+ # methods to upload Parse files directly to Parse and manage file
12
+ # associations with your classes.
13
+ # @example
14
+ # file = File.open("file_path.jpg")
15
+ # contents = file.read
16
+ # file = Parse::File.new("myimage.jpg", contents , "image/jpeg")
17
+ # file.saved? # => false
18
+ # file.save
19
+ #
20
+ # file.url # https://files.parsetfss.com/....
21
+ #
22
+ # # or create and upload a remote file (auto-detected mime type)
23
+ # file = Parse::File.create(some_url)
24
+ #
25
+ #
26
+ # @note The default MIME type for all files is _image/jpeg_. This can be default
27
+ # can be changed by setting a value to `Parse::File.default_mime_type`.
17
28
  class File < Model
18
29
  ATTRIBUTES = { __type: :string, name: :string, url: :string }.freeze
19
- attr_accessor :name, :url
20
- attr_accessor :contents, :mime_type
30
+ # @return [String] the name of the file including extension (if any)
31
+ attr_accessor :name
32
+ # @return [String] the url resource of the file.
33
+ attr_accessor :url
34
+
35
+ # You may set the contents of the file.
36
+ attr_accessor :contents
37
+
38
+ # @return [String] the mime-type of the file whe
39
+ attr_accessor :mime_type
40
+ # @return [Model::TYPE_FILE]
21
41
  def self.parse_class; TYPE_FILE; end;
42
+ # @return [Model::TYPE_FILE]
22
43
  def parse_class; self.class.parse_class; end;
23
44
  alias_method :__type, :parse_class
24
45
  FIELD_NAME = "name"
25
46
  FIELD_URL = "url"
26
47
  class << self
48
+
27
49
  attr_accessor :default_mime_type
28
50
 
51
+ attr_accessor :force_ssl
52
+
53
+ # @return [String] The default mime type for created instances. Default: _'image/jpeg'_
29
54
  def default_mime_type
30
55
  @default_mime_type ||= "image/jpeg"
31
56
  end
57
+
58
+ # @return [Boolean] When set to true, it will make all calls to File#url
59
+ def force_ssl
60
+ @force_ssl ||= false
61
+ end
62
+
32
63
  end
33
64
  # The initializer to create a new file supports different inputs.
34
65
  # If the first paramter is a string which starts with 'http', we then download
@@ -36,6 +67,9 @@ module Parse
36
67
  # If the first parameter is a hash, we assume it might be the Parse File hash format which contains url and name fields only.
37
68
  # If the first paramter is a Parse::File, then we copy fields over
38
69
  # Otherwise, creating a new file requires a name, the actual contents (usually from a File.open("local.jpg").read ) and the mime-type
70
+ # @param name [String]
71
+ # @param contents [Object]
72
+ # @param mime_type [String] Default see default_mime_type
39
73
  def initialize(name, contents = nil, mime_type = nil)
40
74
  mime_type ||= Parse::File.default_mime_type
41
75
 
@@ -65,6 +99,8 @@ module Parse
65
99
  end
66
100
 
67
101
  # This creates a new Parse File Object with from a URL, saves it and returns it
102
+ # @param url [String] A url which will be used to create the file and automatically save it.
103
+ # @return [Parse::File] A newly saved file based on contents of _url_
68
104
  def self.create(url)
69
105
  url = url.url if url.is_a?(Parse::File)
70
106
  file = self.new(url)
@@ -72,16 +108,28 @@ module Parse
72
108
  file
73
109
  end
74
110
 
75
- # A File object is considered saved if the basename of the URL and the name parameters are equal and
76
- # the name of the file begins with 'tfss'
111
+ # A File object is considered saved if the basename of the URL and the name parameters are equal
112
+ # @return [Boolean] true if this file has already been saved.
77
113
  def saved?
78
- @url.present? && @name.present? && @name == File.basename(@url) && @name.start_with?("tfss")
114
+ @url.present? && @name.present? && @name == File.basename(@url)
115
+ end
116
+
117
+ # Returns the url string for this Parse::File pointer. If the *force_ssl* option is
118
+ # set to true, it will make sure it returns a secure url.
119
+ # @return [String] the url string for the file.
120
+ def url
121
+ if @url.present? && Parse::File.force_ssl && @url.starts_with?('http://')
122
+ return @url.sub('http://', 'https://')
123
+ end
124
+ @url
79
125
  end
80
126
 
127
+ # @return [Hash]
81
128
  def attributes
82
129
  ATTRIBUTES
83
130
  end
84
131
 
132
+ # @return [Boolean] Two files are equal if they have the same url
85
133
  def ==(u)
86
134
  return false unless u.is_a?(self.class)
87
135
  @url == u.url
@@ -97,7 +145,11 @@ module Parse
97
145
  end
98
146
  end
99
147
 
100
- # This is a proxy to the ruby ::File.basename method
148
+ # A proxy method for ::File.basename
149
+ # @param file_name [String]
150
+ # @param suffix [String]
151
+ # @return [String] File.basename(file_name)
152
+ # @see ::File.basename
101
153
  def self.basename(file_name, suffix = nil)
102
154
  if suffix.nil?
103
155
  ::File.basename(file_name)
@@ -106,7 +158,8 @@ module Parse
106
158
  end
107
159
  end
108
160
 
109
- # save (create) the file if it has all the proper fields. You cannot update Parse Files.
161
+ # Save the file by uploading it to Parse and creating a file pointer.
162
+ # @return [Boolean] true if successfully uploaded and saved.
110
163
  def save
111
164
  unless saved? || @contents.nil? || @name.nil?
112
165
  response = client.create_file(@name, @contents, @mime_type)
@@ -119,10 +172,13 @@ module Parse
119
172
  saved?
120
173
  end
121
174
 
175
+ # @!visibility private
122
176
  def inspect
123
177
  "<Parse::File @name='#{@name}' @mime_type='#{@mime_type}' @contents=#{@contents.nil?} @url='#{@url}'>"
124
178
  end
125
179
 
180
+ # @return [String] the url
181
+ # @see #url
126
182
  def to_s
127
183
  @url
128
184
  end
@@ -133,13 +189,15 @@ end
133
189
 
134
190
 
135
191
  class Hash
136
- # {"name"=>"tfss-cat.jpg", "url"=>"http://files.parsetfss.com/bcf638bb-3db0-4042-b846-7840b345b0d6/tfss-cat.jpg"}
137
- # This is a helper method that determines whether a hash looks like a Parse::File hash
192
+ # Determines if the hash contains Parse File json metadata fields. This is determined whether
193
+ # the key `__type` exists and is of type `__File` and whether the `name` field matches the File.basename
194
+ # of the `url` field.
195
+ #
196
+ # @return [Boolean] True if this hash contains Parse file metadata.
138
197
  def parse_file?
139
198
  url = self[Parse::File::FIELD_URL]
140
199
  name = self[Parse::File::FIELD_NAME]
141
200
  (count == 2 || self["__type"] == Parse::File.parse_class) &&
142
- url.present? && name.present? &&
143
- name == ::File.basename(url) && name.start_with?("tfss")
201
+ url.present? && name.present? && name == ::File.basename(url)
144
202
  end
145
203
  end
@@ -5,31 +5,54 @@ require_relative "model"
5
5
 
6
6
  module Parse
7
7
 
8
- # A basic geo location object in Parse. It represents a location on a map through a
9
- # latitude and longitue.
8
+ # This class manages the GeoPoint data type that Parse provides to support
9
+ # geo-queries. To define a GeoPoint property, use the `:geopoint` data type.
10
+ # Please note that latitudes should not be between -90.0 and 90.0, and
11
+ # longitudes should be between -180.0 and 180.0.
12
+ # @example
13
+ # class PlaceObject < Parse::Object
14
+ # property :location, :geopoint
15
+ # end
16
+ #
17
+ # san_diego = Parse::GeoPoint.new(32.8233, -117.6542)
18
+ # los_angeles = Parse::GeoPoint.new [34.0192341, -118.970792]
19
+ # san_diego == los_angeles # false
20
+ #
21
+ # place = PlaceObject.new
22
+ # place.location = san_diego
23
+ # place.save
24
+ #
10
25
  class GeoPoint < Model
11
26
  ATTRIBUTES = { __type: :string, latitude: :float, longitude: :float }.freeze
12
- attr_accessor :latitude, :longitude
27
+
28
+ # @return [Float] latitude value between -90.0 and 90.0
29
+ attr_accessor :latitude
30
+ # @return [Float] longitude value between -180.0 and 180.0
31
+ attr_accessor :longitude
13
32
  FIELD_LAT = "latitude"
14
33
  FIELD_LNG = "longitude"
15
- # Latitude should not be -90.0 or 90.0.
16
- # Longitude should not be -180.0 or 180.0.
34
+
17
35
  LAT_MIN = -90.0
18
36
  LAT_MAX = 90.0
19
37
  LNG_MIN = -180.0
20
38
  LNG_MAX = 180.0
39
+
21
40
  alias_method :lat, :latitude
22
41
  alias_method :lng, :longitude
42
+ # @return [Model::TYPE_GEOPOINT]
23
43
  def self.parse_class; TYPE_GEOPOINT; end;
44
+ # @return [Model::TYPE_GEOPOINT]
24
45
  def parse_class; self.class.parse_class; end;
25
46
  alias_method :__type, :parse_class
26
- # To create a GeoPoint, you can either pass a hash (ex. {latitude: 32, longitue: -117})
27
- # or an array (ex. [32,-117]) as the first parameter.
28
- # You may also pass a GeoPoint object or both a lat/lng pair (Ex. GeoPoint.new(32, -117) )
29
- # Points should not equal or exceed the extreme ends of the ranges.
30
-
31
- # Attempting to use GeoPoint’s with latitude and/or longitude outside these ranges will cause an error.
32
47
 
48
+ # The initializer can create a GeoPoint with a hash, array or values.
49
+ # @example
50
+ # san_diego = Parse::GeoPoint.new(32.8233, -117.6542)
51
+ # san_diego = Parse::GeoPoint.new [32.8233, -117.6542]
52
+ # san_diego = Parse::GeoPoint.new { latitude: 32.8233, longitude: -117.6542}
53
+ #
54
+ # @param latitude [Numeric] The latitude value between LAT_MIN and LAT_MAX.
55
+ # @param longitude [Numeric] The longitude value between LNG_MIN and LNG_MAX.
33
56
  def initialize(latitude = nil, longitude = nil)
34
57
  @latitude = @longitude = 0.0
35
58
  if latitude.is_a?(Hash) || latitude.is_a?(Array)
@@ -45,6 +68,7 @@ module Parse
45
68
  _validate_point
46
69
  end
47
70
 
71
+ # @!visibility private
48
72
  def _validate_point
49
73
 
50
74
  unless @latitude.nil? || @latitude.between?(LAT_MIN, LAT_MAX)
@@ -59,10 +83,13 @@ module Parse
59
83
 
60
84
  end
61
85
 
86
+ # @return [Hash]
62
87
  def attributes
63
88
  ATTRIBUTES
64
89
  end
65
90
 
91
+ # Helper method for performing geo-queries with radial miles constraints
92
+ # @return [Array] containing [lat,lng,miles]
66
93
  def max_miles(m)
67
94
  m = 0 if m.nil?
68
95
  [@latitude,@longitude,m]
@@ -92,24 +119,55 @@ module Parse
92
119
  _validate_point
93
120
  end
94
121
 
122
+ # @return [Boolean] true if two geopoints are equal based on lat and lng.
95
123
  def ==(g)
96
124
  return false unless g.is_a?(GeoPoint)
97
125
  @latitude == g.latitude && @longitude == g.longitude
98
126
  end
99
127
 
128
+ # Helper method for reducing the precision of a geopoint.
129
+ # @param precision [Integer] The number of floating digits to keep.
130
+ # @return [GeoPoint] Reduces the precision of a geopoint.
131
+ def estimated(precision = 2)
132
+ Parse::GeoPoint.new(@latitude.to_f.round(precision), @longitude.round(precision))
133
+ end
134
+
135
+ # Returns a tuple containing latitude and longitude
136
+ # @return [Array]
100
137
  def to_a
101
138
  [@latitude,@longitude]
102
139
  end
103
140
 
141
+ # @!visibility private
104
142
  def inspect
105
143
  "#<GeoPoint [#{@latitude},#{@longitude}]>"
106
144
  end
107
145
 
108
- # either GeoPoint, array or lat,lng
146
+ # Calculate the distance in miles to another GeoPoint using Haversine.
147
+ # You may also call this method with a latitude and longitude.
148
+ # @example
149
+ # point.distance_in_miles(geotpoint)
150
+ # point.distance_in_miles(lat, lng)
151
+ #
152
+ # @param geopoint [GeoPoint]
153
+ # @param lng [Float] Longitude assuming that the first parameter
154
+ # is longitude instead of a GeoPoint.
155
+ # @return [Float] number of miles between geopoints.
156
+ # @see #distance_in_km
109
157
  def distance_in_miles(geopoint,lng = nil)
110
158
  distance_in_km(geopoint, lng) * 0.621371
111
159
  end
112
160
 
161
+ # Calculate the distance in kilometers to another GeoPoint using Haversine
162
+ # method. You may also call this method with a latitude and longitude.
163
+ # @example
164
+ # point.distance_in_km(geotpoint)
165
+ # point.distance_in_km(lat, lng)
166
+ #
167
+ # @param geopoint [GeoPoint]
168
+ # @param lng [Float] Longitude assuming that the first parameter is a latitude instead of a GeoPoint.
169
+ # @return [Float] number of miles between geopoints.
170
+ # @see #distance_in_miles
113
171
  def distance_in_km(geopoint,lng = nil)
114
172
  unless geopoint.is_a?(Parse::GeoPoint)
115
173
  geopoint = Parse::GeoPoint.new(geopoint, lng)
@@ -8,10 +8,18 @@ require 'active_support/core_ext/object'
8
8
  require 'active_model_serializers'
9
9
  require_relative '../client'
10
10
 
11
- # This is the base model for all Parse object-type classes.
12
-
13
11
  module Parse
12
+ # Find a corresponding Parse::Object subclass for this string or symbol
13
+ # @param className [String] The name of the Parse class as string (ex. "_User")
14
+ # @return [Class] The proper subclass matching the className.
15
+ def self.classify(className)
16
+ Parse::Model.find_class className.to_parse_class
17
+ end
14
18
 
19
+ # The core model of all Parse-Stack classes. This class works by providing a
20
+ # baseline for all subclass objects to support ActiveModel features such as
21
+ # serialization, dirty tracking, callbacks, etc.
22
+ # @see ActiveModel
15
23
  class Model
16
24
 
17
25
  include Client::Connectable # allows easy default Parse::Client access
@@ -22,7 +30,6 @@ module Parse
22
30
  extend ::ActiveModel::Callbacks # callback support on save, update, delete, etc.
23
31
  extend ::ActiveModel::Naming # provides the methods for getting class names from Model classes
24
32
 
25
- # General Parse constants
26
33
  ID = "id".freeze
27
34
  OBJECT_ID = 'objectId'.freeze
28
35
  KEY_CLASS_NAME = 'className'.freeze
@@ -48,15 +55,40 @@ module Parse
48
55
  # which Parse::Object subclass is responsible for handling this Parse table class.
49
56
  # we use @@model_cache to cache the results of the algorithm since we do this frequently
50
57
  # when encoding and decoding objects.
58
+ # @!visibility private
51
59
  @@model_cache = {}
60
+
61
+ # If set to true, a call to first_or_create will automatically save the object.
62
+ # @return [Boolean]
52
63
  def self.autosave_on_create
53
64
  @@autosave_on_create ||= false
54
65
  end
66
+
55
67
  def self.autosave_on_create=(bool)
56
68
  @@autosave_on_create = bool
57
69
  end
58
70
 
59
71
  class << self
72
+ # By default, we return `true` or `false` for save and destroy operations.
73
+ # If you prefer to have `Parse::Object` raise an exception instead, you
74
+ # can tell to do so either globally or on a per-model basis. When a save
75
+ # fails, it will raise a `Parse::SaveFailureError`.
76
+ #
77
+ # @example
78
+ # Parse::Model.raise_on_save_failure = true # globally across all models
79
+ # Song.raise_on_save_failure = true # per-model
80
+ #
81
+ # # or per-instance raise on failure
82
+ # song.save!
83
+ #
84
+ # When enabled, if an error is returned by Parse due to saving or
85
+ # destroying a record, due to your `before_save` or `before_delete`
86
+ # validation cloud code triggers, `Parse::Object` will return the a
87
+ # `Parse::SaveFailureError` exception type. This exception has an
88
+ # instance method of `#object` which contains the object that failed to save.
89
+ #
90
+ # @return [Boolean]
91
+ attr_accessor :raise_on_save_failure
60
92
 
61
93
  def raise_on_save_failure
62
94
  @global_raise_on_save_failure ||= false
@@ -67,8 +99,23 @@ module Parse
67
99
 
68
100
  end
69
101
 
70
- # class method to find the responsible ruby Parse::Object subclass that handles
71
- # the provided parse class (str).
102
+ # Find a Parse::Model subclass matching this type or Pares collection name.
103
+ # This helper method is useful to find the corresponding class ruby Parse::Object subclass that handles
104
+ # the provided parse class.
105
+ #
106
+ # @example
107
+ # Parse::Model.find_class('_User') # => Parse::User
108
+ # Parse::Model.find_class('_Date') # => Parse::Date
109
+ # Parse::Model.find_class('Installation') # => Parse::Installation
110
+ #
111
+ # class Artist < Parse::Object
112
+ # parse_class "Musician"
113
+ # end
114
+ #
115
+ # Parse::Model.find_class("Musician") # => Artist
116
+ #
117
+ # @param str [String] the class name
118
+ # @return [Parse::Object] a Parse::Object subclass or a specific Parse type.
72
119
  def self.find_class(str)
73
120
  return Parse::File if str == TYPE_FILE
74
121
  return Parse::GeoPoint if str == TYPE_GEOPOINT
@@ -92,14 +139,39 @@ end
92
139
 
93
140
 
94
141
  class String
95
- # short helper method to provide lower-first-camelcase
142
+ # This method returns a camel-cased version of the string with the first letter
143
+ # of the string in lower case. This is the standard naming convention for Parse columns
144
+ # and property fields. This has special exception to the string "id", which returns
145
+ # "objectId". This is the default name filtering method for all defined properties and
146
+ # query keys in Parse::Query.
147
+ #
148
+ # @example
149
+ # "my_field".columnize # => "myField"
150
+ # "MyDataColumn".columnize # => "myDataColumn"
151
+ # "id".columnize # => "objectId" (special)
152
+ #
153
+ # @return [String]
154
+ # @see Parse::Query.field_formatter
96
155
  def columnize
97
156
  return Parse::Model::OBJECT_ID if self == Parse::Model::ID
98
157
  u = '_'.freeze
99
158
  (first == u ? sub(u,'') : self).camelize(:lower)
100
159
  end
101
160
 
102
- #users for properties: ex. :users -> "_User" or :songs -> Song
161
+ # Convert a string to a Parse class name. This method tries to find a
162
+ # responsible Parse::Object subclass that potentially matches the given string.
163
+ # If no match is found, it returns the camelized version of the string. This method
164
+ # is used internally for matching association attributes to registered
165
+ # Parse::Object subclasses. The method can also singularize the name before
166
+ # performing conversion.
167
+ #
168
+ # @example
169
+ # "users".to_parse_class(singularize: true) # => "_User"
170
+ # "users".to_parse_class # => "Users"
171
+ # "song_data".to_parse_class # => "SongData"
172
+ #
173
+ # @param singularize [Boolean] whether the string should be singularized first before performing conversion.
174
+ # @return [String] the matching Parse class for this string.
103
175
  def to_parse_class(singularize: false)
104
176
  final_class = singularize ? self.singularize.camelize : self.camelize
105
177
  klass = Parse::Model.find_class(final_class) || Parse::Model.find_class(self)
@@ -110,19 +182,23 @@ class String
110
182
  end
111
183
 
112
184
  class Symbol
113
- # for compatibility
185
+ # @return [String] a lower-first-camelcased version of the symbol
186
+ # @see String#columnize
114
187
  def columnize
115
188
  to_s.columnize.to_sym
116
189
  end
117
190
 
191
+ # @see String#singularize
118
192
  def singularize
119
193
  to_s.singularize
120
194
  end
121
195
 
196
+ # @see String#camelize
122
197
  def camelize
123
198
  to_s.camelize
124
199
  end
125
200
 
201
+ # @see String#to_parse_class
126
202
  def to_parse_class(singularize: false)
127
203
  to_s.to_parse_class(singularize: singularize)
128
204
  end