Skip to content

Commit 7fd54d6

Browse files
committed
Add configurable app-level default max_depth
1 parent fc90cdf commit 7fd54d6

File tree

5 files changed

+137
-4
lines changed

5 files changed

+137
-4
lines changed

.rubocop.yml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
require: rubocop-rspec
1+
plugins:
2+
- rubocop-rspec
23

34
inherit_from: .rubocop_todo.yml
45

56
AllCops:
6-
TargetRubyVersion: 3.2.5
7+
TargetRubyVersion: 3.2
78
NewCops: disable
89
SuggestExtensions: false
910

.rubocop_todo.yml

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
# This configuration was generated by
22
# `rubocop --auto-gen-config`
3-
# on 2024-06-05 00:21:36 UTC using RuboCop version 1.63.4.
3+
# on 2025-11-17 23:28:22 UTC using RuboCop version 1.81.7.
44
# The point is for the user to remove these configuration records
55
# one by one as the offenses are removed from the code base.
66
# Note that changes in the inspected code, or installation of new
77
# versions of RuboCop, may require this file to be generated again.
88

9+
# Offense count: 2
10+
# Configuration parameters: CountAsOne.
11+
RSpec/ExampleLength:
12+
Max: 14
13+
14+
# Offense count: 2
15+
# Configuration parameters: AllowSubject.
16+
RSpec/MultipleMemoizedHelpers:
17+
Max: 10
18+
919
# Offense count: 2
1020
# Configuration parameters: AllowedConstants.
1121
Style/Documentation:

lib/transmutation.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# frozen_string_literal: true
22

3+
require "transmutation/class_attributes"
4+
35
# A performant and expressive solution for serializing Ruby objects into JSON, with a touch of opinionated "magic" ✨.
46
#
57
# @example Basic usage
@@ -38,6 +40,10 @@
3840
# end
3941
# end
4042
module Transmutation
43+
extend ClassAttributes
44+
45+
class_attribute :max_depth, default: 1
46+
4147
class Error < StandardError; end
4248
end
4349

lib/transmutation/serialization.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ module Serialization
1010
# @param max_depth [Integer] The maximum depth of nested associations to serialize.
1111
#
1212
# @return [Transmutation::Serializer] The serialized object. This will respond to `#as_json` and `#to_json`.
13-
def serialize(object, namespace: nil, serializer: nil, depth: 0, max_depth: 1)
13+
def serialize(object, namespace: nil, serializer: nil, depth: 0, max_depth: Transmutation.max_depth)
1414
if object.respond_to?(:map) && !object.respond_to?(:to_hash)
1515
return object.map { |item| serialize(item, namespace:, serializer:, depth:, max_depth:) }
1616
end

spec/lib/transmutation/serialization_spec.rb

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,120 @@ def last_name = "Doe"
8989
end
9090
end
9191
end
92+
93+
describe ".max_depth" do
94+
let(:top_level_serializer) do
95+
Class.new(Transmutation::Serializer) do
96+
attribute :id
97+
98+
has_one :first_level
99+
end
100+
end
101+
102+
let(:first_level_serializer) do
103+
Class.new(Transmutation::Serializer) do
104+
attribute :id
105+
106+
has_one :second_level
107+
end
108+
end
109+
110+
let(:second_level_serializer) do
111+
Class.new(Transmutation::Serializer) do
112+
attribute :id
113+
end
114+
end
115+
116+
let(:top_level_class) do
117+
Class.new do
118+
attr_accessor :id, :first_level
119+
120+
def initialize(id:, first_level:)
121+
@id = id
122+
@first_level = first_level
123+
end
124+
end
125+
end
126+
127+
let(:first_level_class) do
128+
Class.new do
129+
attr_accessor :id, :second_level
130+
131+
def initialize(id:, second_level:)
132+
@id = id
133+
@second_level = second_level
134+
end
135+
end
136+
end
137+
138+
let(:second_level_class) do
139+
Class.new do
140+
attr_accessor :id
141+
142+
def initialize(id:)
143+
@id = id
144+
end
145+
end
146+
end
147+
148+
before do
149+
stub_const("TopLevelSerializer", top_level_serializer)
150+
stub_const("FirstLevelSerializer", first_level_serializer)
151+
stub_const("SecondLevelSerializer", second_level_serializer)
152+
stub_const("TopLevel", top_level_class)
153+
stub_const("FirstLevel", first_level_class)
154+
stub_const("SecondLevel", second_level_class)
155+
end
156+
157+
it "returns a default value of 1" do
158+
expect(Transmutation.max_depth).to eq(1)
159+
end
160+
161+
it "serializes only 1 level of associations" do
162+
second_level = SecondLevel.new(id: 3)
163+
first_level = FirstLevel.new(id: 2, second_level:)
164+
top_level = TopLevel.new(id: 1, first_level:)
165+
166+
serialized = caller.serialize(top_level)
167+
168+
expected_json = {
169+
"id" => 1,
170+
"first_level" => {
171+
"id" => 2
172+
}
173+
}
174+
175+
expect(serialized.as_json).to eq(expected_json)
176+
end
177+
178+
context "when the value is set to another value" do
179+
before do
180+
Transmutation.max_depth = 2
181+
end
182+
183+
it "returns the maximum depth of the serializer" do
184+
expect(Transmutation.max_depth).to eq(2)
185+
end
186+
187+
it "serializes 2 levels of associations" do
188+
second_level = SecondLevel.new(id: 3)
189+
first_level = FirstLevel.new(id: 2, second_level:)
190+
top_level = TopLevel.new(id: 1, first_level:)
191+
192+
serialized = caller.serialize(top_level)
193+
194+
expected_json = {
195+
"id" => 1,
196+
"first_level" => {
197+
"id" => 2,
198+
"second_level" => {
199+
"id" => 3
200+
}
201+
}
202+
}
203+
204+
expect(serialized.as_json).to eq(expected_json)
205+
end
206+
end
207+
end
92208
end

0 commit comments

Comments
 (0)