To self or not to self - that is the question

I’m pretty new Ruby, and I’m slightly confused about when to use ‘self’.

I’m in a process of writing a common automation framework to test our
(java-based) web products using Cucumber. I’m using the ‘Page Object’
design pattern, which basically means that each page should be
represented by a class.

Some pages, share behavior. For example - many pages utilize JavaScript
popup. I have a couple of methods that handle popups (accept them,
dismiss them etc). My instincts tell me that since popup handling is
basically a collection of methods, and those are state-less, I should be
using a module. Hopefully I’m right to this point.

Now, I’m not sure if I should include the module into my Page Objects,
or “self” the whole module, and just call those methods from the page
object when I need them.

As test frameworks being very ‘procedural’ oriented, I find much of my
code being stateless. Using too many modules and 'self’ing those worry
me (as my C# background should me that I should be extra careful when
I’m using static methods). Some guidelines on when I should be using
self so I won’t over-do it will be useful for me.

hi

are you asking about ‘self’ keyword?

If so,

class Hi
def self.fun
puts ‘this is the class function’
end

def hi
puts ‘hi’
end

def hello
self.hi
puts ‘hello’
end
end
Hi.fun
o=Hi.new
o.hello

ruby hi.rb
this is the class function
hi
hello

Look at the above example, self keyword take the object when it is used
in methods, it takes Class name as object when it’s declared using class
like ‘def Hi.fun’

Hi Raja, thanks for the answer.

I am indeed speaking about the self keyword, sorry if I didn’t made it
clear. My issue is not about how to use it and what it does, but around
when it should be used and why.

Okay, It’s used to invoke the object inside the class and methods,

For an example, you must have heard about ‘each’ keyword isn’t it?

a=[1,2,3,4]

a.each do |i|
puts i
end

Now we can create our own each loop as follows,

class Array
def ourOwneach
for i in self #this self refers to the object ‘a’
yield i
end
end
end

a=[1,2,3,4]

a.ourOwneach do |i|
puts i
end

now does this makes sense? able to understand?

give me the example please

module PopupHandling

def accept_alert
    # Implementation
end

def dismiss_alert
    # Implementation
end

def get_text
    # Implementation
end

end

Class PageObject

def create_user
    fill_in('\\some\xpath', :with => 'Yuval Gal')
    click_button('saveForm')
    !!!! This is where I want to call to 'acceept_alert' method !!!!
end

end

The module PopHandling is sort of an ‘Helper’. Most PageObjects should
be able to handle popups. It stateless and therefore it’s a module.
I can do one of the following:

  1. Include PopupHandling into the PageObject class and call it when I
    need it
  2. extended self the whole PopupHandling module, and call it from any
    PageObject using ‘PopupHandling.accept_alert’.

I’m trying to understand, if any of the above is preferred over the
other, and why. Hopefully it makes more sense now. Thanks :slight_smile:

A helper module is not comparable to a self methods in a class. Modules
are collection of classes, and classes have methods (instance and class
methods).

A class method is usually a “utility”, that is used often but does not
change (or should not change) in different instances of that class.

For example, Ruby has no factorial method (ups), but you can implement
it easily.

If you need it in every instance of a certain class, you can either
define it as an instance method [def fact(n)] or as a class method [def
self.fact(n)].
The difference is minor, the instance variation takes more memory as it
will be duplicated as many times as many class instance exists while
your program is running, the class variation will take less memory as it
will be defined once.

What I’m trying to understand, is the benefits of include an helper
module to a class versus extended self that module and just call it
externally from my class.

Hi Földes László, please see the examples below:

Example 1:

** MyModule.rb **

module HelloWorld

def hello_world
    puts 'Hello World'
end

end

** MyProgram.rb **

require ‘MyModule’

Class Foo
include MyModule
hello_world
end

Example 2:

** MyModule.rb **

module HelloWorld
extends self

def hello_world
    puts 'Hello World'
end

end

** MyProgram.rb **

require ‘MyModule’

Class Foo
include HelloWorld
hello_world
end

Example 3:

** MyModule.rb **

module HelloWorld
extends self

def hello_world
    puts 'Hello World'
end

end

** MyProgram.rb **

require ‘MyModule’

Class Foo
MyModule.hello_world
end

The difference between Example 1 and Example 2 is what you explained. I
understand that.

