denormalize_fields 1.1.1 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7bf731da26d483667dbb6a1942755bdf5c6cf5161aaf1b2d9fb1b2dc84366d96
4
- data.tar.gz: a8e09ec6ced26720d404ca8e693f1e9c036a92b01b9f7d607b8cb6a51587112f
3
+ metadata.gz: b9b1cb8a3c118b8e410665f182f78fd63ec1dfa571af98f2d93f5deca9e0600a
4
+ data.tar.gz: 73785e5dc16509d33978fcc22571e9dc961d9c5dd02e712b640d4a57d8bb8a2f
5
5
  SHA512:
6
- metadata.gz: d3cb5a23f3896d6074020c48e53b954f0e4266a779da1b7c106d8bc5d0df6f22597bcab869ef9872d14aa23de163aa5b6d2df1e7904ac66a190d9546b462d462
7
- data.tar.gz: 75c819d17a023f5fbbade955cb90ee54417e4a22807ab78fb924aff011611bf4d858fbf7cfad1eb63bbf9fe2807f0897c6d89a0be87cde2902757bf08266fbdb
6
+ metadata.gz: 5836ceeb70a8d592d5f9406c6b6c79bd6d0ffe51f5a80b4e3ab202983aba5ec0526ec30fe7a561b02e78da97578a10a8509be898c9a208e9dc3e043417c2387c
7
+ data.tar.gz: 8f87ae5f9efae07bd63eab9e5394d5b78cd6162569583327cac0c086dc244899d718c69ce2c50aa4039d4b35ea21d268641ce83892bdb44df0a899b0e50575e7
@@ -12,10 +12,9 @@ module DenormalizeFields
12
12
  return unless options = association.options[OPTION]
13
13
 
14
14
  DenormalizeFields.denormalize(
15
- fields: options[:fields],
16
- from: association.active_record,
17
- onto: association.name,
18
- prefix: options[:prefix],
15
+ from: association.active_record,
16
+ onto: association.name,
17
+ **options,
19
18
  )
20
19
  end
21
20
  end
@@ -1,3 +1,3 @@
1
1
  module DenormalizeFields
2
- VERSION = '1.1.1'
2
+ VERSION = '1.3.0'
3
3
  end
@@ -4,14 +4,48 @@ require 'denormalize_fields/version'
4
4
  module DenormalizeFields
5
5
  module_function
6
6
 
7
- def denormalize(fields:, from:, onto:, prefix: nil)
7
+ class ArgumentError < ::ArgumentError; end
8
+
9
+ class RelatedRecordInvalid < ::ActiveRecord::RecordInvalid
10
+ attr_accessor :owner, :mapping
11
+
12
+ def initialize(record:, owner:, mapping:)
13
+ super(record)
14
+ self.owner = owner
15
+ self.mapping = mapping
16
+ end
17
+ end
18
+
19
+ def denormalize(fields:, from:, onto:, prefix: nil, **options)
8
20
  mapping = cast_to_mapping(fields, prefix: prefix)
21
+ validate_options(**options)
9
22
 
10
23
  from.after_save do
11
- DenormalizeFields.call(record: self, relation_name: onto, mapping: mapping)
24
+ DenormalizeFields.call(
25
+ record: self,
26
+ relation_name: onto,
27
+ mapping: mapping,
28
+ **options,
29
+ )
12
30
  end
13
31
  end
14
32
 
33
+ def validate_options(**options)
34
+ validate_conditional(options[:if])
35
+ validate_conditional(options[:unless])
36
+ unsupported = (options.keys - %i[if unless]).empty? ||
37
+ raise(ArgumentError, "unsupported denormalize options: #{unsupported}")
38
+ end
39
+
40
+ CONDITIONAL_CLASSES = [NilClass, TrueClass, FalseClass, Symbol, Proc]
41
+
42
+ def validate_conditional(arg)
43
+ CONDITIONAL_CLASSES.include?(arg.class) || raise(
44
+ ArgumentError,
45
+ "`if:` option must be a #{CONDITIONAL_CLASSES.join('/')}, got: #{arg.class}"
46
+ )
47
+ end
48
+
15
49
  def cast_to_mapping(fields, prefix: nil)
16
50
  if fields.is_a?(Hash)
