How to inspect a module - ruby

How can I find out the constructs (methods, constants, etc.) defined in a module?
Let's say there's require 'observer', and I would like to see all that are defined within 'observer'. How can I?

Short answer: You can't, not with absolute certainty.
Long answer: This a product of how Ruby is a very dynamic language at its core and imposes almost no constraints on what a require statement might do. Any number of modules and classes can be created by a library, and there's no requirement for these to be grouped together neatly.
Even if you go through the trouble of taking a snapshot of all defined classes and methods before you require it, and then another one after to find out what's been added there's no assurance you've captured them all. Some classes might be loaded or defined well after the require statement is finished.
The best way to find out is to read through the source. There you'll see all the different modules and classes that could be defined even if they're not triggered by your code.
Reflection tools like methods help to a degree, but it's also highly misleading. Methods can be defined at a later point in time, you may need to exercise the code more thoroughly for them to show up.

If you use pry, simply do ls ModuleName
ls shows all the available methods and instance variables of a certain module or class or instance. More about pry: http://pryrepl.org/
Or you can do
ModuleName.instance_methods to get instance_methods
ModuleName.instance_variables to get instance_variables
As another answer state, it's almost impossible (still doable in a brittle way) to get a full picture of what you require by just an arbitrary require
imo, this kind of implementation itself is brittle and prone to error, unless its your own module and you have full control of the API. But still not a good idea.

If I do not understand the question wrong.
You can do like this, to read the property of Module.
Example:
1st Version:
require "nokogiri"
p Nokogiri.methods # It will print for you all methods in that Module,
# also available methods from ruby.
2nd Version
x = require "nokogiri"
p x.methods #available methods there private, public, protected methods and etc...
p x.private_methods # prints bunch of private methods, [:Nokogiri]

You want to execute Observer methods from outside the module you wish to examine. Here is an example of what you might do.
module Observer
def self.show_all(mod)
puts "owner of methods = #{mod.methods(false)}"
puts "owner of instance methods = #{mod.instance_methods(false)}"
puts "instance variables = #{mod.instance_variables}"
puts "ancestors = #{mod.ancestors}"
puts "included modules = #{mod.included_modules}"
end
end
module A
module B
include Comparable
#a = 1
def self.b; end
def c; end
module C
end
end
end
Observer.show_all(A::B)
# owner of methods = [:b]
# owner of instance methods = [:c]
# instance variables = [:#a]
# ancestors = [A::B, Comparable]
# included modules = [Comparable]
class D; end
class E<D; end
class F<E
include Comparable
#a = 1
def self.e; end
def f; end
end
Observer.show_all(F)
# owner of methods = [:e]
# owner of instance methods = [:f]
# instance variables = [:#a]
# ancestors = [F, Comparable, E, D, Object, Kernel, BasicObject]
# included modules = [Comparable, Kernel]

Related

best way to organize a long piece of code in ruby refinement block

module Access
def last
self[-1]
end
def start_end
self[0] + last
end
end
module StringExt
refine String do
include Access
end
end
using StringExt
puts 'abcd'.last # => d
puts 'abcd'.start_end
When a class being refined with too many connected methods, I think it is better to extract them to a module. However, in above example which demos a problem when one method calls another(see the last statement), and it produces following error.
in 'start_end': undefined local variable or method 'last' for "abcd":String (NameError)
Similar issue was solved using a global variable, which also works for my example. But I'm seeking another better way to organize inter-called methods being refined and avoid a global thing.
How would advice a better way to organize those methods?
Here's a general pattern I ended up using. Basically I found no workaround for using global identifiers at some level. But this can be done fairly cleanly by making those globals classes/modules. This will be more clear as an example:
module StringPatches
def self.non_empty?(string)
!string.empty?
end
def non_empty?
StringPatches.non_empty?(self)
end
def non_non_empty?
!StringPatches.non_empty?(self)
end
refine String do
include StringPatches
end
end
class Foo
using StringPatches
puts "asd".non_empty? # => true
puts "asd".non_non_empty? # => false
end
The class methods on StringPatches don't get exported to using. But since classes/modules are constants (globals) they can be accessed from anywhere.