On the third example, I didn’t include the module. I just called
directly to the class method. I’m trying to understand when I should
including my module into my class (like in Example 1 and 2), versus
calling the class method directly without including it like in the third
example.

Thanks!

Yuval Gal wrote in post #1177132:

The difference between Example 1 and Example 2 is what you explained. I
understand that.

On the third example, I didn’t include the module. I just called
directly to the class method. I’m trying to understand when I should
including my module into my class (like in Example 1 and 2), versus
calling the class method directly without including it like in the third
example.

Thanks!

There are several things mixed up (module vs. class; instance vs. class
methods, terminology on including)

First the main differences with “including”:

  1. “include” adds instance methods to a class
  2. “extend” adds class methods to a class
    Thus: “versus calling the class method directly without including it” is
    invalid, you cannot include a class method.

And your examples cannot run, they both contain syntax errors, and
conceptual mistakes (that manifests as errors), and none of them
contains the ‘problem’ you want to solve.

  1. Class definition is made with lowercase characters “class Foo”
  2. “extends” is wrong, it is “extend”
  3. directly calling “hello_world” in example #2 will throw an error.
    “include” adds instance methods to a class but the time you call
    ‘hello_world’, it is not yet an instance, just a method definition (BUT
    not the c# way! Ruby is interpreted language, it “walks” down your code,
    when it hits ‘hello_world’ it just does not exist)

Classes can have instance methods and class methods, here is an example:
class Hoge
def fuge
puts “fuugeee”
end
def self.piyo
puts “piyooo”
end

defining self.piyo differently

class << self

def piyo

puts “piyooo”

end

end

end

Hoge.new.fuge
“fuugeee”
Hoge.piyo
“piyooo”

  1. ‘fuge’ is an instance method, it does not exist until you ‘new’ the
    class.
  2. ‘piyo’ is a class method, usually you access it on the base class
    (Hoge), however it can be accessed on every instance as well
    (Hoge.new.class.piyo). So it IS available, before you ‘new’ the class.

What “extend self” does: as stated above ‘extend’ adds methods to the
class methods of a class. Up there ‘self’ is the module itself (its
instance methods), so ‘extend self’ just adds every instance method AS
class method to the same module.
If you combine this and the class method example above (that class
methods are available before you ‘new’ the class), means that every
instance method from the module become available without instancing, as
now they are also existing as class methods (this is a plain
duplication, not Ruby magic).

That is why MyModule.hello_world works. “extend self” makes the
hello_world instance method available as class method.

On your final question:

module X
class Y
def hoge

end

def fuge
  ...
end

end
end

to access ‘hoge’ (an instance method), you call: X::Y.new.hoge (that is,
::.new.)

OR

you ‘include X’, then call: Y.new.hoge. Because you included the module,
all of its classes are available in the same namespace as where you main
code runs.

In short: only the naming is different when accessing a method of a
class inside a module, but sometimes it is convenient to include all the
stuff into your namespace, this is especially true if you would like to
redefine some of those methods, after including.

Yuval Gal wrote in post #1177173:

module PopupHandling
def accept_popup
# Impl
end

def reject_popup
    # Impl
end

end

class PageObject
include PopupHandling

def create_user
    # Impl
    accept_popup
end

end

PageObject.new.create_user

This makes sense. As popup handling is something the PageObject should
be able to do. It means I have to include PopupHandling on most of my
page objects, as they need to be able to handle popups. A side effect of
this is that users will be able to do the following:

PageObject.new.accept_popup

Which is more of an utility method which I prefer people not to call
directly.

The second option would be:

module PopupHandling
extend self
def accept_popup
# Impl
end

def reject_popup
    # Impl
end

end

require ‘popup’
class PageObject

def create_user
    # Impl
    PopupHandling::accept_popup
end

end

PageObject.new.create_user

There is no difference between calling:
PageObject.new.accept_popup and
PopupHandling::accept_popup

your users could call any of them, as these methods are public (being
‘instance’ or ‘class’ makes no difference).

If you want to hide certain methods from the Class’ users, check out how
to make a method ‘private’.

To decide the class vs. instance method: if accepting or rejecting that
popup window works the same way everywhere and does not save state (that
is tied to a specific webpage, so a specific class instance), then you
could put in into a class method.
But I mentioned above, having the same code as class method or an
instance method does not make a difference until that method is
stateless.

There is no difference between calling:
PageObject.new.accept_popup and
PopupHandling::accept_popup

