parse-stack 1.8.0 → 1.8.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.solargraph.yml +23 -0
  3. data/.travis.yml +0 -1
  4. data/Gemfile +13 -12
  5. data/Gemfile.lock +88 -51
  6. data/README.md +2 -4
  7. data/Rakefile +14 -14
  8. data/lib/parse/api/aggregate.rb +4 -7
  9. data/lib/parse/api/all.rb +1 -1
  10. data/lib/parse/api/analytics.rb +0 -3
  11. data/lib/parse/api/batch.rb +3 -5
  12. data/lib/parse/api/cloud_functions.rb +0 -3
  13. data/lib/parse/api/config.rb +0 -4
  14. data/lib/parse/api/files.rb +3 -7
  15. data/lib/parse/api/hooks.rb +4 -8
  16. data/lib/parse/api/objects.rb +7 -12
  17. data/lib/parse/api/push.rb +0 -4
  18. data/lib/parse/api/schema.rb +2 -6
  19. data/lib/parse/api/server.rb +4 -7
  20. data/lib/parse/api/sessions.rb +2 -5
  21. data/lib/parse/api/users.rb +9 -14
  22. data/lib/parse/client.rb +54 -50
  23. data/lib/parse/client/authentication.rb +29 -33
  24. data/lib/parse/client/batch.rb +8 -11
  25. data/lib/parse/client/body_builder.rb +19 -20
  26. data/lib/parse/client/caching.rb +23 -28
  27. data/lib/parse/client/protocol.rb +11 -12
  28. data/lib/parse/client/request.rb +4 -6
  29. data/lib/parse/client/response.rb +5 -7
  30. data/lib/parse/model/acl.rb +14 -12
  31. data/lib/parse/model/associations/belongs_to.rb +14 -21
  32. data/lib/parse/model/associations/collection_proxy.rb +328 -329
  33. data/lib/parse/model/associations/has_many.rb +18 -25
  34. data/lib/parse/model/associations/has_one.rb +6 -11
  35. data/lib/parse/model/associations/pointer_collection_proxy.rb +5 -8
  36. data/lib/parse/model/associations/relation_collection_proxy.rb +5 -9
  37. data/lib/parse/model/bytes.rb +8 -10
  38. data/lib/parse/model/classes/installation.rb +2 -4
  39. data/lib/parse/model/classes/product.rb +2 -5
  40. data/lib/parse/model/classes/role.rb +3 -5
  41. data/lib/parse/model/classes/session.rb +2 -5
  42. data/lib/parse/model/classes/user.rb +20 -16
  43. data/lib/parse/model/core/actions.rb +31 -46
  44. data/lib/parse/model/core/builder.rb +6 -6
  45. data/lib/parse/model/core/errors.rb +0 -1
  46. data/lib/parse/model/core/fetching.rb +45 -50
  47. data/lib/parse/model/core/properties.rb +51 -66
  48. data/lib/parse/model/core/querying.rb +291 -294
  49. data/lib/parse/model/core/schema.rb +89 -92
  50. data/lib/parse/model/date.rb +16 -17
  51. data/lib/parse/model/file.rb +171 -174
  52. data/lib/parse/model/geopoint.rb +12 -16
  53. data/lib/parse/model/model.rb +31 -37
  54. data/lib/parse/model/object.rb +47 -53
  55. data/lib/parse/model/pointer.rb +177 -176
  56. data/lib/parse/model/push.rb +8 -10
  57. data/lib/parse/model/shortnames.rb +1 -2
  58. data/lib/parse/model/time_zone.rb +3 -5
  59. data/lib/parse/query.rb +34 -35
  60. data/lib/parse/query/constraint.rb +4 -6
  61. data/lib/parse/query/constraints.rb +21 -29
  62. data/lib/parse/query/operation.rb +8 -11
  63. data/lib/parse/query/ordering.rb +45 -49
  64. data/lib/parse/stack.rb +11 -12
  65. data/lib/parse/stack/generators/rails.rb +28 -30
  66. data/lib/parse/stack/generators/templates/model.erb +5 -6
  67. data/lib/parse/stack/generators/templates/model_installation.rb +0 -1
  68. data/lib/parse/stack/generators/templates/model_role.rb +0 -1
  69. data/lib/parse/stack/generators/templates/model_session.rb +0 -1
  70. data/lib/parse/stack/generators/templates/model_user.rb +0 -1
  71. data/lib/parse/stack/generators/templates/parse.rb +9 -9
  72. data/lib/parse/stack/generators/templates/webhooks.rb +1 -2
  73. data/lib/parse/stack/railtie.rb +2 -4
  74. data/lib/parse/stack/tasks.rb +70 -86
  75. data/lib/parse/stack/version.rb +1 -1
  76. data/lib/parse/webhooks.rb +19 -26
  77. data/lib/parse/webhooks/payload.rb +26 -28
  78. data/lib/parse/webhooks/registration.rb +23 -31
  79. data/parse-stack.gemspec +25 -25
  80. data/parse-stack.png +0 -0
  81. metadata +13 -7
  82. data/.github/parse-ruby-sdk.png +0 -0
