active_remote 5.0.0.pre → 5.0.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 20c9373eff2820fdfaeb4eefd815a1d4cfb752e9fd388e8fd0e2d4ef2c0c5f7f
4
- data.tar.gz: 5f66d51af2723950bad69d3870fc83685e253f5fcfd894d6ae19dd6a78c27516
3
+ metadata.gz: 24ecc4009b9bb7ab623c2f80961e2e15263a249ac412be97c39f86cde123fdaa
4
+ data.tar.gz: ac0215aad0dce875952b9e2583e8c3fe8ce114d33de15978a7393482e7fa65dc
5
5
  SHA512:
6
- metadata.gz: 07d671953169e1eefc9db8b26d2de3af40a39302e1423fdd7beeb212df913c46db1017aeb2dbc2d02c21cf72f0ae35639732d6af86694f0ecd7be894ae03db04
7
- data.tar.gz: 98ee4213dcd636baab1def67ba1848469ff8592aff9334b720348830e4fd797f65e2935450fe399fafdc84261a64f2a07197323d38b743c616d4b70475f7890f
6
+ metadata.gz: c8cd4c36b5dc8840206dc32bbe4ccc3e591f631691e156d1ebcf537877442bf5be00c70506f8d2e890f2340f34b805e6cde7e1f80103c07bd1fcc4799b1829d7
7
+ data.tar.gz: ff8a9f380a3eba79fcd0cb41e4856e02c20ede68044bab07fe80b3996f88962e49e95f6db59308e4cdd7ff51468ff0b280f36307c21fdd5bf5f0cdd8c4bc393e
data/.travis.yml CHANGED
@@ -1,5 +1,5 @@
1
1
  ---
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2
4
+ - 2.3
5
5
  - jruby
@@ -1,6 +1,6 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
- $LOAD_PATH.push File.expand_path("../lib", __FILE__)
3
+ $LOAD_PATH.push File.expand_path("lib", __dir__)
4
4
  require "active_remote/version"
5
5
 
6
6
  Gem::Specification.new do |s|
@@ -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
@@ -14,6 +14,7 @@ module ActiveRemote
14
14
  #
15
15
  def ==(other)
16
16
  return false unless other.instance_of?(self.class)
17
+
17
18
  attributes == other.attributes
18
19
  end
19
20
 
@@ -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(*)
@@ -41,11 +41,11 @@ module ActiveRemote
41
41
 
42
42
  def endpoints(endpoints_hash = nil)
43
43
  @endpoints ||= {
44
- :create => :create,
45
- :delete => :delete,
44
+ :create => :create,
45
+ :delete => :delete,
46
46
  :destroy => :destroy,
47
- :search => :search,
48
- :update => :update
47
+ :search => :search,
48
+ :update => :update
49
49
  }
50
50
  @endpoints.merge!(endpoints_hash) if endpoints_hash.present?
51
51
  @endpoints
@@ -24,7 +24,7 @@ module ActiveRemote
24
24
  # user.to_param # => "GUID-1"
25
25
  #
26
26
  def to_param
27
- self[:guid] && self[:guid].to_s
27
+ self[:guid]&.to_s
28
28
  end
29
29
 
30
30
  ##
@@ -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
- # Use the getter here so we get the type casting.
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
- response = remote_call(:update, updated_attributes)
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
@@ -28,11 +28,7 @@ module ActiveRemote
28
28
  when true then true
29
29
  when false, nil then false
30
30
  else
31
- if value.respond_to?(:zero?)
32
- !value.zero?
33
- else
34
- value.present?
35
- end
31
+ value.present?
36
32
  end
37
33
  end
38
34
 
@@ -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
@@ -1,3 +1,3 @@
1
1
  module ActiveRemote
2
- VERSION = "5.0.0.pre"
2
+ VERSION = "5.0.0.rc1"
3
3
  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.update_attributes({})
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.update_attributes({})
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.update_attributes(attributes)
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.update_attributes(attributes)
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.update_attributes!(attributes)
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.update_attributes!(attributes)
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
- it "is false when the attribute is 0" do
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 false
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.pre
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-10 00:00:00.000000000 Z
11
+ date: 2019-01-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel