Module: DenormalizeFields
- Defined in:
- lib/denormalize_fields.rb,
lib/denormalize_fields/version.rb,
lib/denormalize_fields/association_extension.rb
Defined Under Namespace
Modules: AssociationExtension
Constant Summary
collapse
- VERSION =
'1.1.1'
Class Method Summary
collapse
-
.apply(changeset, to:, owner:, mapping:) ⇒ Object
Note: missing related records are ignored, and new related records are not persisted.
-
.call(record:, relation_name:, mapping:) ⇒ Object
-
.cast_to_mapping(fields, prefix: nil) ⇒ Object
-
.changeset(record:, mapping:) ⇒ Object
-
.copy_errors(errors, to_record:, mapping:) ⇒ Object
TODO: use Errors#import when it becomes available in rails 6.1 or 6.2.
-
.denormalize(fields:, from:, onto:, prefix: nil) ⇒ Object
Class Method Details
.apply(changeset, to:, owner:, mapping:) ⇒ Object
Note: missing related records are ignored, and new related records are not persisted. Extra options to raise/create/persist in this case might be nice.
50
51
52
53
54
55
56
57
58
|
# File 'lib/denormalize_fields.rb', line 50
def apply(changeset, to:, owner:, mapping:)
return if to.nil?
to.assign_attributes(changeset)
return if to.new_record? ? to.valid? : to.save
DenormalizeFields.copy_errors(to.errors, to_record: owner, mapping: mapping)
raise(ActiveRecord::RecordInvalid, to)
end
|
.call(record:, relation_name:, mapping:) ⇒ Object
24
25
26
27
28
29
30
31
32
33
|
# File 'lib/denormalize_fields.rb', line 24
def call(record:, relation_name:, mapping:)
changeset = DenormalizeFields.changeset(record: record, mapping: mapping)
return if changeset.empty?
Array(record.send(relation_name)).each do |related_record|
DenormalizeFields.apply(
changeset, to: related_record, owner: record, mapping: mapping
)
end
end
|
.cast_to_mapping(fields, prefix: nil) ⇒ Object
15
16
17
18
19
20
21
22
|
# File 'lib/denormalize_fields.rb', line 15
def cast_to_mapping(fields, prefix: nil)
if fields.is_a?(Hash)
prefix && raise(ArgumentError, 'pass EITHER a fields Hash OR a prefix')
fields
else
Array(fields).map { |e| [e.to_sym, [prefix, e].join.to_sym] }.to_h
end
end
|
.changeset(record:, mapping:) ⇒ Object
35
36
37
38
39
40
41
42
43
44
45
46
|
# File 'lib/denormalize_fields.rb', line 35
def changeset(record:, mapping:)
mapping.each.with_object({}) do |(source, dest), hash|
if source.is_a?(Array)
if source.any? { |field| record.saved_change_to_attribute?(field) }
current_values = record.attributes.values_at(*source.map(&:to_s))
hash[dest] = current_values.join(' ')
end
elsif change = record.saved_change_to_attribute(source)
hash[dest] = change.last
end
end
end
|
.copy_errors(errors, to_record:, mapping:) ⇒ Object
TODO: use Errors#import when it becomes available in rails 6.1 or 6.2
61
62
63
64
65
66
67
68
|
# File 'lib/denormalize_fields.rb', line 61
def copy_errors(errors, to_record:, mapping:)
errors.details.each do |key, array|
field = mapping.rassoc(key.to_sym).first
array.each do |details|
to_record.errors.add(field, details[:error], details.except(:error))
end
end
end
|
.denormalize(fields:, from:, onto:, prefix: nil) ⇒ Object
7
8
9
10
11
12
13
|
# File 'lib/denormalize_fields.rb', line 7
def denormalize(fields:, from:, onto:, prefix: nil)
mapping = cast_to_mapping(fields, prefix: prefix)
from.after_save do
DenormalizeFields.call(record: self, relation_name: onto, mapping: mapping)
end
end
|