@@ -8,110 +8,107 @@ module Parse
8
8
  # Defines the Schema methods applied to a Parse::Object.
9
9
  module Schema
10
10
 
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
- when :timezone, :time_zone
33
- result[:type] = "String" # no TimeZone native in Parse
34
- else
35
- result[:type] = v.to_s.camelize
36
- end
37
-
38
- sch[:fields][k] = result
39
-
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
+ when :timezone, :time_zone
33
+ result[:type] = "String" # no TimeZone native in Parse
34
+ else
35
+ result[:type] = v.to_s.camelize
40
36
  end
41
- #then add all the relational column attributes
42
- relations.each do |k,v|
43
- sch[:fields][k] = { type: Parse::Model::TYPE_RELATION, targetClass: relations[k] }
44
- end
45
- sch
46
- end
47
37
 
48
- # Update the remote schema for this Parse collection.
49
- # @param schema_updates [Hash] the changes to be made to the schema.
50
- # @return [Parse::Response]
51
- def update_schema(schema_updates = nil)
52
- schema_updates ||= schema
53
- client.update_schema parse_class, schema_updates
38
+ sch[:fields][k] = result
54
39
  end
55
-
56
- # Create a new collection for this model with the schema defined by the local
57
- # model.
58
- # @return [Parse::Response]
59
- # @see Schema.schema
60
- def create_schema
61
- client.create_schema parse_class, schema
40
+ #then add all the relational column attributes
41
+ relations.each do |k, v|
42
+ sch[:fields][k] = { type: Parse::Model::TYPE_RELATION, targetClass: relations[k] }
62
43
  end
44
+ sch
45
+ end
63
46
 
64
- # Fetche the current schema for this collection from Parse server.
65
- # @return [Parse::Response]
66
- def fetch_schema
67
- client.schema parse_class
68
- end
47
+ # Update the remote schema for this Parse collection.
48
+ # @param schema_updates [Hash] the changes to be made to the schema.
49
+ # @return [Parse::Response]
50
+ def update_schema(schema_updates = nil)
51
+ schema_updates ||= schema
52
+ client.update_schema parse_class, schema_updates
53
+ end
69
54
 
70
- # A class method for non-destructive auto upgrading a remote schema based
71
- # on the properties and relations you have defined in your local model. If
72
- # the collection doesn't exist, we create the schema. If the collection already
73
- # exists, the current schema is fetched, and only add the additional fields
74
- # that are missing.
75
- # @note This feature requires use of the master_key. No columns or fields are removed, this is a safe non-destructive upgrade.
76
- # @return [Parse::Response] if the remote schema was modified.
77
- # @return [Boolean] if no changes were made to the schema, it returns true.
78
- def auto_upgrade!
55
+ # Create a new collection for this model with the schema defined by the local
56
+ # model.
57
+ # @return [Parse::Response]
58
+ # @see Schema.schema
59
+ def create_schema
60
+ client.create_schema parse_class, schema
61
+ end
79
62
 
80
- unless client.master_key.present?
81
- warn "[Parse] Schema changes for #{parse_class} is only available with the master key!"
82
- return false
83
- end
84
- # fetch the current schema (requires master key)
85
- response = fetch_schema
63
+ # Fetche the current schema for this collection from Parse server.
64
+ # @return [Parse::Response]
65
+ def fetch_schema
66
+ client.schema parse_class
67
+ end
86
68
 
