active_remote 5.0.0.pre → 5.0.0.rc1
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -1
- data/active_remote.gemspec +1 -1
- data/lib/active_remote/attribute_definition.rb +2 -0
- data/lib/active_remote/attributes.rb +1 -0
- data/lib/active_remote/dirty.rb +8 -0
- data/lib/active_remote/dsl.rb +4 -4
- data/lib/active_remote/integration.rb +1 -1
- data/lib/active_remote/persistence.rb +19 -13
- data/lib/active_remote/query_attributes.rb +1 -5
- data/lib/active_remote/rpc.rb +6 -0
- data/lib/active_remote/version.rb +1 -1
- data/spec/lib/active_remote/dirty_spec.rb +9 -0
- data/spec/lib/active_remote/persistence_spec.rb +70 -15
- data/spec/lib/active_remote/query_attribute_spec.rb +3 -2
- data/spec/lib/active_remote/rpc_spec.rb +31 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 24ecc4009b9bb7ab623c2f80961e2e15263a249ac412be97c39f86cde123fdaa
|
4
|
+
data.tar.gz: ac0215aad0dce875952b9e2583e8c3fe8ce114d33de15978a7393482e7fa65dc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8cd4c36b5dc8840206dc32bbe4ccc3e591f631691e156d1ebcf537877442bf5be00c70506f8d2e890f2340f34b805e6cde7e1f80103c07bd1fcc4799b1829d7
|
7
|
+
data.tar.gz: ff8a9f380a3eba79fcd0cb41e4856e02c20ede68044bab07fe80b3996f88962e49e95f6db59308e4cdd7ff51468ff0b280f36307c21fdd5bf5f0cdd8c4bc393e
|
data/.travis.yml
CHANGED
data/active_remote.gemspec
CHANGED
@@ -28,6 +28,7 @@ module ActiveRemote
|
|
28
28
|
def <=>(other)
|
29
29
|
return nil unless other.instance_of? self.class
|
30
30
|
return nil if name == other.name && options != other.options
|
31
|
+
|
31
32
|
self.name.to_s <=> other.name.to_s
|
32
33
|
end
|
33
34
|
|
@@ -57,6 +58,7 @@ module ActiveRemote
|
|
57
58
|
# @since 0.2.0
|
58
59
|
def initialize(name, type = :value, **options)
|
59
60
|
raise TypeError, "can't convert #{name.class} into Symbol" unless name.respond_to? :to_sym
|
61
|
+
|
60
62
|
@name = name.to_sym
|
61
63
|
@type = ::ActiveModel::Type.lookup(type)
|
62
64
|
@options = options
|
data/lib/active_remote/dirty.rb
CHANGED
@@ -29,6 +29,14 @@ module ActiveRemote
|
|
29
29
|
end
|
30
30
|
end
|
31
31
|
|
32
|
+
# Override #remote to provide dirty tracking.
|
33
|
+
#
|
34
|
+
def remote(*)
|
35
|
+
super.tap do
|
36
|
+
clear_changes_information
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
32
40
|
# Override #save to store changes as previous changes then clear them.
|
33
41
|
#
|
34
42
|
def save(*)
|
data/lib/active_remote/dsl.rb
CHANGED
@@ -41,11 +41,11 @@ module ActiveRemote
|
|
41
41
|
|
42
42
|
def endpoints(endpoints_hash = nil)
|
43
43
|
@endpoints ||= {
|
44
|
-
:create
|
45
|
-
:delete
|
44
|
+
:create => :create,
|
45
|
+
:delete => :delete,
|
46
46
|
:destroy => :destroy,
|
47
|
-
:search
|
48
|
-
:update
|
47
|
+
:search => :search,
|
48
|
+
:update => :update
|
49
49
|
}
|
50
50
|
@endpoints.merge!(endpoints_hash) if endpoints_hash.present?
|
51
51
|
@endpoints
|
@@ -76,6 +76,7 @@ module ActiveRemote
|
|
76
76
|
#
|
77
77
|
def delete
|
78
78
|
raise ReadOnlyRemoteRecord if readonly?
|
79
|
+
|
79
80
|
response = remote_call(:delete, scope_key_hash)
|
80
81
|
|
81
82
|
add_errors(response.errors) if response.respond_to?(:errors)
|
@@ -101,6 +102,7 @@ module ActiveRemote
|
|
101
102
|
#
|
102
103
|
def destroy
|
103
104
|
raise ReadOnlyRemoteRecord if readonly?
|
105
|
+
|
104
106
|
response = remote_call(:destroy, scope_key_hash)
|
105
107
|
|
106
108
|
add_errors(response.errors) if response.respond_to?(:errors)
|
@@ -156,6 +158,19 @@ module ActiveRemote
|
|
156
158
|
self.class.readonly? || @readonly
|
157
159
|
end
|
158
160
|
|
161
|
+
# Executes a remote call on the current object and serializes it's attributes and
|
162
|
+
# errors from the response.
|
163
|
+
#
|
164
|
+
# Defaults request args to the scope key hash (e.g., { guid: 'ABC-123' }) when none are given.
|
165
|
+
# Returns false if the response contained errors; otherwise, returns true.
|
166
|
+
#
|
167
|
+
def remote(endpoint, request_args = scope_key_hash)
|
168
|
+
response = remote_call(endpoint, request_args)
|
169
|
+
assign_attributes_from_rpc(response)
|
170
|
+
|
171
|
+
success?
|
172
|
+
end
|
173
|
+
|
159
174
|
# Saves the remote record.
|
160
175
|
#
|
161
176
|
# If it is a new record, it will be created through the service, otherwise
|
@@ -203,6 +218,7 @@ module ActiveRemote
|
|
203
218
|
# attribute is marked as readonly.
|
204
219
|
def update_attribute(name, value)
|
205
220
|
raise ReadOnlyRemoteRecord if readonly?
|
221
|
+
|
206
222
|
name = name.to_s
|
207
223
|
send("#{name}=", value)
|
208
224
|
save(:validate => false)
|
@@ -235,13 +251,7 @@ module ActiveRemote
|
|
235
251
|
#
|
236
252
|
def remote_create
|
237
253
|
run_callbacks :create do
|
238
|
-
|
239
|
-
new_attributes = attributes
|
240
|
-
|
241
|
-
response = remote_call(:create, new_attributes)
|
242
|
-
|
243
|
-
instantiate(response.to_hash)
|
244
|
-
add_errors(response.errors) if response.respond_to?(:errors)
|
254
|
+
remote(:create, attributes)
|
245
255
|
|
246
256
|
@new_record = has_errors?
|
247
257
|
success?
|
@@ -254,6 +264,7 @@ module ActiveRemote
|
|
254
264
|
#
|
255
265
|
def create_or_update(*args)
|
256
266
|
raise ReadOnlyRemoteRecord if readonly?
|
267
|
+
|
257
268
|
new_record? ? remote_create : remote_update(*args)
|
258
269
|
end
|
259
270
|
|
@@ -268,12 +279,7 @@ module ActiveRemote
|
|
268
279
|
updated_attributes.slice!(*attribute_names)
|
269
280
|
updated_attributes.merge!(scope_key_hash)
|
270
281
|
|
271
|
-
|
272
|
-
|
273
|
-
instantiate(response.to_hash)
|
274
|
-
add_errors(response.errors) if response.respond_to?(:errors)
|
275
|
-
|
276
|
-
success?
|
282
|
+
remote(:update, updated_attributes)
|
277
283
|
end
|
278
284
|
end
|
279
285
|
end
|
data/lib/active_remote/rpc.rb
CHANGED
@@ -52,6 +52,12 @@ module ActiveRemote
|
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
+
def assign_attributes_from_rpc(response)
|
56
|
+
new_attributes = self.class.build_from_rpc(response.to_hash)
|
57
|
+
@attributes.update(new_attributes)
|
58
|
+
add_errors(response.errors) if response.respond_to?(:errors)
|
59
|
+
end
|
60
|
+
|
55
61
|
def remote_call(rpc_method, request_args)
|
56
62
|
self.class.remote_call(rpc_method, request_args)
|
57
63
|
end
|
@@ -54,6 +54,15 @@ describe ActiveRemote::Dirty do
|
|
54
54
|
its(:changes) { should be_empty }
|
55
55
|
end
|
56
56
|
|
57
|
+
describe "#remote" do
|
58
|
+
let(:post) { Post.new(:name => "foo") }
|
59
|
+
|
60
|
+
it "clears changes information" do
|
61
|
+
allow(post).to receive(:remote_call).and_return(::Generic::Remote::Post.new(:name => "foo"))
|
62
|
+
expect { post.remote(:reload) }.to change { post.changed? }.to(false)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
57
66
|
describe "#save" do
|
58
67
|
let!(:changes) { subject.changes }
|
59
68
|
|
@@ -140,15 +140,6 @@ describe ::ActiveRemote::Persistence do
|
|
140
140
|
end
|
141
141
|
end
|
142
142
|
|
143
|
-
describe "#readonly?" do
|
144
|
-
context "when the record is created through instantiate with options[:readonly]" do
|
145
|
-
subject { Tag.instantiate({ :guid => "foo" }, :readonly => true) }
|
146
|
-
|
147
|
-
its(:new_record?) { should be_falsey }
|
148
|
-
its(:readonly?) { should be_truthy }
|
149
|
-
end
|
150
|
-
end
|
151
|
-
|
152
143
|
describe "#has_errors?" do
|
153
144
|
context "when errors are not present" do
|
154
145
|
before { subject.errors.clear }
|
@@ -197,6 +188,70 @@ describe ::ActiveRemote::Persistence do
|
|
197
188
|
end
|
198
189
|
end
|
199
190
|
|
191
|
+
describe "#readonly?" do
|
192
|
+
context "when the record is created through instantiate with options[:readonly]" do
|
193
|
+
subject { Tag.instantiate({ :guid => "foo" }, :readonly => true) }
|
194
|
+
|
195
|
+
its(:new_record?) { should be_falsey }
|
196
|
+
its(:readonly?) { should be_truthy }
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
describe "#remote" do
|
201
|
+
let(:response) { ::Generic::Remote::Tag.new(:guid => tag.guid, :name => "bar") }
|
202
|
+
let(:rpc) { ::ActiveRemote::RPCAdapters::ProtobufAdapter.new(::Tag.service_class, ::Tag.endpoints) }
|
203
|
+
let(:tag) { ::Tag.new(:guid => SecureRandom.uuid) }
|
204
|
+
|
205
|
+
subject { tag }
|
206
|
+
|
207
|
+
before do
|
208
|
+
allow(::Tag).to receive(:rpc).and_return(rpc)
|
209
|
+
allow(rpc).to receive(:execute).and_return(response)
|
210
|
+
end
|
211
|
+
|
212
|
+
it "calls the given RPC method with default args" do
|
213
|
+
expect(::Tag.rpc).to receive(:execute).with(:remote_method, tag.scope_key_hash)
|
214
|
+
tag.remote(:remote_method)
|
215
|
+
end
|
216
|
+
|
217
|
+
it "updates the attributes from the response" do
|
218
|
+
expect { tag.remote(:remote_method) }.to change { tag.name }.to(response.name)
|
219
|
+
end
|
220
|
+
|
221
|
+
it "returns true" do
|
222
|
+
expect(tag.remote(:remote_method)).to be(true)
|
223
|
+
end
|
224
|
+
|
225
|
+
context "when request args are given" do
|
226
|
+
it "calls the given RPC method with default args" do
|
227
|
+
attributes = { :guid => tag.guid, :name => "foo" }
|
228
|
+
expect(::Tag.rpc).to receive(:execute).with(:remote_method, attributes)
|
229
|
+
tag.remote(:remote_method, attributes)
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
context "when response does not respond to errors" do
|
234
|
+
it "returns true" do
|
235
|
+
allow(rpc).to receive(:execute).and_return(double(:response, :to_hash => ::Hash.new))
|
236
|
+
expect(tag.remote(:remote_method)).to be(true)
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context "when errors are returned" do
|
241
|
+
let(:response) {
|
242
|
+
::Generic::Remote::Tag.new(:guid => tag.guid, :name => "bar", :errors => [{ :field => "name", :message => "message" }])
|
243
|
+
}
|
244
|
+
|
245
|
+
it "adds errors from the response" do
|
246
|
+
expect { tag.remote(:remote_method) }.to change { tag.has_errors? }.to(true)
|
247
|
+
end
|
248
|
+
|
249
|
+
it "returns false" do
|
250
|
+
expect(tag.remote(:remote_method)).to be(false)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
end
|
254
|
+
|
200
255
|
describe "#save" do
|
201
256
|
it "runs save callbacks" do
|
202
257
|
allow(subject).to receive(:run_callbacks).with(:validation).and_return(true)
|
@@ -313,12 +368,12 @@ describe ::ActiveRemote::Persistence do
|
|
313
368
|
|
314
369
|
it "runs update callbacks" do
|
315
370
|
expect(tag).to receive(:after_update_callback)
|
316
|
-
tag.
|
371
|
+
tag.update({})
|
317
372
|
end
|
318
373
|
|
319
374
|
it "updates a remote record" do
|
320
375
|
expect(rpc).to receive(:execute).with(:update, tag.scope_key_hash)
|
321
|
-
tag.
|
376
|
+
tag.update({})
|
322
377
|
end
|
323
378
|
|
324
379
|
before { allow(subject).to receive(:save) }
|
@@ -326,12 +381,12 @@ describe ::ActiveRemote::Persistence do
|
|
326
381
|
|
327
382
|
it "assigns new attributes" do
|
328
383
|
expect(subject).to receive(:assign_attributes).with(attributes)
|
329
|
-
subject.
|
384
|
+
subject.update(attributes)
|
330
385
|
end
|
331
386
|
|
332
387
|
it "saves the record" do
|
333
388
|
expect(subject).to receive(:save)
|
334
|
-
subject.
|
389
|
+
subject.update(attributes)
|
335
390
|
end
|
336
391
|
end
|
337
392
|
|
@@ -343,12 +398,12 @@ describe ::ActiveRemote::Persistence do
|
|
343
398
|
|
344
399
|
it "assigns new attributes" do
|
345
400
|
expect(subject).to receive(:assign_attributes).with(attributes)
|
346
|
-
subject.
|
401
|
+
subject.update!(attributes)
|
347
402
|
end
|
348
403
|
|
349
404
|
it "saves! the record" do
|
350
405
|
expect(subject).to receive(:save!)
|
351
|
-
subject.
|
406
|
+
subject.update!(attributes)
|
352
407
|
end
|
353
408
|
end
|
354
409
|
end
|
@@ -38,9 +38,10 @@ describe ::ActiveRemote::QueryAttributes do
|
|
38
38
|
expect(subject.name?).to eq true
|
39
39
|
end
|
40
40
|
|
41
|
-
|
41
|
+
# This behavior varies from ActiveRecord, so we test it explicitly
|
42
|
+
it "is true when the attribute is 0" do
|
42
43
|
subject.name = 0
|
43
|
-
expect(subject.name?).to eq
|
44
|
+
expect(subject.name?).to eq true
|
44
45
|
end
|
45
46
|
|
46
47
|
it "is true when the attribute is 1" do
|
@@ -50,4 +50,35 @@ describe ::ActiveRemote::RPC do
|
|
50
50
|
expect(::Tag.remote_call(:remote_method, args)).to eq response
|
51
51
|
end
|
52
52
|
end
|
53
|
+
|
54
|
+
describe "#assign_attributes_from_rpc" do
|
55
|
+
let(:response) { ::Generic::Remote::Tag.new(:guid => tag.guid, :name => "bar") }
|
56
|
+
let(:tag) { ::Tag.new(:guid => SecureRandom.uuid) }
|
57
|
+
|
58
|
+
it "updates the attributes from the response" do
|
59
|
+
expect { tag.assign_attributes_from_rpc(response) }.to change { tag.name }.to(response.name)
|
60
|
+
end
|
61
|
+
|
62
|
+
context "when response does not respond to errors" do
|
63
|
+
let(:response) { double(:response, :to_hash => ::Hash.new) }
|
64
|
+
|
65
|
+
it "does not add errors from the response" do
|
66
|
+
expect { tag.assign_attributes_from_rpc(response) }.to_not change { tag.has_errors? }
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "when errors are returned" do
|
71
|
+
let(:response) {
|
72
|
+
::Generic::Remote::Tag.new(
|
73
|
+
:guid => tag.guid,
|
74
|
+
:name => "bar",
|
75
|
+
:errors => [{ :field => "name", :message => "message" }]
|
76
|
+
)
|
77
|
+
}
|
78
|
+
|
79
|
+
it "adds errors from the response" do
|
80
|
+
expect { tag.assign_attributes_from_rpc(response) }.to change { tag.has_errors? }.to(true)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
53
84
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_remote
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.0.
|
4
|
+
version: 5.0.0.rc1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adam Hutchison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|