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
@@ -6,7 +6,7 @@ require "support/protobuf/author.pb"
|
|
6
6
|
class DefaultAuthor < ::ActiveRemote::Base
|
7
7
|
service_class ::Generic::Remote::AuthorService
|
8
8
|
|
9
|
-
attribute :guid, :default => lambda { 100 }
|
10
|
-
attribute :name, :default => "John Doe"
|
9
|
+
attribute :guid, :string, :default => lambda { 100 }
|
10
|
+
attribute :name, :string, :default => "John Doe"
|
11
11
|
attribute :books, :default => []
|
12
12
|
end
|
data/spec/support/models/post.rb
CHANGED
@@ -6,11 +6,11 @@ require "support/protobuf/post.pb"
|
|
6
6
|
class Post < ::ActiveRemote::Base
|
7
7
|
service_class ::Generic::Remote::PostService
|
8
8
|
|
9
|
-
attribute :guid
|
10
|
-
attribute :name
|
11
|
-
attribute :author_guid
|
12
|
-
attribute :user_guid
|
13
|
-
attribute :bestseller_guid
|
9
|
+
attribute :guid, :string
|
10
|
+
attribute :name, :string
|
11
|
+
attribute :author_guid, :string
|
12
|
+
attribute :user_guid, :string
|
13
|
+
attribute :bestseller_guid, :string
|
14
14
|
|
15
15
|
belongs_to :author
|
16
16
|
belongs_to :coauthor, :class_name => "::Author"
|
data/spec/support/models/tag.rb
CHANGED
@@ -6,10 +6,10 @@ require "support/protobuf/tag.pb"
|
|
6
6
|
class Tag < ::ActiveRemote::Base
|
7
7
|
service_class ::Generic::Remote::TagService
|
8
8
|
|
9
|
-
attribute :guid
|
10
|
-
attribute :name
|
11
|
-
attribute :updated_at
|
12
|
-
attribute :user_guid
|
9
|
+
attribute :guid, :string
|
10
|
+
attribute :name, :string
|
11
|
+
attribute :updated_at, :datetime
|
12
|
+
attribute :user_guid, :string
|
13
13
|
|
14
14
|
after_update :after_update_callback
|
15
15
|
after_create :after_create_callback
|
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.
|
4
|
+
version: 5.2.0.alpha
|
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-
|
11
|
+
date: 2019-11-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 5.
|
19
|
+
version: '5.2'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 5.
|
26
|
+
version: '5.2'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: activesupport
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: 5.
|
33
|
+
version: '5.2'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: 5.
|
40
|
+
version: '5.2'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: protobuf
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -203,8 +203,7 @@ files:
|
|
203
203
|
- bin/console
|
204
204
|
- lib/active_remote.rb
|
205
205
|
- lib/active_remote/association.rb
|
206
|
-
- lib/active_remote/
|
207
|
-
- lib/active_remote/attributes.rb
|
206
|
+
- lib/active_remote/attribute_methods.rb
|
208
207
|
- lib/active_remote/base.rb
|
209
208
|
- lib/active_remote/config.rb
|
210
209
|
- lib/active_remote/dirty.rb
|
@@ -224,7 +223,6 @@ files:
|
|
224
223
|
- lib/active_remote/validations.rb
|
225
224
|
- lib/active_remote/version.rb
|
226
225
|
- spec/lib/active_remote/association_spec.rb
|
227
|
-
- spec/lib/active_remote/attributes_spec.rb
|
228
226
|
- spec/lib/active_remote/base_spec.rb
|
229
227
|
- spec/lib/active_remote/dirty_spec.rb
|
230
228
|
- spec/lib/active_remote/dsl_spec.rb
|
@@ -256,7 +254,6 @@ files:
|
|
256
254
|
- spec/support/models/no_attributes.rb
|
257
255
|
- spec/support/models/post.rb
|
258
256
|
- spec/support/models/tag.rb
|
259
|
-
- spec/support/models/typecasted_author.rb
|
260
257
|
- spec/support/protobuf.rb
|
261
258
|
- spec/support/protobuf/author.pb.rb
|
262
259
|
- spec/support/protobuf/category.pb.rb
|
@@ -278,18 +275,16 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
278
275
|
version: '0'
|
279
276
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
280
277
|
requirements:
|
281
|
-
- - "
|
278
|
+
- - ">"
|
282
279
|
- !ruby/object:Gem::Version
|
283
|
-
version:
|
280
|
+
version: 1.3.1
|
284
281
|
requirements: []
|
285
|
-
|
286
|
-
rubygems_version: 2.7.6
|
282
|
+
rubygems_version: 3.0.6
|
287
283
|
signing_key:
|
288
284
|
specification_version: 4
|
289
285
|
summary: Active Record for your platform
|
290
286
|
test_files:
|
291
287
|
- spec/lib/active_remote/association_spec.rb
|
292
|
-
- spec/lib/active_remote/attributes_spec.rb
|
293
288
|
- spec/lib/active_remote/base_spec.rb
|
294
289
|
- spec/lib/active_remote/dirty_spec.rb
|
295
290
|
- spec/lib/active_remote/dsl_spec.rb
|
@@ -321,7 +316,6 @@ test_files:
|
|
321
316
|
- spec/support/models/no_attributes.rb
|
322
317
|
- spec/support/models/post.rb
|
323
318
|
- spec/support/models/tag.rb
|
324
|
-
- spec/support/models/typecasted_author.rb
|
325
319
|
- spec/support/protobuf.rb
|
326
320
|
- spec/support/protobuf/author.pb.rb
|
327
321
|
- spec/support/protobuf/category.pb.rb
|
@@ -1,114 +0,0 @@
|
|
1
|
-
require "active_model/type"
|
2
|
-
|
3
|
-
module ActiveRemote
|
4
|
-
# Represents an attribute for reflection
|
5
|
-
#
|
6
|
-
# @example Usage
|
7
|
-
# AttributeDefinition.new(:amount)
|
8
|
-
#
|
9
|
-
# @since 0.2.0
|
10
|
-
class AttributeDefinition
|
11
|
-
include Comparable
|
12
|
-
|
13
|
-
# The attribute name
|
14
|
-
# @since 0.2.0
|
15
|
-
attr_reader :name
|
16
|
-
|
17
|
-
# Compare attribute definitions
|
18
|
-
#
|
19
|
-
# @example
|
20
|
-
# attribute_definition <=> other
|
21
|
-
#
|
22
|
-
# @param [ActiveAttr::AttributeDefinition, Object] other The other
|
23
|
-
# attribute definition to compare with.
|
24
|
-
#
|
25
|
-
# @return [-1, 0, 1, nil]
|
26
|
-
#
|
27
|
-
# @since 0.2.1
|
28
|
-
def <=>(other)
|
29
|
-
return nil unless other.instance_of? self.class
|
30
|
-
return nil if name == other.name && options != other.options
|
31
|
-
|
32
|
-
self.name.to_s <=> other.name.to_s
|
33
|
-
end
|
34
|
-
|
35
|
-
# Read an attribute option
|
36
|
-
#
|
37
|
-
# @example
|
38
|
-
# attribute_definition[:type]
|
39
|
-
#
|
40
|
-
# @param [Symbol] key The option key
|
41
|
-
#
|
42
|
-
# @since 0.5.0
|
43
|
-
def [](key)
|
44
|
-
@options[key]
|
45
|
-
end
|
46
|
-
|
47
|
-
# Creates a new AttributeDefinition
|
48
|
-
#
|
49
|
-
# @example Create an attribute defintion
|
50
|
-
# AttributeDefinition.new(:amount)
|
51
|
-
#
|
52
|
-
# @param [Symbol, String, #to_sym] name attribute name
|
53
|
-
# @param [Symbol] type attribute type
|
54
|
-
# @param [Hash{Symbol => Object}] options attribute options
|
55
|
-
#
|
56
|
-
# @return [ActiveAttr::AttributeDefinition]
|
57
|
-
#
|
58
|
-
# @since 0.2.0
|
59
|
-
def initialize(name, type = :value, **options)
|
60
|
-
raise TypeError, "can't convert #{name.class} into Symbol" unless name.respond_to? :to_sym
|
61
|
-
|
62
|
-
@name = name.to_sym
|
63
|
-
@type = ::ActiveModel::Type.lookup(type)
|
64
|
-
@options = options
|
65
|
-
end
|
66
|
-
|
67
|
-
def from_rpc(value)
|
68
|
-
type.deserialize(value)
|
69
|
-
end
|
70
|
-
|
71
|
-
def from_user(value)
|
72
|
-
type.cast(value)
|
73
|
-
end
|
74
|
-
|
75
|
-
# Returns the code that would generate the attribute definition
|
76
|
-
#
|
77
|
-
# @example Inspect the attribute definition
|
78
|
-
# attribute.inspect
|
79
|
-
#
|
80
|
-
# @return [String] Human-readable presentation of the attribute
|
81
|
-
# definition
|
82
|
-
#
|
83
|
-
# @since 0.6.0
|
84
|
-
def inspect
|
85
|
-
options_description = options.map { |key, value| "#{key.inspect} => #{value.inspect}" }.sort.join(", ")
|
86
|
-
inspected_options = ", #{options_description}" unless options_description.empty?
|
87
|
-
"attribute :#{name}#{inspected_options}"
|
88
|
-
end
|
89
|
-
|
90
|
-
# The attribute name
|
91
|
-
#
|
92
|
-
# @return [String] the attribute name
|
93
|
-
#
|
94
|
-
# @since 0.2.0
|
95
|
-
delegate :to_s, :to => :name
|
96
|
-
|
97
|
-
# The attribute name
|
98
|
-
#
|
99
|
-
# @return [Symbol] the attribute name
|
100
|
-
#
|
101
|
-
# @since 0.2.1
|
102
|
-
def to_sym
|
103
|
-
name
|
104
|
-
end
|
105
|
-
|
106
|
-
protected
|
107
|
-
|
108
|
-
# The attribute options
|
109
|
-
# @since 0.5.0
|
110
|
-
attr_reader :options, :type
|
111
|
-
end
|
112
|
-
|
113
|
-
::ActiveModel::Type.register(:value, ::ActiveModel::Type::Value)
|
114
|
-
end
|
@@ -1,204 +0,0 @@
|
|
1
|
-
module ActiveRemote
|
2
|
-
module Attributes
|
3
|
-
extend ::ActiveSupport::Concern
|
4
|
-
include ::ActiveModel::AttributeMethods
|
5
|
-
|
6
|
-
included do
|
7
|
-
attribute_method_suffix "="
|
8
|
-
end
|
9
|
-
|
10
|
-
# Performs equality checking on the result of attributes and its type.
|
11
|
-
#
|
12
|
-
# @example Compare for equality.
|
13
|
-
# model == other
|
14
|
-
#
|
15
|
-
def ==(other)
|
16
|
-
return false unless other.instance_of?(self.class)
|
17
|
-
|
18
|
-
attributes == other.attributes
|
19
|
-
end
|
20
|
-
|
21
|
-
# Returns a copy of our attributes hash
|
22
|
-
def attributes
|
23
|
-
@attributes.dup
|
24
|
-
end
|
25
|
-
|
26
|
-
# Returns the class name plus its attributes
|
27
|
-
#
|
28
|
-
# @example Inspect the model.
|
29
|
-
# person.inspect
|
30
|
-
#
|
31
|
-
def inspect
|
32
|
-
attribute_descriptions = attributes.sort.map { |key, value| "#{key}: #{value.inspect}" }.join(", ")
|
33
|
-
separator = " " unless attribute_descriptions.empty?
|
34
|
-
"#<#{self.class.name}#{separator}#{attribute_descriptions}>"
|
35
|
-
end
|
36
|
-
|
37
|
-
# Read attribute from the attributes hash
|
38
|
-
#
|
39
|
-
def read_attribute(name)
|
40
|
-
name = name.to_s
|
41
|
-
|
42
|
-
if respond_to?(name)
|
43
|
-
attribute(name)
|
44
|
-
else
|
45
|
-
raise ::ActiveRemote::UnknownAttributeError, "unknown attribute: #{name}"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
alias_method :[], :read_attribute
|
49
|
-
|
50
|
-
# Update an attribute in the attributes hash
|
51
|
-
#
|
52
|
-
def write_attribute(name, value)
|
53
|
-
name = name.to_s
|
54
|
-
|
55
|
-
if respond_to?("#{name}=")
|
56
|
-
__send__("attribute=", name, value)
|
57
|
-
else
|
58
|
-
raise ::ActiveRemote::UnknownAttributeError, "unknown attribute: #{name}"
|
59
|
-
end
|
60
|
-
end
|
61
|
-
alias_method :[]=, :write_attribute
|
62
|
-
|
63
|
-
# Read an attribute from the attributes hash
|
64
|
-
#
|
65
|
-
def attribute(name)
|
66
|
-
@attributes[name]
|
67
|
-
end
|
68
|
-
|
69
|
-
# Write an attribute to the attributes hash
|
70
|
-
#
|
71
|
-
def attribute=(name, value)
|
72
|
-
@attributes[name] = self.class.attributes[name].from_user(value)
|
73
|
-
end
|
74
|
-
|
75
|
-
def attribute_method?(attr_name)
|
76
|
-
# Check if @attributes is defined because dangerous_attribute? method
|
77
|
-
# can check allocate.respond_to? before actaully calling initialize
|
78
|
-
defined?(@attributes) && @attributes.key?(attr_name)
|
79
|
-
end
|
80
|
-
|
81
|
-
module ClassMethods
|
82
|
-
# Defines an attribute
|
83
|
-
#
|
84
|
-
# For each attribute that is defined, a getter and setter will be
|
85
|
-
# added as an instance method to the model. An
|
86
|
-
# {AttributeDefinition} instance will be added to result of the
|
87
|
-
# attributes class method.
|
88
|
-
#
|
89
|
-
# @example Define an attribute.
|
90
|
-
# attribute :name
|
91
|
-
#
|
92
|
-
def attribute(name, options = {})
|
93
|
-
if (dangerous_attribute_method_name = dangerous_attribute?(name))
|
94
|
-
raise ::ActiveRemote::DangerousAttributeError, %(an attribute method named "#{dangerous_attribute_method_name}" would conflict with an existing method)
|
95
|
-
else
|
96
|
-
attribute!(name, options)
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
# Defines an attribute without checking for conflicts
|
101
|
-
#
|
102
|
-
# Allows you to define an attribute whose methods will conflict
|
103
|
-
# with an existing method. For example, Ruby's Timeout library
|
104
|
-
# adds a timeout method to Object. Attempting to define a timeout
|
105
|
-
# attribute using .attribute will raise a
|
106
|
-
# {DangerousAttributeError}, but .attribute! will not.
|
107
|
-
#
|
108
|
-
# @example Define a dangerous attribute.
|
109
|
-
# attribute! :timeout
|
110
|
-
#
|
111
|
-
def attribute!(name, options = {})
|
112
|
-
::ActiveRemote::AttributeDefinition.new(name, options).tap do |attribute_definition|
|
113
|
-
attribute_name = attribute_definition.name.to_s
|
114
|
-
# Force active model to generate attribute methods
|
115
|
-
remove_instance_variable("@attribute_methods_generated") if instance_variable_defined?("@attribute_methods_generated")
|
116
|
-
define_attribute_methods([attribute_definition.name]) unless attribute_names.include?(attribute_name)
|
117
|
-
attributes[attribute_name] = attribute_definition
|
118
|
-
build_default_attributes_hash
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
# Returns an Array of attribute names as Strings
|
123
|
-
#
|
124
|
-
# @example Get attribute names
|
125
|
-
# Person.attribute_names
|
126
|
-
#
|
127
|
-
def attribute_names
|
128
|
-
attributes.keys
|
129
|
-
end
|
130
|
-
|
131
|
-
# Returns a Hash of AttributeDefinition instances
|
132
|
-
#
|
133
|
-
# @example Get attribute definitions
|
134
|
-
# Person.attributes
|
135
|
-
#
|
136
|
-
def attributes
|
137
|
-
@attributes ||= ::ActiveSupport::HashWithIndifferentAccess.new
|
138
|
-
end
|
139
|
-
|
140
|
-
# Determine if a given attribute name is dangerous
|
141
|
-
#
|
142
|
-
# Some attribute names can cause conflicts with existing methods
|
143
|
-
# on an object. For example, an attribute named "timeout" would
|
144
|
-
# conflict with the timeout method that Ruby's Timeout library
|
145
|
-
# mixes into Object.
|
146
|
-
#
|
147
|
-
# @example Testing a harmless attribute
|
148
|
-
# Person.dangerous_attribute? :name #=> false
|
149
|
-
#
|
150
|
-
# @example Testing a dangerous attribute
|
151
|
-
# Person.dangerous_attribute? :timeout #=> "timeout"
|
152
|
-
#
|
153
|
-
def dangerous_attribute?(name)
|
154
|
-
return false if attribute_names.include?(name.to_s)
|
155
|
-
|
156
|
-
attribute_methods(name).detect do |method_name|
|
157
|
-
allocate.respond_to?(method_name, true)
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
# Returns the class name plus its attribute names
|
162
|
-
#
|
163
|
-
# @example Inspect the model's definition.
|
164
|
-
# Person.inspect
|
165
|
-
#
|
166
|
-
def inspect
|
167
|
-
inspected_attributes = attribute_names.sort
|
168
|
-
attributes_list = "(#{inspected_attributes.join(', ')})" unless inspected_attributes.empty?
|
169
|
-
"#{name}#{attributes_list}"
|
170
|
-
end
|
171
|
-
|
172
|
-
protected
|
173
|
-
|
174
|
-
# Assign a set of attribute definitions, used when subclassing models
|
175
|
-
#
|
176
|
-
def attributes=(attributes)
|
177
|
-
@attributes = attributes
|
178
|
-
end
|
179
|
-
|
180
|
-
private
|
181
|
-
|
182
|
-
# Expand an attribute name into its generated methods names
|
183
|
-
#
|
184
|
-
def attribute_methods(name)
|
185
|
-
attribute_method_matchers.map { |matcher| matcher.method_name(name) }
|
186
|
-
end
|
187
|
-
|
188
|
-
def build_default_attributes_hash
|
189
|
-
@default_attributes_hash = Hash[attribute_names.map { |key| [key, nil] }]
|
190
|
-
end
|
191
|
-
|
192
|
-
def default_attributes_hash
|
193
|
-
@default_attributes_hash || {}
|
194
|
-
end
|
195
|
-
|
196
|
-
# Ruby inherited hook to assign superclass attributes to subclasses
|
197
|
-
#
|
198
|
-
def inherited(subclass)
|
199
|
-
super
|
200
|
-
subclass.attributes = attributes.dup
|
201
|
-
end
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|