Class: LedgerSync::Util::ResourceConverter::Attribute

Inherits:
Object
  • Object
show all
Defined in:
lib/ledger_sync/util/resource_converter/attribute.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(args = {}) ⇒ Attribute

Returns a new instance of Attribute.



15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 15

def initialize(args = {})
  @block                 = args.fetch(:block, nil)
  @destination_attribute = args.fetch(:destination_attribute, nil).to_s
  @source_attribute      = args.fetch(:source_attribute, destination_attribute).to_s
  @type                  = args.fetch(:type, nil) || LedgerSync::Type::Value.new
  @if_method             = args.fetch(:if, nil)

  return if block.blank?

  raise 'block cannot be provided on references' if reference?
  raise 'block and destination_attribute cannot both be present' if destination_attribute.present?
  raise 'block and source_attribute cannot both be present' if source_attribute.present?
end

Instance Attribute Details

#blockObject (readonly)

Returns the value of attribute block.



9
10
11
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 9

def block
  @block
end

#destination_attributeObject (readonly)

Returns the value of attribute destination_attribute.



9
10
11
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 9

def destination_attribute
  @destination_attribute
end

#if_methodObject (readonly)

Returns the value of attribute if_method.



9
10
11
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 9

def if_method
  @if_method
end

#source_attributeObject (readonly)

Returns the value of attribute source_attribute.



9
10
11
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 9

def source_attribute
  @source_attribute
end

#typeObject (readonly)

Returns the value of attribute type.



9
10
11
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 9

def type
  @type
end

Instance Method Details

#block?Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 29

def block?
  block.present?
end

#block_value_for(args = {}) ⇒ Object



33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 33

def block_value_for(args = {})
  destination = args.fetch(:destination).dup
  source      = args.fetch(:source).dup

  new_destination = block.call(
    {
      attribute: self,
      destination: destination,
      source: source
    }
  )

  return new_destination if destination.instance_of?(new_destination.class)

  raise "Block value must be the same class as the destination: #{destination.class}"
end

#build_destination!(args = {}) ⇒ Object



50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 50

def build_destination!(args = {})
  destination = args.fetch(:destination)
  destination = Util::HashHelpers.deep_stringify_keys(destination) if destination.is_a?(Hash)
  source      = args.fetch(:source).dup
  source      = Util::HashHelpers.deep_stringify_keys(source) if source.is_a?(Hash)

  if block?
    return block_value_for(
      destination: destination,
      source: source
    )
  end

  value = value(destination: destination, source: source)

  if destination.is_a?(Hash)
    destination = Util::HashHelpers.deep_merge(
      hash_to_merge_into: destination,
      other_hash: destination_attribute_dot_parts.reverse.inject(value) { |a, n| { n => a } }
    )
  else
    destination.assign_attribute(
      destination_attribute_dot_parts.first,
      value
    )
  end

  destination
end

#destination_attribute_class(destination:) ⇒ Object



80
81
82
83
84
85
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 80

def destination_attribute_class(destination:)
  @destination_attribute_type ||= {}
  @destination_attribute_type[destination] ||= destination.class.destination_attributes[
    destination_attribute_dot_parts.first.to_sym
  ].type.resource_class
end

#destination_attribute_dot_partsObject



87
88
89
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 87

def destination_attribute_dot_parts
  @destination_attribute_dot_parts ||= destination_attribute.split('.')
end

#reference?Boolean

Returns:

  • (Boolean)


91
92
93
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 91

def reference?
  references_many? || references_one?
end

#reference_resource_converterObject



103
104
105
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 103

def reference_resource_converter
  @reference_resource_converter ||= type.resource_converter
end

#references_many?Boolean

Returns:

  • (Boolean)


99
100
101
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 99

def references_many?
  type.is_a?(Type::ReferencesManyType)
end

#references_one?Boolean

Returns:

  • (Boolean)


95
96
97
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 95

def references_one?
  type.is_a?(Type::ReferencesOneType)
end

#source_attribute_dot_partsObject



107
108
109
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 107

def source_attribute_dot_parts
  @source_attribute_dot_parts ||= source_attribute.split('.')
end

#value(destination:, source:) ⇒ Object



111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
# File 'lib/ledger_sync/util/resource_converter/attribute.rb', line 111

def value(destination:, source:)
  value = if source.is_a?(Hash)
            source.dig(*source_attribute_dot_parts)
          else
            source_attribute_dot_parts.inject(source) { |r, dot_method| r&.send(dot_method) }
          end

  return type.cast(value: value) unless reference?

  destination_attribute_first_dot_part = destination_attribute_dot_parts.first
  new_destination = if destination.is_a?(Hash)
                      {}
                    else
                      destination.class.resource_attributes.fetch(
                        destination_attribute_first_dot_part.to_sym
                      ).type.resource_class.new
                    end
  type.cast(destination: new_destination, source: source, value: value)
end