Class: Protip::Resource::Associations::BelongsToPolymorphicAssociation
- Inherits:
-
Object
- Object
- Protip::Resource::Associations::BelongsToPolymorphicAssociation
- Includes:
- Association
- Defined in:
- lib/protip/resource/associations/belongs_to_polymorphic_association.rb
Instance Attribute Summary collapse
-
#association_name ⇒ Object
readonly
Returns the value of attribute association_name.
-
#belongs_to_associations ⇒ Object
readonly
Returns the value of attribute belongs_to_associations.
-
#id_field ⇒ Object
readonly
Returns the value of attribute id_field.
-
#resource_class ⇒ Object
readonly
Returns the value of attribute resource_class.
Instance Method Summary collapse
-
#initialize(resource_class, association_name, belongs_to_associations, id_field: nil) ⇒ BelongsToPolymorphicAssociation
constructor
Define a polymorphic association based on a one-of field.
- #read(resource) ⇒ Object
- #write(resource, value) ⇒ Object
Methods included from Association
Constructor Details
#initialize(resource_class, association_name, belongs_to_associations, id_field: nil) ⇒ BelongsToPolymorphicAssociation
Define a polymorphic association based on a one-of field. The options for the oneof must all be IDs with an associated Protip::Resource::Associations::BelongsToAssociation
that’s already been created.
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 21 def initialize(resource_class, association_name, belongs_to_associations, id_field: nil) # The class where accessors will be defined @resource_class = resource_class # The name of the accessor methods @association_name = association_name.to_sym # The oneof field that holds the ID of the foreign resource @id_field = (id_field || Protip::Resource::Associations::BelongsToAssociation.default_id_field(association_name)).to_sym @_oneof = @resource_class..descriptor.lookup_oneof(@id_field.to_s) raise "Invalid field name for polymorphic association: #{@id_field}" unless @_oneof # Internally, keep the nested associations indexed by ID field @_indexed_belongs_to_associations = {} belongs_to_associations.each do |association| if @_indexed_belongs_to_associations.has_key? association.id_field.to_sym raise ArgumentError.new("Duplicate association for #{id_field}") end @_indexed_belongs_to_associations[association.id_field.to_sym] = association end field_names = @_oneof.map{|desc| desc.name.to_sym} unless (field_names.length == @_indexed_belongs_to_associations.length && @_indexed_belongs_to_associations.keys.all?{|id_field| field_names.include? id_field}) raise ArgumentError.new( 'Polymorphic association requires an association to be defined for all nested fields' ) end @belongs_to_associations = Set.new(belongs_to_associations) end |
Instance Attribute Details
#association_name ⇒ Object (readonly)
Returns the value of attribute association_name.
10 11 12 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 10 def association_name @association_name end |
#belongs_to_associations ⇒ Object (readonly)
Returns the value of attribute belongs_to_associations.
10 11 12 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 10 def belongs_to_associations @belongs_to_associations end |
#id_field ⇒ Object (readonly)
Returns the value of attribute id_field.
10 11 12 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 10 def id_field @id_field end |
#resource_class ⇒ Object (readonly)
Returns the value of attribute resource_class.
10 11 12 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 10 def resource_class @resource_class end |
Instance Method Details
#read(resource) ⇒ Object
53 54 55 56 57 58 59 60 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 53 def read(resource) field = resource..public_send(id_field) if field @_indexed_belongs_to_associations[field].read(resource) else nil end end |
#write(resource, value) ⇒ Object
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 |
# File 'lib/protip/resource/associations/belongs_to_polymorphic_association.rb', line 62 def write(resource, value) if value == nil @_oneof.each do |field_descriptor| resource.public_send(:"#{field_descriptor.name}=", nil) end nil else # Find the nested reference matching this association type matching_associations = belongs_to_associations.select do |association| value.is_a? association.associated_resource_class end # Make sure we found exactly one if matching_associations.empty? raise ArgumentError.new("Could not find matching reference for value of type #{value.class}") end if matching_associations.length > 1 raise ArgumentError.new( "Value of type #{value.class} matched with #{matching_references.keys.map(&:to_s).join(', ')}" ) end # And forward the write operation matching_associations.first.write(resource, value) end end |