The number 1 contains 109 additional methods above and beyond the Fixnum class it inherits from.
1.methods - Fixnum.methods => [:%, :&, :*, :**, :+, :+#, :-, :-#, ...]
(1.methods - Fixnum.methods).count => 109
1.is_a? Fixnum => true
So from my understanding, I would say the number 1 is an instance of Fixnum. But why does the number 1 have so many more methods than Fixnum? And where do they come from? How would I write my own method for the number 1?
When you call .methods, it gives the methods defined on that instance. So when you ask for Fixnum.methods, you get the methods you can call on Fixnum the class, not on objects of type Fixnum.
As to your last question, Ruby allows you to extend a class like so:
class Fixnum
def plus9
return self + 9
end
end
They can come from Fixnum's parent classes as well as any modules mixed in along the way. You can use 1.method('<method name>').inspect to find out where exactly does the method originate.
method#source_location is good as well, but it doesn't work for native methods, which is almost everything on 1.
Fixnum itself is an instance of Class, when you call Fixnum.methods, it returns the methods that the Class class and its ancestors have.
So 1.methods - Fixnum.methods has little sense as you are comparing the methods of Fixnum class and the methods of Class class.
Fixnum.class
# => Class
1.class
# => Fixnum
How would I write my own method for the number 1
You can implement your own methods in Fixnum or any of its ancestor classes: Integer, Numeric, etc, depending on which class this method makes sense.
You may misunderstand the Object#methods method.
According to the Ruby API,
methods(regular=true) → Returns a list of the names of public and protected methods of obj.
So Fixnum.methods returns the methods from the perspective of the object, not the class.
Module#instance_methods is what you want
1.methods.count == Fixnum.instance_methods.count # => true
To get the right method list in Ruby is kind of a confusing thing, Idiosyncratic Ruby has a detailed post about method-lists. It helps me sort things up, and hope this can help you, too.
To extend the Fixnum class and add/modify your own methods. You can use this code:
class Fixnum
def newNum_method
puts self.methods
end
end
Also you can modify existing methods the same way. Many times the 'to_s' is modified to produce specific results for example:
class Array
def to_s
puts self.join(":")
end
end
This code ONLY modifies what you specify.
You can also add class specific code for example:
def Array.newMethod
puts Array.methods
end
This allows you to call:
puts Array.newMethod
(Which would technically be the same as "puts Array.methods")
but you can customize this to say or do whatever with the 'Array' class
You could even create a method for the Fixnum class itself to Iterate over its parents and list EACH method from them.
def Fixnum.listParentMethods
.....
end
Try
1.methods - Fixnum.instance_methods
and you'll get an empty array.
In ruby, classes are objects of type Class.
When you call obj.methods, it returns all public methods of obj.
So what if obj is a class?
Related
Currently working on a ruby minifier using Ripper's lex() method. However currently attr_accessor is defined as an identifier... I assume because it's a method.
Where is attr_accessor defined? If I know where it's defined I can easily make exceptions for methods like it.
It is defined in the Module class. (Documentation Link)
EDIT:
Just to make the answer more complete, it is a private method of the Module class, which means you cannot call it with a receiver, need to have the class opened to use it (or using some hack like send or eval):
class MyClassOrModule
attr_accessor :foobar
end
You cannot invoke it as MyClassOrModule.attr_accessor. As you already discovered in our comments below, Module.private_instance_methods will show its presence.
Yes, attr_accessor is defined in the class Module (Module#attr_accessor), but how does one go about finding it in the first place? Having to ask someone, or perhaps Googling, is not a very efficient way of going about it.
We can make use of the method Method#owner.1
owner responds to method objects (instances of the class Method), not to method names, which are symbols. Why? Because many modules/classes have methods that have the same symbolic name. For example, String, Array and Hash all have an instance method named :[]. Therefore, we cannot ask Ruby where :[] is defined. We can ask, however, where the method
m = [1,2,3].method(:[])
#=> #<Method: Array#[]
is defined, namely,
m.owner
#=> Array
The determination of m makes use of the method Object#method.
Alternatively, we could write
m = Array.instance_method(:[])
#=> #<UnboundMethod: Array#[]>
m.owner
#=> Array
This makes use of the method Module#instance_mathod.
Notice that in the first case the method :[] is bound to the instance of Array [1,2,3], whereas in the second case :[] is not bound to any particular instance of Array, so it is referred to as UnboundMethod. Either way, we see that Array#[] is defined in Array (i.e., it is not inherited from an ancestor).
Let's consider another example.
We know that 3.zero? #=> false, but do not find an instance method :zero? in the class Integer. So, where is it? We can write:
m = 3.method(:zero?)
#=> #<Method: Integer(Numeric)#zero?>
or
m = Integer.instance_method(:zero?)
#=> #<UnboundMethod: Integer(Numeric)#zero?>
then
m.owner
#=> Numeric
Aha! It's defined in Numeric, the superclass of Integer, Float, Rationale and Complex.
Notice that, in computing m, the message displayed includes, "Integer(Numeric)". Even before computing m.owner this tells us that the owner is Numeric. By contrast, in finding the owner of Array#[] the message was simply "Array". Helpful as always, Ruby parenthetically gives the owner when the owner is not the class of the receiver of method or the class that is the receiver of instance_method.
So now let us find the owner of the class method :attr_accessor. We know that this method is available for every class (e.g., Class.new.methods.include?(:attr_accessor) #=> true), so we could write, say,
m = Class.method(:attr_accessor)
#=> #<Method: Class.attr_accessor>
m.owner
#=> Module
since Class is itself a class, but we could have instead written, say,
m = Regexp.method(:attr_accessor)
#=> #<Method: Regexp.attr_accessor>
m.owner
#=> Module
or even
m = Class.instance_method(:attr_accessor)
#=> #<UnboundMethod: Class(Module)#attr_accessor>
m.owner
#=> Module
the last because methods of every class (which is an instance of Class) are instance methods of Class.
1 If one forgets where the instance method owner is defined, just remember that it is defined on methods, which are instances of the class Method.
As the title suggests, I would like to assign all the instance methods defined on one class to another. I know at I can get a list of the methods that I want to copy from ClassA to ClassB like this:
ClassA.instance_methods(false)
And I think I can define them on ClassB like this:
ClassA.instance_methods(false).each do |method_name|
ClassB.method_define(method_name, [body here??])
end
Is there a way to get the corresponding method body, and if so, will this method work? If not, is there even a way to do this?
Others already told you to subclass. But to answer your literal question, we would be getting involved with UnboundMethod objects:
class Object
def kokot; 'kokot' end
end
o = Object.new
o.kokot
#=> kokot
3.kokot
#=> kokot
So far so good. Now let's redefine kokot method on Numeric:
class Numeric
def kokot; 'pica' end
end
o.kokot
#=> kokot
3.kokot
#=> pica
But what if we decide, that new kokot method is great for numerics, but just complex numbers should keep using the old kokot method. We can do it like this:
um = Object.instance_method :kokot
#=> #<UnboundMethod: Object#kokot>
Complex( 2, 3 ).kokot # gives the redefined kokot method
#=> pica
Complex.module_exec { define_method :kokot, um }
# Now we've just bound the old kokot to Complex
Complex( 2, 3 ).kokot
#=> kokot
In short, there is a way to "copy and paste" methods among related classes. It is required that the target be a subclass of the unbound method source. Method #source_location shows the file and the line where #kokot has been defined:
um.source_location
#=> ["(irb)", 2]
For built-in methods, #source_location returns nil. In Ruby 2.0, RubyVM class has method #disassemble:
RubyVM::InstructionSequence.disassemble( um )
#=> ( program listing goes here )
In any case, Ruby bytecode is not that beautiful to look at. Going back to your original needs, not even #define_method or UnboundMethod#bind can bind methods to incompatible objects. This cannot be cheated by tricks like redefining #kind_of?, one would have to cheat CLASS_OF() function in the native code...
From the available gems, Sourcify, RubyParser and Sorcerer are of interest. (Thanks, #Casper.) Using these, one could theoretically transplant code between incompatible objects via #eval-ling extracted method source. Long way as it goes, this technique would still fall short of realiable method transfer, as it fails whenever the source is not available at runtime (eg. self-modifying source).
It seems like what you might want is mix-ins:
Taken from http://www.ruby-doc.org/docs/ProgrammingRuby/html/tut_modules.html
module Debug
def whoAmI?
"#{self.type.name} (\##{self.id}): #{self.to_s}"
end
end
class Phonograph
include Debug
# ...
end
class EightTrack
include Debug
# ...
end
ph = Phonograph.new("West End Blues")
et = EightTrack.new("Surrealistic Pillow")
ph.whoAmI? » "Phonograph (#537766170): West End Blues"
et.whoAmI? » "EightTrack (#537765860): Surrealistic Pillow"
In ruby 2.0 you can use modules. Matz explicitly forbade this behavior from classes.
But you can use instance_methods from modules.
ModuleA.instance_methods(false).each do |name|
meth = ModuleA.instance_method(name)
ClassB.send(:define_method, name, meth)
end
define_method is a private method, so that's why you use send here.
But why do this? Just include the module.
If you want to just apply behavior to an object you can unbind a method from any module and bind it to any object.
ModuleA.instance_method(:something).bind(some_object).call(args)
If this is what you want, take a look at casting, a gem that adds a convenience to doing delegation like this as well as adding methods to an object only for the life of a block.
In that case, classB should inherit classA.
I want to create an object that acts as a specific class, such as Fixnum, but isn't an instance of that class nor its subclasses.
There are various use-cases for this. In the Fixnum case, I want to define a more specific integer type that is essentially a Fixnum but implements some extra logic, too. I can't subclass Fixnum itself because immediate types such as Fixnum and Symbol can't be subclassed.
Another use-case is mocking in automated tests: sometimes you want to create an object that acts like a certain class (usually a model instance) but is for technical reasons not an instance of that exact class.
Here's how to create a specific integer type that delegates all methods to an internally stored fixnum:
require 'delegate'
require 'forwardable'
# integer representing a page number
class PageNumber < DelegateClass(Integer)
extend Forwardable
def initialize(value, name)
#name = name
super(value)
end
def inspect
"#{#name} #{to_i}"
end
alias_method :to_i, :__getobj__
def_delegators :to_i, :instance_of?, :kind_of?, :is_a?
end
This object can pass is_a? and similar checks:
page = PageNumber.new(1, "page")
page.is_a? Fixnum #=> true
But nothing I do can make it pass the Module#=== type check:
# my problem:
Fixnum === page #=> false
The fact that my object fails this check is very unfortunate, since the === method is used internally in case statements:
case page
when Fixnum
# it will never get here
when String
# ...
else
# ...
end
My question is how can I create a mock type that passes the === check without augmenting the === methods on built-in classes?
If we are speaking about the MRI1, the answer is simple: you cannot.
The Module#=== method is effectively an alias of rb_obj_is_kind_of C API method. The implementation of latter is so short that I will paste it here:
VALUE
rb_obj_is_kind_of(VALUE obj, VALUE c)
{
VALUE cl = CLASS_OF(obj);
/* Type checking of `c' omitted */
while (cl) {
if (cl == c || RCLASS_M_TBL(cl) == RCLASS_M_TBL(c))
return Qtrue;
cl = RCLASS_SUPER(cl);
}
return Qfalse;
}
As you can see, this method traverses the ancestors of the object being examined, and compares them in two ways: first, it checks if the ancestor is the same as the module which was passed, and then, it checks if they have same method table.
The latter check is required because included modules in Ruby are seemingly inserted in the inheritance chain, but as one module may be included in several other ones, it's not the real module which is inserted into the chain, but a proxy object, which has its constant and method tables pointing to the original module.
For example, let's look at Object's ancestors:
ruby-1.9.2-p136 :001 > Object.ancestors
=> [Object, Kernel, BasicObject]
ruby-1.9.2-p136 :002 > Object.ancestors.map { |mod| Object.new.is_a? mod }
=> [true, true, true]
Here, the Object and BasicObject will be successfully compared by the first check, and Kernel by the second one.
Even if you'll try to make (with a C extension) a proxy object which will try to trick the rb_obj_is_kind_of method, it will need to have the same method table as a real Fixnum, which would effectively include all Fixnum's methods.
1 I've investigated the internals for Ruby 1.9, but they behave exactly same way in 1.8.
This is a hackish solution that I warned against in my question:
Fixnum === page #=> false
Numeric.extend Module.new {
def ===(obj)
obj.instance_of?(PageNumber) or super
end
}
Fixnum === page #=> true
It solves the problem but raises a question is it safe to do? I can't think of any drawbacks of this method from the top of my mind but since we're messing with a very important method here it might not be something we'd want to do.
In C# you can write an extension method like this:
public static Debt[] Foo(this Debt[] arr, int num)
{
// Do something
}
This would allow you to use Foo() on an array of debts: debts.Foo(3)
Can you do this in Ruby? I know you can write a method that will work on arrays:
class Array
def foo
# blah
end
end
but this works on all types of arrays, not just an array of Debts
Thanks in advance.
the extend method is adding the instance methods to a particular object. so in you case it would be:
class YourClass
def foo
# blah
end
end
debts.extend(YourClass)
debts.foo # now foo method is instance method of debts object
Actually it creates singleton class for debts object and then add to it the method. But you can't use this class, that's why it called "ghost" class
This would be a little tricky because Ruby arrays are not homogeneous. That is, you can store different types of objects inside of an array. That would lead me to a solution where I need to first verify that all objects in the array are of type Debt, and if they are then I can act on the array using foo.
You can continue to open up Array and add the foo method, but maybe you should create a FooArray instead and extend Array. This way you can redefine some methods such as << and push to ensure you only take Debts. Since you know that only Debts can be added to your array, you could call foo() without worry.
I believe you can do this by extending Ruby's Array class or better yet defining your own Array-like class and delegating the selected array methods to the native object.
Stack = Array.extract([
:last,
:push,
:pop,
:size,
:clear,
:inspect,
:to_s
])
Why this is better than the alternative methods is explained here.
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.