Module: ActiveSnapshot::SnapshotsConcern

Extended by:
ActiveSupport::Concern
Defined in:
lib/active_snapshot/models/concerns/snapshots_concern.rb

Constant Summary collapse

LEGACY_POSITIONAL_ARGUMENT_WARNING =
"Supplying the snapshots :identifier as a positional argument is now deprecated and will be removed in upcoming versions. Please supply the snapshot identifier using the :identifier keyword argument instead.".freeze

Instance Method Summary collapse

Instance Method Details

#children_to_snapshotObject

[View source]

56
57
58
59
60
61
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
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/active_snapshot/models/concerns/snapshots_concern.rb', line 56

def children_to_snapshot
  snapshot_children_proc = self.class.has_snapshot_children

  if !snapshot_children_proc
    return {}
  else
    records = self.instance_exec(&snapshot_children_proc)

    if records.is_a?(Hash)
      records = records.with_indifferent_access
    else
      raise ArgumentError.new("Invalid `has_snapshot_children` definition. Must return a Hash")
    end

    snapshot_children = {}.with_indifferent_access

    records.each do |assoc_name, opts|
      snapshot_children[assoc_name] = {}

      if opts.nil?
        ### nil is allowed value in case has_one/belongs_to is nil, etc.
        snapshot_children[assoc_name][:records] = []

      elsif opts.is_a?(ActiveRecord::Base)
        ### Support belongs_to / has_one
        snapshot_children[assoc_name][:records] = [opts]

      elsif opts.is_a?(ActiveRecord::Relation) || opts.is_a?(Array)
        snapshot_children[assoc_name][:records] = opts

      elsif opts.is_a?(Hash)
        opts = opts.with_indifferent_access

        if opts.has_key?(:records)
          records = opts[:records]
        elsif opts.has_key?(:record)
          records = opts[:record]
        end

        if records.nil?
          # Do nothing, allow nil value in case a has_one/belong_to returns nil, etc.
        elsif records
          if records.respond_to?(:to_a)
            records = records.to_a
          else
            records = [records]
          end

          snapshot_children[assoc_name][:records] = records
        else
          raise ArgumentError.new("Invalid `has_snapshot_children` definition. Must define a :records key for each child association.")
        end

        delete_method = opts[:delete_method]

        if delete_method.present? && delete_method.to_s != "default"
          if delete_method.respond_to?(:call)
            snapshot_children[assoc_name][:delete_method] = delete_method
          else
            raise ArgumentError.new("Invalid `has_snapshot_children` definition. Invalid :delete_method argument. Must be a Lambda / Proc")
          end
        end

      else
        raise ArgumentError.new("Invalid `has_snapshot_children` definition. Invalid :records argument. Must be a Hash or Array")
      end
    end

    return snapshot_children
  end
end

#create_snapshot!(legacy_identifier = nil, identifier: nil, user: nil, metadata: nil) ⇒ Object

[View source]

11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# File 'lib/active_snapshot/models/concerns/snapshots_concern.rb', line 11

def create_snapshot!(legacy_identifier=nil, identifier: nil, user: nil, metadata: nil)
  if identifier.nil? && legacy_identifier
    identifier = legacy_identifier

    ActiveSupport::Deprecation.warn(LEGACY_POSITIONAL_ARGUMENT_WARNING)
  end

  snapshot = snapshots.create!({
    identifier: identifier,
    user_id: (user.id if user),
    user_type: (user.class.name if user),
    metadata: ( || {}),
  })

  snapshot_items = []

  snapshot_items << snapshot.build_snapshot_item(self)

  snapshot_children = self.children_to_snapshot

  if snapshot_children
    snapshot_children.each do |child_group_name, h|
      h[:records].each do |child_item|
        snapshot_items << snapshot.build_snapshot_item(child_item, child_group_name: child_group_name)
      end
    end
  end

  SnapshotItem.import(snapshot_items, validate: true)

  snapshot
end