Skip to content

Commit 8c664d9

Browse files
committed
Fix diffing of ActiveRecord objects in nested objects
When displaying a diff of two ActiveRecord objects that exist within an array or hash or something like that, make sure that we are using the CustomObject diff formatter instead of the DefaultObject diff formatter. When inspecting attributes, this will output something like: foo: "bar", baz: "qux" instead of: @foo="bar", @baz="qux"
1 parent 5dd3a1c commit 8c664d9

File tree

6 files changed

+111
-2
lines changed

6 files changed

+111
-2
lines changed

lib/super_diff/active_record.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,8 @@ module ActiveRecord
3636
end
3737
end
3838

39+
require "super_diff/active_record/monkey_patches"
40+
3941
SuperDiff::ObjectInspection.map.prepend(
4042
SuperDiff::ActiveRecord::ObjectInspection::MapExtension,
4143
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# rubocop:disable Style/BracesAroundHashParameters, Style/ClassAndModuleChildren
2+
class ActiveRecord::Base
3+
def attributes_for_super_diff
4+
(attributes.keys.sort - ["id"]).reduce({ id: id }) do |hash, key|
5+
hash.merge(key.to_sym => attributes[key])
6+
end
7+
end
8+
end
9+
# rubocop:enable Style/BracesAroundHashParameters, Style/ClassAndModuleChildren

lib/super_diff/operation_sequences/base.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,20 @@ def to_diff(indent_level:, add_comma: false, collection_prefix: nil)
66
raise NotImplementedError
77
end
88
# rubocop:enable Lint/UnusedMethodArgument
9+
10+
def pretty_print(pp)
11+
pp.text "#{self.class.name}.new(["
12+
pp.group_sub do
13+
pp.nest(2) do
14+
pp.breakable
15+
pp.seplist(self) do |value|
16+
pp.pp value
17+
end
18+
end
19+
end
20+
pp.breakable
21+
pp.text("])")
22+
end
923
end
1024
end
1125
end

lib/super_diff/rspec/operational_sequencers/object_having_attributes.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ def self.applies_to?(expected, _actual)
99
protected
1010

1111
def build_operation_sequencer
12-
# TODO: Test this
1312
if actual.respond_to?(:attributes_for_super_diff)
1413
OperationSequences::CustomObject.new([], value_class: actual.class)
1514
else
@@ -18,7 +17,6 @@ def build_operation_sequencer
1817
end
1918

2019
def attribute_names
21-
# TODO: Test this
2220
if actual.respond_to?(:attributes_for_super_diff)
2321
actual.attributes_for_super_diff.keys | expected.expected.keys
2422
else
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
module SuperDiff
2+
module Test
3+
module Models
4+
module ActiveRecord
5+
class Query
6+
attr_reader :results
7+
8+
def initialize(results:)
9+
@results = results
10+
end
11+
end
12+
end
13+
end
14+
end
15+
end

spec/support/shared_examples/active_record.rb

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,75 @@
335335
end
336336
end
337337
end
338+
339+
describe "and RSpec's #match matcher" do
340+
context "when the expected value includes an ActiveRecord object" do
341+
it "produces the correct output" do
342+
as_both_colored_and_uncolored do |color_enabled|
343+
snippet = <<~TEST.strip
344+
SuperDiff::Test::Models::ActiveRecord::Person.create!(
345+
name: "Murphy",
346+
age: 20
347+
)
348+
349+
expected = [
350+
an_object_having_attributes(
351+
results: [
352+
an_object_having_attributes(name: "John", age: 19)
353+
]
354+
)
355+
]
356+
357+
actual = [
358+
SuperDiff::Test::Models::ActiveRecord::Query.new(
359+
results: SuperDiff::Test::Models::ActiveRecord::Person.all
360+
)
361+
]
362+
363+
expect(actual).to match(expected)
364+
TEST
365+
366+
program = make_program(snippet, color_enabled: color_enabled)
367+
368+
expected_output = build_expected_output(
369+
color_enabled: color_enabled,
370+
snippet: %|expect(actual).to match(expected)|,
371+
newline_before_expectation: true,
372+
expectation: proc {
373+
line do
374+
plain "Expected "
375+
beta %|[#<SuperDiff::Test::Models::ActiveRecord::Query @results=#<ActiveRecord::Relation [#<SuperDiff::Test::Models::ActiveRecord::Person id: 1, name: "Murphy", age: 20>]>>]|
376+
end
377+
378+
line do
379+
plain "to match "
380+
alpha %|[#<an object having attributes (results: [#<an object having attributes (name: "John", age: 19)>])>]|
381+
end
382+
},
383+
diff: proc {
384+
plain_line %| [|
385+
plain_line %| #<SuperDiff::Test::Models::ActiveRecord::Query {|
386+
plain_line %| @results=#<ActiveRecord::Relation [|
387+
plain_line %| #<SuperDiff::Test::Models::ActiveRecord::Person {|
388+
plain_line %| id: 1,|
389+
# alpha_line %|- age: 19,| # TODO
390+
alpha_line %|- age: 19|
391+
beta_line %|+ age: 20,|
392+
alpha_line %|- name: "John"|
393+
beta_line %|+ name: "Murphy"|
394+
plain_line %| }>|
395+
plain_line %| ]>|
396+
plain_line %| }>|
397+
plain_line %| ]|
398+
},
399+
)
400+
401+
expect(program).
402+
to produce_output_when_run(expected_output).
403+
in_color(color_enabled).
404+
removing_object_ids
405+
end
406+
end
407+
end
408+
end
338409
end

0 commit comments

Comments
 (0)