dm-parse 0.2.1 → 0.2.2

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 CHANGED
@@ -78,6 +78,9 @@ By this, you can use `User.authenticate(username, password)` to sign in, and use
78
78
  * ParseDate: the date, use it like you use DateTime.
79
79
  * ParseFile: the file, give it a hash contain "name" and "url", or a IO object from web form, it will be uploaded.
80
80
 
81
+ ## Limits
82
+ * Does not support many-to-many relationships.
83
+
81
84
  ## Contributing to dm-parse
82
85
 
83
86
  * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
data/dm-parse.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "dm-parse"
8
- s.version = "0.2.1"
8
+ s.version = "0.2.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Zhi-Qiang Lei"]
12
- s.date = "2012-06-29"
12
+ s.date = "2012-07-02"
13
13
  s.description = "An extension to make DataMapper working on Parse.com"
14
14
  s.email = "zhiqiang.lei@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -32,6 +32,7 @@ Gem::Specification.new do |s|
32
32
  "lib/collection.rb",
33
33
  "lib/dm-parse.rb",
34
34
  "lib/is/parse.rb",
35
+ "lib/parse/engine.rb",
35
36
  "lib/parse/query.rb",
36
37
  "lib/parse/resource.rb",
37
38
  "lib/property/parse_date.rb",
@@ -11,40 +11,32 @@ module DataMapper
11
11
  API_KEY_HEADER = "X-Parse-REST-API-Key"
12
12
  MASTER_KEY_HEADER = "X-Parse-Master-Key"
13
13
 
14
- attr_reader :classes, :users, :login, :password_reset, :file_storage
14
+ attr_reader :engine
15
15
 
16
16
  def initialize(name, options)
17
17
  super
18
- @classes = build_parse_resource_for "classes"
19
- @users = build_parse_resource_for "users"
20
- @login = build_parse_resource_for "login"
21
- @password_reset = build_parse_resource_for "requestPasswordReset"
22
- @file_storage = build_parse_resource_for "files"
23
- end
24
-
25
- def parse_resources_for(model)
26
- storage_name = model.storage_name
27
- storage_name == "_User" ? users : classes[storage_name]
28
- end
29
-
30
- def parse_resource_for(resource)
31
- parse_resources_for(resource.model)[resource.id]
18
+ master = @options[:master].nil? ? false : @options[:master]
19
+ @engine = Parse::Engine.new @options[:app_id], @options[:api_key], master
32
20
  end
33
21
 
34
22
  def create(resources)
35
23
  resources.each do |resource|
36
- params = attributes_as_fields(resource.attributes(:property)).except("objectId", "createdAt", "updatedAt")
37
- model = resource.model
38
- result = parse_resources_for(model).post params: params
24
+ params = attributes_as_fields(resource.attributes(:property)).except("objectId", "createdAt", "updatedAt")
25
+ model = resource.model
26
+ storage_name = model.storage_name
27
+ result = engine.create storage_name, params
28
+
39
29
  initialize_serial resource, result["objectId"]
40
- resource.created_at = resource.updated_at = result["createdAt"]
30
+ resource.created_at = resource.updated_at = result["createdAt"].to_datetime
41
31
  end.size
42
32
  end
43
33
 
44
34
  def read(query)
45
- model = query.model
46
- params = parse_params_for(query)
47
- response = parse_resources_for(model).get params: params
35
+ model = query.model
36
+ params = parse_params_for(query)
37
+ storage_name = model.storage_name
38
+ response = engine.read storage_name, params
39
+
48
40
  response["results"]
49
41
  end
50
42
 
@@ -59,11 +51,13 @@ module DataMapper
59
51
  #
60
52
  # @api semipublic
61
53
  def read_count(query)
62
- model = query.model
63
- params = parse_params_for(query)
64
- params[:count] = 1
65
- params[:limit] = 0
66
- response = parse_resources_for(model).get params: params
54
+ model = query.model
55
+ params = parse_params_for(query)
56
+ params[:count] = 1
57
+ params[:limit] = 0
58
+ storage_name = model.storage_name
59
+ response = engine.read storage_name, params
60
+
67
61
  response["count"]
68
62
  end
69
63
 