How to detect my anonymous modules in ancestors of some class

During long run I prepend foreign classes with my anonymous modules (that are being created on the fly.)
At some point, given an instance of arbitrary class, I need to list my anonymous modules, prepended to it. Unfortunately, Module#new, unlike Class#new, does not accept a parent parameter (in other words, they cannot all have a same common dummy parent, that I could use to sieve my modules out of all ancestors.)
I could define a specific my_litmus_dummy_method on each of my anonymous modules and check for it while ancestors.select, but this is ugly.
I could include DummyLitmusModule in each of my anonymous modules and check for it being an ancestor while ancestors.select, but this is ugly either.
So, my question is: is there any elegant way to mark my anonymous modules so that later on I could easily sieve them out of all modules list?
UPD Code example
def patch_class klazz
klazz.send :prepend, Module.new { define_method(:my_method) {} }
end
...
# load list of classes from somewhere and patch them
classes = my_parse_yaml('config.yml')
classes.each do |c|
patch_class c
end
...
# somewhere in other place
instance.patches # ⇐ I want to implement this
At this point I need^W want to know, what methods were patched. I kinda reimplement alias_method_chain from Rails and I want to report the “usages” to my interface user.
What about patching Module#prepend?
class Module
attr_reader :mods_prepended
alias :old_prepend :prepend
def prepend(*mods)
#mods_prepended =|| {}
(#mods_prepended[self] =|| []).concat(mods)
end
old_prepend(*mods)
end
class C
def patches
Module.mods_prepended[self.class]
end
end
Then the desired information is given by:
C.new.patches
Store your anonymous modules somewhere and then you will be able to find them:
patches = [Module.new] # some other module
c = Class.new
m = Module.new
c.prepend m
patches << m
instance = c.new
used_patches = patches.select{|p| instance.is_a? p}

Why is Ruby include polluting unrelated classes?

I am really confused why the methods in modules B and C are mixed in to the class in module A when I use include C. Does include somehow recursively mix in with all classes below the namespace where it is called?
module A
class AClass
def a_method_
end
end
end
module B
extend self
def b_method_
end
end
module C
extend self
include B
def c_method_
puts A::AClass.new.methods.grep /_method_/
end
end
C.c_method_
puts "----"
include C
c_method_
With the result that before the include, the AClass instance correctly only has method a_method_, but after the include it has access to the other two methods as well.
a_method_
----
a_method_
c_method_
b_method_
Can someone please help explain this?
If you change the tail end of your code to this:
C.c_method_
puts self.inspect
puts "----"
include C
c_method_
you should help you see what's going on. That will give you this output:
a_method_
main
----
a_method_
c_method_
b_method_
So what is this main business? Chuck has a nice summary over in this answer:
Everything in Ruby occurs in the context of some object. The object at the top level is called "main". It's basically an instance of Object with the special property that any methods defined there are added as instance methods of Object (so they're available everywhere).
That means that saying this at the top level:
include C
is the same as saying:
Object.send(:include, C)
Adding things to Object pollutes everything.
You might find this illuminating:
puts Object.instance_methods.grep /_method_/
# c_method_
# b_method_
Your methods have been added to everything, not just AClass! And to really demonstrate the weirdness, try changing that last bit to:
class D
include C
puts Object.instance_methods.grep /_method_/
end
No more output! You've stumbled upon one of the weird, intentional behaviors of Ruby's main (the implicit receiver when nothing else is specified). The basic motivation is that if you define a method in main, you want to be able to call it anywhere:
def foo
end
# now all of these work:
class A
foo
end
module B
foo
end
A.new.instance_eval { foo }
A.singleton_class.class_eval { foo }
This isn't about scope resolution either; if you change that to foo = :bar you'll get NameErrors. This is for stuff like puts and gets where you generally don't care who the receiver is when you call them. But this behavior doesn't jive at all with Ruby's object model, so matz hacked it in: every method defined in main gets added to Object as an instance method. Since everything is an object, the rest works as expected.

