active_remote 5.1.1 → 5.2.0.alpha
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/active_remote.gemspec +2 -2
- data/bin/benchmark +12 -5
- data/lib/active_remote/association.rb +7 -9
- data/lib/active_remote/attribute_methods.rb +51 -0
- data/lib/active_remote/base.rb +64 -14
- data/lib/active_remote/dirty.rb +4 -7
- data/lib/active_remote/integration.rb +112 -26
- data/lib/active_remote/persistence.rb +1 -1
- data/lib/active_remote/primary_key.rb +18 -0
- data/lib/active_remote/rpc.rb +3 -4
- data/lib/active_remote/search.rb +2 -1
- data/lib/active_remote/version.rb +1 -1
- data/spec/lib/active_remote/association_spec.rb +0 -16
- data/spec/lib/active_remote/dirty_spec.rb +14 -29
- data/spec/lib/active_remote/integration_spec.rb +80 -12
- data/spec/lib/active_remote/query_attribute_spec.rb +8 -17
- data/spec/lib/active_remote/rpc_spec.rb +5 -1
- data/spec/lib/active_remote/search_spec.rb +4 -3
- data/spec/support/models.rb +0 -1
- data/spec/support/models/author.rb +10 -6
- data/spec/support/models/category.rb +3 -3
- data/spec/support/models/default_author.rb +2 -2
- data/spec/support/models/post.rb +5 -5
- data/spec/support/models/tag.rb +4 -4
- metadata +10 -16
- data/lib/active_remote/attribute_definition.rb +0 -114
- data/lib/active_remote/attributes.rb +0 -204
- data/spec/lib/active_remote/attributes_spec.rb +0 -223
- data/spec/support/models/typecasted_author.rb +0 -8
@@ -48,7 +48,7 @@ module ActiveRemote
|
|
48
48
|
# Instantiate a record with the given remote attributes. Generally used
|
49
49
|
# when retrieving records that already exist, so @new_record is set to false.
|
50
50
|
#
|
51
|
-
def instantiate(new_attributes, options = {})
|
51
|
+
def instantiate(new_attributes = {}, options = {})
|
52
52
|
attributes = self.build_from_rpc(new_attributes)
|
53
53
|
new_object = self.allocate.init_with(attributes)
|
54
54
|
new_object.readonly! if options[:readonly]
|
@@ -32,5 +32,23 @@ module ActiveRemote
|
|
32
32
|
def primary_key
|
33
33
|
self.class.primary_key
|
34
34
|
end
|
35
|
+
|
36
|
+
# Returns an Array of all key attributes if any of the attributes is set, whether or not
|
37
|
+
# the object is persisted. Returns +nil+ if there are no key attributes.
|
38
|
+
#
|
39
|
+
# class Person
|
40
|
+
# include ActiveModel::Conversion
|
41
|
+
# attr_accessor :id
|
42
|
+
#
|
43
|
+
# def initialize(id)
|
44
|
+
# @id = id
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
#
|
48
|
+
# person = Person.new(1)
|
49
|
+
# person.to_key # => [1]
|
50
|
+
def to_key
|
51
|
+
send(primary_key) ? [send(primary_key)] : nil
|
52
|
+
end
|
35
53
|
end
|
36
54
|
end
|
data/lib/active_remote/rpc.rb
CHANGED
@@ -15,8 +15,8 @@ module ActiveRemote
|
|
15
15
|
def build_from_rpc(values)
|
16
16
|
values = values.stringify_keys
|
17
17
|
|
18
|
-
|
19
|
-
attributes
|
18
|
+
attribute_names.inject(_default_attributes.deep_dup) do |attributes, name|
|
19
|
+
attributes.write_from_database(name, values[name])
|
20
20
|
attributes
|
21
21
|
end
|
22
22
|
end
|
@@ -53,8 +53,7 @@ module ActiveRemote
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def assign_attributes_from_rpc(response)
|
56
|
-
|
57
|
-
@attributes.update(new_attributes)
|
56
|
+
@attributes = self.class.build_from_rpc(response.to_hash)
|
58
57
|
add_errors(response.errors) if response.respond_to?(:errors)
|
59
58
|
end
|
60
59
|
|
data/lib/active_remote/search.rb
CHANGED
@@ -117,7 +117,8 @@ module ActiveRemote
|
|
117
117
|
#
|
118
118
|
def reload
|
119
119
|
fresh_object = self.class.find(scope_key_hash)
|
120
|
-
@attributes
|
120
|
+
@attributes = fresh_object.instance_variable_get("@attributes")
|
121
|
+
self
|
121
122
|
end
|
122
123
|
end
|
123
124
|
end
|
@@ -155,14 +155,6 @@ describe ActiveRemote::Association do
|
|
155
155
|
expect(subject.user_posts).to eq(records)
|
156
156
|
end
|
157
157
|
|
158
|
-
context "when user_guid doesnt exist on model " do
|
159
|
-
before { allow(subject).to receive(:respond_to?).with("user_guid").and_return(false) }
|
160
|
-
|
161
|
-
it "raises an error" do
|
162
|
-
expect { subject.user_posts }.to raise_error(::ActiveRemote::UnknownAttributeError)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
158
|
context "when user_guid doesnt exist on associated model " do
|
167
159
|
before { allow(Post).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
|
168
160
|
|
@@ -251,14 +243,6 @@ describe ActiveRemote::Association do
|
|
251
243
|
expect(subject.chief_editor).to eq(record)
|
252
244
|
end
|
253
245
|
|
254
|
-
context "when user_guid doesnt exist on model " do
|
255
|
-
before { allow(subject).to receive(:respond_to?).with("user_guid").and_return(false) }
|
256
|
-
|
257
|
-
it "raises an error" do
|
258
|
-
expect { subject.chief_editor }.to raise_error(::ActiveRemote::UnknownAttributeError)
|
259
|
-
end
|
260
|
-
end
|
261
|
-
|
262
246
|
context "when user_guid doesnt exist on associated model " do
|
263
247
|
before { allow(Author).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
|
264
248
|
|
@@ -4,10 +4,10 @@ describe ActiveRemote::Dirty do
|
|
4
4
|
context "when writing attributes through the setter" do
|
5
5
|
subject { Post.new(:name => "foo") }
|
6
6
|
|
7
|
-
before
|
8
|
-
subject.
|
9
|
-
subject.
|
10
|
-
|
7
|
+
before do
|
8
|
+
subject.changes_applied
|
9
|
+
subject.clear_changes_information
|
10
|
+
end
|
11
11
|
|
12
12
|
context "when the value changes" do
|
13
13
|
before { subject.name = "bar" }
|
@@ -25,10 +25,10 @@ describe ActiveRemote::Dirty do
|
|
25
25
|
context "when writing attributes directly" do
|
26
26
|
subject { Post.new(:name => "foo") }
|
27
27
|
|
28
|
-
before
|
29
|
-
subject.
|
30
|
-
subject.
|
31
|
-
|
28
|
+
before do
|
29
|
+
subject.changes_applied
|
30
|
+
subject.clear_changes_information
|
31
|
+
end
|
32
32
|
|
33
33
|
context "when the value changes" do
|
34
34
|
before { subject[:name] = "bar" }
|
@@ -46,10 +46,10 @@ describe ActiveRemote::Dirty do
|
|
46
46
|
describe "#reload" do
|
47
47
|
subject { Post.new(:name => "foo") }
|
48
48
|
|
49
|
-
before
|
49
|
+
before do
|
50
50
|
allow(Post).to receive(:find).and_return(Post.new(:name => "foo"))
|
51
51
|
subject.reload
|
52
|
-
|
52
|
+
end
|
53
53
|
|
54
54
|
its(:changes) { should be_empty }
|
55
55
|
end
|
@@ -68,10 +68,10 @@ describe ActiveRemote::Dirty do
|
|
68
68
|
|
69
69
|
subject { Post.new(:name => "foo") }
|
70
70
|
|
71
|
-
before
|
71
|
+
before do
|
72
72
|
allow(subject).to receive(:create_or_update).and_return(true)
|
73
73
|
subject.save
|
74
|
-
|
74
|
+
end
|
75
75
|
|
76
76
|
its(:previous_changes) { should eq changes }
|
77
77
|
its(:changes) { should be_empty }
|
@@ -82,27 +82,12 @@ describe ActiveRemote::Dirty do
|
|
82
82
|
|
83
83
|
subject { Post.new(:name => "foo") }
|
84
84
|
|
85
|
-
before
|
85
|
+
before do
|
86
86
|
allow(subject).to receive(:save).and_return(true)
|
87
87
|
subject.save!
|
88
|
-
|
88
|
+
end
|
89
89
|
|
90
90
|
its(:previous_changes) { should eq changes }
|
91
91
|
its(:changes) { should be_empty }
|
92
92
|
end
|
93
|
-
|
94
|
-
describe "#instantiate" do
|
95
|
-
let(:post) { Post.new }
|
96
|
-
let(:record) { ::Generic::Remote::Post.new(:name => "foo") }
|
97
|
-
|
98
|
-
it "clears previous changes" do
|
99
|
-
new_record = post.instantiate(record.to_hash)
|
100
|
-
expect(new_record.previous_changes).to eq({})
|
101
|
-
end
|
102
|
-
|
103
|
-
it "clears changes" do
|
104
|
-
new_record = post.instantiate(record.to_hash)
|
105
|
-
expect(new_record.changes).to be_empty
|
106
|
-
end
|
107
|
-
end
|
108
93
|
end
|
@@ -2,37 +2,41 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe ::ActiveRemote::Integration do
|
4
4
|
let(:guid) { "GUID-derp" }
|
5
|
-
|
5
|
+
let(:tag) { ::Tag.new(:guid => guid) }
|
6
|
+
|
7
|
+
subject { tag }
|
8
|
+
|
9
|
+
context ".to_param" do
|
10
|
+
specify { expect(::Tag).to respond_to(:to_param) }
|
11
|
+
end
|
6
12
|
|
7
13
|
context "#to_param" do
|
8
|
-
# API
|
9
14
|
specify { expect(subject).to respond_to(:to_param) }
|
10
15
|
|
11
16
|
it "returns the guid if the guid is present (by default)" do
|
12
|
-
expect(
|
17
|
+
expect(tag.to_param).to eq(guid)
|
13
18
|
end
|
14
19
|
end
|
15
20
|
|
16
21
|
context "#cache_key" do
|
17
|
-
# API
|
18
22
|
specify { expect(subject).to respond_to(:cache_key) }
|
19
23
|
|
20
24
|
it "sets 'new' as the identifier when the record has not been persisted" do
|
21
|
-
expect(
|
22
|
-
expect(
|
25
|
+
expect(tag).to receive(:new_record?).and_return(true)
|
26
|
+
expect(tag.cache_key).to match(/tags\/new/)
|
23
27
|
end
|
24
28
|
|
25
29
|
it "sets the cache_key to the class/guid as a default" do
|
26
|
-
expect(
|
27
|
-
expect(
|
30
|
+
expect(tag).to receive(:new_record?).and_return(false)
|
31
|
+
expect(tag.cache_key).to eq("tags/#{guid}")
|
28
32
|
end
|
29
33
|
|
30
34
|
it "adds the 'updated_at' attribute to the cache_key if updated_at is present" do
|
31
35
|
::ActiveRemote.config.default_cache_key_updated_at = true
|
32
|
-
twenty_o_one_one =
|
33
|
-
expect(
|
34
|
-
expect(
|
35
|
-
|
36
|
+
twenty_o_one_one = tag.updated_at = DateTime.new(2001, 0o1, 0o1)
|
37
|
+
expect(tag).to receive(:new_record?).and_return(false)
|
38
|
+
expect(tag.cache_key).to eq("tags/#{guid}-#{twenty_o_one_one.to_s(:usec)}")
|
39
|
+
tag.updated_at = nil
|
36
40
|
::ActiveRemote.config.default_cache_key_updated_at = false
|
37
41
|
end
|
38
42
|
|
@@ -40,4 +44,68 @@ describe ::ActiveRemote::Integration do
|
|
40
44
|
expect(::ActiveRemote.config.default_cache_key_updated_at?).to be_falsey
|
41
45
|
end
|
42
46
|
end
|
47
|
+
|
48
|
+
describe "#cache_key_with_version" do
|
49
|
+
let(:tag) { ::Tag.new(:guid => guid, :updated_at => ::DateTime.current) }
|
50
|
+
|
51
|
+
specify { expect(subject).to respond_to(:cache_key_with_version) }
|
52
|
+
|
53
|
+
context "when cache versioning is enabled" do
|
54
|
+
around do |example|
|
55
|
+
cache_versioning_value = ::Tag.cache_versioning
|
56
|
+
::Tag.cache_versioning = true
|
57
|
+
example.run
|
58
|
+
::Tag.cache_versioning = cache_versioning_value
|
59
|
+
end
|
60
|
+
|
61
|
+
it "returns a cache key with the version" do
|
62
|
+
expect(tag.cache_version).to be_present
|
63
|
+
expect(tag.cache_key_with_version).to eq("#{tag.cache_key}-#{tag.cache_version}")
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
context "when cache versioning is not enabled" do
|
68
|
+
around do |example|
|
69
|
+
cache_versioning_value = ::Tag.cache_versioning
|
70
|
+
::Tag.cache_versioning = false
|
71
|
+
example.run
|
72
|
+
::Tag.cache_versioning = cache_versioning_value
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns a cache key without the version" do
|
76
|
+
expect(tag.cache_key_with_version).to eq(tag.cache_key)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "#cache_version" do
|
82
|
+
specify { expect(subject).to respond_to(:cache_version) }
|
83
|
+
|
84
|
+
context "when cache versioning is enabled" do
|
85
|
+
around do |example|
|
86
|
+
cache_versioning_value = ::Tag.cache_versioning
|
87
|
+
::Tag.cache_versioning = true
|
88
|
+
example.run
|
89
|
+
::Tag.cache_versioning = cache_versioning_value
|
90
|
+
end
|
91
|
+
|
92
|
+
it "returns a cache version" do
|
93
|
+
tag.updated_at = DateTime.new(2001, 0o1, 0o1)
|
94
|
+
expect(tag.cache_version).to eq(tag.updated_at.utc.to_s(:usec))
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when cache versioning is not enabled" do
|
99
|
+
around do |example|
|
100
|
+
cache_versioning_value = ::Tag.cache_versioning
|
101
|
+
::Tag.cache_versioning = false
|
102
|
+
example.run
|
103
|
+
::Tag.cache_versioning = cache_versioning_value
|
104
|
+
end
|
105
|
+
|
106
|
+
it "returns nil" do
|
107
|
+
expect(tag.cache_version).to be_nil
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
43
111
|
end
|
@@ -4,18 +4,14 @@ describe ::ActiveRemote::QueryAttributes do
|
|
4
4
|
subject { ::Author.new }
|
5
5
|
|
6
6
|
describe "#query_attribute" do
|
7
|
-
it "raises when getting an undefined attribute" do
|
8
|
-
expect { subject.query_attribute(:foobar) }.to raise_error(::ActiveRemote::UnknownAttributeError)
|
9
|
-
end
|
10
|
-
|
11
7
|
it "is false when the attribute is false" do
|
12
|
-
subject.
|
13
|
-
expect(subject.
|
8
|
+
subject.writes_fiction = false
|
9
|
+
expect(subject.writes_fiction?).to eq false
|
14
10
|
end
|
15
11
|
|
16
12
|
it "is true when the attribute is true" do
|
17
|
-
subject.
|
18
|
-
expect(subject.
|
13
|
+
subject.writes_fiction = true
|
14
|
+
expect(subject.writes_fiction?).to eq true
|
19
15
|
end
|
20
16
|
|
21
17
|
it "is false when the attribute is nil" do
|
@@ -23,11 +19,6 @@ describe ::ActiveRemote::QueryAttributes do
|
|
23
19
|
expect(subject.name?).to eq false
|
24
20
|
end
|
25
21
|
|
26
|
-
it "is true when the attribute is an Object" do
|
27
|
-
subject.name = Object.new
|
28
|
-
expect(subject.name?).to eq true
|
29
|
-
end
|
30
|
-
|
31
22
|
it "is false when the attribute is an empty string" do
|
32
23
|
subject.name = ""
|
33
24
|
expect(subject.name?).to eq false
|
@@ -40,13 +31,13 @@ describe ::ActiveRemote::QueryAttributes do
|
|
40
31
|
|
41
32
|
# This behavior varies from ActiveRecord, so we test it explicitly
|
42
33
|
it "is true when the attribute is 0" do
|
43
|
-
subject.
|
44
|
-
expect(subject.
|
34
|
+
subject.age = 0
|
35
|
+
expect(subject.age?).to eq true
|
45
36
|
end
|
46
37
|
|
47
38
|
it "is true when the attribute is 1" do
|
48
|
-
subject.
|
49
|
-
expect(subject.
|
39
|
+
subject.age = 1
|
40
|
+
expect(subject.age?).to eq true
|
50
41
|
end
|
51
42
|
end
|
52
43
|
end
|
@@ -6,6 +6,10 @@ describe ::ActiveRemote::RPC do
|
|
6
6
|
describe ".build_from_rpc" do
|
7
7
|
let(:new_attributes) { { :name => "test" } }
|
8
8
|
|
9
|
+
it "dups the default attributes" do
|
10
|
+
expect { ::Tag.build_from_rpc(new_attributes) }.to_not change { ::Tag._default_attributes["name"] }
|
11
|
+
end
|
12
|
+
|
9
13
|
context "missing attributes from rpc" do
|
10
14
|
it "initializes to nil" do
|
11
15
|
expect(::Tag.build_from_rpc(new_attributes)).to include("guid" => nil)
|
@@ -25,7 +29,7 @@ describe ::ActiveRemote::RPC do
|
|
25
29
|
|
26
30
|
it "calls the typecasters" do
|
27
31
|
expect(
|
28
|
-
::
|
32
|
+
::Author.build_from_rpc(new_attributes)
|
29
33
|
).to include("birthday" => "2017-01-01".to_datetime)
|
30
34
|
end
|
31
35
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "spec_helper"
|
2
2
|
|
3
3
|
describe ActiveRemote::Search do
|
4
|
-
let(:records) { [Generic::Remote::Tag.new] }
|
4
|
+
let(:records) { [Generic::Remote::Tag.new(:guid => "123")] }
|
5
5
|
let(:response) { Generic::Remote::Tags.new(:records => records) }
|
6
6
|
let(:rpc) { double(:rpc) }
|
7
7
|
|
@@ -37,7 +37,7 @@ describe ActiveRemote::Search do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
describe ".search" do
|
40
|
-
let(:serialized_records) { [Tag.
|
40
|
+
let(:serialized_records) { [Tag.instantiate(:guid => "123")] }
|
41
41
|
|
42
42
|
context "given args that respond to :to_hash" do
|
43
43
|
let(:args) { {} }
|
@@ -52,7 +52,8 @@ describe ActiveRemote::Search do
|
|
52
52
|
end
|
53
53
|
|
54
54
|
it "returns records" do
|
55
|
-
|
55
|
+
records = Tag.search(args)
|
56
|
+
expect(records).to eq serialized_records
|
56
57
|
end
|
57
58
|
end
|
58
59
|
|
data/spec/support/models.rb
CHANGED
@@ -6,12 +6,16 @@ require "support/protobuf/author.pb"
|
|
6
6
|
class Author < ::ActiveRemote::Base
|
7
7
|
service_class ::Generic::Remote::AuthorService
|
8
8
|
|
9
|
-
attribute :guid
|
10
|
-
attribute :name
|
11
|
-
attribute :user_guid
|
12
|
-
attribute :chief_editor_guid
|
13
|
-
attribute :editor_guid
|
14
|
-
attribute :category_guid
|
9
|
+
attribute :guid, :string
|
10
|
+
attribute :name, :string
|
11
|
+
attribute :user_guid, :string
|
12
|
+
attribute :chief_editor_guid, :string
|
13
|
+
attribute :editor_guid, :string
|
14
|
+
attribute :category_guid, :string
|
15
|
+
attribute :age, :integer
|
16
|
+
attribute :birthday, :datetime
|
17
|
+
attribute :writes_fiction, :boolean
|
18
|
+
attribute :net_sales, :float
|
15
19
|
|
16
20
|
has_many :posts
|
17
21
|
has_many :user_posts, :class_name => "::Post", :scope => :user_guid
|
@@ -6,9 +6,9 @@ require "support/protobuf/category.pb"
|
|
6
6
|
class Category < ::ActiveRemote::Base
|
7
7
|
service_class ::Generic::Remote::CategoryService
|
8
8
|
|
9
|
-
attribute :guid
|
10
|
-
attribute :user_guid
|
11
|
-
attribute :chief_editor_guid
|
9
|
+
attribute :guid, :string
|
10
|
+
attribute :user_guid, :string
|
11
|
+
attribute :chief_editor_guid, :string
|
12
12
|
|
13
13
|
has_many :posts
|
14
14
|
|