@@ -79,7 +73,7 @@ module DataMapper
79
73
  #
80
74
  # @api semipublic
81
75
  def sign_in(username, password)
82
- login.get params: {username: username, password: password}
76
+ engine.sign_in username, password
83
77
  end
84
78
 
85
79
  # Request a password reset email
@@ -91,7 +85,7 @@ module DataMapper
91
85
  # @return [Hash]
92
86
  # a empty Hash
93
87
  def request_password_reset(email)
94
- password_reset.post params: {email: email}
88
+ engine.request_password_reset email
95
89
  end
96
90
 
97
91
  # Upload a file
@@ -108,38 +102,28 @@ module DataMapper
108
102
  #
109
103
  # @return [Hash]
110
104
  # the uploaded file information
111
- def upload_file(filename, content, content_type = MIME::Types.type_for(filename).first)
112
- headers = file_storage.options[:headers]
113
- headers = headers.merge("Content-Type" => content_type) if content_type
114
- file_storage[URI.escape(filename)].post body: content, headers: headers
105
+ def upload_file(filename, content, content_type)
106
+ engine.upload_file filename, content, content_type
115
107
  end
116
108
 
117
109
  def delete(resources)
118
110
  resources.each do |resource|
119
- parse_resource_for(resource).delete
111
+ storage_name = resource.model.storage_name
112
+
113
+ engine.delete storage_name, resource.id
120
114
  end.size
121
115
  end
122
116
 
123
117
  def update(attributes, resources)
124
118
  resources.each do |resource|
125
- params = attributes_as_fields(attributes).except("createdAt", "updatedAt")
126
- parse_resource_for(resource).put(params: params)
119
+ params = attributes_as_fields(attributes).except("createdAt", "updatedAt")
120
+ storage_name = resource.model.storage_name
121
+
122
+ engine.update storage_name, resource.id, params
127
123
  end.size
128
124
  end
129
125
 
130
126
  private
131
- def build_parse_resource_for(name)
132
- Parse::Resource.new(HOST, format: :json, headers: key_headers)[VERSION][name]
133
- end
134
-
135
- def key_headers
136
- key_type = @options[:master] ? MASTER_KEY_HEADER : API_KEY_HEADER
137
- {
138
- APP_ID_HEADER => @options[:app_id],
139
- key_type => @options[:api_key]
140
- }
141
- end
142
-
143
127
  def parse_params_for(query)
144
128
  result = { :limit => parse_limit_for(query) }
145
129
  if conditions = parse_conditions_for(query)
@@ -197,9 +181,20 @@ module DataMapper
197
181
  end
198
182
 
199
183
  def feed_for(parse_query, condition, comparison_class)
200
- field = condition.subject.field
201
- comparison = comparison_class.new condition.value
202
- parse_query.add field, comparison
184
+ subject = condition.subject
185
+ case subject
186
+ when DataMapper::Property
187
+ comparison = comparison_class.new condition.value
188
+ parse_query.add subject.field, comparison
189
+ when DataMapper::Associations::OneToMany::Relationship
190
+ child_key = condition.subject.child_key.first
191
+ parse_query.add "objectId", comparison_class.new(condition.value.map { |resource| resource.send child_key.name })
192
+ when DataMapper::Associations::ManyToOne::Relationship
193
+ child_key = subject.child_key.first
194
+ parse_query.add child_key.field, comparison_class.new(condition.foreign_key_mapping.value)
195
+ else
196
+ raise NotImplementedError, "Condition: #{condition}"
197
+ end
203
198
  end
204
199
 
205
200
  def feed_reversely(parse_query, conditions)
@@ -212,7 +207,7 @@ module DataMapper
212
207
  when LessThanOrEqualToComparison then feed_for(parse_query, condition, Gt)
213
208
  when NotOperation then feed_directly(parse_query, condition)
214
209
  when AndOperation then feed_reversely(parse_query, condition)
215
- when InclusionComparison then feed_inclusion(parse_query, condition, Nin)
210
+ when InclusionComparison then feed_for(parse_query, condition, Nin)
216
211
  else
217
212
  raise NotImplementedError
218
213
  end
@@ -241,23 +236,14 @@ module DataMapper
241
236
  when GreaterThanOrEqualToComparison then feed_for(parse_query, condition, Gte)
242
237
  when LessThanComparison then feed_for(parse_query, condition, Lt)
243
238
  when LessThanOrEqualToComparison then feed_for(parse_query, condition, Lte)
239
+ when InclusionComparison then feed_for(parse_query, condition, In)
244
240
  when NotOperation then feed_reversely(parse_query, condition)
245
241
  when AndOperation then feed_directly(parse_query, condition)
246
- when InclusionComparison then feed_inclusion(parse_query, condition, In)
247
242
  else
248
243
  raise NotImplementedError
249
244
  end
250
245
  end
251
246
 
252
- def feed_inclusion(parse_query, condition, comparison_class)
253
- if condition.subject.is_a?(DataMapper::Associations::OneToMany::Relationship)
254
- child_key = condition.subject.child_key.first.name
255
- parse_query.add "objectId", comparison_class.new(condition.value.map { |resource| resource.send child_key })
256
- else
257
- feed_for(parse_query, condition, comparison_class)
258
- end
259
- end
260
-
261
247
  end
262
248
 
263
249
  const_added(:ParseAdapter)
data/lib/dm-parse.rb CHANGED
@@ -10,6 +10,7 @@ require "property/parse_date"
10
10
  require "property/parse_file"
11
11
  require "property/parse_geo_point"
12
12
  require "parse/resource"
13
+ require "parse/engine"
13
14
  require "parse/query"
14
15
  require "adapters/parse_adapter"
15
16
  require "is/parse"
@@ -0,0 +1,76 @@
1
+ module DataMapper
2
+ module Parse
3
+
4
+ class Engine
5
+
6
+ HOST = "https://api.parse.com"
7
+ VERSION = "1"
8
+ APP_ID_HEADER = "X-Parse-Application-Id"
9
+ API_KEY_HEADER = "X-Parse-REST-API-Key"
10
+ MASTER_KEY_HEADER = "X-Parse-Master-Key"
11
+
12
+ attr_reader :classes, :users, :login, :password_reset, :file_storage
13
+
14
+ def initialize(app_id, api_key, master)
15
+ @app_id = app_id
16
+ @api_key = api_key
17
+ @master = master
18
+ @classes = build_parse_resource_for "classes"
19
+ @users = build_parse_resource_for "users"
20
+ @login = build_parse_resource_for "login"
21
+ @password_reset = build_parse_resource_for "requestPasswordReset"
22
+ @file_storage = build_parse_resource_for "files"
23
+ end
24
+
25
+ def read(storage_name, params)
26
+ parse_resources_for(storage_name).get params: params
27
+ end
28
+
29
+ def delete(storage_name, id)
30
+ parse_resources_for(storage_name)[id].delete
31
+ end
32
+
33
+ def create(storage_name, attributes)
34
+ parse_resources_for(storage_name).post body: attributes.to_json
35
+ end
36
+
37
+ def update(storage_name, id, attributes)
38
+ parse_resources_for(storage_name)[id].put body: attributes.to_json
39
+ end
40
+
41
+ def sign_in(username, password)
42
+ login.get params: {username: username, password: password}
43
+ end
44
+
45
+ def upload_file(filename, content, content_type)
46
+ storage = file_storage[URI.escape(filename)]
47
+ storage.options[:headers]["Content-Type"] = content_type
48
+ storage.post body: content
49
+ end
50
+
51
+ def request_password_reset(email)
52
+ password_reset.post params: {email: email}
53
+ end
54
+
55
+ private
56
+
57
+ def parse_resources_for(storage_name)
58
+ storage_name == "_User" ? users : classes[storage_name]
59
+ end
60
+
61
+ def build_parse_resource_for(name)
62
+ Parse::Resource.new(HOST, format: :json, headers: key_headers)[VERSION][name]
63
+ end
64
+
65
+ def key_headers
66
+ key_type = @master ? MASTER_KEY_HEADER : API_KEY_HEADER
67
+ {
68
+ APP_ID_HEADER => @app_id,
69
+ key_type => @api_key
70
+ }
71
+ end
72
+
73
+ end
74
+
75
+ end
76
+ end
@@ -1,5 +1,42 @@
1
1
  module DataMapper
