Related
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]
I include and extend some modules into my class.
I put binding.pry then step into it. Use self.methods to list all methods I have.
But the list is too long , How could I list the methods only in the modules I include. Excepts the methods in my self.class and the methods from ancestors like inspect to_s , ...
include SnapshotsHelper
extend SnapshotsHelper
Thanks
I think something like below you are looking for :
when you will include modules
module A
def meth1;end
def meth2;end
end
module B
def meth11;end
def meth21;end
end
class C
include A,B
end
list = C.included_modules.each_with_object({}) do |m,ob|
module_arry = m.instance_methods
ob[m]=C.instance_methods.select{|e| module_arry.include?(e)} if m != Kernel
end
p list
# >> {A=>[:meth1, :meth2], B=>[:meth11, :meth21]}
when you will extend modules
module A
def meth1;end
def meth2;end
end
module B
def meth11;end
def meth21;end
end
class C
extend A,B
end
list = C.singleton_class.included_modules.each_with_object({}) do |m,ob|
module_arry = m.instance_methods
class_methods = C.methods - C.instance_methods
ob[m]= class_methods.select{|e| module_arry.include?(e)} if m != Kernel
end
p list
# >> {A=>[:meth1, :meth2], B=>[:meth11, :meth21]}
I suppose you want only methods from modules included in the very child you're in, filtering out methods from modules included in parents. If you also want modules included from parents, #Arup answer is the good one.
There's no provided core method to do what you want, but you can create one if you need this often.
Prerequisite knowledge
There are three sources of methods for a given class :
methods defined in the class itself and its monkey patches
methods from parent
methods from modules
Method from modules may be inserted in class itself or from parents (or even by hook in modules, but let's keep that aside).
Note also that Class inherits from Module, so a Class is a Module.
How to retrieve modules
Now, having all of that, what you want to do is to get all modules included in your current class, remove parent modules and get methods. The basic formula is thus :
methods_from_module_included_in_current_class = ( modules_in_class - modules_in_parent ).methods
To get all module in class, you can use the #ancestors method. It will list all classes and modules which has been mixed in current class (remember : a class is just a module).
modules_in_class = MyClass.ancestors.reject { |ancestor| Class === ancestor }
Here, we reject what is a Class from the list (Class === ancestor is the same than doing ancestor.is_a? Class), so we know we only have modules. Again, we can't just select modules, since Class are Module.
Finally, we can apply the same pattern to get modules from parent :
module_in_parent = MyClass.superclass.ancestors.reject { |ancestor| Class === ancestor }
Getting methods
So, to get all your methods from modules included in current class :
( MyClass.ancestors.reject { |ancestor| Class === ancestor } - MyClass.superclass.ancestors.reject { |ancestor| Class === ancestor } ).map( &:instance_methods ).flatten
To get class methods (thus methods added using #extend) rather, replace instance_methods with methods.
Note you may still have a few unfamiliar methods here if some anonymous module is declared on class initialization, like rails does on ActiveRecord::Base.
Factoring that
If you find yourself using this frequently, you can factorize it in a method :
class Object
def inner_module_methods
( self.class.ancestors.reject { |ancestor| Class === ancestor } - self.class.superclass.ancestors.reject { |ancestor| Class === ancestor } ).map( &:instance_methods ).flatten
end
end
You can now do :
obj.inner_module_methods
Or within pry :
inner_module_methods
Alternative
You may also want to filter methods by source file. If find this being more effective and volatile, in the long run.
Is there a way to override a class's operator, by creating a new operator method inside a module, then mixing that module into the class?
eg, this overrides Fixnum's + operator:
class Fixnum
def +(x)
product = x
product = product * self
return product
end
end
p 3 + 3
# => 9
This does not override Fixnum's + operator:
module NewOperators
def +(x)
product = x
product = product * self
return product
end
end
class Fixnum
include NewOperators
end
p 3 + 3
# => 6
Your question led me to this interesting article which describes the problem:
Fixing Ruby’s Inheritance Model with Metamorph
This is the ultimate problem with Ruby’s inheritance model, in my opinion. Because mixins always take lower priority than methods defined directly in a class body, A#foo can not be overridden by mixin inclusion. Moreover, because mixins take lower priority than methods, A#foo is now violating encapsulation [...]
And his solution is to transparently define all new methods inside an anonymous inner module:
class Object
def self.method_added(name)
return if name == :initialize
const_set(:InstanceMethods, Module.new) unless defined?(self::InstanceMethods)
meth = instance_method(name)
self::InstanceMethods.send(:define_method, name) {|*args, &block| meth.bind(self).call(*args, &block) }
remove_method(name)
include self::InstanceMethods
end
end
This is also conveniently packaged in a library called metamorph, which allows you to have mixin methods override class methods by just requiring it.
No, because in a method lookup you don't get a chance to pull in methods that were defined in mixins or parent classes until you've actually looked at the current class.
That said, you can create a method that, when called on a class, will create methods in that class. This can give you a way to inject operators into classes easily.
Be warned that actually doing this is a good recipe for surprise. This is doubly true when you are changing standard modules whose behavior is relied upon by others. See http://avdi.org/devblog/2008/02/23/why-monkeypatching-is-destroying-ruby/ for context.
I know in Ruby that I can use respond_to? to check if an object has a certain method.
But, given the class, how can I check if the instance has a certain method?
i.e, something like
Foo.new.respond_to?(:bar)
But I feel like there's gotta be a better way than instantiating a new instance.
I don't know why everyone is suggesting you should be using instance_methods and include? when method_defined? does the job.
class Test
def hello; end
end
Test.method_defined? :hello #=> true
NOTE
In case you are coming to Ruby from another OO language OR you think that method_defined means ONLY methods that you defined explicitly with:
def my_method
end
then read this:
In Ruby, a property (attribute) on your model is basically a method also. So method_defined? will also return true for properties, not just methods.
For example:
Given an instance of a class that has a String attribute first_name:
<instance>.first_name.class #=> String
<instance>.class.method_defined?(:first_name) #=> true
since first_name is both an attribute and a method (and a string of type String).
You can use method_defined? as follows:
String.method_defined? :upcase # => true
Much easier, portable and efficient than the instance_methods.include? everyone else seems to be suggesting.
Keep in mind that you won't know if a class responds dynamically to some calls with method_missing, for example by redefining respond_to?, or since Ruby 1.9.2 by defining respond_to_missing?.
Actually this doesn't work for both Objects and Classes.
This does:
class TestClass
def methodName
end
end
So with the given answer, this works:
TestClass.method_defined? :methodName # => TRUE
But this does NOT work:
t = TestClass.new
t.method_defined? : methodName # => ERROR!
So I use this for both classes and objects:
Classes:
TestClass.methods.include? 'methodName' # => TRUE
Objects:
t = TestClass.new
t.methods.include? 'methodName' # => TRUE
The answer to "Given a class, see if instance has method (Ruby)" is better. Apparently Ruby has this built-in, and I somehow missed it. My answer is left for reference, regardless.
Ruby classes respond to the methods instance_methods and public_instance_methods. In Ruby 1.8, the first lists all instance method names in an array of strings, and the second restricts it to public methods. The second behavior is what you'd most likely want, since respond_to? restricts itself to public methods by default, as well.
Foo.public_instance_methods.include?('bar')
In Ruby 1.9, though, those methods return arrays of symbols.
Foo.public_instance_methods.include?(:bar)
If you're planning on doing this often, you might want to extend Module to include a shortcut method. (It may seem odd to assign this to Module instead of Class, but since that's where the instance_methods methods live, it's best to keep in line with that pattern.)
class Module
def instance_respond_to?(method_name)
public_instance_methods.include?(method_name)
end
end
If you want to support both Ruby 1.8 and Ruby 1.9, that would be a convenient place to add the logic to search for both strings and symbols, as well.
Try Foo.instance_methods.include? :bar
Not sure if this is the best way, but you could always do this:
Foo.instance_methods.include? 'bar'
I think there is something wrong with method_defined? in Rails. It may be inconsistent or something, so if you use Rails, it's better to use something from attribute_method?(attribute).
"testing for method_defined? on ActiveRecord classes doesn't work until an instantiation" is a question about the inconsistency.
If you're checking to see if an object can respond to a series of methods, you could do something like:
methods = [:valid?, :chase, :test]
def has_methods?(something, methods)
methods & something.methods == methods
end
the methods & something.methods will join the two arrays on their common/matching elements. something.methods includes all of the methods you're checking for, it'll equal methods. For example:
[1,2] & [1,2,3,4,5]
==> [1,2]
so
[1,2] & [1,2,3,4,5] == [1,2]
==> true
In this situation, you'd want to use symbols, because when you call .methods, it returns an array of symbols and if you used ["my", "methods"], it'd return false.
klass.instance_methods.include :method_name or "method_name", depending on the Ruby version I think.
class Foo
def self.fclass_method
end
def finstance_method
end
end
foo_obj = Foo.new
foo_obj.class.methods(false)
=> [:fclass_method]
foo_obj.class.instance_methods(false)
=> [:fclass_method]
Hope this helps you!
While respond_to? will return true only for public methods, checking for "method definition" on a class may also pertain to private methods.
On Ruby v2.0+ checking both public and private sets can be achieved with
Foo.private_instance_methods.include?(:bar) || Foo.instance_methods.include?(:bar)
On my case working with ruby 2.5.3 the following sentences have worked perfectly :
value = "hello world"
value.methods.include? :upcase
It will return a boolean value true or false.
I have a class that has a number of modules that are mixed in with it based on some runtime criteria.
I want to be able to get a list of which modules have been mixed into this class. How can you do that?
UPDATE
So when I said class I meant object as it is the object that is being extended at runtime using:
obj.extend(MyModule)
obj.included_modules and obj.ancestors don't exist so you can't get the modules that have been mixed in from there.
Try:
MyClass.ancestors.select {|o| o.class == Module }
for example:
>> Array.ancestors.select {|o| o.class == Module}
=> [Enumerable, Kernel]
UPDATE
To get the modules mixed into an object instance at runtime you'll need to retrieve the eigenclass of the instance. There is no clean way to do this in Ruby, but a reasonably common idiom is the following:
(class << obj; self; end).included_modules
If you find yourself using this a lot, you can make it generally available:
module Kernel
def eigenclass
class << self
self
end
end
end
and the solution is then:
obj.eigenclass.included_modules
This might be a better idea:
MyClass.included_modules
irb(main):001:0> Array.included_modules
=> [Enumerable, Kernel]
If you're looking for the whole list, Swanand's answer is your best bet.
If, on the other hand, you want to check whether a class includes a particular module, the < operator is your friend:
module Foo
end
class Bar
include Foo
end
Bar < Foo
# => true
obj.singleton_class.included_modules
And if you want to check if module included:
obj.singleton_class.include? MyModule
Here is another effective way to see if a module has been included or extended by a class.
As others have mentioned, you can determine whether a module is included on a class by checking the included_modules class method that exists on all classes in ruby.
So if you had a class named MyClass and you wanted to see if it included the Comparable module you could do something like this:
# will return true if MyClass.include(Comparable)
MyClass.included_modules.include?(Comparable)
If you want to determine whether your class has extended the ActiveRecord::Querying module, as all rails model classes do, you can actually use this:
# will return true if MyClass.extend(ActiveRecord::Querying)
MyClass.kind_of?(ActiveRecord::Querying)
Why does this work? To quote the book Eloquent Ruby, by Russ Olsen:
When you mix a module into a class, Ruby rewires the class hierarchy a bit, inserting the module as a sort of pseudo superclass of the class.
This also means that another way to determine whether a module has been included into your class is to do something like this (although I still prefer the included_modules method):
# will also return true if MyClass.include(Comparable)
MyClass.new.kind_of?(Comparable)
Only classes can story methods and when you add a method to an instance you are actualy adding it to the objects metaclass. The module you are looking for will be in this metaclass ancestors list.
module TestModule; end
obj = "test"
obj.extend(TestModule)
class Object
def metaclass
class << self; self; end
end
end
obj.metaclass.ancestors
# => [TestModule, String, Comparable, Object, Kernel, BasicObject]
I like #AlexParamonov's solution, but I played around and found out that this works just as well:
obj.class.include? MyModule
MyClass.include? MyModule
http://www.ruby-doc.org/core-2.1.2/Module.html#method-i-include-3F