Class: YamlExporter::Nodes::OneReference

Inherits:
Object
  • Object
show all
Defined in:
lib/yaml_exporter/nodes/one_reference.rb

Overview

one :assoc, find_by: :column — belongs_to reference. The FK column lives on the current record; the target is externally managed.

Phase: :pre_save (sets the FK column on record before record.save!).

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name:, owner_class:, find_by:) ⇒ OneReference

Returns a new instance of OneReference.



12
13
14
15
16
17
18
19
20
21
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 12

def initialize(name:, owner_class:, find_by:)
  @name = name.to_sym
  @owner_class = owner_class
  @find_by = find_by.to_sym
  reflection = owner_class.reflect_on_association(@name)
  unless reflection
    raise ArgumentError,
          "`one #{name.inspect}`: #{owner_class} has no association `#{name}`"
  end
end

Instance Attribute Details

#find_byObject (readonly)

Returns the value of attribute find_by.



10
11
12
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 10

def find_by
  @find_by
end

#nameObject (readonly)

Returns the value of attribute name.



10
11
12
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 10

def name
  @name
end

#owner_classObject (readonly)

Returns the value of attribute owner_class.



10
11
12
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 10

def owner_class
  @owner_class
end

Instance Method Details

#export(record, exporter:) ⇒ Object



60
61
62
63
64
65
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 60

def export(record, exporter:)
  target = record.public_send(@name)
  return [@name.to_s, nil] if target.nil?

  [@name.to_s, target.public_send(@find_by)]
end

#import(record, data, path:, importer:) ⇒ Object

Assign via the association setter (not the raw FK column) so that:

- Rails uses the target's `association_primary_key`, not a hardcoded
:id (composite/custom primary keys keep working).
- The in-memory association cache on `record` is updated, so a
subsequent `record.publisher` returns the freshly-assigned target
instead of a stale one.
- Polymorphic `*_type` columns would be set too, if we ever grow
that feature.


43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 43

def import(record, data, path:, importer:)
  value = data.key?(@name.to_s) ? data[@name.to_s] : nil

  if value.nil?
    record.public_send("#{@name}=", nil)
    return
  end

  target = target_class.find_by(@find_by => value)
  unless target
    raise ActiveRecord::RecordNotFound,
          "no #{target_class} with #{@find_by}=#{value.inspect}"
  end

  record.public_send("#{@name}=", target)
end

#phaseObject



23
24
25
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 23

def phase
  :pre_save
end

#schema_fragmentObject



67
68
69
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 67

def schema_fragment
  { @name => { type: TypeInference.schema_type_for(target_class, @find_by) } }
end

#target_classObject



31
32
33
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 31

def target_class
  @target_class ||= @owner_class.reflect_on_association(@name).klass
end

#yaml_keysObject



27
28
29
# File 'lib/yaml_exporter/nodes/one_reference.rb', line 27

def yaml_keys
  [@name.to_s]
end