added instance variable not shown with inspect in Ruby - ruby

Inspect will tell object representation. so I tried this:
animal = "cat"
animal.instance_variable_set(:#a, "dog")
p "inspect object animal: #{animal.inspect}"
But inspect only gave me "cat", I cannot see #a="dog"
If I do this:
puts "instance variables are: #{animal.instance_variables}"
Then I can see [:#a] as output
Why is inspect not giving me everything?
Thanks

String overrides #inspect (String#inspect) to return the original string wrapped in quotes, as opposed to Object#inspect, which dumps everything.
You shouldn't need to re-define String#inspect to account for your special use-case though. If you want your string to have some additional data, you should create your own class instead:
class Animal
def initialize(name, other)
#name = name
#other = other
end
end
Animal.new("cat", "dog")
# #<Animal:0x007faf9404d828 #name="cat", #other="dog">

Why is inspect not giving me everything?
DON'T DO THIS -> remove the String#inspect method and see what happen.
class String
remove_method :inspect
end
animal = "cat"
animal.instance_variable_set(:#a, "dog")
animal # => #<String:0x9976b94 #a=#<String:0x9976b80>>
The above output is what Object#inspect explained -
The default inspect shows the object’s class name, an encoding of the object id, and a list of the instance variables and their values (by calling inspect on each of them).
But, in your case you are calling, String#inspect which is the overridden version of Object#inspect.
Returns a printable version of str, surrounded by quote marks, with special characters escaped.
And your output is what exactly documentation mentioned.
I wanted to give you some in sight. Now don't play like this with Ruby core classes, create your own custom classes, and play with them as much as you can.

Related

How to Modify Class Print Output

I have some classes that have large instance variables attached to them. When I initialize these classes the large instance variables attached to them are outputted along with them resulting in the output taking the entirety of my shell and being kinda annoying. Is there a way I can override what the output of my class should be when its returned in a terminal to avoid this?
I know what you mean. Every once in a while I have to work with an object that has a print-out of several screens. And when it's not a single object, it's a collection.
I do this to prevent it from flooding my screen
my_obj = get_a_huge_object_or_collection; nil
In this case, nil becomes the value of this expression and is printed out.
But if you really want to permanently alter how your objects print to the console, you can override inspect.
Sergio Tulentsev already provided an answer on how to suppress verbose output.
Another option might be to change how an instance of that class is output. This can be done by defining an inspect method.
Imagine you have a class Foolike this:
class Foo
attr_accessor :bar
end
then you would see output like this:
foo = Foo.new
foo.bar = "extremely long value"
foo
#=> #<Foo:0x00007ffab9aaf3f0 #bar="extremely long value">
But when you add a custom inspect method to your class then you can control how the output looks like and you can, for example, truncate long attributes or can only show the most interesting values:
class Foo
attr_accessor :bar
def inspect
"#<Foo #bar=\"#{bar[0,8]}...\">"
end
end
foo = Foo.new
foo.bar = "extremely long value"
foo
#=> #<Foo #bar="extremel..."

Remove object_id from to_s call

I am currently editing a class' to_s method to make it puts out something prettier. At the last line, the object_id is include #<Profile:0x007fde5aadd280>. Any way to remove this object_id from the output without doing so explicitly after calling to_s
You need to write your own #inspect method.
class Foo
def inspect
"<#%s>" % self.class
end
end
Foo.new # => <#Foo>
Read the documentation Object#inspect
Returns a string containing a human-readable representation of obj. By default, show the class name and the list of the instance variables and their values (by calling inspect on each of them). User defined classes should override this method to make better representation of obj. When overriding this method, it should return a string whose encoding is compatible with the default external encoding.

Show object as name value pair instead of instance variable

I'm trying to implement a gem that is redis wrapper for other library i.e to store the ruby object in the redis.
all work well but what I want is when I do
[Class].all
It give object like this
[#<Peagon:0x007fba589de3a0 #name="a", #omg=false ,#payload="one",#handler="--- one\n...\n"> ,#<Peagon:0x007fba589de1a0 #name="b", #omg=true,#payload="two",#handler="--- two\n...\n">]
but instead I want it to be look like how active record present the object
[#<Peagon name: "a",omg: false ,handler: "--- one\n...\n"> ,#<Peagon name="b", omg: true,handler: "--- two\n...\n">]
The reason for this that I not interested in showing the user the #payload instance variable because that is something set by the other library
so basically like this happen
[My gem]
class Peagon
include SomeModule
attr_accessor :name,:omg,:handler
def initialize(options)
#name = options[:name]
#omg = options
self.payload_object = options[:payload_object]
end
end
Now the [Other Library] has this module in it
module SomeModule
def payload=(object)
#payload ||= object
self.handler = #payload.to_yaml
end
def payload
#payload ||= YAML.load(self.handler)
end
end
NOTE :
Overwriting the payload method from other library is not in my mind
Now is it possible to get what I meant above
Looks like you just want to adjust what irb, the Rails console, and friends will display for objects of your class. If so, they just call inspect:
inspect → string
Returns a string containing a human-readable representation of obj. By default, show the class name and the list of the instance variables and their values (by calling inspect on each of them). User defined classes should override this method to make better representation of obj.
So all you need to do is provide your own inspect implementation, something like:
def inspect
"#<#{class} name: #{#name.inspect} ...>"
end

Ruby Class Return Value

I'm learning Ruby and made a class to help:
class WhatImDoing
def initialize
puts "not doing anything"
end
end
with the output of:
not doing anything
#<WhatImDoing:0xb74b14e8>
I'm curious, what is the second line all about? Is it a reference location for the WhatImDoing object I created? Can I access objects through this location(like a pointer or something)? Etc... Just trying to get a better understanding of Ruby, in general.
Thanks.
The second line is the output of irb, showing the return value of the last statement.
If you set something equal to that value:
> class WhatImDoing
def initialize
puts "not doing anything"
end
def ohai
puts "Ohai"
end
end
> tmp = WhatImDoing.new
=> #<WhatImDoing:0x5cd5a2a9>
You could use it:
> tmp.ohai
Ohai
If you had a custom to_s it would show that instead:
> class WhatImDoing
def to_s
"#{super} kthxbai"
end
endt
> tmp = WhatImDoing.new
=> #<WhatImDoing:0x3e389405> kthxbai
I'm assuming that was the output of irb. Irb tried to print your object, i.e. convert it to a string. Since you didn't provide a custom to_s ("to string") method, your object inherited this one:
http://ruby-doc.org/core-1.9.3/Object.html#method-i-to_s
Returns a string representing obj. The default to_s prints the object’s class and an encoding of the object id. As a special case, the top-level object that is the initial execution context of Ruby programs returns “main.”
Further digging into the source code reveals that the hexadecimal number is, indeed, the memory address occupied by that object instance. There isn't really anything fancy you can do with that information, in Ruby. It's just a convenient way to generate an unique identifier for an object instance.
Yes, it is reference to the object you are creating. Yes, you can access that object.

Cant write string to attr_accessor in ruby

Please tell me what am I doing wrong here. I want to be able to capitalize any string that is being added later in the code through the method titles .
class Book
attr_accessor :book_title
def initialize
#book_title = String.new
end
def titles
book_title.capitalize
end
end
#book = Book.new
puts #book.titles = "steve jobs"
Because when I execute it, I get undefined method `titles=' for #<Book:0x007fbd25813d98 #book_title=""> (NoMethodError)
It's a little unclear as to what you're trying to accomplish. You're adding an attr_accessor for book_title, not for titles (which isn't a variable at all). You need to call
puts #book.book_titles = "Steve Jobs"
in order to set (and print) the title.
If you're trying to pass a title to titles and have that method capitalize the title and set #book_title to that, you need to declare it as an assignment method using =, pass in the parameter title, and actually set #book_title to that. Something like this
def titles= title
#book_title = title.capitalize
end
Currently your titles method only returns the capitalized local variable book_title, which doesn't exist (it needs the # to reference the instance variable).
It's saying "undefined method titles=" because you haven't defined a method named titles=. Instead, attr_accessor (one of Ruby's many misleading names) defines two methods, in your case named book_title and book_title=. Then you add titles. None of these is named titles= (the equal sign is significant).
Your titles method (by the way, you should figure out if it's singular or plural) is redundant with book_title, which will lead to confusion. As someone seeing this code for the first time -- or once again, after a break -- how am I to know which method to call?
You need to decide whether to capitalize the string on the way in (during the setter) or on the way out (during the getter). No matter what you do, I recommend that you stop using attr_accessor for a bit, and just explicitly define a getter and a setter (def title and def title=) until it's clear in your mind what they do. The attr_accessor macro is just a shorthand; you should learn longhand first.

Resources