The un-googleable ruby's method method - ruby

There is apparently a ruby method called method and I can't find any docs or examples on it so far. Could someone please post a few useful annotated examples?

there is docs about that method in ruby api documentation
http://www.ruby-doc.org/core-1.9.3/Object.html#method-i-method
there is also method_defined? which could be also useful if you need method it self
http://www.ruby-doc.org/core-1.9.3/Module.html#method-i-method_defined-3F

I've mostly used it to look up source location of a specific method. (example run in irb on ruby-1.9.2-p290)
class Thing
def foo
end
end
Thing.new.method(:foo).source_location
=> ["(irb)", 2]
Thing.new.method(:foo).owner
=> Thing

It's part of Object and is documented here:
http://www.ruby-doc.org/core-1.9.3/Object.html#method-i-method
The class Method is documented here, and gives some examples:
http://www.ruby-doc.org/core-1.9.3/Method.html

One of the best uses of the bound method object returned by Object#method is for blocks. The return result of that method can be converted to a block argument. Imagine you have:
class Converter
def convert_item(item)
item.transmorph
end
end
Then you could do this
c = Converter.new
elements.map(&c.method(:convert_item))
or when you are within the convertor
elements.map(&method(:convert_item))
which IMO is more elegant than the explicit block creation syntax. It also supports to_proc so you can do this
some_object.callback = my_handler.method(:activate).to_proc
and then in some_object you can do
#callback.call(data)

Object#method, is this what you are looking for?
http://www.ruby-doc.org/core-1.9.3/Object.html#method-i-method

Related

Using the Class itself as a Method

Today I came across the Pathname class in Ruby and noticed that you could directly call the class itself as a method (which would basically return a new instance):
Pathname("some/path")
# => #<Pathname:some/path>
I've been trying to replicate the same thing with my CustomClass but haven't been successful. I don't know what these methods are called and I can't find any Ruby code that gives me an idea on how to do this. My Question is how do I use the Class name as method?
Things I've tried so far:
Defining self.self()
Defining self.class()
Using the class << self syntax
Googling - But it just returns comparisons of class methods vs instance methods
This isn't using the class itself. This is calling a method in Kernel with the same name as the class. It's generally discouraged to do it yourself as you pollute almost all objects with new methods and leads to confusion (as you already see).
Here is the documentation for the method. There are a few others like Array, Hash, String, etc.
What you're looking for is a conversion method to coerce the input to the instance of the class.
It is not a method of the class itself, but a method in Kernel module. So in order to be able to use the form of MyClass(value) you should add the method to Kernel module:
module Kernel
def Foo(value)
# you can implement any logic here
value.is_a?(Foo) ? value : Foo.new(value)
end
module_function :Foo
end
class Foo
def initialize(bar)
#bar = bar
end
end
baz = Foo('bar')
#=> #<Foo:0x007fd4e5070370 #bar="bar">
Foo(baz)
#=> #<Foo:0x007fd4e5070370 #bar="bar">
baz == Foo(baz)
#=> true
This is not a class call, but a shortcut. And the trickiest part - it was defined for a Kernel module to be available everywhere in the form as you just specified.
Please proceed to the link of the official docs. There you can see, that requiring a Pathname module, it extend Kernel module to add the method of the same name.
To be honest, I strongly recommend against extending Kernel with your own method. Or at least to use refinements

How to get the method which is handling a method call

I have an app which uses Ruby 1.8. 6 in a Rails 2.2.2 app.
It has many definitions of the method url_for in various parts of the code base (classes, modules etc).
When debugging, I'd like to see in the log which method handles a specific call to url_for. E.g.,
foo = "bar"
baz = url_for(foo)
#would like to log the location of the url_for method which actually
#handled the call, here.
It's fine if the only way to do this is to raise an exception inside url_for and look at the stack trace, eg
baz = url_for(something_which_wont_raise_here_but_will_raise_inside_the_url_for_method)
To go further, what if the method is being called on an instance of a (heavily patched) class:
foo = #baz.bar("qux")
EDIT: I didn't specify that it was Ruby 1.8.6 in my question, and it looks like i can't use the .source_location method. Very sorry about not specifying the version earlier! Does anyone have any other ideas?
It sounds like you want to do
method(:url_for)
to get a Method object, and then use source_location to find out where it was defined
You can use method and source_location methods chain to get the location of the method definition.
For example:
If you do:
method(:url_for).owner
It will give you the module/class in which the method is defined. This should be enough to let you identify the method (unless the same method is redundantly defined in the same module multiple times). You can then look at the definition of url_for in that module/class.