17
51
  prefix && raise(ArgumentError, 'pass EITHER a fields Hash OR a prefix')
@@ -21,7 +55,10 @@ module DenormalizeFields
21
55
  end
22
56
  end
23
57
 
24
- def call(record:, relation_name:, mapping:)
58
+ def call(record:, relation_name:, mapping:, **options)
59
+ return unless conditional_passes?(options[:if], record, false)
60
+ return unless conditional_passes?(options[:unless], record, true)
61
+
25
62
  changeset = DenormalizeFields.changeset(record: record, mapping: mapping)
26
63
  return if changeset.empty?
27
64
 
@@ -32,6 +69,21 @@ module DenormalizeFields
32
69
  end
33
70
  end
34
71
 
72
+ def conditional_passes?(conditional, record, inverted)
73
+ return true if conditional.nil?
74
+
75
+ result =
76
+ if conditional.respond_to?(:call)
77
+ record.instance_exec(&conditional)
78
+ elsif conditional.class == Symbol
79
+ record.send(conditional)
80
+ else # true, false
81
+ conditional
82
+ end
83
+
84
+ inverted ? !result : !!result
85
+ end
86
+
35
87
  def changeset(record:, mapping:)
36
88
  mapping.each.with_object({}) do |(source, dest), hash|
37
89
  if source.is_a?(Array)
@@ -54,15 +106,16 @@ module DenormalizeFields
54
106
  return if to.new_record? ? to.valid? : to.save
55
107
 
56
108
  DenormalizeFields.copy_errors(to.errors, to_record: owner, mapping: mapping)
57
- raise(ActiveRecord::RecordInvalid, to)
109
+ raise RelatedRecordInvalid.new(record: to, owner: owner, mapping: mapping)
58
110
  end
59
111
 
60
112
  # TODO: use Errors#import when it becomes available in rails 6.1 or 6.2
61
113
  def copy_errors(errors, to_record:, mapping:)
62
114
  errors.details.each do |key, array|
63
- field = mapping.rassoc(key.to_sym).first
64
- array.each do |details|
65
- to_record.errors.add(field, details[:error], details.except(:error))
115
+ Array(mapping.rassoc(key.to_sym)).compact.each do |field|
116
+ array.each do |details|
117
+ to_record.errors.add(field, details[:error], **details.except(:error))
118
+ end
66
119
  end
67
120
  end
68
121
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: denormalize_fields
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Janosch Müller
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-26 00:00:00.000000000 Z
11
+ date: 2021-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 4.1.14
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: 7.0.0
22
+ version: 8.0.0
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,27 +29,21 @@ dependencies:
29
29
  version: 4.1.14
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: 7.0.0
32
+ version: 8.0.0
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: rails
35
35
  requirement: !ruby/object:Gem::Requirement
36
36
  requirements:
37
- - - ">="
38
- - !ruby/object:Gem::Version
39
- version: 4.1.14
40
- - - "<"
37
+ - - "~>"
41
38
  - !ruby/object:Gem::Version
42
- version: 7.0.0
39
+ version: '7.0'
43
40
  type: :development
44
41
  prerelease: false
45
42
  version_requirements: !ruby/object:Gem::Requirement
46
43
  requirements:
47
- - - ">="
48
- - !ruby/object:Gem::Version
49
- version: 4.1.14
50
- - - "<"
44
+ - - "~>"
51
45
  - !ruby/object:Gem::Version
52
- version: 7.0.0
46
+ version: '7.0'
53
47
  - !ruby/object:Gem::Dependency
54
48
  name: rake
55
49
  requirement: !ruby/object:Gem::Requirement
@@ -121,7 +115,7 @@ homepage: https://www.github.com/jaynetics/denormalize_fields
121
115
  licenses:
122
116
  - MIT
123
117
  metadata: {}
124
- post_install_message:
118
+ post_install_message:
125
119
  rdoc_options: []
126
120
  require_paths:
127
121
  - lib
@@ -136,8 +130,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
136
130
  - !ruby/object:Gem::Version
137
131
  version: '0'
138
132
  requirements: []
139
- rubygems_version: 3.1.2
140
- signing_key:
133
+ rubygems_version: 3.2.32
134
+ signing_key:
141
135
  specification_version: 4
142
136
  summary: Simplify denormalizing fields from one record to another.
143
137
  test_files: []