i override the to_s method to get pretty output when i use puts but at the same time i seem to loose my ability to inspect the object. Is there a way to get the normal output of inspect while overriding to_s ?
class Person
attr_accessor :first, :last, :birthdate
def initialize(first=nil, last=nil, birthdate=nil)
@first, @last, @birthdate = first, last, birthdate
end
def age
if birthdate
Time.now.year-birthdate
else
0
end
end
def to_s
"#{@first} #{@last} (#{age})"
end
end
me = Person.new("Peter", "Marien", 1962)
p me >>Peter Marien (50)
p me.inspect >>"Peter Marien (50)"
#Need #<Person:0x1ec2550 @first="Peter", @last="Marien", @birthdate=1962>
Ruby documentation clearly states , that by default inspect
uses to_s
as its output.
If you don't need the address of the object, you could provide your own inspect, to have almost the same behavior:
class Person
def inspect
vars = self.instance_variables.
map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(", ")
"<#{self.class}: #{vars}>"
end
end
But you could also install a gem called awesome_print
that will give very nice output. First in console:
$ gem install awesome_print
then in irb or your script:
require 'awesome_print'
ap Person.new("John")
There is also a built-in pp
library, which have similar purpose. Still it is not immune (at least in Ruby 1.9.2-p290) to overriding of to_s
.
A quick example of pp
:
require 'pp'
pp Person.new("John")
I believe that by default inspect uses the to_s method.
However, you could also override inspect, including aliasing the old to_s method to it before overriding.
Here the sollution of Aleksander, the first p should give the overridden to_s but doesn't, you have to explictly call to_s like in the second p to get the result i want. I'm also not sure this inspect will give the same result as the original one with more complex objects, i'll try it at home. Anyone a still better shot ? I'm aware of the awesome_print gem but IMHO for something basic like this you shouldn't need to include gems.
class Person
def initialize(first=nil, last=nil, birthdate=nil)
@first, @last, @birthdate = first, last, birthdate
end
# New implementation of to_s
def to_s
"#{@first} #{@last}"
end
def inspect
vars = self.instance_variables.
map{|v| "#{v}=#{instance_variable_get(v).inspect}"}.join(", ")
"<#{self.class}: #{vars}>"
end
end
me = Person.new("John")
p me #--><Person: @first="John", @last=nil, @birthdate=nil>
p me.to_s #-->"John "
p me.inspect #-->"<Person: @first=\"John\", @last=nil, @birthdate=nil>"
Edit: i just tried awesome_print and i'm pleased, was afraid i had to use IRB to make use of it but it isn't, i run my scripts in my editor namely
require 'awesome_print'
ap me -->
#<Person:0x027efe20
@birthdate = nil,
@first = "John",
@last = nil
>
Edit, using pretty_print as suggested by Aleksander, doesn't interfere with the overridden to_s
require 'PP'
class Person
def initialize(first=nil, last=nil, birthdate=nil)
@first, @last, @birthdate = first, last, birthdate
end
# New implementation of to_s
def to_s
"#{@first} #{@last}"
end
end
me = Person.new("John")
pp me #--> <Person: @first="John", @last=nil, @birthdate=nil>
warn me.pretty_inspect #--> <Person: @first="John", @last=nil, @birthdate=nil>
Perry, here one of the many combinations i tried to get alias or alias_method to work, if you think this works, can you submit a working snippet ?
class Person
attr_accessor :first, :last, :birthdate
def initialize(first=nil, last=nil, birthdate=nil)
@first, @last, @birthdate = first, last, birthdate
end
alias old_to_s to_s
def inspect
old_to_s
end
def to_s
"#{@first} #{@last}"
end
end
me = Person.new("Peter")
p me #-->#<Person:0x1da26b8>
p me.inspect #-->"#<Person:0x1da26b8>"
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.