Related
From Wikibooks' Ruby Programming/Overview:
When I said that every Ruby object has a class, I lied. The truth is, every object has two classes: a “regular” class and a singleton class. An object’s singleton class is a nameless class whose only instance is that object. Every object has its very own singleton class, created automatically along with the object. Singleton classes inherit from their object’s regular class and are initially empty, but you can open them up and add methods to them, which can then be called on the lone object belonging to them. This is Ruby’s secret trick to avoid “class methods” and keep its type system simple and elegant
The above passage says that Ruby's secret trick to avoid class methods. I don't understand what the author means here. Where is Ruby stopping us to avoid class methods? for an example, look at the example shown below
class Raj
def self.hi
puts 'Hi'
end
def hello
puts 'hello'
end
end
object=Raj.new
object.hello
Raj.hi
As you can see in the preceding example, the class methods can still be created.
yes?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
But, in any case, it's allowing me to create the method 'hi,' right?
So, what does it mean when it says, 'This is Ruby's secret trick for avoiding "class methods" and keeping its type system simple and elegant'?
I understand that there are no true class methods in Ruby; instead, they are methods that are created for the Raj object.
That's exactly it, though.
def self.hi
puts 'Hi'
end
This is not a class method or static method. Those don't exist in Ruby. That's the whole point. Your class Raj defines an object of type Class. We can see its type with the #class function.
> Raj.class
=> Class
We can also see its ancestors.
> Raj.class.ancestors
=> [Class, Module, Object, PP::ObjectMixin, Kernel, BasicObject]
Class inherits from Module, since (for the most part) classes can do everything modules can. Module, in turn, inherits from Object, which has some modules of its own mixed in (PP:ObjectMixin is for pretty-printing, and Kernel gets you the nice helpers like puts) and eventually inherits from the root class BasicObject.
But this isn't the whole story, for Raj has its own class as well: its singleton class. We can see the full story by calling #singleton_class instead of #class.
> Raj.singleton_class.ancestors
=>
[#<Class:Raj>,
#<Class:Object>,
#<Class:BasicObject>,
Class,
Module,
Object,
PP::ObjectMixin,
Kernel,
BasicObject]
Now there's a lot more going on. Raj is an instance of the singleton class of Raj, which inherits from the singleton class of Object, which in turn inherits from the singleton class of BasicObject, which inherits from Class and all of the stuff we saw before.
So when you define a method on the class Raj, you're defining it (as an instance method) on the singleton class #<Class:Raj>. And that class (currently) has one instance: Raj.
By the way, it's also useful to know that the term "singleton class" is a bit of a lie. As you can see, the class is very much not a singleton in general. For instance, the singleton class of Object, called #<Class:Object> above, actually has several instances: Object, Raj, String, and most Ruby classes. Personally, I prefer to call them eigenclasses for that reason, but "singleton class" is the official (and more well-known) term.
The author is talking about the singleton class in this sentence, there is a really nice article to deep dive into ruby singleton class: https://medium.com/#leo_hetsch/demystifying-singleton-classes-in-ruby-caf3fa4c9d91
Here is a nice example extracted from this article:
class Vehicle
def initialize(kms)
#kms = kms
end
def drive
puts "let's go!"
end
end
car = Vehicle.new(1000)
bus = Vehicle.new(3000)
def car.drive
print "I'm driving a car! "
super
end
car.drive # "I'm driving a car! let's go!"
bus.drive # "let's go!"
As you can see, here the #drive method has been overridden but only for the car object, the bus object is still using the #drive method defined in the Vehicle class.
This new method is defined on the singleton class (or shadow class) of the object, this is allowing you to define new methods on the fly on an object without polluting all the objects of this class.
This means that Ruby doesn't implement class methods.
Indeed, the Ruby OBJECT Model, allows you to "emulate" the definition of class methods by defining instance methods on the Eigenclass:
class Greeting
def self.hello
'hello world!'
end
def self.eigenclass
class << self
self
end
end
end
Greeting.eigenclass # => #<Class:Greeting>
Greeting.eigenclass.name # => nil
Greeting.singleton_methods # => [:hello, :eigenclass]
Greeting.eigenclass.instance_methods(false) # => [:hello, :eigenclass]
First, we define a Greeting.eigenclass method. This method returns self in the context of the eigenclass — by using the class << self ... end syntax. In this case, self contains an unnamed instance of the class Class (a.k.a an anonymous class). This anonymous class keeps track of the class to which it is attached — the Greeting class in our case.
Then, we can see that the singleton methods of the Greeting class are the instance methods of the Greeting eigenclass.
Feel free to have a look to this very detailed article to learn more about this concept.
To illustrate #Sébastien P.'s answer:
dice = [1,2,3,4,5,6] #an ordinary array instance
def dice.throw #now it has an extra
sample
end
p dice.throw #=>3
I'm near the finish of the Ruby track in Code Academy, and I'm curious about a peculiar thing: I was under the impression that a class is a repository of constants, methods, etc... and that in order to access most of them, you would first need to create an instance of that class or in some cases the methods of themselves can be invoked (as in they are all technically part of the global object). And then I saw something like this:
#Worked
Time.now
I understood as this as the method [now] of instance of class [Time] being invoked. I then tried to invoke the method on its own:
#Failed
now
and that failed, and I assumed that while a method can be created in the general scope [as part of the global object], if it relies on initialized variables of "parent" class, it cannot be called on its own, because it would not know which object to search for those initialized variables. Following that I created a test class:
class Clock
def initialize
#hours = 1
#minutes = 30
end
def showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
#this worked
watch = Clock.new
watch.showTime
#this failed
showTime
I then just created a basic method (assuming it's in the global level)
def mymethod
puts "The mighty METHOD!"
end
#Works
mymethod
and calling this method the way I did, without referencing the global object worked. So... the questions I have are as follows:
How can [Time.now] be called in this fashion? Shouldn't there be an instance of Time first created?
Why can't I call the method [now] on its own? Am I right that it relies on resources that it cannot find when called this way?
Why could I not call the method showTime on its own? But if I define any method on the "global" level I can access it without referencing the global object
First of all, your intuition is correct.
Every methods must be an instance method of some receiver.
Global methods are defined as private instance methods on Object class and hence seem to be globally available. Why? From any context Object is always in the class hierarchy of self and hence private methods on Object are always callable without receiver.
def fuuuuuuuuuuun
end
Object.private_methods.include?(:fuuuuuuuuuuun)
# => true
Class methods are defined as instance methods on the "singleton class" of their class instance. Every object in Ruby has two classes, a "singleton class" with instance methods just for that one single object and a "normal class" with method for all objects of that class. Classes are no different, they are objects of the Class class and may have singleton methods.
class A
class << self # the singleton class
def example
end
end
end
A.singleton_class.instance_methods.include?(:example)
# => true
Alternative ways of defining class methods are
class A
def self.example
end
end
# or
def A.example
end
Fun fact, you can define singleton methods on any object (not just on class objects) using the same syntax def (receiver).(method name) as follows
str = "hello"
def str.square_size
size * size
end
str.square_size
# => 25
"any other string".square_size
# => raises NoMethodError
Some programming language history — Singleton classes are taken from the Smalltalk language where they are called "metaclasses". Basically all object-oriented features in Ruby (as well as the functional-style enumerators on Enumerable) are taken from the Smalltalk language. Smalltalk was an early class-based object-oriented language created in the 70ies. It was also the language that invented graphical user interfaces like overlapping windows and menus et cetera. If you love Ruby maybe also take a look at Smalltalk, you might fall in love yet again.
This is known as a class method. If CodeAcademy didn't cover it, that's a shame. Here's some examples:
# basic way
class Foo
def self.bar; :ok; end
end
Foo.bar # => :ok
# alternate syntax
class Foo
class << self
def bar; :ok; end
end
end
# alternate syntax, if Foo class already exists
def Foo.bar; :ok; end
# alternate approach if Foo class already exists
Foo.class_exec do
def bar; :ok; end
end
# to define a class method on an anonymous 'class' for a single instance
# you won't need to use this often
Foo.new.singleton_class.class_exec do
def bar; :ok; end
end
# to define a class method on an instance's actual class
Foo.new.class.class_exec do
def bar; :ok; end
end
Another way to get class methods is to extend a module.
module FooMethods
def bar; :ok; end
end
module Foo
extend FooMethods
end
Foo.bar # => :ok
Note that with Modules, the methods are always defined as instance methods. This way they can be either extended into class scope or included into instance scope. Modules can also have class methods, using the exact same syntax / examples as shown above with classes. However there's not such as easy to load a module's class methods via include or extend.
How can [Time.now] be called in this fashion? Shouldn't there be an
instance of Time first created?
The Time.now method is a class method, not an instance method and therefore can be called directly on the Time class rather than an instance of it Time.new
Class methods are defined on the class themselves using the self keyword:
class Time
def self.now
# code
end
end
Time.now # works
Why can't I call the method [now] on its own? Am I right that it
relies on resources that it cannot find when called this way?
When you call a method "on its own" you're actually implicitly calling it on self:
self.now
The above is the same as just doing:
now
Why could I not call the method showTime on its own? But if I define
any method on the "global" level I can access it without referencing
the global object
You defined the showTime method on a specific class so you have to send that method to that class. When you define a method in the "global" scope you're implicitly defining it on self and the subsequent call to mymethod is actually self.mymethod so it will work.
Time.now is a class method.
To define a class method, you need to define the method with self. : def self.method_name
class Clock
#hours = 1
#minutes = 30
def self.showTime
puts "The time is: #{#hours}:#{#minutes}"
end
end
Clock.showTime
#=> The time is: 1:30
If you want to call now on its own, you can do so inside Time class :
class Time
puts now
#=> 2017-01-19 22:17:29 +0100
end
In the program below, the method of the child class calls the private method of the parent class.
class Parent
private
def new_name
'Private Method'
end
end
class Child < Parent
def get_parent_name
puts new_name
end
end
obj = Child.new
obj.get_parent_name
Ruby is said to be object oriented language so the line
puts new_name
accesses the private method of parent class. Internally, how does it call the method? As being a Object Oriented Programming Language, it should call it using an object. But an object cannot access a private method.
Private methods in Ruby are inherited. So if you define private method for Parent, it's also present in Child.
Answering you comment on the first answer.
There is an implicit reference to the current instance within the class. When you do puts new_name inside get_parent_name what you are really doing is calling new_name on the current instance.
Well in fact, when you say private what Ruby does is to avoid calling the method using an explicit object reference.
class Klass
private
def new_name
'Private Method'
end
def new_name_pub__wrong
self.new_name # won't work since using an explicit object reference
end
def new_name_pub__ok
new_name # will work but means basically the same as self.new_name
end
end
Then in your case this is just basic OOP
Child call new_name on the instance (as I said above), finding none it will crawl the inheritance hierarchy and find the Parent new_name (private methods are visible for all sub-classes)
In Ruby, you can make the receiver implicit, in which case it is implied to be self. This is similar to Self, Java, C#, Scala and many other object-oriented languages, and unlike Smalltalk, which always requires an explicit receiver.
Also, you seem to have no trouble at all understanding how the private puts method inherited from Kernel gets called, but there is no difference between puts and new_name, so why are you having trouble with one but not the other?
Ruby use send to call the method. You can do it yourself and access any private method:
puts obj.send(:new_name)
Here is the doc
Let there be class Example defined as:
class Example
def initialize(test='hey')
self.class.send(:define_method, :say_hello, lambda { test })
end
end
On calling Example.new; Example.new I get a warning: method redefined; discarding old say_hello. This, I conclude, must be because it defines a method in the actual class (which makes sense, from the syntax). And that, of course, would prove disastrous should there be multiple instances of Example with different values in their methods.
Is there a way to create methods just for the instance of a class from inside that instance?
You need to grab a reference to the instance's singleton class, the class that holds all the instance specific stuff, and define the method on it. In ruby 1.8, it looks a little messy. (if you find a cleaner solution let me know!)
Ruby 1.8
class Example
def initialize(test='hey')
singleton = class << self; self end
singleton.send :define_method, :say_hello, lambda { test }
end
end
Ruby 1.9 however, provides a much easier way in.
Ruby 1.9
class Example
def initialize(test='hey')
define_singleton_method :say_hello, lambda { test }
end
end
First off, a small style tip:
self.class.send(:define_method, :say_hello, lambda { test })
You can make this look a little bit nicer by using the new proc literal in Ruby 1.9:
self.class.send(:define_method, :say_hello, -> { test })
But you don't need that. Ruby has something called blocks, which are basically a piece of code that you can pass as an argument to a method. In fact, you already used blocks, since lambda is just a method which takes a block as an argument and returns a Proc. However, define_method already takes a block anyway, there is no need to pass a block to lambda which converts it to a Proc which it passes to define_method which then converts it back into a block:
self.class.send(:define_method, :say_hello) { test }
As you already noticed, you are defining the method on the wrong class. You are defining it on the Example class, since inside an instance method like initialize, self is the current object (i.e. ex1 or ex2 in #mikej's example), which means that self.class is ex1's class, which is Example. So, you are overwriting the same method over and over again.
This leads to the following unwanted behavior:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2') # warning: method redefined; discarding old say_hello
ex1.say_hello # => ex2 # Huh?!?
Instead, if you want a singleton method, you need to define it on the singleton class:
(class << self; self end).send(:define_method, :say_hello) { test }
This works as intended:
ex1 = Example.new('ex1')
ex2 = Example.new('ex2')
ex1.say_hello # => ex1
ex2.say_hello # => ex2
In Ruby 1.9, there's a method that does that:
define_singleton_method(:say_hello) { test }
Now, this works the way you want it to, but there's a higher-level problem here: this is not Ruby code. It is Ruby syntax, but it's not Ruby code, it's Scheme.
Now, Scheme is a brilliant language and writing Scheme code in Ruby syntax is certainly not a bad thing to do. It beats the hell out of writing Java or PHP code in Ruby syntax, or, as was the case in a StackOverflow question yesterday, Fortran-57 code in Ruby syntax. But it's not as good as writing Ruby code in Ruby syntax.
Scheme is a functional language. Functional languages use functions (more precisely, function closures) for encapsulation and state. But Ruby is not a functional language, it is an object-oriented language and OO languages use objects for encapsulation and state.
So, function closures become objects and captured variables become instance variables.
We can also come at this from a completely different angle: what you are doing is that you are defining a singleton method, which is a method whose purpose it is to define behavior which is specific to one object. But you are defining that singleton method for every instance of the class, and you are defining the same singleton method for every instance of the class. We already have a mechanism for defining behavior for every instance of a class: instance methods.
Both of these arguments come from completely opposite directions, but they arrive at the same destination:
class Example
def initialize(test='hey')
#test = test
end
def say_hello
#test
end
end
I know it was asked two years back, but I would like to add one more answer. .instance_eval will help to add methods to instance object
string = "String"
string.instance_eval do
def new_method
self.reverse
end
end
Define instance method from outside:
example = Example.new
def example.say_hello
puts 'hello'
end
From inside:
class Example
def initialize(word='hey')
#word = word
def self.say_hello
puts "example: #{#word}"
end
end
end
Tested on ruby 2.5
What's the best way to unit test protected and private methods in Ruby, using the standard Ruby Test::Unit framework?
I'm sure somebody will pipe up and dogmatically assert that "you should only unit test public methods; if it needs unit testing, it shouldn't be a protected or private method", but I'm not really interested in debating that. I've got several methods that are protected or private for good and valid reasons, these private/protected methods are moderately complex, and the public methods in the class depend upon these protected/private methods functioning correctly, therefore I need a way to test the protected/private methods.
One more thing... I generally put all the methods for a given class in one file, and the unit tests for that class in another file. Ideally, I'd like all the magic to implement this "unit test of protected and private methods" functionality into the unit test file, not the main source file, in order to keep the main source file as simple and straightforward as possible.
You can bypass encapsulation with the send method:
myobject.send(:method_name, args)
This is a 'feature' of Ruby. :)
There was internal debate during Ruby 1.9 development which considered having send respect privacy and send! ignore it, but in the end nothing changed in Ruby 1.9. Ignore the comments below discussing send! and breaking things.
Here's one easy way if you use RSpec:
before(:each) do
MyClass.send(:public, *MyClass.protected_instance_methods)
end
Just reopen the class in your test file, and redefine the method or methods as public. You don't have to redefine the guts of the method itself, just pass the symbol into the public call.
If you original class is defined like this:
class MyClass
private
def foo
true
end
end
In you test file, just do something like this:
class MyClass
public :foo
end
You can pass multiple symbols to public if you want to expose more private methods.
public :foo, :bar
instance_eval() might help:
--------------------------------------------------- Object#instance_eval
obj.instance_eval(string [, filename [, lineno]] ) => obj
obj.instance_eval {| | block } => obj
------------------------------------------------------------------------
Evaluates a string containing Ruby source code, or the given
block, within the context of the receiver (obj). In order to set
the context, the variable self is set to obj while the code is
executing, giving the code access to obj's instance variables. In
the version of instance_eval that takes a String, the optional
second and third parameters supply a filename and starting line
number that are used when reporting compilation errors.
class Klass
def initialize
#secret = 99
end
end
k = Klass.new
k.instance_eval { #secret } #=> 99
You can use it to access private methods and instance variables directly.
You could also consider using send(), which will also give you access to private and protected methods (like James Baker suggested)
Alternatively, you could modify the metaclass of your test object to make the private/protected methods public just for that object.
test_obj.a_private_method(...) #=> raises NoMethodError
test_obj.a_protected_method(...) #=> raises NoMethodError
class << test_obj
public :a_private_method, :a_protected_method
end
test_obj.a_private_method(...) # executes
test_obj.a_protected_method(...) # executes
other_test_obj = test.obj.class.new
other_test_obj.a_private_method(...) #=> raises NoMethodError
other_test_obj.a_protected_method(...) #=> raises NoMethodError
This will let you call these methods without affecting other objects of that class.
You could reopen the class within your test directory and make them public for all the
instances within your test code, but that might affect your test of the public interface.
One way I've done it in the past is:
class foo
def public_method
private_method
end
private unless 'test' == Rails.env
def private_method
'private'
end
end
I'm sure somebody will pipe up and
dogmatically assert that "you should
only unit test public methods; if it
needs unit testing, it shouldn't be a
protected or private method", but I'm
not really interested in debating
that.
You could also refactor those into a new object in which those methods are public, and delegate to them privately in the original class. This will allow you to test the methods without magic metaruby in your specs while yet keeping them private.
I've got several methods that are
protected or private for good and
valid reasons
What are those valid reasons? Other OOP languages can get away without private methods at all (smalltalk comes to mind - where private methods only exist as a convention).
Similar to #WillSargent's response, here's what I've used in a describe block for the special case of testing some protected validators without needing to go through the heavyweight process of creating/updating them with FactoryGirl (and you could use private_instance_methods similarly):
describe "protected custom `validates` methods" do
# Test these methods directly to avoid needing FactoryGirl.create
# to trigger before_create, etc.
before(:all) do
#protected_methods = MyClass.protected_instance_methods
MyClass.send(:public, *#protected_methods)
end
after(:all) do
MyClass.send(:protected, *#protected_methods)
#protected_methods = nil
end
# ...do some tests...
end
To make public all protected and private method for the described class, you can add the following to your spec_helper.rb and not having to touch any of your spec files.
RSpec.configure do |config|
config.before(:each) do
described_class.send(:public, *described_class.protected_instance_methods)
described_class.send(:public, *described_class.private_instance_methods)
end
end
You can "reopen" the class and provide a new method that delegates to the private one:
class Foo
private
def bar; puts "Oi! how did you reach me??"; end
end
# and then
class Foo
def ah_hah; bar; end
end
# then
Foo.new.ah_hah
I would probably lean toward using instance_eval(). Before I knew about instance_eval(), however, I would create a derived class in my unit test file. I would then set the private method(s) to be public.
In the example below, the build_year_range method is private in the PublicationSearch::ISIQuery class. Deriving a new class just for testing purposes allows me to set a method(s) to be public and, therefore, directly testable. Likewise, the derived class exposes an instance variable called 'result' that was previously not exposed.
# A derived class useful for testing.
class MockISIQuery < PublicationSearch::ISIQuery
attr_accessor :result
public :build_year_range
end
In my unit test I have a test case which instantiates the MockISIQuery class and directly tests the build_year_range() method.
In Test::Unit framework can write,
MyClass.send(:public, :method_name)
Here "method_name" is private method.
& while calling this method can write,
assert_equal expected, MyClass.instance.method_name(params)
Here is a general addition to Class which I use. It's a bit more shotgun than only making public the method you are testing, but in most cases it doesn't matter, and it's much more readable.
class Class
def publicize_methods
saved_private_instance_methods = self.private_instance_methods
self.class_eval { public *saved_private_instance_methods }
begin
yield
ensure
self.class_eval { private *saved_private_instance_methods }
end
end
end
MyClass.publicize_methods do
assert_equal 10, MyClass.new.secret_private_method
end
Using send to access protected/private methods is broken in 1.9, so is not a recommended solution.
To correct the top answer above: in Ruby 1.9.1, it's Object#send that sends all the messages, and Object#public_send that respects privacy.
Instead of obj.send you can use a singleton method. It’s 3 more lines of code in your
test class and requires no changes in the actual code to be tested.
def obj.my_private_method_publicly (*args)
my_private_method(*args)
end
In the test cases you then use my_private_method_publicly whenever you want to test my_private_method.
http://mathandprogramming.blogspot.com/2010/01/ruby-testing-private-methods.html
obj.send for private methods was replaced by send! in 1.9, but later send! was removed again. So obj.send works perfectly well.
In order to do this:
disrespect_privacy #object do |p|
assert p.private_method
end
You can implement this in your test_helper file:
class ActiveSupport::TestCase
def disrespect_privacy(object_or_class, &block) # access private methods in a block
raise ArgumentError, 'Block must be specified' unless block_given?
yield Disrespect.new(object_or_class)
end
class Disrespect
def initialize(object_or_class)
#object = object_or_class
end
def method_missing(method, *args)
#object.send(method, *args)
end
end
end
I know I'm late to the party, but don't test private methods....I can't think of a reason to do this. A publicly accessible method is using that private method somewhere, test the public method and the variety of scenarios that would cause that private method to be used. Something goes in, something comes out. Testing private methods is a big no-no, and it makes it much harder to refactor your code later. They are private for a reason.