2
2
  module Parse
3
+ # Read the body to get detail of Parse error
4
+ class Connection < ::Nestful::Connection
5
+ def handle_response(response)
6
+ response.read_body if (400...500).include? response.code.to_i
7
+ super
8
+ end
9
+ end
10
+
11
+ ::Nestful::Request.class_eval do
12
+ def connection
13
+ conn = Connection.new(uri, format)
14
+ conn.proxy = proxy if proxy
15
+ conn.user = user if user
16
+ conn.password = password if password
17
+ conn.auth_type = auth_type if auth_type
18
+ conn.timeout = timeout if timeout
19
+ conn.ssl_options = ssl_options if ssl_options
20
+ conn
21
+ end
22
+ end # This is a workaround. Mixin for Connection does not work somehow.
23
+
24
+ module ParseError
25
+ def to_s
26
+ error = JSON.parse(response.body)["error"]
27
+ super + " Response Parse Error = #{error}"
28
+ end
29
+ end
30
+
31
+ ::Nestful::BadRequest.send :include, ParseError
32
+ ::Nestful::UnauthorizedAccess.send :include, ParseError
33
+ ::Nestful::ForbiddenAccess.send :include, ParseError
34
+ ::Nestful::ResourceNotFound.send :include, ParseError
35
+ ::Nestful::MethodNotAllowed.send :include, ParseError
36
+ ::Nestful::ResourceConflict.send :include, ParseError
37
+ ::Nestful::ResourceGone.send :include, ParseError
38
+ ::Nestful::ResourceInvalid.send :include, ParseError
39
+
3
40
  class Resource < ::Nestful::Resource
4
41
  attr_reader :options
5
42
 
@@ -7,10 +7,11 @@ module DataMapper
7
7
  if value.is_a?(Hash)
8
8
  value.merge("__type" => "File")
9
9
  elsif value.respond_to?(:original_filename) && value.respond_to?(:read)
10
- adapter = model.repository.adapter
11
- filename = value.original_filename
12
- content = value.read
13
- adapter.upload_file(filename, content).merge("__type" => "File")
10
+ adapter = model.repository.adapter
11
+ filename = value.original_filename
12
+ content = value.read
13
+ content_type = MIME::Types.type_for(filename).first
14
+ dump adapter.upload_file(filename, content, content_type)
14
15
  else
15
16
  nil
16
17
  end
@@ -3,10 +3,10 @@ require "spec_helper"
3
3
  describe "resource" do
4
4
  subject { resource }
5
5
 
6
- let(:resource) { model.new title: "Test Title", rank: 3, body: "Test Body" }
7
- let(:model) { Article }
6
+ let(:resource) { Article.new title: "Test Title", rank: 3, body: "Test Body" }
8
7
 
9
- before { model.all.destroy }
8
+ before { Article.all.destroy }
9
+ before { Comment.all.destroy }
10
10
 
11
11
  it { should be_new }
12
12
  it { should be_dirty }
@@ -23,22 +23,28 @@ describe "resource" do
23
23
  its(:created_at) { should_not be_nil }
24
24
  its(:updated_at) { should_not be_nil }
25
25
  end
26
+
27
+ context "when resource is a child" do
28
+ let(:resource) { Comment.create article: parent }
29
+ let(:parent) { Article.create }
30
+
31
+ its(:article) { should be(parent) }
32
+ end
26
33
  end
27
34
 
28
35
  describe "collection" do
29
36
  subject { collection }
30
37
 
31
- let(:model) { Article }
32
- let(:collection) { model.all(:rank.gte => 5, :closed_at.gt => 1.day.from_now, :closed_at.lt => 3.days.from_now, :comments => { :body => /aa/im }) }
38
+ let(:collection) { Article.all(:rank.gte => 5, :closed_at.gt => 1.day.from_now, :closed_at.lt => 3.days.from_now, :comments => { :body => /aa/im }) }
33
39
 
34
- before { model.all.destroy }
40
+ before { Article.all.destroy }
35
41
  before { Comment.all.destroy }
36
42
 
37
43
  its(:size) { should eq(0) }
38
44
 
39
45
  context "when resource in scope is saved" do
40
46
  before do
