active_remote 7.1.0 → 7.2.0

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.
Files changed (59) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -1
  3. data/.standard.yml +2 -1
  4. data/{CHANGES.md → CHANGELOG.md} +10 -4
  5. data/CODE_OF_CONDUCT.md +132 -0
  6. data/LICENSE.txt +21 -0
  7. data/Rakefile +13 -8
  8. data/lib/active_remote/association.rb +8 -13
  9. data/lib/active_remote/attribute_methods.rb +1 -1
  10. data/lib/active_remote/base.rb +2 -4
  11. data/lib/active_remote/dirty.rb +0 -32
  12. data/lib/active_remote/version.rb +1 -1
  13. metadata +18 -186
  14. data/.github/workflows/main.yml +0 -41
  15. data/.gitignore +0 -13
  16. data/Gemfile +0 -4
  17. data/LICENSE +0 -22
  18. data/active_remote.gemspec +0 -38
  19. data/bin/benchmark +0 -43
  20. data/bin/console +0 -10
  21. data/spec/lib/active_remote/association_spec.rb +0 -257
  22. data/spec/lib/active_remote/base_spec.rb +0 -10
  23. data/spec/lib/active_remote/dirty_spec.rb +0 -93
  24. data/spec/lib/active_remote/dsl_spec.rb +0 -85
  25. data/spec/lib/active_remote/errors_spec.rb +0 -31
  26. data/spec/lib/active_remote/integration_spec.rb +0 -111
  27. data/spec/lib/active_remote/persistence_spec.rb +0 -416
  28. data/spec/lib/active_remote/primary_key_spec.rb +0 -49
  29. data/spec/lib/active_remote/query_attribute_spec.rb +0 -43
  30. data/spec/lib/active_remote/rpc_adapters/protobuf_adapter_spec.rb +0 -24
  31. data/spec/lib/active_remote/rpc_spec.rb +0 -86
  32. data/spec/lib/active_remote/scope_keys_spec.rb +0 -42
  33. data/spec/lib/active_remote/search_spec.rb +0 -114
  34. data/spec/lib/active_remote/serialization_spec.rb +0 -33
  35. data/spec/lib/active_remote/serializers/protobuf_spec.rb +0 -89
  36. data/spec/lib/active_remote/validations_spec.rb +0 -56
  37. data/spec/spec_helper.rb +0 -29
  38. data/spec/support/definitions/author.proto +0 -30
  39. data/spec/support/definitions/category.proto +0 -33
  40. data/spec/support/definitions/error.proto +0 -6
  41. data/spec/support/definitions/post.proto +0 -35
  42. data/spec/support/definitions/serializer.proto +0 -23
  43. data/spec/support/definitions/tag.proto +0 -30
  44. data/spec/support/helpers.rb +0 -35
  45. data/spec/support/models/author.rb +0 -26
  46. data/spec/support/models/category.rb +0 -19
  47. data/spec/support/models/default_author.rb +0 -12
  48. data/spec/support/models/message_with_options.rb +0 -11
  49. data/spec/support/models/no_attributes.rb +0 -2
  50. data/spec/support/models/post.rb +0 -21
  51. data/spec/support/models/tag.rb +0 -22
  52. data/spec/support/models.rb +0 -7
  53. data/spec/support/protobuf/author.pb.rb +0 -58
  54. data/spec/support/protobuf/category.pb.rb +0 -61
  55. data/spec/support/protobuf/error.pb.rb +0 -21
  56. data/spec/support/protobuf/post.pb.rb +0 -63
  57. data/spec/support/protobuf/serializer.pb.rb +0 -36
  58. data/spec/support/protobuf/tag.pb.rb +0 -58
  59. data/spec/support/protobuf.rb +0 -5
