active_remote 2.4.0 → 3.0.0.pre1
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 +5 -0
- data/CHANGES.md +22 -0
- data/README.md +2 -0
- data/active_remote.gemspec +2 -2
- data/bin/console +10 -0
- data/lib/active_remote/association.rb +4 -0
- data/lib/active_remote/attribute_assignment.rb +53 -0
- data/lib/active_remote/attribute_definition.rb +106 -0
- data/lib/active_remote/attributes.rb +165 -8
- data/lib/active_remote/base.rb +41 -36
- data/lib/active_remote/dirty.rb +0 -9
- data/lib/active_remote/errors.rb +6 -0
- data/lib/active_remote/persistence.rb +10 -19
- data/lib/active_remote/query_attributes.rb +45 -0
- data/lib/active_remote/rpc.rb +17 -67
- data/lib/active_remote/search.rb +0 -20
- data/lib/active_remote/serialization.rb +1 -32
- data/lib/active_remote/typecasting.rb +3 -12
- data/lib/active_remote/version.rb +1 -1
- data/lib/active_remote.rb +0 -2
- data/spec/lib/active_remote/association_spec.rb +11 -2
- data/spec/lib/active_remote/attributes_spec.rb +177 -0
- data/spec/lib/active_remote/persistence_spec.rb +7 -16
- data/spec/lib/active_remote/query_attribute_spec.rb +171 -0
- data/spec/lib/active_remote/rpc_spec.rb +33 -75
- data/spec/lib/active_remote/search_spec.rb +0 -21
- data/spec/lib/active_remote/serialization_spec.rb +0 -23
- data/spec/support/models/no_attributes.rb +2 -0
- data/spec/support/models.rb +1 -0
- metadata +21 -66
- data/lib/active_remote/attribute_defaults.rb +0 -100
- data/lib/active_remote/bulk.rb +0 -168
- data/lib/active_remote/core_ext/date.rb +0 -7
- data/lib/active_remote/core_ext/date_time.rb +0 -7
- data/lib/active_remote/core_ext/integer.rb +0 -19
- data/lib/active_remote/core_ext.rb +0 -3
- data/lib/active_remote/publication.rb +0 -54
- data/lib/active_remote/serializers/json.rb +0 -16
- data/spec/core_ext/date_time_spec.rb +0 -9
- data/spec/lib/active_remote/attribute_defaults_spec.rb +0 -26
- data/spec/lib/active_remote/bulk_spec.rb +0 -83
- data/spec/lib/active_remote/publication_spec.rb +0 -18
- data/spec/lib/active_remote/serializers/json_spec.rb +0 -78
data/lib/active_remote/bulk.rb
DELETED
@@ -1,168 +0,0 @@
|
|
1
|
-
require 'active_remote/persistence'
|
2
|
-
|
3
|
-
module ActiveRemote
|
4
|
-
module Bulk
|
5
|
-
extend ActiveSupport::Concern
|
6
|
-
|
7
|
-
included do
|
8
|
-
include Persistence
|
9
|
-
end
|
10
|
-
|
11
|
-
module ClassMethods
|
12
|
-
|
13
|
-
# Create multiple records at the same time. Returns a collection of active
|
14
|
-
# remote objects from the passed records. Records that were not created
|
15
|
-
# are returned with error messages indicating what went wrong.
|
16
|
-
#
|
17
|
-
# ====Examples
|
18
|
-
#
|
19
|
-
# # A single hash
|
20
|
-
# Tag.create_all({ :name => 'foo' })
|
21
|
-
#
|
22
|
-
# # Hashes
|
23
|
-
# Tag.create_all({ :name => 'foo' }, { :name => 'bar' })
|
24
|
-
#
|
25
|
-
# # Active remote objects
|
26
|
-
# Tag.create_all(Tag.new(:name => 'foo'), Tag.new(:name => 'bar'))
|
27
|
-
#
|
28
|
-
# # Protobuf objects
|
29
|
-
# Tag.create_all(Generic::Remote::Tag.new(:name => 'foo'), Generic::Remote::Tag.new(:name => 'bar'))
|
30
|
-
#
|
31
|
-
# # Bulk protobuf object
|
32
|
-
# Tag.create_all(Generic::Remote::Tags.new(:records => [ Generic::Remote::Tag.new(:name => 'foo') ])
|
33
|
-
#
|
34
|
-
def create_all(*records)
|
35
|
-
response = rpc.execute(:create_all, _parse_records(records))
|
36
|
-
|
37
|
-
if response.respond_to?(:records)
|
38
|
-
serialize_records(response.records)
|
39
|
-
else
|
40
|
-
warn "DEPRECATED responses to bulk methods must respond to :records. In Active Remote 3.0, bulk responses that don't respond to :records will raise an exception"
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
# Delete multiple records at the same time. Returns a collection of active
|
45
|
-
# remote objects from the passed records. Records that were not deleted
|
46
|
-
# are returned with error messages indicating what went wrong.
|
47
|
-
#
|
48
|
-
# ====Examples
|
49
|
-
#
|
50
|
-
# # A single hash
|
51
|
-
# Tag.delete_all({ :guid => 'foo' })
|
52
|
-
#
|
53
|
-
# # Hashes
|
54
|
-
# Tag.delete_all({ :guid => 'foo' }, { :guid => 'bar' })
|
55
|
-
#
|
56
|
-
# # Active remote objects
|
57
|
-
# Tag.delete_all(Tag.new(:guid => 'foo'), Tag.new(:guid => 'bar'))
|
58
|
-
#
|
59
|
-
# # Protobuf objects
|
60
|
-
# Tag.delete_all(Generic::Remote::Tag.new(:guid => 'foo'), Generic::Remote::Tag.new(:guid => 'bar'))
|
61
|
-
#
|
62
|
-
# # Bulk protobuf object
|
63
|
-
# Tag.delete_all(Generic::Remote::Tags.new(:records => [ Generic::Remote::Tag.new(:guid => 'foo') ])
|
64
|
-
#
|
65
|
-
def delete_all(*records)
|
66
|
-
response = rpc.execute(:delete_all, _parse_records(records))
|
67
|
-
|
68
|
-
if response.respond_to?(:records)
|
69
|
-
serialize_records(response.records)
|
70
|
-
else
|
71
|
-
warn "DEPRECATED responses to bulk methods must respond to :records. In Active Remote 3.0, bulk responses that don't respond to :records will raise an exception"
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Destroy multiple records at the same time. Returns a collection of active
|
76
|
-
# remote objects from the passed records. Records that were not destroyed
|
77
|
-
# are returned with error messages indicating what went wrong.
|
78
|
-
#
|
79
|
-
# ====Examples
|
80
|
-
#
|
81
|
-
# # A single hash
|
82
|
-
# Tag.destroy_all({ :guid => 'foo' })
|
83
|
-
#
|
84
|
-
# # Hashes
|
85
|
-
# Tag.destroy_all({ :guid => 'foo' }, { :guid => 'bar' })
|
86
|
-
#
|
87
|
-
# # Active remote objects
|
88
|
-
# Tag.destroy_all(Tag.new(:guid => 'foo'), Tag.new(:guid => 'bar'))
|
89
|
-
#
|
90
|
-
# # Protobuf objects
|
91
|
-
# Tag.destroy_all(Generic::Remote::Tag.new(:guid => 'foo'), Generic::Remote::Tag.new(:guid => 'bar'))
|
92
|
-
#
|
93
|
-
# # Bulk protobuf object
|
94
|
-
# Tag.destroy_all(Generic::Remote::Tags.new(:records => [ Generic::Remote::Tag.new(:guid => 'foo') ])
|
95
|
-
#
|
96
|
-
def destroy_all(*records)
|
97
|
-
response = rpc.execute(:destroy_all, _parse_records(records))
|
98
|
-
|
99
|
-
if response.respond_to?(:records)
|
100
|
-
serialize_records(response.records)
|
101
|
-
else
|
102
|
-
warn "DEPRECATED responses to bulk methods must respond to :records. In Active Remote 3.0, bulk responses that don't respond to :records will raise an exception"
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
# Parse given records to get them ready to be built into a request.
|
107
|
-
#
|
108
|
-
# It handles any object that responds to +to_hash+, so protobuf messages
|
109
|
-
# and active remote objects will work just like hashes.
|
110
|
-
#
|
111
|
-
# Returns +{ :records => records }+.
|
112
|
-
#
|
113
|
-
def parse_records(*records)
|
114
|
-
warn "DEPRECATED Model.parse_records is deprecated. It will be removed in Active Remove 3.0"
|
115
|
-
|
116
|
-
_parse_records(*records)
|
117
|
-
end
|
118
|
-
|
119
|
-
# Update multiple records at the same time. Returns a collection of active
|
120
|
-
# remote objects from the passed records. Records that were not updated
|
121
|
-
# are returned with error messages indicating what went wrong.
|
122
|
-
#
|
123
|
-
# ====Examples
|
124
|
-
#
|
125
|
-
# # A single hash
|
126
|
-
# Tag.update_all({ :guid => 'foo', :name => 'baz' })
|
127
|
-
#
|
128
|
-
# # Hashes
|
129
|
-
# Tag.update_all({ :guid => 'foo', :name => 'baz' }, { :guid => 'bar', :name => 'qux' })
|
130
|
-
#
|
131
|
-
# # Active remote objects
|
132
|
-
# Tag.update_all(Tag.new(:guid => 'foo', :name => 'baz'), Tag.new(:guid => 'bar', :name => 'qux'))
|
133
|
-
#
|
134
|
-
# # Protobuf objects
|
135
|
-
# Tag.update_all(Generic::Remote::Tag.new(:guid => 'foo', :name => 'baz'), Generic::Remote::Tag.new(:guid => 'bar', :name => 'qux'))
|
136
|
-
#
|
137
|
-
# # Bulk protobuf object
|
138
|
-
# Tag.update_all(Generic::Remote::Tags.new(:records => [ Generic::Remote::Tag.new(:guid => 'foo', :name => 'baz') ])
|
139
|
-
#
|
140
|
-
def update_all(*records)
|
141
|
-
response = rpc.execute(:update_all, _parse_records(records))
|
142
|
-
|
143
|
-
if response.respond_to?(:records)
|
144
|
-
serialize_records(response.records)
|
145
|
-
else
|
146
|
-
warn "DEPRECATED responses to bulk methods must respond to :records. In Active Remote 3.0, bulk responses that don't respond to :records will raise an exception"
|
147
|
-
end
|
148
|
-
end
|
149
|
-
|
150
|
-
private
|
151
|
-
|
152
|
-
def _parse_records(*records)
|
153
|
-
records.flatten!
|
154
|
-
|
155
|
-
if records.first.respond_to?(:attributes)
|
156
|
-
records.collect!(&:attributes)
|
157
|
-
else
|
158
|
-
records.collect!(&:to_hash)
|
159
|
-
end
|
160
|
-
|
161
|
-
return records.first if records.first && records.first.has_key?(:records)
|
162
|
-
|
163
|
-
# If we made it this far, build a bulk-formatted hash.
|
164
|
-
return { :records => records }
|
165
|
-
end
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
@@ -1,19 +0,0 @@
|
|
1
|
-
Integer.class_eval do
|
2
|
-
unless instance_methods.include?(:to_date)
|
3
|
-
def to_date
|
4
|
-
to_time.to_date
|
5
|
-
end
|
6
|
-
end
|
7
|
-
|
8
|
-
unless instance_methods.include?(:to_datetime)
|
9
|
-
def to_datetime
|
10
|
-
to_time.to_datetime
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
|
-
unless instance_methods.include?(:to_time)
|
15
|
-
def to_time
|
16
|
-
Time.at(self)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,54 +0,0 @@
|
|
1
|
-
module ActiveRemote
|
2
|
-
module Publication
|
3
|
-
# Returns a hash of publishable attributes.
|
4
|
-
#
|
5
|
-
def publishable_hash
|
6
|
-
keys = _publishable_attributes_or_attribute_keys
|
7
|
-
|
8
|
-
attributes_hash = keys.inject({}) do |publishable_hash, key|
|
9
|
-
value = respond_to?(key) ? __send__(key) : read_attribute(key)
|
10
|
-
|
11
|
-
publishable_hash[key] = case
|
12
|
-
when value.respond_to?(:map) then
|
13
|
-
_map_value(value)
|
14
|
-
when value.respond_to?(:publishable_hash) then
|
15
|
-
value.publishable_hash
|
16
|
-
when value.respond_to?(:to_hash) then
|
17
|
-
value.to_hash
|
18
|
-
else
|
19
|
-
value
|
20
|
-
end
|
21
|
-
|
22
|
-
publishable_hash
|
23
|
-
end
|
24
|
-
|
25
|
-
attributes_hash
|
26
|
-
end
|
27
|
-
|
28
|
-
def _publishable_json_attributes
|
29
|
-
_publishable_attributes_or_attribute_keys - _publishable_json_methods
|
30
|
-
end
|
31
|
-
|
32
|
-
def _publishable_json_methods
|
33
|
-
_publishable_attributes_or_attribute_keys.reject { |attribute| @attributes.key?(attribute) }
|
34
|
-
end
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
|
-
def _map_value(value)
|
39
|
-
case
|
40
|
-
when value.any? { |obj| obj.respond_to?(:publishable_hash) } then
|
41
|
-
value.map(&:publishable_hash)
|
42
|
-
when value.any? { |obj| obj.respond_to?(:to_hash) } then
|
43
|
-
value.map(&:to_hash)
|
44
|
-
else
|
45
|
-
value
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
def _publishable_attributes_or_attribute_keys
|
50
|
-
@_publishable_attributes_or_attribute_keys = _publishable_attributes
|
51
|
-
@_publishable_attributes_or_attribute_keys ||= @attributes.keys
|
52
|
-
end
|
53
|
-
end
|
54
|
-
end
|
@@ -1,16 +0,0 @@
|
|
1
|
-
module ActiveRemote
|
2
|
-
module Serializers
|
3
|
-
module JSON
|
4
|
-
# Returns a json representation of the whitelisted publishable attributes.
|
5
|
-
#
|
6
|
-
def as_json(options = {})
|
7
|
-
options ||= {}
|
8
|
-
|
9
|
-
default_options = { :only => _publishable_json_attributes, :methods => _publishable_json_methods }
|
10
|
-
default_options.merge!(options)
|
11
|
-
|
12
|
-
super(default_options)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
describe "attribute defailts" do
|
4
|
-
let(:test_class) { ::DefaultAuthor }
|
5
|
-
|
6
|
-
describe "string" do
|
7
|
-
it "defaults to a string" do
|
8
|
-
record = test_class.new
|
9
|
-
expect(record.name).to eq("John Doe")
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
describe "lambda" do
|
14
|
-
it "calls the lambda" do
|
15
|
-
record = test_class.new
|
16
|
-
expect(record.guid).to eq(100)
|
17
|
-
end
|
18
|
-
end
|
19
|
-
|
20
|
-
describe "array" do
|
21
|
-
it "defaults to an array" do
|
22
|
-
record = test_class.new
|
23
|
-
expect(record.books).to eq([])
|
24
|
-
end
|
25
|
-
end
|
26
|
-
end
|
@@ -1,83 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRemote::Bulk do
|
4
|
-
shared_examples_for "a bulk method" do |bulk_method|
|
5
|
-
let(:records) { [ Hash.new ] }
|
6
|
-
let(:response) { double(:response, :records => []) }
|
7
|
-
let(:rpc) { ::ActiveRemote::RPCAdapters::ProtobufAdapter.new(::Tag.service_class) }
|
8
|
-
|
9
|
-
before { allow(rpc).to receive(:execute).and_return(response) }
|
10
|
-
before { allow(::Tag).to receive(:rpc).and_return(rpc) }
|
11
|
-
|
12
|
-
context "given an empty array" do
|
13
|
-
let(:parsed_records) { { :records => records } }
|
14
|
-
let(:records) { [] }
|
15
|
-
|
16
|
-
it "calls #{bulk_method} with parsed records" do
|
17
|
-
expect(rpc).to receive(:execute).with(bulk_method, parsed_records)
|
18
|
-
Tag.__send__(bulk_method, records)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
context "given an array of record hashes" do
|
23
|
-
let(:hash_record){ double(:record, :to_hash => {}) }
|
24
|
-
let(:parsed_records) { { :records => records.map(&:to_hash) } }
|
25
|
-
let(:records) { [ hash_record ] }
|
26
|
-
|
27
|
-
it "calls #{bulk_method} with parsed records" do
|
28
|
-
expect(rpc).to receive(:execute).with(bulk_method, parsed_records)
|
29
|
-
Tag.__send__(bulk_method, records)
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
context "given an array of remote records" do
|
34
|
-
let(:parsed_records) { { :records => records.map(&:attributes) } }
|
35
|
-
let(:records) { [ remote_record ] }
|
36
|
-
let(:remote_record) { double(:remote, :attributes => {}) }
|
37
|
-
|
38
|
-
it "calls #{bulk_method} with parsed records" do
|
39
|
-
expect(rpc).to receive(:execute).with(bulk_method, parsed_records)
|
40
|
-
Tag.__send__(bulk_method, records)
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
|
-
context "given a bulk message" do
|
45
|
-
let(:parsed_records) { { :records => records.map(&:to_hash) } }
|
46
|
-
let(:tag) { Generic::Remote::Tag.new }
|
47
|
-
let(:tags) { Generic::Remote::Tags.new(:records => [ tag ]) }
|
48
|
-
|
49
|
-
it "calls #{bulk_method} with parsed records" do
|
50
|
-
expect(rpc).to receive(:execute).with(bulk_method, parsed_records)
|
51
|
-
Tag.__send__(bulk_method, tags)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
context "response with errors" do
|
56
|
-
let(:record_with_errors) { double(:record, :errors => [double(:error, :messages => ["whine"], :field => "wat")], :to_hash => {}) }
|
57
|
-
let(:response) { double(:response, :records => [record_with_errors]) }
|
58
|
-
let(:tag) { Generic::Remote::Tag.new }
|
59
|
-
let(:tags) { Generic::Remote::Tags.new(:records => [ tag ]) }
|
60
|
-
|
61
|
-
it "sets the errors on the inflated ActiveRemote objects" do
|
62
|
-
records = Tag.__send__(bulk_method, tags)
|
63
|
-
expect(records.first.errors["wat"]).to eq(["whine"])
|
64
|
-
end
|
65
|
-
end
|
66
|
-
end
|
67
|
-
|
68
|
-
describe ".create_all" do
|
69
|
-
it_behaves_like "a bulk method", :create_all
|
70
|
-
end
|
71
|
-
|
72
|
-
describe ".delete_all" do
|
73
|
-
it_behaves_like "a bulk method", :delete_all
|
74
|
-
end
|
75
|
-
|
76
|
-
describe ".destroy_all" do
|
77
|
-
it_behaves_like "a bulk method", :destroy_all
|
78
|
-
end
|
79
|
-
|
80
|
-
describe ".update_all" do
|
81
|
-
it_behaves_like "a bulk method", :update_all
|
82
|
-
end
|
83
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRemote::Publication do
|
4
|
-
let(:attributes) { { :guid => 'foo', :name => 'bar' } }
|
5
|
-
|
6
|
-
subject { Tag.new(attributes) }
|
7
|
-
|
8
|
-
context "with publishable attributes defined" do
|
9
|
-
let(:expected_hash) { attributes.slice(:name) }
|
10
|
-
|
11
|
-
before { Tag.attr_publishable :name }
|
12
|
-
after { reset_publishable_attributes(Tag) }
|
13
|
-
|
14
|
-
it "serializes to a hash with only the publishable attributes" do
|
15
|
-
expect(subject.publishable_hash).to eq expected_hash
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
describe ActiveRemote::Serializers::JSON do
|
4
|
-
describe "#as_json" do
|
5
|
-
let(:attributes) { { :guid => 'foo', :name => 'bar', :updated_at => nil, :user_guid => 'baz' } }
|
6
|
-
let(:serializable_attributes) { { "tag" => attributes.stringify_keys } }
|
7
|
-
|
8
|
-
subject { Tag.new(attributes) }
|
9
|
-
|
10
|
-
context "with roots in json" do
|
11
|
-
context "when options are nil" do
|
12
|
-
it "substitutes an empty hash" do
|
13
|
-
expect(subject.as_json(nil)).to eq serializable_attributes
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
it "accepts standard JSON options" do
|
18
|
-
expect(subject.as_json(:root => false)).to eq attributes.stringify_keys
|
19
|
-
end
|
20
|
-
|
21
|
-
context "with publishable attributes defined" do
|
22
|
-
let(:expected_json) { { :tag => attributes.slice(:name) }.to_json }
|
23
|
-
|
24
|
-
before { Tag.attr_publishable :name }
|
25
|
-
after { reset_publishable_attributes(Tag) }
|
26
|
-
|
27
|
-
it "serializes to JSON with only the publishable attributes" do
|
28
|
-
expect(subject.to_json).to eq expected_json
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
context "without publishable attributes defined" do
|
33
|
-
let(:expected_json) { { :tag => attributes }.to_json }
|
34
|
-
|
35
|
-
it "serializes to JSON" do
|
36
|
-
expect(subject.to_json).to eq expected_json
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context "without roots in json" do
|
42
|
-
let(:serializable_attributes) { attributes.stringify_keys }
|
43
|
-
|
44
|
-
before(:each) do
|
45
|
-
::ActiveRemote.config.include_root_in_json = false
|
46
|
-
end
|
47
|
-
|
48
|
-
after(:each) do
|
49
|
-
::ActiveRemote.config.include_root_in_json = true
|
50
|
-
end
|
51
|
-
|
52
|
-
context "when options are nil" do
|
53
|
-
it "substitutes an empty hash" do
|
54
|
-
expect(subject.as_json(nil)).to eq serializable_attributes
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "with publishable attributes defined" do
|
59
|
-
let(:expected_json) { attributes.slice(:name).to_json }
|
60
|
-
|
61
|
-
before { Tag.attr_publishable :name }
|
62
|
-
after { reset_publishable_attributes(Tag) }
|
63
|
-
|
64
|
-
it "serializes to JSON with only the publishable attributes" do
|
65
|
-
expect(subject.to_json).to eq expected_json
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
context "without publishable attributes defined" do
|
70
|
-
let(:expected_json) { attributes.to_json }
|
71
|
-
|
72
|
-
it "serializes to JSON" do
|
73
|
-
expect(subject.to_json).to eq expected_json
|
74
|
-
end
|
75
|
-
end
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|