parse_resource 1.6.0 → 1.6.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/README.md +2 -2
- data/VERSION +1 -1
- data/lib/base.rb +221 -230
- data/lib/criteria.rb +79 -0
- data/lib/parse_resource.rb +1 -0
- data/parse_resource.gemspec +3 -3
- data/rdoc/ParseResource.html +18 -1138
- data/rdoc/created.rid +5 -3
- data/rdoc/index.html +58 -30
- data/rdoc/lib/parse_resource_rb.html +4 -14
- data/test/test_parse_resource.rb +57 -0
- metadata +24 -24
- data/lib/parse_resource_old.rb +0 -286
data/README.md
CHANGED
@@ -44,7 +44,7 @@ Installation
|
|
44
44
|
Include in your `Gemfile`:
|
45
45
|
|
46
46
|
```ruby
|
47
|
-
gem "parse_resource", "~> 1.
|
47
|
+
gem "parse_resource", "~> 1.6.0"
|
48
48
|
```
|
49
49
|
|
50
50
|
Or just gem install:
|
@@ -75,7 +75,7 @@ In a non-Rails app, include this somewhere (preferable in an initializer):
|
|
75
75
|
|
76
76
|
|
77
77
|
```ruby
|
78
|
-
ParseResource.load!("your_app_id", "your_master_key")
|
78
|
+
ParseResource::Base.load!("your_app_id", "your_master_key")
|
79
79
|
```
|
80
80
|
|
81
81
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
1.6.
|
1
|
+
1.6.1
|
data/lib/base.rb
CHANGED
@@ -5,285 +5,276 @@ require "erb"
|
|
5
5
|
require "rest-client"
|
6
6
|
require "json"
|
7
7
|
require "active_support/hash_with_indifferent_access"
|
8
|
+
require "criteria"
|
8
9
|
|
9
10
|
module ParseResource
|
10
11
|
|
11
12
|
class Base
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
create_setters!
|
44
|
-
end
|
45
|
-
|
46
|
-
# Explicitly adds a field to the model.
|
47
|
-
#
|
48
|
-
# @param [Symbol] name the name of the field, eg `:author`.
|
49
|
-
# @param [Boolean] val the return value of the field. Only use this within the class.
|
50
|
-
def self.field(name, val=nil)
|
51
|
-
class_eval do
|
52
|
-
define_method(name) do
|
53
|
-
@attributes[name] ? @attributes[name] : @unsaved_attributes[name]
|
13
|
+
# ParseResource::Base provides an easy way to use Ruby to interace with a Parse.com backend
|
14
|
+
# Usage:
|
15
|
+
# class Post < ParseResource::Base
|
16
|
+
# fields :title, :author, :body
|
17
|
+
# end
|
18
|
+
|
19
|
+
include ActiveModel::Validations
|
20
|
+
include ActiveModel::Conversion
|
21
|
+
include ActiveModel::AttributeMethods
|
22
|
+
extend ActiveModel::Naming
|
23
|
+
extend ActiveModel::Callbacks
|
24
|
+
HashWithIndifferentAccess = ActiveSupport::HashWithIndifferentAccess
|
25
|
+
|
26
|
+
define_model_callbacks :save, :create, :update, :destroy
|
27
|
+
|
28
|
+
|
29
|
+
# Instantiates a ParseResource::Base object
|
30
|
+
#
|
31
|
+
# @params [Hash], [Boolean] a `Hash` of attributes and a `Boolean` that should be false only if the object already exists
|
32
|
+
# @return [ParseResource::Base] an object that subclasses `Parseresource::Base`
|
33
|
+
def initialize(attributes = {}, new=true)
|
34
|
+
attributes = HashWithIndifferentAccess.new(attributes)
|
35
|
+
if new
|
36
|
+
@unsaved_attributes = attributes
|
37
|
+
else
|
38
|
+
@unsaved_attributes = {}
|
39
|
+
end
|
40
|
+
self.attributes = {}
|
41
|
+
self.attributes.merge!(attributes)
|
42
|
+
self.attributes unless self.attributes.empty?
|
43
|
+
create_setters!
|
54
44
|
end
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
45
|
+
|
46
|
+
# Explicitly adds a field to the model.
|
47
|
+
#
|
48
|
+
# @param [Symbol] name the name of the field, eg `:author`.
|
49
|
+
# @param [Boolean] val the return value of the field. Only use this within the class.
|
50
|
+
def self.field(name, val=nil)
|
51
|
+
class_eval do
|
52
|
+
define_method(name) do
|
53
|
+
@attributes[name] ? @attributes[name] : @unsaved_attributes[name]
|
54
|
+
end
|
55
|
+
define_method("#{name}=") do |val|
|
56
|
+
@attributes[name] = val
|
57
|
+
@unsaved_attributes[name] = val
|
58
|
+
val
|
59
|
+
end
|
60
|
+
end
|
59
61
|
end
|
60
|
-
end
|
61
|
-
end
|
62
62
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
63
|
+
# Add multiple fields in one line. Same as `#field`, but accepts multiple args.
|
64
|
+
#
|
65
|
+
# @param [Array] *args an array of `Symbol`s, `eg :author, :body, :title`.
|
66
|
+
def self.fields(*args)
|
67
|
+
args.each {|f| field(f)}
|
68
|
+
end
|
69
69
|
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
70
|
+
# Creates getter and setter methods for model fields
|
71
|
+
#
|
72
|
+
def create_setters!
|
73
|
+
@attributes.each_pair do |k,v|
|
74
|
+
self.class.send(:define_method, "#{k}=") do |val|
|
75
|
+
if k.is_a?(Symbol)
|
76
|
+
k = k.to_s
|
77
|
+
end
|
78
|
+
@attributes[k.to_s] = val
|
79
|
+
@unsaved_attributes[k.to_s] = val
|
80
|
+
val
|
81
|
+
end
|
82
|
+
self.class.send(:define_method, "#{k}") do
|
83
|
+
if k.is_a?(Symbol)
|
84
|
+
k = k.to_s
|
85
|
+
end
|
86
|
+
|
87
|
+
@attributes[k.to_s]
|
88
|
+
end
|
77
89
|
end
|
78
|
-
@attributes[k.to_s] = val
|
79
|
-
@unsaved_attributes[k.to_s] = val
|
80
|
-
val
|
81
90
|
end
|
82
|
-
self.class.send(:define_method, "#{k}") do
|
83
|
-
if k.is_a?(Symbol)
|
84
|
-
k = k.to_s
|
85
|
-
end
|
86
91
|
|
87
|
-
|
88
|
-
end
|
89
|
-
end
|
90
|
-
end
|
92
|
+
class << self
|
91
93
|
|
92
|
-
|
93
|
-
def has_one(child_name)
|
94
|
-
class_eval do
|
94
|
+
@@settings ||= nil
|
95
95
|
|
96
|
-
|
97
|
-
|
96
|
+
# Explicitly set Parse.com API keys.
|
97
|
+
#
|
98
|
+
# @param [String] app_id the Application ID of your Parse database
|
99
|
+
# @param [String] master_key the Master Key of your Parse database
|
100
|
+
def load!(app_id, master_key)
|
101
|
+
@@settings = {"app_id" => app_id, "master_key" => master_key}
|
98
102
|
end
|
99
103
|
|
100
|
-
|
101
|
-
|
104
|
+
# Creates a RESTful resource
|
105
|
+
# sends requests to [base_uri]/[classname]
|
106
|
+
#
|
107
|
+
def resource
|
108
|
+
if @@settings.nil?
|
109
|
+
path = "config/parse_resource.yml"
|
110
|
+
environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"]
|
111
|
+
@@settings = YAML.load(ERB.new(File.new(path).read).result)[environment]
|
112
|
+
end
|
113
|
+
base_uri = "https://api.parse.com/1/classes/#{model_name}"
|
114
|
+
app_id = @@settings['app_id']
|
115
|
+
master_key = @@settings['master_key']
|
116
|
+
RestClient::Resource.new(base_uri, app_id, master_key)
|
102
117
|
end
|
103
118
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
119
|
+
# Find a ParseResource::Base object by ID
|
120
|
+
#
|
121
|
+
# @param [String] id the ID of the Parse object you want to find.
|
122
|
+
# @return [ParseResource] an object that subclasses ParseResource.
|
123
|
+
def find(id)
|
124
|
+
where(:objectId => id).first
|
125
|
+
end
|
109
126
|
|
110
|
-
|
111
|
-
|
127
|
+
# Find a ParseResource::Base object by chaining #where method calls.
|
128
|
+
#
|
129
|
+
def where(*args)
|
130
|
+
Criteria.new(self).where(*args)
|
112
131
|
end
|
113
132
|
|
114
|
-
|
115
|
-
|
133
|
+
# Add this at the end of a method chain to get the count of objects, instead of an Array of objects
|
134
|
+
def count
|
135
|
+
#https://www.parse.com/docs/rest#queries-counting
|
136
|
+
Criteria.new(self).count(1)
|
116
137
|
end
|
117
138
|
|
118
|
-
|
119
|
-
|
139
|
+
# Find all ParseResource::Base objects for that model.
|
140
|
+
#
|
141
|
+
# @return [Array] an `Array` of objects that subclass `ParseResource`.
|
142
|
+
def all
|
143
|
+
Criteria.new(self).all
|
144
|
+
end
|
120
145
|
|
146
|
+
# Find the first object. Fairly random, not based on any specific condition.
|
147
|
+
#
|
148
|
+
def first
|
149
|
+
Criteria.new(self).limit(1).first
|
150
|
+
end
|
121
151
|
|
122
|
-
|
152
|
+
# Limits the number of objects returned
|
153
|
+
#
|
154
|
+
def limit(n)
|
155
|
+
Criteria.new(self).limit(n)
|
156
|
+
end
|
123
157
|
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
158
|
+
# Create a ParseResource::Base object.
|
159
|
+
#
|
160
|
+
# @param [Hash] attributes a `Hash` of attributes
|
161
|
+
# @return [ParseResource] an object that subclasses `ParseResource`. Or returns `false` if object fails to save.
|
162
|
+
def create(attributes = {})
|
163
|
+
attributes = HashWithIndifferentAccess.new(attributes)
|
164
|
+
new(attributes).save
|
165
|
+
end
|
131
166
|
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
path = "config/parse_resource.yml"
|
138
|
-
environment = defined?(Rails) && Rails.respond_to?(:env) ? Rails.env : ENV["RACK_ENV"]
|
139
|
-
@@settings = YAML.load(ERB.new(File.new(path).read).result)[environment]
|
140
|
-
end
|
141
|
-
base_uri = "https://api.parse.com/1/classes/#{model_name}"
|
142
|
-
app_id = @@settings['app_id']
|
143
|
-
master_key = @@settings['master_key']
|
144
|
-
RestClient::Resource.new(base_uri, app_id, master_key)
|
145
|
-
end
|
167
|
+
def destroy_all
|
168
|
+
all.each do |object|
|
169
|
+
object.destroy
|
170
|
+
end
|
171
|
+
end
|
146
172
|
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
# @return [ParseResource] an object that subclasses ParseResource.
|
151
|
-
def find(id)
|
152
|
-
where(:objectId => id).first
|
153
|
-
end
|
173
|
+
def class_attributes
|
174
|
+
@class_attributes ||= {}
|
175
|
+
end
|
154
176
|
|
155
|
-
|
156
|
-
#
|
157
|
-
# @param [Hash] parameters a `Hash` of conditions.
|
158
|
-
# @return [Array] an `Array` of objects that subclass `ParseResource`.
|
159
|
-
def where(parameters)
|
160
|
-
resp = resource.get(:params => {:where => parameters.to_json})
|
161
|
-
results = JSON.parse(resp)['results']
|
162
|
-
results.map {|r| model_name.constantize.new(r, false)}
|
163
|
-
end
|
177
|
+
end
|
164
178
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
end
|
179
|
+
def persisted?
|
180
|
+
if id
|
181
|
+
true
|
182
|
+
else
|
183
|
+
false
|
184
|
+
end
|
185
|
+
end
|
173
186
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
# @return [ParseResource] an object that subclasses `ParseResource`. Or returns `false` if object fails to save.
|
178
|
-
def create(attributes = {})
|
179
|
-
attributes = HashWithIndifferentAccess.new(attributes)
|
180
|
-
new(attributes).save
|
181
|
-
end
|
187
|
+
def new?
|
188
|
+
!persisted?
|
189
|
+
end
|
182
190
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
end
|
191
|
+
# delegate from Class method
|
192
|
+
def resource
|
193
|
+
self.class.resource
|
194
|
+
end
|
188
195
|
|
189
|
-
|
190
|
-
|
191
|
-
|
196
|
+
# create RESTful resource for the specific Parse object
|
197
|
+
# sends requests to [base_uri]/[classname]/[objectId]
|
198
|
+
def instance_resource
|
199
|
+
self.class.resource["#{self.id}"]
|
200
|
+
end
|
192
201
|
|
193
|
-
|
202
|
+
def create
|
203
|
+
resp = self.resource.post(@unsaved_attributes.to_json, :content_type => "application/json")
|
204
|
+
@attributes.merge!(JSON.parse(resp))
|
205
|
+
@attributes.merge!(@unsaved_attributes)
|
206
|
+
attributes = HashWithIndifferentAccess.new(attributes)
|
207
|
+
@unsaved_attributes = {}
|
208
|
+
create_setters!
|
209
|
+
self
|
210
|
+
end
|
194
211
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
212
|
+
def save
|
213
|
+
if valid?
|
214
|
+
run_callbacks :save do
|
215
|
+
new? ? create : update
|
216
|
+
end
|
217
|
+
else
|
218
|
+
false
|
219
|
+
end
|
220
|
+
rescue false
|
221
|
+
end
|
202
222
|
|
203
|
-
|
204
|
-
|
205
|
-
|
223
|
+
def update(attributes = {})
|
224
|
+
attributes = HashWithIndifferentAccess.new(attributes)
|
225
|
+
@unsaved_attributes.merge!(attributes)
|
206
226
|
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
227
|
+
put_attrs = @unsaved_attributes
|
228
|
+
put_attrs.delete('objectId')
|
229
|
+
put_attrs.delete('createdAt')
|
230
|
+
put_attrs.delete('updatedAt')
|
231
|
+
put_attrs = put_attrs.to_json
|
211
232
|
|
212
|
-
|
213
|
-
# sends requests to [base_uri]/[classname]/[objectId]
|
214
|
-
def instance_resource
|
215
|
-
self.class.resource["#{self.id}"]
|
216
|
-
end
|
233
|
+
resp = self.instance_resource.put(put_attrs, :content_type => "application/json")
|
217
234
|
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
attributes = HashWithIndifferentAccess.new(attributes)
|
223
|
-
@unsaved_attributes = {}
|
224
|
-
create_setters!
|
225
|
-
self
|
226
|
-
end
|
235
|
+
@attributes.merge!(JSON.parse(resp))
|
236
|
+
@attributes.merge!(@unsaved_attributes)
|
237
|
+
@unsaved_attributes = {}
|
238
|
+
create_setters!
|
227
239
|
|
228
|
-
|
229
|
-
if valid?
|
230
|
-
run_callbacks :save do
|
231
|
-
new? ? create : update
|
240
|
+
self
|
232
241
|
end
|
233
|
-
else
|
234
|
-
false
|
235
|
-
end
|
236
|
-
rescue false
|
237
|
-
end
|
238
|
-
|
239
|
-
def update(attributes = {})
|
240
|
-
attributes = HashWithIndifferentAccess.new(attributes)
|
241
|
-
@unsaved_attributes.merge!(attributes)
|
242
|
-
|
243
|
-
put_attrs = @unsaved_attributes
|
244
|
-
put_attrs.delete('objectId')
|
245
|
-
put_attrs.delete('createdAt')
|
246
|
-
put_attrs.delete('updatedAt')
|
247
|
-
put_attrs = put_attrs.to_json
|
248
242
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
@attributes.merge!(@unsaved_attributes)
|
253
|
-
@unsaved_attributes = {}
|
254
|
-
create_setters!
|
243
|
+
def update_attributes(attributes = {})
|
244
|
+
self.update(attributes)
|
245
|
+
end
|
255
246
|
|
256
|
-
|
257
|
-
|
247
|
+
def destroy
|
248
|
+
self.instance_resource.delete
|
249
|
+
@attributes = {}
|
250
|
+
@unsaved_attributes = {}
|
251
|
+
nil
|
252
|
+
end
|
258
253
|
|
259
|
-
|
260
|
-
|
261
|
-
|
254
|
+
# provides access to @attributes for getting and setting
|
255
|
+
def attributes
|
256
|
+
@attributes ||= self.class.class_attributes
|
257
|
+
@attributes
|
258
|
+
end
|
262
259
|
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
nil
|
268
|
-
end
|
260
|
+
def attributes=(n)
|
261
|
+
@attributes = n
|
262
|
+
@attributes
|
263
|
+
end
|
269
264
|
|
270
|
-
|
271
|
-
|
272
|
-
@attributes ||= self.class.class_attributes
|
273
|
-
@attributes
|
274
|
-
end
|
265
|
+
# aliasing for idiomatic Ruby
|
266
|
+
def id; self.objectId rescue nil; end
|
275
267
|
|
276
|
-
|
277
|
-
@attributes = n
|
278
|
-
@attributes
|
279
|
-
end
|
268
|
+
def created_at; self.createdAt; end
|
280
269
|
|
281
|
-
|
282
|
-
def id; self.objectId rescue nil; end
|
270
|
+
def updated_at; self.updatedAt rescue nil; end
|
283
271
|
|
284
|
-
|
272
|
+
def self.included(base)
|
273
|
+
base.extend(ClassMethods)
|
274
|
+
end
|
285
275
|
|
286
|
-
|
276
|
+
module ClassMethods
|
277
|
+
end
|
287
278
|
|
288
279
|
end
|
289
280
|
end
|
data/lib/criteria.rb
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
class Criteria
|
2
|
+
|
3
|
+
def initialize(klass)
|
4
|
+
@klass = klass
|
5
|
+
end
|
6
|
+
|
7
|
+
def criteria
|
8
|
+
@criteria ||= { :conditions => {} }
|
9
|
+
end
|
10
|
+
|
11
|
+
def where(args)
|
12
|
+
criteria[:conditions].merge!(args)
|
13
|
+
self
|
14
|
+
end
|
15
|
+
|
16
|
+
def limit(limit)
|
17
|
+
criteria[:limit] = limit
|
18
|
+
self
|
19
|
+
end
|
20
|
+
|
21
|
+
#TODO: make this work
|
22
|
+
#def skip(skip)
|
23
|
+
# criteria[:skip] = skip
|
24
|
+
# self
|
25
|
+
#end
|
26
|
+
|
27
|
+
def count(count)
|
28
|
+
criteria[:count] = count
|
29
|
+
#self
|
30
|
+
all
|
31
|
+
end
|
32
|
+
|
33
|
+
#def each(&block)
|
34
|
+
# resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
|
35
|
+
# results = JSON.parse(resp)['results']
|
36
|
+
# results.map {|r| @klass.model_name.constantize.new(r, false)}.each(&block)
|
37
|
+
#end
|
38
|
+
|
39
|
+
#def first
|
40
|
+
# resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
|
41
|
+
# results = JSON.parse(resp)['results']
|
42
|
+
# results.map {|r| @klass.model_name.constantize.new(r, false)}.first
|
43
|
+
#end
|
44
|
+
|
45
|
+
#def length
|
46
|
+
# resp = @klass.resource.get(:params => {:where => criteria[:conditions].to_json})
|
47
|
+
# results = JSON.parse(resp)['results']
|
48
|
+
# results.length
|
49
|
+
#end
|
50
|
+
|
51
|
+
def all
|
52
|
+
params = {}
|
53
|
+
params.merge!({:where => criteria[:conditions].to_json}) if criteria[:conditions]
|
54
|
+
params.merge!({:limit => criteria[:limit].to_json}) if criteria[:limit]
|
55
|
+
params.merge!({:skip => criteria[:skip].to_json}) if criteria[:skip]
|
56
|
+
params.merge!({:count => criteria[:count].to_json}) if criteria[:count]
|
57
|
+
|
58
|
+
resp = @klass.resource.get(:params => params)
|
59
|
+
|
60
|
+
if criteria[:count] == 1
|
61
|
+
results = JSON.parse(resp)['count']
|
62
|
+
return results.to_i
|
63
|
+
else
|
64
|
+
results = JSON.parse(resp)['results']
|
65
|
+
return results.map {|r| @klass.model_name.constantize.new(r, false)}
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_missing(meth)
|
70
|
+
if Array.method_defined?(meth)
|
71
|
+
all.send(meth)
|
72
|
+
else
|
73
|
+
super
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
end
|
data/lib/parse_resource.rb
CHANGED
data/parse_resource.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "parse_resource"
|
8
|
-
s.version = "1.6.
|
8
|
+
s.version = "1.6.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Alan deLevie"]
|
12
|
-
s.date = "2011-12-
|
12
|
+
s.date = "2011-12-09"
|
13
13
|
s.description = ""
|
14
14
|
s.email = "adelevie@gmail.com"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -25,9 +25,9 @@ Gem::Specification.new do |s|
|
|
25
25
|
"Rakefile",
|
26
26
|
"VERSION",
|
27
27
|
"lib/base.rb",
|
28
|
+
"lib/criteria.rb",
|
28
29
|
"lib/examples/post.rb",
|
29
30
|
"lib/parse_resource.rb",
|
30
|
-
"lib/parse_resource_old.rb",
|
31
31
|
"parse_resource.gemspec",
|
32
32
|
"rdoc/ParseResource.html",
|
33
33
|
"rdoc/created.rid",
|