data/.gitignore DELETED
@@ -1,13 +0,0 @@
1
- *.gem
2
- *.swp
3
- .DS_Store
4
- .bundle
5
- .config
6
- .ruby-*
7
- .rvmrc
8
- .yardoc
9
- .idea
10
- Gemfile.lock
11
- coverage
12
- pkg/*
13
- tmp
data/Gemfile DELETED
@@ -1,4 +0,0 @@
1
- source "https://rubygems.org"
2
-
3
- # Specify your gem's dependencies in active_remote.gemspec
4
- gemspec
data/LICENSE DELETED
@@ -1,22 +0,0 @@
1
- Copyright (c) 2012 Adam Hutchison
2
-
3
- MIT License
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining
6
- a copy of this software and associated documentation files (the
7
- "Software"), to deal in the Software without restriction, including
8
- without limitation the rights to use, copy, modify, merge, publish,
9
- distribute, sublicense, and/or sell copies of the Software, and to
10
- permit persons to whom the Software is furnished to do so, subject to
11
- the following conditions:
12
-
13
- The above copyright notice and this permission notice shall be
14
- included in all copies or substantial portions of the Software.
15
-
16
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -1,38 +0,0 @@
1
- $LOAD_PATH.push File.expand_path("lib", __dir__)
2
- require "active_remote/version"
3
-
4
- Gem::Specification.new do |s|
5
- s.name = "active_remote"
6
- s.version = ActiveRemote::VERSION
7
- s.authors = ["Adam Hutchison"]
8
- s.email = ["liveh2o@gmail.com"]
9
- s.homepage = "https://github.com/liveh2o/active_remote"
10
- s.summary = "Active Record for your platform"
11
- s.description = "Active Remote provides Active Record-like object-relational mapping over RPC. It was written for use with Google Protocol Buffers, but could be extended to use any RPC data format."
12
-
13
- s.files = `git ls-files`.split("\n")
14
- s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
15
- s.require_paths = ["lib"]
16
-
17
- s.required_ruby_version = ">= 2.7.0"
18
-
19
- ##
20
- # Dependencies
21
- #
22
- s.add_dependency "activemodel", "~> 7.1.0"
23
- s.add_dependency "activesupport", "~> 7.1.0"
24
- s.add_dependency "protobuf", ">= 3.0"
25
-
26
- ##
27
- # Development Dependencies
28
- #
29
- s.add_development_dependency "benchmark-ips"
30
- s.add_development_dependency "protobuf-rspec", ">= 1.1.2"
31
- s.add_development_dependency "pry"
32
- s.add_development_dependency "rspec-its"
33
- s.add_development_dependency "rspec-pride", ">= 3.1.0"
34
- s.add_development_dependency "rspec", ">= 3.3.0"
35
- s.add_development_dependency "simplecov"
36
- s.add_development_dependency "standard"
37
- s.add_development_dependency "rake"
38
- end
data/bin/benchmark DELETED
@@ -1,43 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
-
5
- require "active_remote"
6
- require "benchmark/ips"
7
-
8
- class Author < ::ActiveRemote::Base
9
- attribute :guid, :string
10
- attribute :name, :string
11
- attribute :age, :integer
12
- attribute :birthday, :datetime
13
- attribute :writes_fiction, :boolean
14
- attribute :net_sales, :float
15
- end
16
-
17
- ATTRIBUTES = {
18
- :guid => "0c030733-3b78-4587-b94b-5e0cf26497c5",
19
- :name => "Charles Dickens",
20
- :age => 68,
21
- :birthday => "1812-02-07 00:00:00",
22
- :writes_fiction => true,
23
- :net_sales => 1_000_000.0
24
- }
25
-
26
- ::Benchmark.ips do |x|
27
- x.config(:time => 20, :warmup => 10)
28
- x.report("initialize") do
29
- ::Author.new(ATTRIBUTES)
30
- end
31
-
32
- x.report("instantiate") do
33
- ::Author.instantiate(ATTRIBUTES)
34
- end
35
-
36
- x.report("init attributes") do
37
- ::Author.new(ATTRIBUTES).attributes
38
- end
39
-
40
- x.report("inst attributes") do
41
- ::Author.instantiate(ATTRIBUTES).attributes
42
- end
43
- end
data/bin/console DELETED
@@ -1,10 +0,0 @@
1
- #!/usr/bin/env ruby
2
-
3
- require "bundler/setup"
4
- require "active_remote"
5
-
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- require "pry"
10
- Pry.start
@@ -1,257 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe ActiveRemote::Association do
4
- let(:record) { double(:record) }
5
- let(:records) { [record] }
6
-
7
- describe ".belongs_to" do
8
- context "simple association" do
9
- let(:author_guid) { "AUT-123" }
10
- let(:user_guid) { "USR-123" }
11
- let(:default_category_guid) { "CAT-123" }
12
- subject { Post.new(author_guid: author_guid, user_guid: user_guid) }
13
-
14
- it { is_expected.to respond_to(:author) }
15
- it { is_expected.to respond_to(:author=) }
16
-
17
- it "searches the associated model for a single record" do
18
- expect(Author).to receive(:search).with({guid: subject.author_guid}).and_return(records)
19
- expect(subject.author).to eq record
20
- end
21
-
22
- it "memoizes the result record" do
23
- expect(Author).to receive(:search).once.with({guid: subject.author_guid}).and_return(records)
24
- 3.times { expect(subject.author).to eq record }
25
- end
26
-
27
- context "when guid is nil" do
28
- subject { Post.new }
29
-
30
- it "returns nil" do
31
- expect(subject.author).to be_nil
32
- end
33
- end
34
-
35
- context "when the search is empty" do
36
- it "returns a nil" do
37
- expect(Author).to receive(:search).with({guid: subject.author_guid}).and_return([])
38
- expect(subject.author).to be_nil
39
- end
40
- end
41
-
42
- context "scoped field" do
43
- it { is_expected.to respond_to(:user) }
44
-
45
- it "searches the associated model for multiple records" do
46
- expect(Author).to receive(:search).with({guid: subject.author_guid, user_guid: subject.user_guid}).and_return(records)
47
- expect(subject.user).to eq(record)
48
- end
49
-
50
- context "when user_guid doesnt exist on model " do
51
- before { allow(subject.class).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
52
-
53
- it "raises an error" do
54
- expect { subject.user }.to raise_error(::RuntimeError, /Could not find attribute/)
55
- end
56
- end
57
-
58
- context "when user_guid doesnt exist on associated model " do
59
- before { allow(Author).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
60
-
61
- it "raises an error" do
62
- expect { subject.user }.to raise_error(::RuntimeError, /Could not find attribute/)
63
- end
64
- end
65
- end
66
- end
67
-
68
- context "specific association with class name" do
69
- let(:author_guid) { "AUT-456" }
70
-
71
- subject { Post.new(author_guid: author_guid) }
72
- it { is_expected.to respond_to(:coauthor) }
73
-
74
- it "searches the associated model for a single record" do
75
- expect(Author).to receive(:search).with({guid: subject.author_guid}).and_return(records)
76
- expect(subject.coauthor).to eq record
77
- end
78
-
79
- it "creates a setter method" do
80
- author = Author.new(guid: author_guid)
81
- subject.coauthor = author
82
- expect(subject.coauthor).to eq(author)
83
- end
84
- end
85
-
86
- context "specific association with class name and foreign_key" do
87
- let(:author_guid) { "AUT-456" }
88
-
89
- subject { Post.new(bestseller_guid: author_guid) }
90
- it { is_expected.to respond_to(:bestseller) }
91
-
92
- it "searches the associated model for a single record" do
93
- expect(Author).to receive(:search).with({guid: subject.bestseller_guid}).and_return(records)
94
- expect(subject.bestseller).to eq record
95
- end
96
- end
97
- end
98
-
99
- describe ".has_many" do
100
- let(:records) { [record, record, record] }
101
- let(:guid) { "AUT-123" }
102
- let(:user_guid) { "USR-123" }
103
-
104
- subject { Author.new(guid: guid, user_guid: user_guid) }
105
-
106
- it { is_expected.to respond_to(:posts) }
107
- it { is_expected.to respond_to(:posts=) }
108
-
109
- it "searches the associated model for all associated records" do
110
- expect(Post).to receive(:search).with({author_guid: subject.guid}).and_return(records)
111
- expect(subject.posts).to eq records
112
- end
113
-
114
- it "memoizes the result record" do
115
- expect(Post).to receive(:search).once.with({author_guid: subject.guid}).and_return(records)
116
- 3.times { expect(subject.posts).to eq records }
117
- end
118
-
119
- context "when guid is nil" do
120
- subject { Author.new }
121
-
122
- it "returns []" do
123
- expect(subject.posts).to eq []
124
- end
125
- end
126
-
127
- context "when the search is empty" do
128
- it "returns the empty set" do
129
- expect(Post).to receive(:search).with({author_guid: subject.guid}).and_return([])
130
- expect(subject.posts).to be_empty
131
- end
132
- end
133
-
134
- context "specific association with class name" do
135
- it { is_expected.to respond_to(:flagged_posts) }
136
-
137
- it "searches the associated model for a single record" do
138
- expect(Post).to receive(:search).with({author_guid: subject.guid}).and_return([])
139
- expect(subject.flagged_posts).to be_empty
140
- end
141
- end
142
-
143
- context "specific association with class name and foreign_key" do
144
- it { is_expected.to respond_to(:bestseller_posts) }
145
-
146
- it "searches the associated model for multiple record" do
147
- expect(Post).to receive(:search).with({bestseller_guid: subject.guid}).and_return(records)
148
- expect(subject.bestseller_posts).to eq(records)
149
- end
150
- end
151
-
152
- context "scoped field" do
153
- it { is_expected.to respond_to(:user_posts) }
154
-
155
- it "searches the associated model for multiple records" do
156
- expect(Post).to receive(:search).with({author_guid: subject.guid, user_guid: subject.user_guid}).and_return(records)
157
- expect(subject.user_posts).to eq(records)
158
- end
159
-
160
- context "when user_guid doesnt exist on associated model " do
161
- before { allow(Post).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
162
-
163
- it "raises an error" do
164
- expect { subject.user_posts }.to raise_error(::RuntimeError, /Could not find attribute/)
165
- end
166
- end
167
- end
168
-
169
- context "writer method" do
170
- context "when new value is not an array" do
171
- it "should raise error" do
172
- expect { subject.posts = Post.new }.to raise_error(::RuntimeError, /New value must be an array/)
173
- end
174
- end
175
- end
176
- end
177
-
178
- describe ".has_one" do
179
- let(:guid) { "CAT-123" }
180
- let(:user_guid) { "USR-123" }
181
- let(:category_attributes) {
182
- {
183
- guid: guid,
184
- user_guid: user_guid
185
- }
186
- }
187
-
188
- subject { Category.new(category_attributes) }
189
-
190
- it { is_expected.to respond_to(:author) }
191
- it { is_expected.to respond_to(:author=) }
192
-
193
- it "searches the associated model for all associated records" do
194
- expect(Author).to receive(:search).with({category_guid: subject.guid}).and_return(records)
195
- expect(subject.author).to eq record
196
- end
197
-
198
- it "memoizes the result record" do
199
- expect(Author).to receive(:search).once.with({category_guid: subject.guid}).and_return(records)
200
- 3.times { expect(subject.author).to eq record }
201
- end
202
-
203
- context "when guid is nil" do
204
- subject { Category.new }
205
-
206
- it "returns nil" do
207
- expect(subject.author).to be_nil
208
- end
209
- end
210
-
211
- context "when the search is empty" do
212
- it "returns a nil value" do
213
- expect(Author).to receive(:search).with({category_guid: subject.guid}).and_return([])
214
- expect(subject.author).to be_nil
215
- end
216
- end
217
-
218
- context "specific association with class name" do
219
- it { is_expected.to respond_to(:senior_author) }
220
-
221
- it "searches the associated model for a single record" do
222
- expect(Author).to receive(:search).with({category_guid: subject.guid}).and_return(records)
223
- expect(subject.senior_author).to eq record
224
- end
225
-
226
- it "should create a setter method" do
227
- expect(subject).to respond_to(:senior_author=)
228
- end
229
- end
230
-
231
- context "specific association with class name and foreign_key" do
232
- it { is_expected.to respond_to(:primary_editor) }
233
-
234
- it "searches the associated model for a single record" do
235
- expect(Author).to receive(:search).with({editor_guid: subject.guid}).and_return(records)
236
- expect(subject.primary_editor).to eq record
237
- end
238
- end
239
-
240
- context "scoped field" do
241
- it { is_expected.to respond_to(:chief_editor) }
242
-
243
- it "searches the associated model for multiple records" do
244
- expect(Author).to receive(:search).with({chief_editor_guid: subject.guid, user_guid: subject.user_guid}).and_return(records)
245
- expect(subject.chief_editor).to eq(record)
246
- end
247
-
248
- context "when user_guid doesnt exist on associated model " do
249
- before { allow(Author).to receive_message_chain(:public_instance_methods, :include?).with(:user_guid).and_return(false) }
250
-
251
- it "raises an error" do
252
- expect { subject.chief_editor }.to raise_error(::RuntimeError, /Could not find attribute/)
253
- end
254
- end
255
- end
256
- end
257
- end
@@ -1,10 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe ActiveRemote::Base do
4
- describe "#initialize" do
5
- it "runs callbacks" do
6
- expect_any_instance_of(described_class).to receive(:run_callbacks).with(:initialize)
7
- described_class.new
8
- end
9
- end
10
- end
@@ -1,93 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe ActiveRemote::Dirty do
4
- context "when writing attributes through the setter" do
5
- subject { Post.new(name: "foo") }
6
-
7
- before do
8
- subject.changes_applied
9
- subject.clear_changes_information
10
- end
11
-
12
- context "when the value changes" do
13
- before { subject.name = "bar" }
14
-
15
- its(:name_changed?) { should be_truthy }
16
- end
17
-
18
- context "when the value doesn't change" do
19
- before { subject.name = "foo" }
20
-
21
- its(:name_changed?) { should be_falsey }
22
- end
23
- end
24
-
25
- context "when writing attributes directly" do
26
- subject { Post.new(name: "foo") }
27
-
28
- before do
29
- subject.changes_applied
30
- subject.clear_changes_information
31
- end
32
-
33
- context "when the value changes" do
34
- before { subject[:name] = "bar" }
35
-
36
- its(:name_changed?) { should be_truthy }
37
- end
38
-
39
- context "when the value doesn't change" do
40
- before { subject[:name] = "foo" }
41
-
42
- its(:name_changed?) { should be_falsey }
43
- end
44
- end
45
-
46
- describe "#reload" do
47
- subject { Post.new(name: "foo") }
48
-
49
- before do
50
- allow(Post).to receive(:find).and_return(Post.new(name: "foo"))
51
- subject.reload
52
- end
53
-
54
- its(:changes) { should be_empty }
55
- end
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
-
66
- describe "#save" do
67
- let!(:changes) { subject.changes }
68
-
69
- subject { Post.new(name: "foo") }
70
-
71
- before do
72
- allow(subject).to receive(:create_or_update).and_return(true)
73
- subject.save
74
- end
75
-
76
- its(:previous_changes) { should eq changes }
77
- its(:changes) { should be_empty }
78
- end
79
-
80
- describe "#save!" do
81
- let!(:changes) { subject.changes }
82
-
83
- subject { Post.new(name: "foo") }
84
-
85
- before do
86
- allow(subject).to receive(:save).and_return(true)
87
- subject.save!
88
- end
89
-
90
- its(:previous_changes) { should eq changes }
91
- its(:changes) { should be_empty }
92
- end
93
- end
@@ -1,85 +0,0 @@
1
- require "spec_helper"
2
-
3
- # For testing the DSL methods
4
- module Another
5
- class TagService < Protobuf::Rpc::Service
6
- end
7
- end
8
-
9
- describe ActiveRemote::DSL do
10
- before { reset_dsl_variables(Tag) }
11
- after { Tag.service_class Generic::Remote::TagService }
12
-
13
- describe ".attr_publishable" do
14
- after { reset_publishable_attributes(Tag) }
15
-
16
- it "appends given attributes to @publishable_attributes" do
17
- Tag.attr_publishable :guid
18
- Tag.attr_publishable :name
19
-
20
- expect(Tag.publishable_attributes).to match_array([:guid, :name])
21
- end
22
- end
23
-
24
- describe ".endpoints" do
25
- it "has default values" do
26
- expect(Tag.endpoints).to eq(
27
- create: :create,
28
- delete: :delete,
29
- destroy: :destroy,
30
- search: :search,
31
- update: :update
32
- )
33
- end
34
-
35
- context "given a new value for an endpoint" do
36
- after { Tag.endpoints(create: :create) }
37
-
38
- it "overwrites default values" do
39
- Tag.endpoints(create: :register)
40
- expect(Tag.endpoints[:create]).to eq(:register)
41
- end
42
- end
43
- end
44
-
45
- describe ".namespace" do
46
- context "when given a value" do
47
- it "sets @namespace to the value" do
48
- Tag.namespace :foo
49
- expect(Tag.namespace).to eq :foo
50
- end
51
- end
52
- end
53
-
54
- describe ".service_class" do
55
- context "when nil" do
56
- it "determines the service class" do
57
- Tag.namespace :another
58
-
59
- expect(Tag.service_class).to eq Another::TagService
60
- end
61
- end
62
-
63
- context "when given a value" do
64
- it "sets @service_class to the value" do
65
- Tag.service_class Generic::Remote::TagService
66
- expect(Tag.service_class).to eq Generic::Remote::TagService
67
- end
68
- end
69
- end
70
-
71
- describe ".service_name" do
72
- context "when nil" do
73
- it "determines the service name" do
74
- expect(Tag.service_name).to eq :tag_service
75
- end
76
- end
77
-
78
- context "when given a value" do
79
- it "sets @service_name to the value" do
80
- Tag.service_name :foo
81
- expect(Tag.service_name).to eq :foo
82
- end
83
- end
84
- end
85
- end
@@ -1,31 +0,0 @@
1
- require "spec_helper"
2
-
3
- describe ::ActiveRemote::RemoteRecordNotSaved do
4
- let(:record) { ::Tag.new }
5
-
6
- before do
7
- record.errors.add(:base, :invalid, message: "Some error one!")
8
- record.errors.add(:base, :invalid, message: "Some error two!")
9
- end
10
-
11
- context "when an active remote record is used" do
12
- it "uses embedded errors in message" do
13
- expect { fail(::ActiveRemote::RemoteRecordNotSaved, record) }
14
- .to raise_error(ActiveRemote::RemoteRecordNotSaved, "Some error one!, Some error two!")
15
- end
16
- end
17
-
18
- context "when a string is used" do
19
- it "uses the string in the error message" do
20
- expect { fail(::ActiveRemote::RemoteRecordNotSaved, "something bad happened") }
21
- .to raise_error(ActiveRemote::RemoteRecordNotSaved, "something bad happened")
22
- end
23
- end
24
-
25
- context "when no message is used" do
26
- it "raises the error" do
27
- expect { raise(::ActiveRemote::RemoteRecordNotSaved) }
28
- .to raise_error(ActiveRemote::RemoteRecordNotSaved)
29
- end
30
- end
31
- end