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 +3 -0
- data/VERSION +1 -1
- data/dm-parse.gemspec +3 -2
- data/lib/adapters/parse_adapter.rb +48 -62
- data/lib/dm-parse.rb +1 -0
- data/lib/parse/engine.rb +76 -0
- data/lib/parse/resource.rb +37 -0
- data/lib/property/parse_file.rb +5 -4
- data/spec/integration_spec.rb +42 -11
- data/spec/parse_adapter_spec.rb +0 -120
- data/spec/parse_file_spec.rb +1 -1
- metadata +4 -3
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
|
+
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.
|
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-
|
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 :
|
14
|
+
attr_reader :engine
|
15
15
|
|
16
16
|
def initialize(name, options)
|
17
17
|
super
|
18
|
-
|
19
|
-
@
|
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
|
37
|
-
model
|
38
|
-
|
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
|
46
|
-
params
|
47
|
-
|
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
|
63
|
-
params
|
64
|
-
params[:count]
|
65
|
-
params[:limit]
|
66
|
-
|
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
|
-
|
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
|
-
|
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
|
112
|
-
|
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
|
-
|
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
|
126
|
-
|
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
|
-
|
201
|
-
|
202
|
-
|
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
|
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
data/lib/parse/engine.rb
ADDED
@@ -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
|
data/lib/parse/resource.rb
CHANGED
@@ -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
|
|
data/lib/property/parse_file.rb
CHANGED
@@ -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
|
11
|
-
filename
|
12
|
-
content
|
13
|
-
|
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
|
data/spec/integration_spec.rb
CHANGED
@@ -3,10 +3,10 @@ require "spec_helper"
|
|
3
3
|
describe "resource" do
|
4
4
|
subject { resource }
|
5
5
|
|
6
|
-
let(:resource) {
|
7
|
-
let(:model) { Article }
|
6
|
+
let(:resource) { Article.new title: "Test Title", rank: 3, body: "Test Body" }
|
8
7
|
|
9
|
-
before {
|
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(:
|
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 {
|
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
|
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 {
|
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)
|
109
|
-
let(:content)
|
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
|
data/spec/parse_adapter_spec.rb
CHANGED
@@ -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
|
data/spec/parse_file_spec.rb
CHANGED
@@ -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::
|
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.
|
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-
|
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:
|
262
|
+
hash: -20848500741311829
|
262
263
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
263
264
|
none: false
|
264
265
|
requirements:
|