Skip to content

Commit 4e11f89

Browse files
committed
Add support for #attributes_for_inspect
Implements #214
1 parent d7dd036 commit 4e11f89

File tree

2 files changed

+64
-17
lines changed

2 files changed

+64
-17
lines changed

lib/active_type/virtual_attributes.rb

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,34 @@ def self.deep_dup(hash)
134134
result
135135
end
136136

137+
def self.attribute_for_inspect(value)
138+
if value.is_a?(String) && value.length > 50
139+
"#{value[0, 50]}...".inspect
140+
elsif value.is_a?(Date) || value.is_a?(Time)
141+
%("#{value.to_formatted_s(:db)}")
142+
elsif value.is_a?(Array) && value.size > 10
143+
inspected = value.first(10).inspect
144+
%(#{inspected[0...-1]}, ...])
145+
else
146+
value.inspect
147+
end
148+
end
149+
137150
extend ActiveSupport::Concern
138151

139152
included do
140153
include ActiveType::VirtualAttributes::Serialization
141154
class_attribute :virtual_columns_hash
142155
self.virtual_columns_hash = {}
143156

157+
if respond_to?(:attributes_for_inspect)
158+
# 7.1 had [:id] as a default, we want a consistent default across all versions
159+
self.attributes_for_inspect = :all
160+
else
161+
# ActiveRecord < 7.2
162+
class_attribute :attributes_for_inspect, default: :all
163+
end
164+
144165
class << self
145166
if method_defined?(:attribute)
146167
alias_method :ar_attribute, :attribute
@@ -270,25 +291,28 @@ def write_virtual_attribute(name, value)
270291
virtual_attributes[name] = value
271292
end
272293

273-
# Returns the contents of the record as a nicely formatted string.
294+
def attributes_for_inspect
295+
self.class.attributes_for_inspect == :all ? attributes.keys : self.class.attributes_for_inspect
296+
end
297+
274298
def inspect
275-
inspection = attributes.collect do |name, value|
276-
"#{name}: #{VirtualAttributes.attribute_for_inspect(value)}"
277-
end.sort.compact.join(", ")
278-
"#<#{self.class} #{inspection}>"
299+
inspect_with_attributes(attributes_for_inspect)
279300
end
280301

281-
def self.attribute_for_inspect(value)
282-
if value.is_a?(String) && value.length > 50
283-
"#{value[0, 50]}...".inspect
284-
elsif value.is_a?(Date) || value.is_a?(Time)
285-
%("#{value.to_formatted_s(:db)}")
286-
elsif value.is_a?(Array) && value.size > 10
287-
inspected = value.first(10).inspect
288-
%(#{inspected[0...-1]}, ...])
289-
else
290-
value.inspect
291-
end
302+
def full_inspect
303+
inspect_with_attributes(attributes.keys)
304+
end
305+
306+
# Returns the contents of the record as a nicely formatted string.
307+
def inspect_with_attributes(attribute_names)
308+
inspection = attribute_names.collect do |name|
309+
name = name.to_s
310+
if attributes.key?(name)
311+
value = attributes[name]
312+
"#{name}: #{VirtualAttributes.attribute_for_inspect(value)}"
313+
end
314+
end.compact.sort.join(", ")
315+
"#<#{self.class} #{inspection}>"
292316
end
293317

294318
private

spec/active_type/object_spec.rb

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,12 @@ class ObjectWithUnsupportedTypes < Object
131131
attribute :virtual_hash, :hash
132132
end
133133

134+
class ObjectWithClassInspectFilter < ActiveType::Object
135+
attribute :visible, :string
136+
attribute :hidden, :string
137+
138+
self.attributes_for_inspect = [:visible]
139+
end
134140
end
135141

136142

@@ -246,7 +252,6 @@ class ObjectWithUnsupportedTypes < Object
246252
end
247253

248254
describe '#inspect' do
249-
250255
it 'returns the contents of the object as a nicely formatted string' do
251256
t = Time.now
252257
subject.virtual_string = "string"
@@ -258,6 +263,24 @@ class ObjectWithUnsupportedTypes < Object
258263
expect(subject.inspect).to eq("#<ObjectSpec::Object virtual_attribute: nil, virtual_boolean: true, virtual_date: \"#{Date.today}\", virtual_integer: 17, virtual_string: \"string\", virtual_time: \"#{t.to_formatted_s(:db)}\", virtual_type_attribute: nil>")
259264
end
260265

266+
it 'does not filter out any attributes per default' do
267+
object = ObjectSpec::ObjectWithClassInspectFilter.new(visible: 'seen', hidden: 'also-seen')
268+
expect(object.full_inspect).to eq('#<ObjectSpec::ObjectWithClassInspectFilter hidden: "also-seen", visible: "seen">')
269+
end
270+
271+
context 'with attributes_for_inspect class attribute' do
272+
it 'filters attributes based on the class configuration' do
273+
object = ObjectSpec::ObjectWithClassInspectFilter.new(visible: 'seen', hidden: 'invisible')
274+
expect(object.inspect).to eq('#<ObjectSpec::ObjectWithClassInspectFilter visible: "seen">')
275+
end
276+
end
277+
end
278+
279+
describe '#full_inspect' do
280+
it 'shows all attributes' do
281+
object = ObjectSpec::ObjectWithClassInspectFilter.new(visible: 'seen', hidden: 'not-so-invisible-anymore')
282+
expect(object.full_inspect).to eq('#<ObjectSpec::ObjectWithClassInspectFilter hidden: "not-so-invisible-anymore", visible: "seen">')
283+
end
261284
end
262285

263286
describe '#attributes' do

0 commit comments

Comments
 (0)