parsecom 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +139 -0
- data/Rakefile +1 -0
- data/lib/parse/client.rb +161 -0
- data/lib/parse/cloud_code.rb +2 -0
- data/lib/parse/ext/string.rb +11 -0
- data/lib/parse/file.rb +36 -0
- data/lib/parse/http_client.rb +23 -0
- data/lib/parse/object.rb +176 -0
- data/lib/parse/pointer.rb +25 -0
- data/lib/parse/query.rb +286 -0
- data/lib/parse/user.rb +47 -0
- data/lib/parse/version.rb +3 -0
- data/lib/parsecom.rb +58 -0
- data/parsecom.gemspec +21 -0
- data/spec/parse_object_spec.rb +54 -0
- data/spec/parse_query_spec.rb +176 -0
- data/spec/parse_user_spec.rb +23 -0
- data/spec/spec_helper.rb +14 -0
- metadata +87 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ando Yasushi
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,139 @@
|
|
1
|
+
# Parsecom
|
2
|
+
|
3
|
+
Yet-Another Parse.com Library written in Pure Ruby
|
4
|
+
|
5
|
+
## Usage
|
6
|
+
|
7
|
+
### Preparing
|
8
|
+
|
9
|
+
Before using the library, you should import this and set your credentials on
|
10
|
+
the library.
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
require 'parsecom'
|
14
|
+
Parse.credentials application_id:'YOUR APPID', api_key:'YOUR APIKEY'
|
15
|
+
```
|
16
|
+
|
17
|
+
### Declaring Parse Classes
|
18
|
+
|
19
|
+
There are three ways to declare a parse class.
|
20
|
+
|
21
|
+
First, you can declare a ruby class inherited from Parse::Object. By using
|
22
|
+
this way, you can add your own properties and methods to the class.
|
23
|
+
|
24
|
+
```ruby
|
25
|
+
class GameScore < Parse::Object
|
26
|
+
# ..snip..
|
27
|
+
end
|
28
|
+
```
|
29
|
+
|
30
|
+
Secondly, you can also declare your parse class by calling the Parse::Object
|
31
|
+
method.
|
32
|
+
|
33
|
+
```ruby
|
34
|
+
Parse::Object(:GameScore)
|
35
|
+
```
|
36
|
+
|
37
|
+
It returns a parse class, so that you can call its class methods directly.
|
38
|
+
|
39
|
+
```ruby
|
40
|
+
Parse::Object(:GameScore).find :limit => 3
|
41
|
+
```
|
42
|
+
|
43
|
+
Lastly, Parse::Object class provides create method for you to declare new
|
44
|
+
class.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
Parse::Object.create :GameScore
|
48
|
+
```
|
49
|
+
|
50
|
+
It may suitable for writing code in declarative style.
|
51
|
+
|
52
|
+
### Creating Objects
|
53
|
+
|
54
|
+
To create new parse object, juse new and save the object.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
game_score = GameScore.new
|
58
|
+
game_score.score = 1337
|
59
|
+
game_score.playerName = 'Sean Plott'
|
60
|
+
game_score.cheatMode = false
|
61
|
+
game_score.new? # => true
|
62
|
+
game_score.save
|
63
|
+
game_score.new? # => false
|
64
|
+
game_score.obj_id # => 'Ed1nuqPvcm'
|
65
|
+
```
|
66
|
+
|
67
|
+
### Retrieving Objects
|
68
|
+
|
69
|
+
There are two ways to retrieve objects. One is using Query objects directly and
|
70
|
+
another is using Parse::Object as a facade of query objects.
|
71
|
+
|
72
|
+
```ruby
|
73
|
+
# useing Query object directly
|
74
|
+
query = Parse::Query.new GameScore
|
75
|
+
query.where :objectId => 'Ed1nuqPvcm'
|
76
|
+
results = query.invoke
|
77
|
+
|
78
|
+
# using Query object through Parse::Object
|
79
|
+
results = GameScore.find :where => {:objectId => 'Ed1nuqPvcm'}
|
80
|
+
# if you would like to find by objectId, you can easily pass it directly
|
81
|
+
result = GameScore.find 'Ed1nuqPvcm'
|
82
|
+
```
|
83
|
+
|
84
|
+
More complex search
|
85
|
+
|
86
|
+
```ruby
|
87
|
+
# useing Query object directly
|
88
|
+
results = Parse::Query.new(GameScore).
|
89
|
+
limit(10).
|
90
|
+
order(score).
|
91
|
+
where do
|
92
|
+
column(:score).gte(1000).lte(3000)
|
93
|
+
column(:cheatMode).eq(false)
|
94
|
+
end.
|
95
|
+
invoke
|
96
|
+
|
97
|
+
# using Query object through Parse::Object
|
98
|
+
results = GameScore.find :limit => 10, :order => 'score',
|
99
|
+
:where => proc{
|
100
|
+
column(:score).gte(1000).lte(3000)
|
101
|
+
column(:cheatMode).eq(false)
|
102
|
+
}
|
103
|
+
```
|
104
|
+
|
105
|
+
To know more about retrieving objects, see spec/parse_query_spec.rb
|
106
|
+
|
107
|
+
### Updating Objects
|
108
|
+
|
109
|
+
To update attributes, just update the attribute and save.
|
110
|
+
|
111
|
+
```ruby
|
112
|
+
result = GameScore.find 'Ed1nuqPvcm'
|
113
|
+
result.score = 73453
|
114
|
+
result.save
|
115
|
+
```
|
116
|
+
|
117
|
+
If you want to update attributes without retrieving the object, you can use
|
118
|
+
the Parse::Client object for it.
|
119
|
+
|
120
|
+
```ruby
|
121
|
+
score = GameScore.new :objectId => 'Ed1nuqPvcm'
|
122
|
+
Parse::Client.default_client.update score, :score => 73453
|
123
|
+
```
|
124
|
+
|
125
|
+
### Deleting Objects
|
126
|
+
|
127
|
+
TBD
|
128
|
+
|
129
|
+
### Sign up
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
user = Parse::User.sign_up 'YOUR USERNAME', 'YOUR PASSWORD'
|
133
|
+
```
|
134
|
+
|
135
|
+
### Log in
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
user = Parse::User.log_in 'YOUR USERNAME', 'YOUR PASSWORD'
|
139
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/lib/parse/client.rb
ADDED
@@ -0,0 +1,161 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
module Parse
|
3
|
+
class Client
|
4
|
+
API_SERVER = 'api.parse.com'
|
5
|
+
API_VERSION = 1
|
6
|
+
@@default_client = nil
|
7
|
+
|
8
|
+
attr_accessor :http_client, :session_token
|
9
|
+
|
10
|
+
def self.default_client
|
11
|
+
@@default_client ||= new
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize application_id=nil, api_key=nil, http_client=nil
|
15
|
+
@application_id = application_id || Parse.application_id
|
16
|
+
@api_key = api_key || Parse.api_key
|
17
|
+
if @application_id.nil? || @api_key.nil?
|
18
|
+
raise ArgumentError.new <<-EOS
|
19
|
+
Both Application ID and API Key must be set.
|
20
|
+
ex. Parse.credentials application_id: APPLICATION_ID, api_key: API_KEY
|
21
|
+
EOS
|
22
|
+
end
|
23
|
+
@http_client = http_client || Parse::HttpClient.new(API_SERVER)
|
24
|
+
end
|
25
|
+
|
26
|
+
def call_api method, endpoint, body=nil, opt_headers={}, &block
|
27
|
+
endpoint = "/#{API_VERSION}/#{endpoint}" unless endpoint[0] == '/'
|
28
|
+
headers = {
|
29
|
+
'X-Parse-Application-Id' => @application_id,
|
30
|
+
'X-Parse-REST-API-Key' => @api_key,
|
31
|
+
'Content-Type' => 'application/json'
|
32
|
+
}
|
33
|
+
headers.update('X-Parse-Session-Token' => @session_token) if @session_token
|
34
|
+
headers.update opt_headers
|
35
|
+
if body.is_a?(Hash)
|
36
|
+
body = Hash[*(body.to_a.map{|k, v| [k, URI.encode(v)]}.flatten)].to_json
|
37
|
+
end
|
38
|
+
@http_client.request method, endpoint, headers, body, &block
|
39
|
+
end
|
40
|
+
|
41
|
+
def sign_up username, password, opts={}, &block
|
42
|
+
call_api :post, 'users', {'username' => username, 'password' => password}.update(opts || {}), &block
|
43
|
+
end
|
44
|
+
|
45
|
+
def log_in username, password, &block
|
46
|
+
call_api :get, "login?username=#{URI.encode username}&password=#{
|
47
|
+
URI.encode password}", nil, &block
|
48
|
+
end
|
49
|
+
|
50
|
+
def find parse_class, object_id_or_conditions, opts={}
|
51
|
+
if object_id_or_conditions.is_a? String
|
52
|
+
find_by_id parse_class, object_id_or_conditions, opts
|
53
|
+
elsif object_id_or_conditions.is_a? Hash
|
54
|
+
find_by_query parse_class, object_id_or_conditions
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def find_by_id parse_class, object_id, opts={}
|
59
|
+
call_api :get, "classes/#{parse_class.parse_class_name}/#{object_id}" do |resp_body|
|
60
|
+
convert parse_class, resp_body
|
61
|
+
|
62
|
+
if opts.has_key? :include
|
63
|
+
included_keys = opts[:include]
|
64
|
+
included_keys = [included_keys] unless included_keys.is_a? Enumerable
|
65
|
+
included_keys.each do |included_key|
|
66
|
+
pointer = resp_body[included_key]
|
67
|
+
pointer.load
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
parse_class.new resp_body
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def find_by_query parse_class, conditions
|
76
|
+
query = Query.new parse_class
|
77
|
+
query.limit conditions[:limit] if conditions.has_key? :limit
|
78
|
+
query.skip conditions[:skip] if conditions.has_key? :skip
|
79
|
+
query.count conditions[:count] if conditions.has_key? :count
|
80
|
+
if conditions.has_key? :order
|
81
|
+
order = conditions[:order]
|
82
|
+
order = [order] unless order.is_a? Array
|
83
|
+
query.order order
|
84
|
+
end
|
85
|
+
if conditions.has_key? :keys
|
86
|
+
keys = conditions[:keys]
|
87
|
+
keys = [keys] unless keys.is_a? Array
|
88
|
+
query.keys keys
|
89
|
+
end
|
90
|
+
if conditions.has_key? :include
|
91
|
+
include = conditions[:include]
|
92
|
+
include = [include] unless include.is_a? Array
|
93
|
+
query.include include
|
94
|
+
end
|
95
|
+
if conditions.has_key? :where
|
96
|
+
case condition = conditions[:where]
|
97
|
+
when Hash
|
98
|
+
query.where condition
|
99
|
+
when Proc
|
100
|
+
query.where condition
|
101
|
+
else
|
102
|
+
raise 'wrong condition'
|
103
|
+
end
|
104
|
+
end
|
105
|
+
query.invoke
|
106
|
+
end
|
107
|
+
|
108
|
+
def create parse_object, values
|
109
|
+
call_api :post, "classes/#{parse_object.parse_class_name}", values.to_json do |resp_body|
|
110
|
+
resp_body
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def update parse_object, values
|
115
|
+
call_api :put, "classes/#{parse_object.parse_class_name}/#{parse_object.object_id}", values.to_json do |resp_body|
|
116
|
+
resp_body
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def delete parse_object
|
121
|
+
call_api :delete, "classes/#{parse_object.parse_class_name}/#{parse_object.object_id}" do |resp_body|
|
122
|
+
resp_body
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
def call_function name, param
|
127
|
+
func_name = Parse.auto_snake_case ? name.to_s.gsub(/_([a-z])/) {$1.upcase} : name
|
128
|
+
call_api :post, "functions/#{func_name}", param.to_json do |resp_body|
|
129
|
+
if resp_body.has_key? 'result'
|
130
|
+
resp_body['result']
|
131
|
+
else
|
132
|
+
raise StandartError.new 'unknown error'
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def method_missing name, *args, &block
|
138
|
+
call_function name, args.first
|
139
|
+
end
|
140
|
+
|
141
|
+
private
|
142
|
+
|
143
|
+
def convert parse_class, resp_body
|
144
|
+
resp_body.each do |k, v|
|
145
|
+
if v.is_a?(Hash) && v.has_key?('__type')
|
146
|
+
resp_body[k] = case v['__type']
|
147
|
+
when 'Date'
|
148
|
+
Date.parse v['iso']
|
149
|
+
when 'File'
|
150
|
+
Parse::File.new v
|
151
|
+
when 'Pointer'
|
152
|
+
# TODO: too many arguments
|
153
|
+
Parse::Pointer.new self, parse_class, resp_body, k, v
|
154
|
+
else
|
155
|
+
v
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
data/lib/parse/file.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding:utf-8
|
2
|
+
module Parse
|
3
|
+
class File
|
4
|
+
attr_accessor :name, :url
|
5
|
+
|
6
|
+
def initialize hash
|
7
|
+
@raw_hash = hash
|
8
|
+
@name = hash['name']
|
9
|
+
@url = hash['url']
|
10
|
+
end
|
11
|
+
|
12
|
+
def load &block
|
13
|
+
open @url do |data| @data = data.read end unless @data
|
14
|
+
block.call @data
|
15
|
+
end
|
16
|
+
|
17
|
+
def store filepath=nil
|
18
|
+
filepath ||= @name
|
19
|
+
raise 'filepath is mandatory' unless filepath
|
20
|
+
|
21
|
+
FileUtils.mkdir_p ::File.dirname(filepath)
|
22
|
+
load do |data|
|
23
|
+
open filepath, 'wb' do |file|
|
24
|
+
file.write data
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def inspect
|
30
|
+
data, @data = @data, '..snip..'
|
31
|
+
ret = super
|
32
|
+
@data = data
|
33
|
+
ret
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
module Parse
|
3
|
+
class HttpClient
|
4
|
+
def initialize host
|
5
|
+
@host = host
|
6
|
+
end
|
7
|
+
|
8
|
+
def request method, endpoint, headers={}, body=nil, &block
|
9
|
+
req = eval("Net::HTTP::#{method.to_s.capitalize}").new endpoint, headers
|
10
|
+
req.body = body if body
|
11
|
+
client = Net::HTTP.new @host, 443
|
12
|
+
#client.set_debug_output $stderr
|
13
|
+
client.use_ssl = true
|
14
|
+
client.start do
|
15
|
+
resp = client.request req
|
16
|
+
resp_body = JSON.parse resp.body
|
17
|
+
raise StandardError.new "error calling #{endpoint}: #{
|
18
|
+
resp_body['error']}" if resp_body.has_key? 'error'
|
19
|
+
block.call resp_body if block
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/parse/object.rb
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
module Parse
|
3
|
+
class Object
|
4
|
+
class << self
|
5
|
+
attr_accessor :parse_class_name, :parse_client, :auto_camel_case
|
6
|
+
|
7
|
+
def create parse_class_name, mod=::Object
|
8
|
+
raise 'already defined' if mod.const_defined? parse_class_name
|
9
|
+
|
10
|
+
klass = Class.new(Parse::Object)
|
11
|
+
klass.parse_class_name = parse_class_name.to_sym
|
12
|
+
klass.auto_camel_case = true
|
13
|
+
mod.const_set parse_class_name, klass
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse_class_name
|
17
|
+
@parse_class_name || name.split('::').last
|
18
|
+
end
|
19
|
+
|
20
|
+
def parse_client
|
21
|
+
@parse_client ||= Parse::Client.default_client
|
22
|
+
end
|
23
|
+
|
24
|
+
def find object_id_or_conditions, opts={}
|
25
|
+
parse_client.find self, object_id_or_conditions, opts
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_accessor :obj_id, :created_at, :updated_at, :acl
|
30
|
+
|
31
|
+
def initialize hash={}
|
32
|
+
hash = string_keyed_hash hash
|
33
|
+
if hash.has_key? 'objectId'
|
34
|
+
@obj_id = hash['objectId']
|
35
|
+
@raw_hash = hash
|
36
|
+
@updated_hash = {}
|
37
|
+
else
|
38
|
+
@raw_hash = {}
|
39
|
+
@updated_hash = hash
|
40
|
+
end
|
41
|
+
@deleted = false
|
42
|
+
end
|
43
|
+
|
44
|
+
def new?
|
45
|
+
!@deleted && @raw_hash.empty?
|
46
|
+
end
|
47
|
+
|
48
|
+
def updated?
|
49
|
+
!@deleted && !@updated_hash.empty?
|
50
|
+
end
|
51
|
+
|
52
|
+
def deleted?
|
53
|
+
@deleted
|
54
|
+
end
|
55
|
+
|
56
|
+
def parse_client
|
57
|
+
self.class.parse_client
|
58
|
+
end
|
59
|
+
|
60
|
+
def parse_class_name
|
61
|
+
self.class.parse_class_name
|
62
|
+
end
|
63
|
+
|
64
|
+
def save hash=@updated_hash
|
65
|
+
check_deleted!
|
66
|
+
hash = string_keyed_hash hash
|
67
|
+
if new?
|
68
|
+
create hash
|
69
|
+
else
|
70
|
+
update hash
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
def create hash
|
75
|
+
check_deleted!
|
76
|
+
hash = string_keyed_hash hash
|
77
|
+
@updated_hash.update hash
|
78
|
+
parse_client.create(self, @updated_hash).tap do |response|
|
79
|
+
@obj_id = response['objectId']
|
80
|
+
@created_at = Date.parse response['createdAt']
|
81
|
+
@updated_at = @created_at
|
82
|
+
@raw_hash.update @updated_hash
|
83
|
+
@raw_hash.update response
|
84
|
+
@updated_hash.clear
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def update hash
|
89
|
+
check_deleted!
|
90
|
+
hash = string_keyed_hash hash
|
91
|
+
parse_client.update(self, hash).tap do |response|
|
92
|
+
@updated_at = Date.parse response['updatedAt']
|
93
|
+
@raw_hash.update @updated_hash
|
94
|
+
@updated_hash.clear
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def delete
|
99
|
+
raise 'You cannot delete new object' if new?
|
100
|
+
check_deleted!
|
101
|
+
parse_client.delete(self).tap do |response|
|
102
|
+
@deleted = true
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def obj_id
|
107
|
+
@obj_id || @raw_hash['objectId']
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_column name
|
111
|
+
name = name.to_s
|
112
|
+
ret = @updated_hash[name]
|
113
|
+
if ret.nil? && self.class.auto_camel_case
|
114
|
+
ret = @updated_hash[name.camelize :lower]
|
115
|
+
end
|
116
|
+
if ret.nil?
|
117
|
+
ret = @raw_hash[name]
|
118
|
+
if ret.nil? && self.class.auto_camel_case
|
119
|
+
ret = @raw_hash[name.camelize :lower]
|
120
|
+
end
|
121
|
+
end
|
122
|
+
ret
|
123
|
+
end
|
124
|
+
|
125
|
+
def set_column name, value
|
126
|
+
check_deleted!
|
127
|
+
@updated_hash[name] = value
|
128
|
+
end
|
129
|
+
|
130
|
+
def to_s
|
131
|
+
"<#{parse_class_name}: #{{}.update(@raw_hash).update(@updated_hash).to_s}>"
|
132
|
+
end
|
133
|
+
|
134
|
+
def method_missing name, *args, &block
|
135
|
+
if name =~ /^\w+$/ && args.empty? && block.nil?
|
136
|
+
get_column name
|
137
|
+
elsif name[-1] == '=' && args.size == 1 && block.nil?
|
138
|
+
set_column name[0..-2], args.first
|
139
|
+
else
|
140
|
+
super
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
private
|
145
|
+
|
146
|
+
def string_keyed_hash hash
|
147
|
+
new_hash = {}
|
148
|
+
hash.each do |k, v|
|
149
|
+
new_hash[k.to_s] = v
|
150
|
+
end
|
151
|
+
new_hash
|
152
|
+
end
|
153
|
+
|
154
|
+
def check_deleted!
|
155
|
+
raise 'This object has already been deleted.' if deleted?
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# create or get ParseObject class in the given module
|
161
|
+
#
|
162
|
+
# == Parameters:
|
163
|
+
# parse_class_name::
|
164
|
+
# Parse class name
|
165
|
+
# mod::
|
166
|
+
# module where ParseObject is populated
|
167
|
+
#
|
168
|
+
# == Returns:
|
169
|
+
# subclass of ParseObject for the given parse_class_name
|
170
|
+
#
|
171
|
+
def self.Object parse_class_name, mod=::Object
|
172
|
+
Parse::Object.create parse_class_name, mod \
|
173
|
+
unless mod.const_defined? parse_class_name
|
174
|
+
mod.const_get parse_class_name
|
175
|
+
end
|
176
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding:utf-8
|
2
|
+
module Parse
|
3
|
+
class Pointer
|
4
|
+
def initialize parse_client, parent_parse_class, parent_hash, parent_key, hash
|
5
|
+
@parse_client = parse_client
|
6
|
+
@parent_parse_class = parent_parse_class
|
7
|
+
@parent_hash = parent_hash
|
8
|
+
@parent_key = parent_key
|
9
|
+
@raw_hash = hash
|
10
|
+
end
|
11
|
+
|
12
|
+
def load &block
|
13
|
+
included_parse_class_name = @raw_hash['className']
|
14
|
+
mod = @parent_parse_class.name.include?('::') ? \
|
15
|
+
eval(@perent_parse_class.name.split('::')[0..-2]) : ::Object
|
16
|
+
included_parse_class = Parse::Object included_parse_class_name, mod
|
17
|
+
@parent_hash[@parent_key] = @parse_client.find(
|
18
|
+
included_parse_class, @raw_hash['objectId']).tap do |real_value|
|
19
|
+
if block
|
20
|
+
block.call real_value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|