41
- resource = model.create! rank: 5, closed_at: 2.day.from_now
47
+ resource = Article.create rank: 5, closed_at: 2.day.from_now
42
48
  resource.comments.create body: "AA"
43
49
  end
44
50
 
@@ -47,11 +53,20 @@ describe "collection" do
47
53
  end
48
54
 
49
55
  context "when resource out of scope is saved" do
50
- before { model.create rank: 4 }
56
+ before { Article.create rank: 4 }
51
57
 
52
58
  its(:size) { should eq(0) }
53
59
  its(:count) { should eq(0) }
54
60
  end
61
+
62
+ context "when collection are children" do
63
+ let(:collection) { parent.comments }
64
+ let(:parent) { Article.create }
65
+ let!(:comment) { Comment.create article: parent }
66
+
67
+ its(:size) { should eq(1) }
68
+ its(:first) { should eq(comment) }
69
+ end
55
70
  end
56
71
 
57
72
  describe User do
@@ -103,12 +118,28 @@ describe "adapter" do
103
118
  let(:adapter) { DataMapper::Repository.adapters[:default] }
104
119
 
105
120
  describe "#upload_file" do
106
- subject { adapter.upload_file filename, content }
121
+ subject { adapter.upload_file filename, content, content_type }
107
122
 
108
- let(:filename) { "xf x.txt" }
109
- let(:content) { "xx" }
123
+ let(:filename) { "xf x.txt" }
124
+ let(:content) { "xx" }
125
+ let(:content_type) { "plain/txt" }
110
126
 
111
127
  it { should be_has_key("name") }
112
128
  it { should be_has_key("url") }
113
129
  end
130
+
131
+ describe "#request_password_reset" do
132
+ subject { adapter.request_password_reset email }
133
+
134
+ before do
135
+ repository :master do
136
+ User.all.destroy
137
+ end
138
+ end
139
+
140
+ let(:email) { user.email }
141
+ let(:user) { User.create! username: "a", password: "a", email: "a@abc.cn" }
142
+
143
+ it { should eq({}) }
144
+ end
114
145
  end
@@ -185,124 +185,4 @@ describe DataMapper::Adapters::ParseAdapter do
185
185
  end
186
186
  end # #parse_params_for
187
187
 
