I am new to Ruby, so go easy :).
Anyway, I am trying to work out some stuff in the chef-provisioning-aws gem. One thing in particular is that there is an object called:
new_resource.driver.ec2_client
When I do an inspect on that object it returns exactly this:
#<Aws::EC2::Client>
So, my question is: what is this? What sort of "thing" in Ruby starts with a pound sign (hash) and has <...> in it?
Much appreciated.
The output of Ruby's inspect method is roughly like this unless you override it:
"#<#{self.class}:0x#{self.object_id.to_s(16)}"
So in other words: "#<ClassName:0xobject_id in hex>".
class Foo ; end
Foo.new.inspect
#=> "#<Foo:0x007ffe0eeea520>"
It seems that for Aws::EC2::Client it was overriden and does not include the object id.
It's the default implementation of the inspect method (although then the object ID should be included). It may be useful in some situations to implement your own method, so you can get an instant overview of what you want to know about this object. The # is just a random character and has no further meaning here.
Related
This is a bit of a weird question, but I'm not quite sure how to look it up. In our project, we already have an existing concept of a "shift". There's a section of code that reads:
foo.shift
In this scenario, it's easy to read this as trying to access the shift variable of object foo. But it could also be Array#shift. Is there a way to specify which class we expect the method to belong to? I've tried variations such as:
foo.send(Array.shift)
Array.shift(foo)
to make it more obvious which method was being called, but I can't get it to work. Is there a way to be more explicit about which class the method you're trying to call belongs to to help in code readability?
On a fundamental level you shouldn't be concerned about this sort of thing and you absolutely can't tell the Array shift method to operate on anything but an Array object. Many of the core Ruby classes are implemented in C and have optimizations that often depend on specific internals being present. There's safety measures in place to prevent you from trying to do something too crazy, like rebinding and applying methods of that sort arbitrarily.
Here's an example of two "shifty" objects to help illustrate a real-world situation and how that applies:
class CharacterArray < Array
def initialize(*args)
super(args.flat_map(&:chars))
end
def inspect
join('').inspect
end
end
class CharacterList < String
def shift
slice!(0, 1)
end
end
You can smash Array#shift on to the first and it will work by pure chance because you're dealing with an Array. It won't work with the second one because that's not an Array, it's missing significant methods that the shift method likely depends on.
In practice it doesn't matter what you're using, they're both the same:
list_a = CharacterArray.new("test")
list_a.shift
# => "t"
list_a.shift
# => "e"
list_a << "y"
# => "sty"
list_b = CharacterList.new("test")
list_b.shift
# => "t"
list_b.shift
# => "e"
list_b << "y"
# => "sty"
These both implement the same interfaces, they both produce the same results, and as far as you're concerned, as the caller, that's good enough. This is the foundation of Duck Typing which is the philosophy Ruby has deeply embraced.
If you try the rebind trick on the CharacterList you're going to end up in trouble, it won't work, yet that class delivers on all your expectations as far as interface goes.
Edit: As Sergio points out, you can't use the rebind technique, Ruby abruptly explodes:
Array.instance_method(:shift).bind(list_b).call
# => Error: bind argument must be an instance of Array (TypeError)
If readability is the goal then that has 35 more characters than list_b.shift which is usually going dramatically in the wrong direction.
After some discussion in the comments, one solution is:
Array.instance_method(:shift).bind(foo).call
Super ugly, but gets across the idea that I wanted which was to completely specify which instance method was actually being called. Alternatives would be to rename the variable to something like foo_array or to call it as foo.to_a.shift.
The reason this is difficult is that Ruby is not strongly-typed, and this question is all about trying to bring stronger typing to it. That's why the solution is gross! Thanks to everybody for their input!
I have an object, and I want to dump all its information.
For debugging purpose, can I convert it to json or other suitable format?
I know using p object, sometimes can print out all its information; but not always. So I am asking is there other ways when p object becomes invalid
Try pry
It is excellent for exploring objects. Especially large objects because it has paging. The objects are also color coded to make it more readable.
Steps:
install pry
Add require 'pry' to the script file you want to debug
Add binding.pry below the object declaration of anywhere the object is in scope
Run your script
This will pop open the pry console with access to your object
Type in the object name
'ls object' will list all the instance variables of the object
There's couple ways you can go. Using json from the standard lib is one way to convert an object to json.
this converts an object in ruby to a json string:
require "json"
h = Hash.new(name: "example")
JSON.dump(h)
But you seem to be wanting to inspect an object in detail. The best solution is probably the "Pry" gem that others have suggested if you really need a lot of detail.
so after installing pry you can "cd" into objects and inspect instance variables public/private methods and the source code of methods/classes, etc. its really great stuff.
require "pry"
cd SomeObject
ls # this shows you everything defined in the object.
The problem with object.inspect that others have suggested is that it can be overriden, often is, and thus will oft not show you enough information. So it depends on what you want to find out.
puts o.instance_variables #=> shows all an objects instance variable names
puts o.instance_variable_get :#some_var #=> returns the value held by #some_var
puts o.methods - Object.methods #=> roughly speaking, shows you the methods defined on an object itself and not inheritted from parent objects
Unfortunately there's not a perfect answer here, but for debugging purposes I personally think nothing beats out pry especially with the pry debugger addon gem (forgot actual name) that allows you to step through the call stack.
You can use "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). "
Example:
puts object.inspect
you can try puts my_object.as_json.to_json
I am new to Ruby and am learning from reading an already written code.
I encounter this code:
label = TkLabel.new(#root) do
text 'Current Score: '
background 'lightblue'
end
What is the semantics of the syntax "do" above?
I played around with it and it seems like creating a TkLabel object then set its class variable text and background to be what specified in quote. However when I tried to do the same thing to a class I created, that didn't work.
Oh yeah, also about passing hash into function, such as
object.function('argument1'=>123, 'argument2'=>321)
How do I make a function that accepts that kind of argument?
Thanks in advance
What you're looking at is commonly referred to as a DSL, or Domain Specific Language.
At first glance it may not be clear why the code you see works, as text and background are seemingly undefined, but the trick here is that that code is actually evaluated in a scope in which they are. At it's simplest, the code driving it might look something like this:
class TkLabel
def initialize(root, &block)
#root = root
if block
# the code inside the block in your app is actually
# evaluated in the scope of the new instance of TkLabel
instance_eval(&block)
end
end
def text(value)
# set the text
end
def background(value)
# set the background
end
end
Second question first: that's just a hash. Create a function that accepts a single argument, and treat it like a hash.
The "semantics" are that initialize accepts a block (the do...end bit), and some methods accepting string parameters to set specific attributes.
Without knowing how you tried to do it, it's difficult to go much beyond that. Here are a few, possible, references that might help you over some initial hurdles.
Ruby is pretty decent at making miniature, internal DSLs because of its ability to accepts blocks and its forgiving (if arcane at times) syntax.
Is there a nice, recommended way to get the name of the file that called a method? I don't want to pass __FILE__ every time. The closest thing I've found is taking the first element of Kernel.caller, which is okay but has the calling line number appended like "test.rb:7". It's easy enough to strip off, but using it seems like something that might be dependent on the interpreter or might change in the future.
In Ruby 2.0+ you can do this using Kernel#caller_locations. It's very similar to caller, with the added benefit that you don't need to parse out the file name manually, since it returns Thread::Backtrace::Location objects instead of Strings:
file1.rb:
def some_method
puts caller_locations.first.path
end
file2.rb:
require_relative './file1'
some_method
Shell:
$ ruby file2.rb
file2.rb
Perhaps it's safer than you think? I found this other post http://snippets.dzone.com/posts/show/2787 where someone did something similar to what you're suggesting...
I was trying to add a method to the String class. This method should mutate the current string (of course it would be possible to write a not mutating version but I'd prefer the mutating one). I had no idea how to do this and after some googling I found the method rb_str_modify which makes a given string mutable. That's exactly what I need but I couldn't find an equivalent in the Ruby language. Did I miss something or is there really no possibility in the language itself?
Reopening Classes
All classes in Ruby are open for extension so you can simply do this ...
Class String
def my_new_method(args)
# Some sort of modification to self
self.replace "SOME CALCULATED VALUE"
end
end
... somewhere in your code. I've modified string a few times in different applications - usually I just put the modifications into one particular module, making it easy to reuse them or remove them as required.
Modifying individual objects
Modifying a class in its entirety is dangerous as it's very difficult to identify all of the consequences - I once broke Merb by modifying a method in the String class. It's much safer to modify particular objects. This is easy in Ruby - you use the extend keyword. You define a module, add your function and then modify the target object. This example ...
module Humor
def tickle
"hee, hee!"
end
end
a = "Grouchy"
a.extend Humor
a.tickle ยป "hee, hee!"
is taken from the Pickaxe book
Chris