parsecom 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|