protip 0.18.2 → 0.18.3
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
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b3cc36d1a0119a9d6a0c7aa985ef1c7ec9d0c80
|
4
|
+
data.tar.gz: 1172ca37789032767087b77783d8f274bac71e6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 50fc9db60514ea58304d94e2b16ba3c9d565a748b9163ea0f1ef676a9d85c7d2b04355c9a3a92df812fb778d599b6631be9c8da79f1a2a9e0bcc082ca872c2ff
|
7
|
+
data.tar.gz: 1f3adf1b6aab2af7a433d9ab3257f584ea8fbaadf8126578b44248d83733bdfdb331ce508bab4c4ff748c45bd4cdc16c3bbc37c2810789308d2cd51cb9e4fb13
|
data/lib/protip/resource.rb
CHANGED
@@ -50,6 +50,10 @@ module Protip
|
|
50
50
|
|
51
51
|
def_delegator :@wrapper, :message
|
52
52
|
def_delegator :@wrapper, :as_json
|
53
|
+
|
54
|
+
# Initialize housekeeping variables
|
55
|
+
@belongs_to_associations = Set.new
|
56
|
+
@belongs_to_polymorphic_associations = Set.new
|
53
57
|
end
|
54
58
|
|
55
59
|
module ClassMethods
|
@@ -58,7 +62,7 @@ module Protip
|
|
58
62
|
|
59
63
|
attr_accessor :client
|
60
64
|
|
61
|
-
attr_reader :message, :nested_resources
|
65
|
+
attr_reader :message, :nested_resources, :belongs_to_associations, :belongs_to_polymorphic_associations
|
62
66
|
|
63
67
|
attr_writer :base_path, :converter
|
64
68
|
|
@@ -210,6 +214,7 @@ module Protip
|
|
210
214
|
def belongs_to(association_name, options = {})
|
211
215
|
association = ::Protip::Resource::Associations::BelongsToAssociation.new(self, association_name, options)
|
212
216
|
association.define_accessors!
|
217
|
+
@belongs_to_associations.add association
|
213
218
|
association
|
214
219
|
end
|
215
220
|
|
@@ -233,6 +238,7 @@ module Protip
|
|
233
238
|
association = ::Protip::Resource::Associations::BelongsToPolymorphicAssociation.new self,
|
234
239
|
association_name, nested_association_creator.associations, options
|
235
240
|
association.define_accessors!
|
241
|
+
@belongs_to_polymorphic_associations.add association
|
236
242
|
association
|
237
243
|
end
|
238
244
|
|
@@ -7,18 +7,18 @@ module Protip
|
|
7
7
|
class BelongsToPolymorphicAssociation
|
8
8
|
|
9
9
|
include Protip::Resource::Associations::Association
|
10
|
-
attr_reader :resource_class, :association_name, :id_field
|
10
|
+
attr_reader :resource_class, :association_name, :id_field, :belongs_to_associations
|
11
11
|
|
12
12
|
# Define a polymorphic association based on a one-of field. The options for the oneof must all be IDs with
|
13
13
|
# an associated +Protip::Resource::Associations::BelongsToAssociation+ that's already been created.
|
14
14
|
#
|
15
15
|
# @param [Class] resource_class The +Protip::Resource+ class that holds a reference to an associated object.
|
16
16
|
# @param [String] association_name The name to use when defining accessors for the associated object.
|
17
|
-
# @param [
|
18
|
-
# associations corresponding to the fields within the `oneof`.
|
17
|
+
# @param [Enumerable<Protip::Resource::Associations::BelongsToAssociation>] belongs_to_associations The
|
18
|
+
# individual associations corresponding to the fields within the `oneof`.
|
19
19
|
# @param [Symbol|String] id_field The name of the `oneof` field that holds the association ID. Defaults to
|
20
20
|
# `#{association_name}_id`.
|
21
|
-
def initialize(resource_class, association_name,
|
21
|
+
def initialize(resource_class, association_name, belongs_to_associations, id_field: nil)
|
22
22
|
# The class where accessors will be defined
|
23
23
|
@resource_class = resource_class
|
24
24
|
|
@@ -28,30 +28,32 @@ module Protip
|
|
28
28
|
# The oneof field that holds the ID of the foreign resource
|
29
29
|
@id_field = (id_field ||
|
30
30
|
Protip::Resource::Associations::BelongsToAssociation.default_id_field(association_name)).to_sym
|
31
|
-
@
|
32
|
-
raise "Invalid field name for polymorphic association: #{@id_field}" unless @
|
31
|
+
@_oneof = @resource_class.message.descriptor.lookup_oneof(@id_field.to_s)
|
32
|
+
raise "Invalid field name for polymorphic association: #{@id_field}" unless @_oneof
|
33
|
+
|
33
34
|
|
34
35
|
# Internally, keep the nested associations indexed by ID field
|
35
|
-
@
|
36
|
-
|
37
|
-
if @
|
36
|
+
@_indexed_belongs_to_associations = {}
|
37
|
+
belongs_to_associations.each do |association|
|
38
|
+
if @_indexed_belongs_to_associations.has_key? association.id_field.to_sym
|
38
39
|
raise ArgumentError.new("Duplicate association for #{id_field}")
|
39
40
|
end
|
40
|
-
@
|
41
|
+
@_indexed_belongs_to_associations[association.id_field.to_sym] = association
|
41
42
|
end
|
42
|
-
field_names = @
|
43
|
-
unless (field_names.length == @
|
44
|
-
@
|
43
|
+
field_names = @_oneof.map{|desc| desc.name.to_sym}
|
44
|
+
unless (field_names.length == @_indexed_belongs_to_associations.length &&
|
45
|
+
@_indexed_belongs_to_associations.keys.all?{|id_field| field_names.include? id_field})
|
45
46
|
raise ArgumentError.new(
|
46
47
|
'Polymorphic association requires an association to be defined for all nested fields'
|
47
48
|
)
|
48
49
|
end
|
50
|
+
@belongs_to_associations = Set.new(belongs_to_associations)
|
49
51
|
end
|
50
52
|
|
51
53
|
def read(resource)
|
52
54
|
field = resource.message.public_send(id_field)
|
53
55
|
if field
|
54
|
-
@
|
56
|
+
@_indexed_belongs_to_associations[field].read(resource)
|
55
57
|
else
|
56
58
|
nil
|
57
59
|
end
|
@@ -59,28 +61,28 @@ module Protip
|
|
59
61
|
|
60
62
|
def write(resource, value)
|
61
63
|
if value == nil
|
62
|
-
@
|
64
|
+
@_oneof.each do |field_descriptor|
|
63
65
|
resource.public_send(:"#{field_descriptor.name}=", nil)
|
64
66
|
end
|
65
67
|
nil
|
66
68
|
else
|
67
69
|
# Find the nested reference matching this association type
|
68
|
-
|
69
|
-
value.is_a?
|
70
|
+
matching_associations = belongs_to_associations.select do |association|
|
71
|
+
value.is_a? association.associated_resource_class
|
70
72
|
end
|
71
73
|
|
72
74
|
# Make sure we found exactly one
|
73
|
-
if
|
75
|
+
if matching_associations.empty?
|
74
76
|
raise ArgumentError.new("Could not find matching reference for value of type #{value.class}")
|
75
77
|
end
|
76
|
-
if
|
78
|
+
if matching_associations.length > 1
|
77
79
|
raise ArgumentError.new(
|
78
80
|
"Value of type #{value.class} matched with #{matching_references.keys.map(&:to_s).join(', ')}"
|
79
81
|
)
|
80
82
|
end
|
81
83
|
|
82
84
|
# And forward the write operation
|
83
|
-
|
85
|
+
matching_associations.first.write(resource, value)
|
84
86
|
end
|
85
87
|
end
|
86
88
|
end
|
@@ -70,6 +70,14 @@ describe Protip::Resource::Associations::BelongsToPolymorphicAssociation do
|
|
70
70
|
:foo, [rick_ross_association, fetty_wap_association], id_field: :reference_id
|
71
71
|
assert_equal :reference_id, association.id_field
|
72
72
|
end
|
73
|
+
|
74
|
+
it 'stores the nested belongs-to associations' do
|
75
|
+
association = Protip::Resource::Associations::BelongsToPolymorphicAssociation.new resource_class,
|
76
|
+
:reference, [rick_ross_association, fetty_wap_association]
|
77
|
+
assert_equal 2, association.belongs_to_associations.length
|
78
|
+
assert_includes association.belongs_to_associations, rick_ross_association
|
79
|
+
assert_includes association.belongs_to_associations, fetty_wap_association
|
80
|
+
end
|
73
81
|
end
|
74
82
|
|
75
83
|
describe '(accessors)' do
|
@@ -882,6 +882,18 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
882
882
|
assert_equal association, resource_class.instance_variable_get(:'@result'), 'association was not returned'
|
883
883
|
end
|
884
884
|
|
885
|
+
it 'stores the created association' do
|
886
|
+
association_class.expects(:new).once.returns(association)
|
887
|
+
resource_class.class_exec(method) { |method| send method, :association_name, &block }
|
888
|
+
assert_includes resource_class.public_send(:"#{method}_associations"), association
|
889
|
+
end
|
890
|
+
|
891
|
+
it 'initializes the set of associations to the empty set' do
|
892
|
+
stored_associations = resource_class.public_send(:"#{method}_associations")
|
893
|
+
assert_instance_of Set, stored_associations
|
894
|
+
assert_empty stored_associations
|
895
|
+
end
|
896
|
+
|
885
897
|
it 'raises an error on invalid options' do
|
886
898
|
error = assert_raises ArgumentError do
|
887
899
|
resource_class.class_exec(method) do |method|
|
@@ -935,31 +947,6 @@ module Protip::ResourceTest # Namespace for internal constants
|
|
935
947
|
Protip::Resource::Associations::BelongsToPolymorphicAssociation) { }
|
936
948
|
end
|
937
949
|
|
938
|
-
# {
|
939
|
-
# references_through_one_of: Protip::Resource::Associations::ReferencesThroughOneOfAssociation,
|
940
|
-
# }.each do |method, association_class|
|
941
|
-
# describe ".#{method}" do
|
942
|
-
# it 'creates an association of the correct type and defines accessors' do
|
943
|
-
# association = mock.responds_like_instance_of(association_class)
|
944
|
-
# association_class.expects(:new).once.with(resource_class, :some_id, {class_name: 'Foo'}).returns(association)
|
945
|
-
# association.expects(:define_accessors!)
|
946
|
-
# resource_class.class_exec(method) do
|
947
|
-
# send(method, :some_id, class_name: 'Foo')
|
948
|
-
# end
|
949
|
-
# end
|
950
|
-
#
|
951
|
-
# it 'raises an error on invalid options' do
|
952
|
-
# error = assert_raises ArgumentError do
|
953
|
-
# resource_class.class_exec(method) do
|
954
|
-
# send(method, :some_id, bad_option: 'bad')
|
955
|
-
# end
|
956
|
-
# end
|
957
|
-
#
|
958
|
-
# assert_match /bad_option/, error.message
|
959
|
-
# end
|
960
|
-
# end
|
961
|
-
# end
|
962
|
-
|
963
950
|
describe '.converter' do
|
964
951
|
describe 'default value' do
|
965
952
|
it 'defaults to the standard converter' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protip
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.18.
|
4
|
+
version: 0.18.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AngelList
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-02-
|
11
|
+
date: 2016-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|