87
- # if it's a core class that doesn't exist, then create the collection without any fields,
88
- # since parse-server will automatically create the collection with the set of core fields.
89
- # then fetch the schema again, to add the missing fields.
90
- if response.error? && self.to_s.start_with?('Parse::') #is it a core class?
91
- client.create_schema parse_class, {}
92
- response = fetch_schema
93
- # if it still wasn't able to be created, raise an error.
94
- if response.error?
95
- warn "[Parse] Schema error: unable to create class #{parse_class}"
96
- return response
97
- end
98
- end
69
+ # A class method for non-destructive auto upgrading a remote schema based
70
+ # on the properties and relations you have defined in your local model. If
71
+ # the collection doesn't exist, we create the schema. If the collection already
72
+ # exists, the current schema is fetched, and only add the additional fields
73
+ # that are missing.
74
+ # @note This feature requires use of the master_key. No columns or fields are removed, this is a safe non-destructive upgrade.
75
+ # @return [Parse::Response] if the remote schema was modified.
76
+ # @return [Boolean] if no changes were made to the schema, it returns true.
77
+ def auto_upgrade!
78
+ unless client.master_key.present?
79
+ warn "[Parse] Schema changes for #{parse_class} is only available with the master key!"
80
+ return false
81
+ end
82
+ # fetch the current schema (requires master key)
83
+ response = fetch_schema
99
84
 
100
- if response.success?
101
- #let's figure out the diff fields
102
- remote_fields = response.result['fields']
103
- current_schema = schema
104
- current_schema[:fields] = current_schema[:fields].reduce({}) do |h,(k,v)|
105
- #if the field does not exist in Parse, then add it to the update list
106
- h[k] = v if remote_fields[k.to_s].nil?
107
- h
108
- end
109
- return true if current_schema[:fields].empty?
110
- return update_schema( current_schema )
85
+ # if it's a core class that doesn't exist, then create the collection without any fields,
86
+ # since parse-server will automatically create the collection with the set of core fields.
87
+ # then fetch the schema again, to add the missing fields.
88
+ if response.error? && self.to_s.start_with?("Parse::") #is it a core class?
89
+ client.create_schema parse_class, {}
90
+ response = fetch_schema
91
+ # if it still wasn't able to be created, raise an error.
92
+ if response.error?
93
+ warn "[Parse] Schema error: unable to create class #{parse_class}"
94
+ return response
111
95
  end
112
- create_schema
113
96
  end
114
97
 
98
+ if response.success?
99
+ #let's figure out the diff fields
100
+ remote_fields = response.result["fields"]
101
+ current_schema = schema
102
+ current_schema[:fields] = current_schema[:fields].reduce({}) do |h, (k, v)|
103
+ #if the field does not exist in Parse, then add it to the update list
104
+ h[k] = v if remote_fields[k.to_s].nil?
105
+ h
106
+ end
107
+ return true if current_schema[:fields].empty?
108
+ return update_schema(current_schema)
109
+ end
110
+ create_schema
111
+ end
115
112
  end
116
113
  end
117
114
  end
@@ -1,31 +1,32 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'time'
5
- require 'date'
6
- require 'active_model'
7
- require 'active_support'
8
- require 'active_support/inflector'
9
- require 'active_support/core_ext/object'
10
- require 'active_support/core_ext/date/calculations'
11
- require 'active_support/core_ext/date_time/calculations'
12
- require 'active_support/core_ext/time/calculations'
13
- require 'active_model_serializers'
14
- require_relative 'model'
4
+ require "time"
5
+ require "date"
6
+ require "active_model"
7
+ require "active_support"
8
+ require "active_support/inflector"
9
+ require "active_support/core_ext/object"
10
+ require "active_support/core_ext/date/calculations"
11
+ require "active_support/core_ext/date_time/calculations"
12
+ require "active_support/core_ext/time/calculations"
13
+ require "active_model_serializers"
14
+ require_relative "model"
15
15
 
16
16
  module Parse
17
17
  # This class manages dates in the special JSON format it requires for
18
- # properties of type _:date_.
18
+ # properties of type _:date_.
19
19
  class Date < ::DateTime
20
20
  # The default attributes in a Parse Date hash.
21
- ATTRIBUTES = { __type: :string, iso: :string }.freeze
21
+ ATTRIBUTES = { __type: :string, iso: :string }.freeze
22
22
  include ::ActiveModel::Model
23
23
  include ::ActiveModel::Serializers::JSON
24
24
 
25
25
  # @return [Parse::Model::TYPE_DATE]
26
- def self.parse_class; Parse::Model::TYPE_DATE; end;
26
+ def self.parse_class; Parse::Model::TYPE_DATE; end
27
27
  # @return [Parse::Model::TYPE_DATE]
28
- def parse_class; self.class.parse_class; end;
28
+ def parse_class; self.class.parse_class; end
29
+
29
30
  alias_method :__type, :parse_class