188
- shared_examples_for DataMapper::Parse::Resource do
189
- let(:options) { { adapter: :parse, app_id: app_id, api_key: api_key} }
190
-
191
- it { should be_a(DataMapper::Parse::Resource) }
192
- its(:options) { should eq(format: :json, headers: {app_id_header => app_id, api_key_header => api_key}) }
193
- context "when master mode is on" do
194
- let(:options) { { adapter: :parse, app_id: app_id, api_key: api_key, master: true } }
195
-
196
- its(:options) { should eq(format: :json, headers: {app_id_header => app_id, master_key_header => api_key}) }
197
- end
198
- end
199
-
200
- describe "#classes" do
201
- subject { adapter.classes }
202
- its(:url) { should eq("https://api.parse.com/1/classes") }
203
- it_should_behave_like DataMapper::Parse::Resource
204
- end
205
-
206
- describe "#users" do
207
- subject { adapter.users }
208
- its(:url) { should eq("https://api.parse.com/1/users") }
209
- it_should_behave_like DataMapper::Parse::Resource
210
- end
211
-
212
- describe "#login" do
213
- subject { adapter.login }
214
- its(:url) { should eq("https://api.parse.com/1/login") }
215
- it_should_behave_like DataMapper::Parse::Resource
216
- end
217
-
218
- describe "#password_reset" do
219
- subject { adapter.password_reset }
220
- its(:url) { should eq("https://api.parse.com/1/requestPasswordReset") }
221
- it_should_behave_like DataMapper::Parse::Resource
222
- end
223
-
224
- describe "#file_storage" do
225
- subject { adapter.file_storage }
226
- its(:url) { should eq("https://api.parse.com/1/files") }
227
- it_should_behave_like DataMapper::Parse::Resource
228
- end
229
-
230
- describe "#parse_resources_for" do
231
- subject { adapter.parse_resources_for model }
232
- it { should eq(adapter.classes[model.storage_name]) }
233
-
234
- context "when storage_name of model is _User" do
235
- before(:each) { model.stub(storage_name: "_User") }
236
- it { should eq(adapter.users) }
237
- end
238
- end
239
-
240
- describe "#parse_resource_for" do
241
- subject { adapter.parse_resource_for resource }
242
- let(:resource) { model.new id: "xxx" }
243
- it { should eq(adapter.parse_resources_for(model)["xxx"]) }
244
- end
245
-
246
- describe "#create" do
247
- subject { adapter.create resources }
248
-
249
- let(:resources) { [resource] }
250
- let(:resource) { model.new attributes }
251
- let(:attributes) { { id: "fd", rank: 3, created_at: 1.day.ago, updated_at: 2.days.ago } }
252
-
253
- before(:each) do
254
- double_resources = double("resource")
255
- double_resources.should_receive(:post).with(params: {"rank" => 3}).once.and_return({"createdAt" => "2011-08-20T02:06:57.931Z", "objectId" => "Ed1nuqPvcm"})
256
- adapter.stub(parse_resources_for: double_resources)
257
- end
258
-
259
- it { should eq(1) }
260
- end
261
-
262
- describe "#read" do
263
- subject { adapter.read query }
264
-
265
- let(:query) { model.all(:rank => 4).query }
266
- let(:results) { [{"objectId" => "anything"}] }
267
-
268
- before(:each) do
269
- double_resources = double("resource")
270
- double_resources.should_receive(:get).with(params: { limit: 1000, where: {"rank" => 4}.to_json }).once.and_return("results" => results)
271
- adapter.stub(parse_resources_for: double_resources)
272
- end
273
-
274
- it { should eq(results) }
275
- end
276
-
277
- describe "#delete" do
278
- subject { adapter.delete resources }
279
-
280
- let(:resources) { [resource] }
281
- let(:resource) { model.new id: id }
282
- let(:id) { "xxx" }
283
-
284
- before(:each) do
285
- double_resource = double("resource")
286
- double_resource.should_receive(:delete).with(no_args).once.and_return({})
287
- adapter.stub(parse_resource_for: double_resource)
288
- end
289
-
290
- it { should eq(1) }
291
- end
292
-
293
- describe "#update" do
294
- subject { adapter.update attributes, resources }
295
-
296
- let(:resources) { [resource] }
297
- let(:resource) { model.new id: "xxx" }
298
- let(:attributes) { model.new(rank: 5, created_at: 1.day.ago, updated_at: 2.days.ago).attributes(:property) }
299
-
300
- before(:each) do
301
- double_resource = double("resource")
302
- double_resource.should_receive(:put).with(params: {"rank" => 5}).once.and_return("updatedAt" => "2011-08-21T18:02:52.248Z")
303
- adapter.stub(parse_resource_for: double_resource)
304
- end
305
-
306
- it { should eq(1) }
307
- end
308
188
  end
@@ -22,7 +22,7 @@ describe DataMapper::Property::ParseFile do
22
22
  let(:value) { StringIO.new "xx" }
23
23
 
24
24
  before { value.stub(original_filename: "xx.txt") }
25
- before { DataMapper::Parse::Resource.any_instance.stub(post: {"name" => "x", "url" => "y"}) }
25
+ before { DataMapper::Adapters::ParseAdapter.any_instance.stub(upload_file: {"name" => "x", "url" => "y"}) }
26
26
 
27
27
  it { should be_has_key("__type") }
28
28
  it { should be_has_key("name") }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-parse
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-29 00:00:00.000000000 Z
12
+ date: 2012-07-02 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: dm-core
@@ -226,6 +226,7 @@ files:
226
226
  - lib/collection.rb
227
227
  - lib/dm-parse.rb
228
228
  - lib/is/parse.rb
229
+ - lib/parse/engine.rb
229
230
  - lib/parse/query.rb
230
231
  - lib/parse/resource.rb
231
232
  - lib/property/parse_date.rb
@@ -258,7 +259,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
258
259
  version: '0'
259
260
  segments:
260
261
  - 0
261
- hash: 1921482253732220163
262
+ hash: -20848500741311829
262
263
  required_rubygems_version: !ruby/object:Gem::Requirement
263
264
  none: false
264
265
  requirements: