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.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -0
  3. data/CHANGES.md +22 -0
  4. data/README.md +2 -0
  5. data/active_remote.gemspec +2 -2
  6. data/bin/console +10 -0
  7. data/lib/active_remote/association.rb +4 -0
  8. data/lib/active_remote/attribute_assignment.rb +53 -0
  9. data/lib/active_remote/attribute_definition.rb +106 -0
  10. data/lib/active_remote/attributes.rb +165 -8
  11. data/lib/active_remote/base.rb +41 -36
  12. data/lib/active_remote/dirty.rb +0 -9
  13. data/lib/active_remote/errors.rb +6 -0
  14. data/lib/active_remote/persistence.rb +10 -19
  15. data/lib/active_remote/query_attributes.rb +45 -0
  16. data/lib/active_remote/rpc.rb +17 -67
  17. data/lib/active_remote/search.rb +0 -20
  18. data/lib/active_remote/serialization.rb +1 -32
  19. data/lib/active_remote/typecasting.rb +3 -12
  20. data/lib/active_remote/version.rb +1 -1
  21. data/lib/active_remote.rb +0 -2
  22. data/spec/lib/active_remote/association_spec.rb +11 -2
  23. data/spec/lib/active_remote/attributes_spec.rb +177 -0
  24. data/spec/lib/active_remote/persistence_spec.rb +7 -16
  25. data/spec/lib/active_remote/query_attribute_spec.rb +171 -0
  26. data/spec/lib/active_remote/rpc_spec.rb +33 -75
  27. data/spec/lib/active_remote/search_spec.rb +0 -21
  28. data/spec/lib/active_remote/serialization_spec.rb +0 -23
  29. data/spec/support/models/no_attributes.rb +2 -0
  30. data/spec/support/models.rb +1 -0
  31. metadata +21 -66
  32. data/lib/active_remote/attribute_defaults.rb +0 -100
  33. data/lib/active_remote/bulk.rb +0 -168
  34. data/lib/active_remote/core_ext/date.rb +0 -7
  35. data/lib/active_remote/core_ext/date_time.rb +0 -7
  36. data/lib/active_remote/core_ext/integer.rb +0 -19
  37. data/lib/active_remote/core_ext.rb +0 -3
  38. data/lib/active_remote/publication.rb +0 -54
  39. data/lib/active_remote/serializers/json.rb +0 -16
  40. data/spec/core_ext/date_time_spec.rb +0 -9
  41. data/spec/lib/active_remote/attribute_defaults_spec.rb +0 -26
  42. data/spec/lib/active_remote/bulk_spec.rb +0 -83
  43. data/spec/lib/active_remote/publication_spec.rb +0 -18
  44. data/spec/lib/active_remote/serializers/json_spec.rb +0 -78
@@ -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,7 +0,0 @@
1
- Date.class_eval do
2
- unless instance_methods.include?(:to_i)
3
- def to_i
4
- to_time.to_i
5
- end
6
- end
7
- end
@@ -1,7 +0,0 @@
1
- DateTime.class_eval do
2
- unless instance_methods.include?(:to_i)
3
- def to_i
4
- to_time.to_i
5
- end
6
- end
7
- 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,3 +0,0 @@
1
- require 'active_remote/core_ext/date_time'
2
- require 'active_remote/core_ext/date'
3
- require 'active_remote/core_ext/integer'
@@ -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,9 +0,0 @@
1
- require 'spec_helper'
2
-
3
- describe DateTime do
4
- describe "#to_i" do
5
- it "does not raise errors bj" do
6
- expect { subject.to_i }.to_not raise_error
7
- end
8
- end
9
- 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