30
31
 
31
32
  # @return [Hash]
@@ -42,7 +43,6 @@ module Parse
42
43
  def to_s(*args)
43
44
  args.empty? ? iso : super(*args)
44
45
  end
45
-
46
46
  end
47
47
  end
48
48
 
@@ -52,7 +52,6 @@ class Time
52
52
  def parse_date
53
53
  Parse::Date.parse iso8601(3)
54
54
  end
55
-
56
55
  end
57
56
 
58
57
  # Adds extensions to DateTime class to be compatible with {Parse::Date}.
@@ -1,204 +1,201 @@
1
1
  # encoding: UTF-8
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'active_support'
5
- require 'active_support/core_ext/object'
4
+ require "active_support"
5
+ require "active_support/core_ext/object"
6
6
  require_relative "model"
7
- require 'open-uri'
7
+ require "open-uri"
8
8
 
9
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`.
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.
32
- ATTRIBUTES = { __type: :string, name: :string, url: :string }.freeze
33
- # @return [String] the name of the file including extension (if any)
34
- attr_accessor :name
35
- # @return [String] the url resource of the file.
36
- attr_accessor :url
37
-
38
- # @return [Object] the contents of the file.
39
- attr_accessor :contents
40
-
41
- # @return [String] the mime-type of the file whe
42
- attr_accessor :mime_type
43
- # @return [Model::TYPE_FILE]
44
- def self.parse_class; TYPE_FILE; end;
45
- # @return [Model::TYPE_FILE]
46
- def parse_class; self.class.parse_class; end;
47
- alias_method :__type, :parse_class
48
- # @!visibility private
49
- FIELD_NAME = "name"
50
- # @!visibility private
51
- FIELD_URL = "url"
52
- class << self
53
-
54
- # @return [String] the default mime-type
55
- attr_accessor :default_mime_type
56
-
57
- # @return [Boolean] whether to force all urls to be https.
58
- attr_accessor :force_ssl
59
-
60
- # @return [String] The default mime type for created instances. Default: _'image/jpeg'_
61
- def default_mime_type
62
- @default_mime_type ||= "image/jpeg"
63
- end
64
-
65
- # @return [Boolean] When set to true, it will make all calls to File#url
66
- def force_ssl
67
- @force_ssl ||= false
68
- end
69
-
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`.
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.
32
+ ATTRIBUTES = { __type: :string, name: :string, url: :string }.freeze
33
+ # @return [String] the name of the file including extension (if any)
34
+ attr_accessor :name
35
+ # @return [String] the url resource of the file.
36
+ attr_accessor :url
37
+
38
+ # @return [Object] the contents of the file.
39
+ attr_accessor :contents
40
+
41
+ # @return [String] the mime-type of the file whe
42
+ attr_accessor :mime_type
43
+ # @return [Model::TYPE_FILE]
44
+ def self.parse_class; TYPE_FILE; end
45
+ # @return [Model::TYPE_FILE]
46
+ def parse_class; self.class.parse_class; end
47
+
48
+ alias_method :__type, :parse_class
49
+ # @!visibility private
50
+ FIELD_NAME = "name"
51
+ # @!visibility private
52
+ FIELD_URL = "url"
53
+ class << self
54
+
55
+ # @return [String] the default mime-type
56
+ attr_accessor :default_mime_type
57
+
58
+ # @return [Boolean] whether to force all urls to be https.
59
+ attr_accessor :force_ssl
60
+
61
+ # @return [String] The default mime type for created instances. Default: _'image/jpeg'_
62
+ def default_mime_type
63
+ @default_mime_type ||= "image/jpeg"
70
64
  end
71
- # The initializer to create a new file supports different inputs.
72
- # If the first paramter is a string which starts with 'http', we then download
73
- # the content of the file (and use the detected mime-type) to set the content and mime_type fields.
74
- # If the first parameter is a hash, we assume it might be the Parse File hash format which contains url and name fields only.
75
- # If the first paramter is a Parse::File, then we copy fields over
76
- # Otherwise, creating a new file requires a name, the actual contents (usually from a File.open("local.jpg").read ) and the mime-type
77
- # @param name [String]
78
- # @param contents [Object]
79
- # @param mime_type [String] Default see default_mime_type
80
- def initialize(name, contents = nil, mime_type = nil)
81
- mime_type ||= Parse::File.default_mime_type
82
-
83
- if name.is_a?(String) && name.start_with?('http') #could be url string
84
- file = open( name )
85
- @contents = file.read
86
- @name = File.basename file.base_uri.to_s
87
- @mime_type = file.content_type
88
- elsif name.is_a?(Hash)
89
- self.attributes = name
90
- elsif name.is_a?(::File)
91
- @contents = contents || name.read
92
- @name = File.basename name.to_path
93
- elsif name.is_a?(Parse::File)
94
- @name = name.name
95
- @url = name.url
96
- else
97
- @name = name
98
- @contents = contents
99
- end
100
- if @name.blank?
101
- raise ArgumentError, "Invalid Parse::File initialization with name '#{@name}'"
102
- end
103
-
104
- @mime_type ||= mime_type
105
65
 