Extract information about method receiver from stack

If we call caller method, we get something like:
prog.rb:3:in `a'
prog.rb:6:in `b'
prog.rb:9:in `c'
This is helpful for humans, but if I wanted to analyze the stack programmatically, not really, as two methods called :a may be entirely unrelated.
Is there any way/method to extract information about the receiver of the methods (like its class or object id) as well? For example:
prog.rb:3:in `Klass#a'
prog.rb:6:in `Modoole#b'
prog.rb:9:in `OtherKlass#c'
Formatting is only an example; this info might be an Array or anything.
I'm trying to emulate this with TracePoint, but forming a separate stack is a bad solution. Is there any Ruby way I missed in the docs?
There's an alternative to Kernel#caller named Kernel#caller_locations, that returns an array of Thread::Backtrace::Location objects. According to the manual, these should in theory be able to give you this information through the #label method.
Returns the label of this frame.
Usually consists of method, class, module, etc names with decoration.
After trying this out however, I need to question the term usually in the docs, because it seems to only return the method name still. Unless usually means it works for you, there seems to be no way of accomplishing this as of now.
Edit:
As per comment, one case that satisfies the condition of usually is when the method call is coming from within a Class or Module body:
class A
def trace
puts caller_locations.first.label
end
end
class B
A.new.trace
end
#=> <class:B>
module C
A.new.trace
end
#=> <module:C>

Why use Rails public_method?

I am reading through Avdi Grimm's book 'Objects in Rails' and he uses the method public_method and I dont understand why. Here is the code example:
class Blog
# ...
attr_writer :post_source
# ...
private
def post_source
#post_source ||= Post.public_method(:new)
end
end
Why would you call Post.public_method(:new) and not Post.new? Do these methods do anything different or are they exactly the same? Thanks for the help.
Post.new
is not equivalent to
Post.public_method(:new)
The former is an invocation of method new, which, by default, creates a new Post object. The latter, however, does not call new immediately. It merely prepares it to be called later. I haven't read that particular book, but if you look around in the associated source code, you'll see this line
#post_source.call # maybe some params are passed here
This is where Post#new finally gets called.
Documentation: Object#public_method, Object#method.
Post.public_method(:new) and Post.new are different things. The latter creates an instance of Post. The former creates an instance of Method, which is not the result of applying such method but is an abstraction of the method itself. You can take out the result of it by doing call on it later.
Post.public_method(:new) may be replaced by Post.method(:new), unless there is a private or protected method named new. It is just making sure not to refer to such methods if there are any.

In how many ways can methods be added to a ruby object?

When it comes to run time introspection and dynamic code generation I don't think ruby has any rivals except possibly for some lisp dialects. The other day I was doing some code exercise to explore ruby's dynamic facilities and I started to wonder about ways of adding methods to existing objects. Here are 3 ways I could think of:
obj = Object.new
# add a method directly
def obj.new_method
...
end
# add a method indirectly with the singleton class
class << obj
def new_method
...
end
end
# add a method by opening up the class
obj.class.class_eval do
def new_method
...
end
end
This is just the tip of the iceberg because I still haven't explored various combinations of instance_eval, module_eval and define_method. Is there an online/offline resource where I can find out more about such dynamic tricks?
Ruby Metaprogramming seems to be a good resource. (And, linked from there, The Book of Ruby.)
If obj has a superclass, you can add methods to obj from the superclass using define_method (API) as you mentioned. If you ever look at the Rails source code, you'll notice that they do this quite a bit.
Also while this isn't exactly what you're asking for, you can easily give the impression of creating an almost infinite number of methods dynamically by using method_missing:
def method_missing(name, *args)
string_name = name.to_s
return super unless string_name =~ /^expected_\w+/
# otherwise do something as if you have a method called expected_name
end
Adding that to your class will allow it to respond to any method call which looks like
#instance.expected_something
I like the book Metaprogramming Ruby which is published by the publishers of the pickaxe book.

Resources