How can I find a Ruby method dependencies?
You can sort of get this using set_trace_func, but since Ruby is dynamic you would also need test code to call the methods so that the call order is printed.
set_trace_func proc { |event, filename, line, id, binding, klass| puts "#{klass}##{id}" }
In Ruby 2.0, TracePoint is a superior alternative.
p parsed[desc][someKey], in ruby what does p mean?
It's Kernel#p
method.
According to the documentation:
p(obj) → obj click to toggle source
p(obj1, obj2, ...) → [obj, ...]
p() → nil
For each object, directly writes obj.inspect followed by a newline to
the program’s standard output.
What is difference between p and pp?
p
is used to inspect a variable as a debug aide. It works printing the output of the method #inspect
. For example p foo
will output the content of foo.inspect
.
Sometimes you need to debug complex variables or nested variables. In this case p
will output a long line that is hard to understand. Instead, pp
will put try to arrange the content of the variable so that it is easier to understand, for example indenting nested arrays or using one line for each instance variable of a complex object. pp
does this calling the #pretty_inspect
method (the pp
library adds #pretty_inspect
methods to many classes such as String
, Array
or Struct
).
To remember: p
= print, pp
= pretty print.
Global methods in Ruby
For runtime Ruby has special object the main
.
It's some kind of trick that all code runs in the context of this object.
So when you're typing methods like puts
, p
and so on, all of them are calling in the context of self
object and passing to self
object.
And here's the second thing - the access control.
As you probably know, Ruby has keywords like private
, protected
and public
- all of them manage the access of calling methods on object. Ruby is checking this access control only when you're have construction like
<name_of_object>.your_method
and self.your_method
So when you're typing
self.p "something"
Ruby will decline this call because the p
method is private method.
Ruby: is there a keyword to call a method from within itself (analogous to super)?
You can use Kernel#__method__
that returns the name of the current method as a Symbol
. Unlike super
it's not a keyword but a regular method so you have to pass it to send
method along with required arguments in order to call the method.
Here is what __method__
returns:
obj = Object.new
def obj.foo
p __method__
end
obj.foo
# => :foo
And here is an example of class method that dynamically defines factorial methods:
class Foo
def self.define_fact(method_name)
define_method(method_name) do |n|
n > 0 ? n * send(__method__, n - 1) : 1
end
end
end
f = Foo.new
# puts f.fact(5)
# => undefined method `fact' for #<Foo:0x8ede45c> (NoMethodError)
Foo.define_fact :fact
puts f.fact(5)
# => 120
Without __method__
I can't think of any solution that wouldn't involve some kind of eval
that is better to avoid if possible.
Finding out where methods are defined in Ruby/Rails (as opposed to Java)
The Pry gem is designed precisely for this kind of explorative use-case.
Pry is an interactive shell that lets you navigate your way around a program's source-code using shell-like commands such as cd
and ls
.
You can pull the documentation for any method you encounter and even view the source code, including the native C code in some cases (with the pry-doc
plugin). You can even jump directly to the file/line where a particular method is defined with the edit-method
command. The show-method
and show-doc
commands also display the precise location of the method they're acting on.
Watch the railscast screencast for more information.
Here are some examples below:
pry(main)> show-doc OpenStruct#initialize
From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 11
visibility: private
signature: initialize(hash=?)
Create a new OpenStruct object. The optional hash, if given, will
generate attributes and values. For example.
require 'ostruct'
hash = { "country" => "Australia", :population => 20_000_000 }
data = OpenStruct.new(hash)
p data # -> <OpenStruct country="Australia" population=20000000>
By default, the resulting OpenStruct object will have no attributes.
pry(main)>
You can also look up sourcecode with the show-method
command:
pry(main)> show-method OpenStruct#initialize
From: /Users/john/.rvm/rubies/ruby-1.9.2-p180/lib/ruby/1.9.1/ostruct.rb @ line 46:
Number of lines: 9
def initialize(hash=nil)
@table = {}
if hash
for k,v in hash
@table[k.to_sym] = v
new_ostruct_member(k)
end
end
end
pry(main)>
See http://pry.github.com for more information :)
Adding methods when subclassing `Struct`
Why does greeting become a method of the created subclass?
The short answer is: because that's how Struct.new
works.
Why would it work that way? Imagine if it didn't. greeting
would be added to all Structs and that would be bad.
It's passed to the block as an argument.
This is the "how". The "block" is really you defining a function and passing it into new
. The code above is syntax sugar for...
func = Proc.new do |new_class|
p "The new subclass is #{new_class}"
def greeting
"Hello #{name} at #{address}"
end
end
Customer = Struct.new('Customer', :name, :address, &func)
See The Ultimate Guide to Blocks, Procs & Lambdas for more.
Struct.new
runs the proc, passing in the name of the new class, but it runs it in a special way. It runs it as if it were the class Struct::Customer
. It does this (probably) by calling class_eval
to run a proc as if it were defined inside another class.
We can do the same to demonstrate.
class Foo
# Defined inside the Foo class, farewell is a method of Foo.
def farewell
"goodbye"
end
end
# This proc is defined outside the Foo class...
func = Proc.new do
def greeting
"hello"
end
end
# ...but we can run it as if it were.
Foo.class_exec(&func)
dave = Foo.new
p dave.greeting
Many Ruby libraries use this trick, and ones like it.
The block passed to each
is also a proc, but each
just runs it normally passing in each element of the Enumerable.
However, what you're written is rather odd. This...
[1,2,5].each { |x|
public
def m1 a
a + self
end
}[0].m1 3
Is really this.
nums = [1,2,5].each { |x|
public
def m1(a)
a + self
end
}
nums[0].m1(3)
Which is really this.
[1,2,5].each { |x|
public
def m1(a)
a + self
end
}
1.m1(3)
each
returns what it iterated over, so it returns [1,2,5]
. nums[0]
is 1. So we're calling m1
on an Integer. Why would m1
be defined on an Integer?
It isn't! It's actually defined on Object
. Why?
Everything is an object in Ruby, there always has to be a self
. When outside a class in Ruby, self
is main
which is an Object
. m1
is a method of Object
.
p self # main
p self.class # Object
Integer
inherits from Object
so it can call m1
. We can see this using method
. Everything is an object, including Methods.
p self.method(:m1) #<Method: Object#m1>
p 1.method(:m1) #<Method: Integer(Object)#m1>
That says m1 is defined on Object and Integer inherits it from Object.
But why is it private? Any method defined like this is defined on Object
. (Almost) everything inherits from Object
. If it were public, methods in a script would be polluting other classes. So they're private. This is a special case only for main.
Defining m1
in each
is a red herring. each
is just running the code but doing nothing special. You can just define it in main
(ie. Object) and get the same effect.
public
def m1(a)
p a + self
end
p self.method(:m1)
p 1.method(:m1)
In Ruby, is there an Array method that combines 'select' and 'map'?
I usually use map
and compact
together along with my selection criteria as a postfix if
. compact
gets rid of the nils.
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}
=> [3, 3, 3, nil, nil, nil]
jruby-1.5.0 > [1,1,1,2,3,4].map{|n| n*3 if n==1}.compact
=> [3, 3, 3]
Related Topics
Gem Install Wrong Number of Arguments (Given 4, Expected 1)
Rails Object#Blank? VS. String#Empty? Confusion
Ruby Getting Deeply Nested JSON API Data
Deep Convert Openstruct to JSON
Initializing a Hash with Empty Array Unexpected Behaviour
Installing Ruby Using Rvm Fails, Without Trace
How to Combine Multiple Arrays of the Same Size in Ruby
Why Non-Explicit Splat Param Plus Default Param Is Wrong Syntax for Method Definition in Ruby 1.9
How to Fix Ruby Script Which Fails with Encoding Error: "\Xd8" on Us-Ascii
Disabling Irb Autocomplete on Heroku
Regexp Search Through a Very Large File
Iterate Through Array of Hashes in Ruby
Algorithm to Shuffle an Array Randomly Based on Different Weights
Uml Sequence Diagram - How to Represent Method Arguments That Instantiate Objects
Why Doesn't Array Override the Triple Equal Sign Method in Ruby
Rmagick How to Convert Image in Memory
Ternary Expression with "Defined" Returns "Expression" Instead of Value