How to Modify Class Print Output - ruby

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..."

Related

Metaprogramming in Ruby with derived classes

I'm trying to write a method that prints class variable names and their values. As an example:
class A
def printvars
???
end
end
class <<A
def varlist(*args)
???
end
end
class B < A
varlist :c
def initialize(c)
#c = c
end
b = B.new(10)
b.printvars()
And I would like the output to be c => 10. But I don't know what goes in the ???. I've tried using a self.class_eval in the body of varlist, but that won't let me store args. I've also tried keeping a hash in the class A and just printing it out in printvars, but the singleton class is a superclass of A and so has no access to this hash. So far everything I've tried doesn't work.
I think something similar must be possible, since Rails does something related with its validates_* methods. Ideally I could make this work exactly as expected, but even a pointer to how to print just the variable names (so just c as output) would be most appreciated.
You might like this answer: What is attr_accessor in Ruby?
Basically, as you surmised, varlist needs to be a class method which takes a variable list of arguments (*args). Once you have those arguments you could try any number of things using send, respond_to?, or maybe even instance_variable_get. Note, none of those are really recommended, but I wanted to answer your question a bit.
The other half is that you should probably look into method_missing in order to understand how things like validates_* are working. The * part necessitates that you do something like method_missing because you can't actually do module_eval until you know what you're looking for. In the case of the magic rails methods, you don't necessarily ever know what you're looking for! So we rely on the built in method_missing to let us know what got called.
For funzies, try this in IRB:
class A
def method_missing(method, *args, &block)
puts method, args.inspect
end
end
A.new.banana(13, 'snakes')
A.new.validates_serenity_of('Scooters', :within => [:calm, :uncalm])
Does that help?
Just use Module#class_variables
As far as I can tell, you're vastly over-complicating this. All you need is the pre-defined Module#class_variables method. You can call this directly on the class, or invoke it through self if you want to bind it to an instance of the class. For example:
class Foo
##bar = "baz"
def show_class_variables
self.class.class_variables
end
end
Foo.class_variables
#=> [:##bar]
foo = Foo.new
foo.show_class_variables
#=> [:##bar]

added instance variable not shown with inspect in 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.

Within a Ruby method, should I create a proc or a method?

Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.

Ruby: define a class that returns something other than itself when an instance is called without any methods

I'm wondering if there's a way to return an object instead of a string when calling an object without any methods.
For instance:
class Foo
def initialize
#bar = Bar.new
end
end
Is there any way to define the Foo class so that the following happens:
foo = Foo.new
foo #returns #bar
In the specific case I'm interested in I'm using a presenter in a Rails view. The presenter sets up one main object and then loads a bunch of related content. The important part looks like this:
class ExamplePresenter
def initialize( id )
#example = Example.find( id )
end
def example
#example
end
...
end
If I want to return the example used by the ExamplePresenter I can call:
#presenter = ExamplePresenter.new(1)
#presenter.example
It would be nice if I could also return the example object by just calling:
#presenter
So, is there a way to set a default method to return when an object is called, like to_s but returning an object instead of a string?
If I understand correctly, you want to return the instance of Example when you call the ExamplePresenter instance. Such a direct mechanism does not exist in any language, and even if it did, it would block all access to the ExamplePresenter instance and its methods. So it is not logical.
There is something you can do however. You can make the ExamplePresenter class delegate methods to the Example instance inside it. Effectively you do not get a real Example from #presenter but you get an ExamplePresenter that passes all eligible methods into its internal Example effectively acting in behalf of it.
Some ways of doing this is:
method_missing
class ExamplePresenter
… # as defined in the question
def method_missing symbol, *args
if #example.respond_to?(symbol)
#example.send(symbol, *args)
else
super
end
end
end
This will pass any method call down to the internal Example if the ExamplePresenter cannot respond to it. Be careful, you may expose more than you want of the internal Example this way, and any method already defined on ExamplePresenter cannot be passed along.
You can use additional logic inside method_missing to limit exposure or pre/post process the arguments/return values.
Wrapper methods
You can define wrapper methods on ExamplePresenter that do nothing but pass everything to the internal Example. This gives you explicit control on how much of it you want to expose.
class ExamplePresenter
… # as before
def a_method
#example.a_method
end
def another_method(argument, another_argument)
#example.another_method(argument, another_argument)
end
end
This gets tedious fast, but you can also add logic to alter arguments before passing it along to the Example or post process the results.
You can also mix and match the above two methods
Delegator library
There is a library in Ruby stdlib called Delegator built exactly for this purpose. You may look into it.
Although this is not recommended, you can do:
class Foo
def self.new
#bar = Bar.new
end
end
If you actually do need to create an instance of Foo, then
class << Foo
alias original_new :new
end
class Foo
def self.new
self.original_new # It will not be useful unless you assign this to some variable.
#bar = Bar.new
end
end

In Ruby, how to write code inside a class so that getter foo and setter self.foo = ... look more similar?

In Ruby, inside a class's instance method, we use a getter by
foo
and we use a setter by
self.foo = something
One doesn't need to have a self. and the other does, is there a way to make them look more similar, and not using something like self.foo as the getter, as it also looks verbose.
(update: note that getter and setter may simply get or set an instance variable, but they might also do a lot of work, such as going into the DB and check the existence of a record and if not, create it, etc)
Since local scope takes precedence, when you say foo = something, a local variable foo will be created and assigned the contents of something.
The reason you can write foo in order to use the getter is because Ruby will move up in scope when it can't find a variable with that name and it will eventually find the method.
If there is a local variable with the same name as the getter method, Ruby will use its value instead:
class Foo
attr_accessor :foo
def initialize
#foo = :one
end
def f
foo = :two
foo
end
end
Foo.new.f
# => :two
In order to make it clear that you want to access the setter, you must write self.foo = something. That will tell Ruby you want to execute the foo= method on the self object with something as parameter.
If you are willing to break the conventions, you can write your setters using jQuery style, using the same method for getter and setter, depending of whether it has arguments or not:
def foo *args
return #foo if args.empty?
#foo = args.first
end
# => nil
foo
# => nil
foo(:bar) # foo = :bar
# => :bar
foo
# => :bar
As far as I know, there isn't a way around this in Ruby. I'm pretty confident this is simply how Ruby evaluates expressions.
When given a value, Ruby will first check if there is a local variable within the context which matches the one being called. If there is (perhaps 'foo' in your case), that will be the value used. If there is no such value, then Ruby will try to look up the value as a method call (falling through to "self" as the caller). If no such method exists in the look up path, an error will be raised.
The need to use "self" in the setter is to avoid Ruby setting the value as a local variable, while the lack of the use of "self" only works in the getter instance when there is no local variable of the same name being used in that context. It is probably better and clearer, albeit slightly more verbose, to be explicit with your use of self as to avoid confusion about where values are coming from.

Resources