66
+ # @return [Boolean] When set to true, it will make all calls to File#url
67
+ def force_ssl
68
+ @force_ssl ||= false
106
69
  end
107
-
108
- # This creates a new Parse File Object with from a URL, saves it and returns it
109
- # @param url [String] A url which will be used to create the file and automatically save it.
110
- # @return [Parse::File] A newly saved file based on contents of _url_
111
- def self.create(url)
112
- url = url.url if url.is_a?(Parse::File)
113
- file = self.new(url)
114
- file.save
115
- file
70
+ end
71
+ # The initializer to create a new file supports different inputs.
72
+ # If the first paramter is a string which starts with 'http', we then download
73
+ # the content of the file (and use the detected mime-type) to set the content and mime_type fields.
74
+ # If the first parameter is a hash, we assume it might be the Parse File hash format which contains url and name fields only.
75
+ # If the first paramter is a Parse::File, then we copy fields over
76
+ # Otherwise, creating a new file requires a name, the actual contents (usually from a File.open("local.jpg").read ) and the mime-type
77
+ # @param name [String]
78
+ # @param contents [Object]
79
+ # @param mime_type [String] Default see default_mime_type
80
+ def initialize(name, contents = nil, mime_type = nil)
81
+ mime_type ||= Parse::File.default_mime_type
82
+
83
+ if name.is_a?(String) && name.start_with?("http") #could be url string
84
+ file = open(name)
85
+ @contents = file.read
86
+ @name = File.basename file.base_uri.to_s
87
+ @mime_type = file.content_type
88
+ elsif name.is_a?(Hash)
89
+ self.attributes = name
90
+ elsif name.is_a?(::File)
91
+ @contents = contents || name.read
92
+ @name = File.basename name.to_path
93
+ elsif name.is_a?(Parse::File)
94
+ @name = name.name
95
+ @url = name.url
96
+ else
97
+ @name = name
98
+ @contents = contents
116
99
  end
117
-
118
- # A File object is considered saved if the basename of the URL and the name parameters are equal
119
- # @return [Boolean] true if this file has already been saved.
120
- def saved?
121
- @url.present? && @name.present? && @name == File.basename(@url)
100
+ if @name.blank?
101
+ raise ArgumentError, "Invalid Parse::File initialization with name '#{@name}'"
122
102
  end
123
103
 
124
- # Returns the url string for this Parse::File pointer. If the *force_ssl* option is
125
- # set to true, it will make sure it returns a secure url.
126
- # @return [String] the url string for the file.
127
- def url
128
- if @url.present? && Parse::File.force_ssl && @url.starts_with?('http://')
129
- return @url.sub('http://', 'https://')
130
- end
131
- @url
132
- end
104
+ @mime_type ||= mime_type
105
+ end
133
106
 
134
- # @return [Hash]
135
- def attributes
136
- ATTRIBUTES
137
- end
107
+ # This creates a new Parse File Object with from a URL, saves it and returns it
108
+ # @param url [String] A url which will be used to create the file and automatically save it.
109
+ # @return [Parse::File] A newly saved file based on contents of _url_
110
+ def self.create(url)
111
+ url = url.url if url.is_a?(Parse::File)
112
+ file = self.new(url)
113
+ file.save
114
+ file
115
+ end
138
116
 
139
- # @return [Boolean] Two files are equal if they have the same url
140
- def ==(u)
141
- return false unless u.is_a?(self.class)
142
- @url == u.url
143
- end
117
+ # A File object is considered saved if the basename of the URL and the name parameters are equal
118
+ # @return [Boolean] true if this file has already been saved.
119
+ def saved?
120
+ @url.present? && @name.present? && @name == File.basename(@url)
121
+ end
144
122
 
