Module: Lutaml::Model::ComparableModel::StructuralDiff
- Defined in:
- lib/lutaml/model/comparable_model.rb
Overview
Structured, path-addressed diff between two model trees (lutaml-model#18). Used by ComparableModel#diff.
Defined Under Namespace
Classes: Entry
Class Method Summary collapse
- .comparable_pair?(left, right) ⇒ Boolean
- .diff(left, right, path = []) ⇒ Object
- .diff_collections(lval, rval, path) ⇒ Object
- .differing?(lval, rval) ⇒ Boolean
- .path_string(path) ⇒ Object
Class Method Details
.comparable_pair?(left, right) ⇒ Boolean
219 220 221 222 |
# File 'lib/lutaml/model/comparable_model.rb', line 219 def comparable_pair?(left, right) left.is_a?(ComparableModel) && right.is_a?(ComparableModel) && left.instance_of?(right.class) end |
.diff(left, right, path = []) ⇒ Object
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
# File 'lib/lutaml/model/comparable_model.rb', line 181 def diff(left, right, path = []) return [] if left.equal?(right) return [Entry.new(path_string(path), left, right)] unless comparable_pair?(left, right) entries = [] left.class.attributes.each_key do |attr| lval = left.public_send(attr) rval = right.public_send(attr) child_path = path + [attr] if comparable_pair?(lval, rval) entries.concat(diff(lval, rval, child_path)) elsif lval.is_a?(::Array) && rval.is_a?(::Array) entries.concat(diff_collections(lval, rval, child_path)) elsif differing?(lval, rval) entries << Entry.new(path_string(child_path), lval, rval) end end entries end |
.diff_collections(lval, rval, path) ⇒ Object
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 |
# File 'lib/lutaml/model/comparable_model.rb', line 202 def diff_collections(lval, rval, path) entries = [] max = [lval.size, rval.size].max max.times do |i| li = lval[i] ri = rval[i] child_path = path + [i] if comparable_pair?(li, ri) entries.concat(diff(li, ri, child_path)) elsif differing?(li, ri) entries << Entry.new(path_string(child_path), li, ri) end end entries end |
.differing?(lval, rval) ⇒ Boolean
224 225 226 227 228 229 230 231 |
# File 'lib/lutaml/model/comparable_model.rb', line 224 def differing?(lval, rval) if lval.is_a?(::Array) && rval.is_a?(::Array) lval.size != rval.size || lval.zip(rval).any? { |l, r| l != r } else lval != rval end end |
.path_string(path) ⇒ Object
233 234 235 236 237 |
# File 'lib/lutaml/model/comparable_model.rb', line 233 def path_string(path) path.reduce("") do |acc, seg| seg.is_a?(::Integer) ? "#{acc}[#{seg}]" : "#{acc}.#{seg}" end.delete_prefix(".") end |