your users could call any of them, as these methods are public (being
‘instance’ or ‘class’ makes no difference).

If you want to hide certain methods from the Class’ users, check out how
to make a method ‘private’.

To decide the class vs. instance method: if accepting or rejecting that
popup window works the same way everywhere and does not save state (that
is tied to a specific webpage, so a specific class instance), then you
could put in into a class method.
But I mentioned above, having the same code as class method or an
instance method does not make a difference until that method is
stateless.

Oh, I didn’t know you can set a private modifier to Modules.

then you could put in into a class method.

Is that the technical term? wouldn’t that be a ‘module’ method, as I
self it inside the module and does not include it into a class?

Thank you Földes László. This clears and connects few dots for me. I
appreciated your time and sorry for the code examples, I should have
check they work before posting them.

Now that we are (hopefully :-)) speaking the same language - Let’s
return to the original problem at hand. I have a Web Page that is being
represented by a class. The class can do all kind of actions that are
related only to this specific page. One of the things that this page can
do, is to accept or reject a popup window. This behavior however - is
not specific to this web-page, and being needed in many other classes. I
can do one of the following:

module PopupHandling
def accept_popup
# Impl
end

def reject_popup
    # Impl
end

end

class PageObject
include PopupHandling

def create_user
    # Impl
    accept_popup
end

end

PageObject.new.create_user

This makes sense. As popup handling is something the PageObject should
be able to do. It means I have to include PopupHandling on most of my
page objects, as they need to be able to handle popups. A side effect of
this is that users will be able to do the following:

PageObject.new.accept_popup

Which is more of an utility method which I prefer people not to call
directly.

The second option would be:

module PopupHandling
extend self
def accept_popup
# Impl
end

def reject_popup
    # Impl
end

end

require ‘popup’
class PageObject

def create_user
    # Impl
    PopupHandling::accept_popup
end

end

PageObject.new.create_user

This means that accept_popup and reject_popup are not getting included
into the PageObject class, but rather the PageObject class ‘calls’ the
module class method? This ‘solves’ the issues above, as the user can’t
access ‘accept_popup’ or ‘reject_popup’.

Is this what it boils down into? sharing my module methods to the user
vs encapsulating those? is there any rule of a thumb I should be
thinking about when encountering this kind of problem again?

Thanks again!

Yuval Gal wrote in post #1177225:

Oh, I didn’t know you can set a private modifier to Modules.

then you could put in into a class method.

Is that the technical term? wouldn’t that be a ‘module’ method, as I
self it inside the module and does not include it into a class?

A Module is very similar to a Class, you can set its method private:

module Hoge
def fuge
puts “'ere we go!”
end
private :fuge
end

Being similar to a Clas, a Module also has instance and class methods,
just as a Class can have them. However you CAN’T call a module’s
instance method, as there is no way you can ‘instantiate’ a module, you
can only ‘include’ that module into a Class and THEN instantiate it the
Class, and call the instance methods. (it is probably possible to call a
module’s instance method with some metaprogramming wizardry, but that is
not an everyday use).

You can however call the module’s class method directly.

If I understand the question correctly, the problem is what to use:
independent (external) module methods or include this module into the
Page Object class.

And the concept answer, I think, lies in the Single respondibility
principle. Just ask yourself: “Who should care about this
responsibilities? What object is an owner (from conceptual point of
view) of this methods?”

So, let’s look at the first example from that question:

module PopupHandling

def accept_alert
    # Implementation
end

def dismiss_alert
    # Implementation
end

def get_text
    # Implementation
end

end

Class PageObject

def create_user
    fill_in('\\some\xpath', :with => 'Yuval Gal')
    click_button('saveForm')
    !!!! This is where I want to call to 'acceept_alert' method !!!!
end

end

In my mind, #accept_alert, #dismiss_alert and other methods from
PopupHandling module belongs to PageObject itself. Thus, PageObject.new
should call them and the 1st version (include PopupHandling module
inside PageObject class) is true.

Földes László, excellent. I didn’t know you can have private module
methods. I appreciate your help.

Evgeniy Fateev,
Interesting. This makes sense. Because accept_alert and dismiss_alert
has no state - should they be anyhow class methods in the page object
class? I’m trying to figure out when a method should be class method vs
instance method (as most methods I can think of does not hold state,
they alter a state of a class variable.

This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.

| Privacy Policy | Terms of Service | Remote Ruby Jobs