145
- # Allows mass assignment from a Parse JSON hash.
146
- def attributes=(h)
147
- if h.is_a?(String)
148
- @url = h
149
- @name = File.basename(h)
150
- elsif h.is_a?(Hash)
151
- @url = h[FIELD_URL] || h[:url] || @url
152
- @name = h[FIELD_NAME] || h[:name] || @name
153
- end
123
+ # Returns the url string for this Parse::File pointer. If the *force_ssl* option is
124
+ # set to true, it will make sure it returns a secure url.
125
+ # @return [String] the url string for the file.
126
+ def url
127
+ if @url.present? && Parse::File.force_ssl && @url.starts_with?("http://")
128
+ return @url.sub("http://", "https://")
154
129
  end
130
+ @url
131
+ end
155
132
 
156
- # A proxy method for ::File.basename
157
- # @param file_name [String]
158
- # @param suffix [String]
159
- # @return [String] File.basename(file_name)
160
- # @see ::File.basename
161
- def self.basename(file_name, suffix = nil)
162
- if suffix.nil?
163
- ::File.basename(file_name)
164
- else
165
- ::File.basename(file_name, suffix)
166
- end
167
- end
133
+ # @return [Hash]
134
+ def attributes
135
+ ATTRIBUTES
136
+ end
168
137
 
169
- # Save the file by uploading it to Parse and creating a file pointer.
170
- # @return [Boolean] true if successfully uploaded and saved.
171
- def save
172
- unless saved? || @contents.nil? || @name.nil?
173
- response = client.create_file(@name, @contents, @mime_type)
174
- unless response.error?
175
- result = response.result
176
- @name = result[FIELD_NAME] || File.basename(result[FIELD_URL])
177
- @url = result[FIELD_URL]
178
- end
179
- end
180
- saved?
181
- end
138
+ # @return [Boolean] Two files are equal if they have the same url
139
+ def ==(u)
140
+ return false unless u.is_a?(self.class)
141
+ @url == u.url
142
+ end
182
143
 
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')
144
+ # Allows mass assignment from a Parse JSON hash.
145
+ def attributes=(h)
146
+ if h.is_a?(String)
147
+ @url = h
148
+ @name = File.basename(h)
149
+ elsif h.is_a?(Hash)
150
+ @url = h[FIELD_URL] || h[:url] || @url
151
+ @name = h[FIELD_NAME] || h[:name] || @name
187
152
  end
153
+ end
188
154
 
189
- # @!visibility private
190
- def inspect
191
- "<Parse::File @name='#{@name}' @mime_type='#{@mime_type}' @contents=#{@contents.nil?} @url='#{@url}'>"
155
+ # A proxy method for ::File.basename
156
+ # @param file_name [String]
157
+ # @param suffix [String]
158
+ # @return [String] File.basename(file_name)
159
+ # @see ::File.basename
160
+ def self.basename(file_name, suffix = nil)
161
+ if suffix.nil?
162
+ ::File.basename(file_name)
163
+ else
164
+ ::File.basename(file_name, suffix)
192
165
  end
166
+ end
193
167
 
194
- # @return [String] the url
195
- # @see #url
196
- def to_s
197
- @url
168
+ # Save the file by uploading it to Parse and creating a file pointer.
169
+ # @return [Boolean] true if successfully uploaded and saved.
170
+ def save
171
+ unless saved? || @contents.nil? || @name.nil?
172
+ response = client.create_file(@name, @contents, @mime_type)
173
+ unless response.error?
174
+ result = response.result
175
+ @name = result[FIELD_NAME] || File.basename(result[FIELD_URL])
176
+ @url = result[FIELD_URL]
177
+ end
198
178
  end
179
+ saved?
180
+ end
199
181
 
182
+ # @return [Boolean] true if this file is hosted by Parse's servers.
183
+ def parse_hosted_file?
184
+ return false if @url.blank?
185
+ ::File.basename(@url).starts_with?("tfss-") || @url.starts_with?("http://files.parsetfss.com")
200
186
  end
201
187
 
188
+ # @!visibility private
189
+ def inspect
190
+ "<Parse::File @name='#{@name}' @mime_type='#{@mime_type}' @contents=#{@contents.nil?} @url='#{@url}'>"
191
+ end
192
+
193
+ # @return [String] the url
194
+ # @see #url
195
+ def to_s
196
+ @url
197
+ end
198
+ end
202
199
  end
203
200
 
204
201
  # Adds extensions to Hash class.