Ruby Classes within Classes (or Modules within Modules)

As I'm reading different Ruby books, I've noticed that Ruby classes can be defined within other Ruby classes or modules. Here's an example of a class within a class:
class Outerclass
def foobar
puts "FOOBAR"
end
class Innerclass
def barfoo
puts "BARFOO"
end
end
end
Here's some code that I ran in IRB to try to understand this conceptually:
oc = Outerclass.new # => #<Outerclass:0x00000100a46478>
Outerclass.instance_methods(false) # => [:foobar]
ic = Outerclass::Innerclass.new # => #<Outerclass::Innerclass:0x00000100a0b120>
ic = Outerclass::Innerclass.instance_methods(false) # => [:barfoo]
Here are my questions:
When the ruby interpreter first encounters my Class definition code above, does it go through the methods I've written and store it somewhere? I know that the instance method "foobar" doesn't actually get run since there's no call being made to it within the Outerclass definition.
Piggybacking off the 1st question, what about when Ruby encounters the class Innerclass? What happens here?
In general, what are some reasons why you would want to have classes within classes? Are there any advantages to doing this?
Does an instance of Outerclass know anything about the class Innerclass?
Does an instance of Innerclass know anything about the class Outerclass?
Appreciate any help you can provide!
When the interpreter is going through this file, it is assigning classes like this:
OuterClass = Class.new do
def foobar
puts "FOOBAR"
end
InnerClass = Class.new do
def barfoo
puts "BARFOO"
end
end
end
So when Ruby encounters the nested class, it assigns it to constant InnerClass which is assigned to constant OuterClass They have no relation to each other whatsoever.
The InnerClass has no inheritance to OuterClass:
InnerClass.ancestors
=> [InnerClass, Object, Kernel, BasicObject]
When you call OuterClass::InnerClass constant you are refering to the InnerClass constant that is namespaced under the OuterClass contstant which equals the Class.new statement assigned to it.
A good book to read about this is "Metaprogramming Ruby". It goes into the details of classes, singletons, modules etc.
Jörg W Mittag put it best in his comment on Michael Papile's answer:
There is no inner and outer class. There are just two completely and utterly unrelated classes. One just happens to be assigned to a constant namespaced inside the other.

Writing Ruby Libraries - hiding methods from outside the module

I'm writing a Ruby library which has a module with a bunch of classes inside it. Many of these classes need to be usable and modifiable by calling scripts, but I don't want (some of) the initializers to be visible/callable:
module MyLib
class Control
def initialize
# They can use this
end
def do_stuff
Helper.new('things')
end
end
class Helper
# Shouldn't be visible
def initialize(what)
#what = what
end
def shout
#what
end
end
end
c = MyLib::Control.new
h = c.do_stuff
p h.shout
# => "things"
# ^ All of this is desired
# v This is undesirable
p MyLib::Helper.new('!')
# => <MyLib::Helper #what='!'>
If it's a simple thing, then I'd also appreciate the generated RDoc not even include the .new method for the Helper class either. Any ideas?
Thanks for reading!
My original answer was completely wrong, as #Matthew pointed out. But there are other workarounds. For instance, you can assign an anonymous class to a class variable on Control, and still define methods as normal by using class_eval:
module MyLib
class Control
def initialize
end
def do_stuff
##helper.new('things')
end
##helper = Class.new
##helper.class_eval do
def initialize(what)
#what = what
end
def shout
#what
end
end
end
end
The snippet
c = MyLib::Control.new
h = c.do_stuff
p h.shout
still writes "things", but now there's no way to access ##helper except through the class variable. If someone really wants to access it my reopening the Control class or using class_eval, there's nothing to stop them, but that's just something you have to deal with in a dynamic language.
I chose to assign the anonymous class to a class variable so that it would only be created once; but if you don't care about redefining the anonymous class many times, there's no reason it couldn't be an instance variable.
Ruby has access control.

Resources