Forum: Ruby module scope not clear to me

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2008-10-04 08:14
I had a program which inherits from a superclass. It also has
common/convenience methods in a module.

<code>
 require 'common'
 include 'Common'
 class Prog < Application
    f = Obj.new
    g = Foo.new
    #... etc ...
</code>


Some convenience methods rely on a variable being set in the superclass.
(I know that does not sound good but it shields this detail from
individual programs.)

Then i refactored ... moved a lot of functionality out from the program
to objects it was creating. I would guess that these objects should
_not_ be able to call the module methods. Suprisingly, they were.

The problem came up that the variable was obviously not set when called
by these objects, (since the class of the module was now the object's
class not the program's class.)

So my basic question is: if a program includes a module, can all its
composed objects also call on the module.

What are the scope rules?

Any do's and don'ts/insights/suggestions are welcome.
Fc8263f8baca7a7b76605cfdd0c4afa2?d=identicon&s=25 Ragav Satish (ragav)
on 2008-10-04 10:12
Nit Khair wrote:
> I had a program which inherits from a superclass. It also has
> common/convenience methods in a module.
>
> <code>
>  require 'common'
>  include 'Common'
>  class Prog < Application
>     f = Obj.new
>     g = Foo.new
>     #... etc ...
> </code>
>
>
> Some convenience methods rely on a variable being set in the superclass.
> (I know that does not sound good but it shields this detail from
> individual programs.)
>
> Then i refactored ... moved a lot of functionality out from the program
> to objects it was creating. I would guess that these objects should
> _not_ be able to call the module methods. Suprisingly, they were.
>
> The problem came up that the variable was obviously not set when called
> by these objects, (since the class of the module was now the object's
> class not the program's class.)
>
> So my basic question is: if a program includes a module, can all its
> composed objects also call on the module.

Depends on where the module is included. If its included at the top
level (outside of another class/module) then it's mixed into the Object
class from which all other classes ultimately derive , so method lookup
on any object will always find it.

    module M
      def foo; puts "module foo" end
    end

    class C; end
    # method name resolution chain before include
    p C.ancestors #=> [C, Object, Kernel]

    include M     # including at top level has M as the

    p C.ancestors #=> [C, Object, M, Kernel]

    C.new.foo     #=> module foo

    # heck you can even call it on "M", "C" since they are also objects
    M.foo   #=> module foo
    C.foo   #=> module foo.

Once you include a module at the *top level* you are creating a set of
methods accessible from anywhere.

--Cheers
--Ragav
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2008-10-04 11:23
Ragav Satish wrote:
>>
>> <code>
>>  require 'common'
>>  include 'Common'
>>  class Prog < Application
>>     f = Obj.new
>>     g = Foo.new
>>     #... etc ...
>> </code>
>>
> Depends on where the module is included. If its included at the top
> level (outside of another class/module) then it's mixed into the Object
> class from which all other classes ultimately derive , so method lookup
> on any object will always find it.
> --Cheers
> --Ragav

Wow ! That said, earlier in the case i gave above is it at the top
level?

Because my situation was like this (before refactoring). There were 2
classes in my file, and the first did NOT find it. It had to use a
reference of the second class to call the module methods. Let me
explain:

==== common.rb contains:
def printme
end

==== prog.rb

  require 'common'
  include 'Common'

  class Datasource
      # saves reference to Prog in constructor
      def initialize (app)
         @main = app
      end


      printme         # this failed.
      @main.printme   # this works
    end

   class Prog < Application
      new Datasource(self)
      printme  # works
   end

   if __FILE__ == $0
      p = new Prog...
      p.run ...
   end

== end of file

Here, class Prog was able to refer to all Module methods, but class
datasource could not and i had to pass a ref of Prog, so it could.
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2008-10-04 11:26
>       p = new Prog...

Sorry that should read Prog.new (old java habits still lingering) , the
above is not the real source code, just a represntative sample.
F53b05cdbdf561cfe141f69b421244f3?d=identicon&s=25 David A. Black (Guest)
on 2008-10-04 13:34
(Received via mailing list)
Hi --

On Sat, 4 Oct 2008, Nit Khair wrote:

>>>
> Because my situation was like this (before refactoring). There were 2
>  require 'common'
>  include 'Common'

That's an error: you include modules, not strings. But there's no
Common module anyway, so it's an error either way.

>  class Datasource
>      # saves reference to Prog in constructor
>      def initialize (app)
>         @main = app
>      end
>
>
>      printme         # this failed.
>      @main.printme   # this works

If you fix the errors I pointed out above, both of these call printme.
@main is nil at this point (and keep in mind that this @main has
nothing to do with the @main in initialize).

>    end
>
>   class Prog < Application
>      new Datasource(self)

No such method.

>      printme  # works
>   end

This is so full of errors that it's impossible to know what your real
problem was. Can you post some actual code that illustrates the
problem? It's not only easier for people trying to help you but
ultimately much more relevant for you, if you present your actual
problem and not a set of problems that only exist because you've
introduced them into your post.


David
0026dd77fd9ecc97b36e5b79cdbcf590?d=identicon&s=25 R. Kumar (sentinel)
on 2008-10-04 14:30
David A. Black wrote:
> Hi --
>
> On Sat, 4 Oct 2008, Nit Khair wrote:
>
>
> This is so full of errors that it's impossible to know what your real
> problem was. Can you post some actual code that illustrates the
> problem? It's not only easier for people trying to help you but
> ultimately much more relevant for you, if you present your actual
> problem and not a set of problems that only exist because you've
> introduced them into your post.
>
>
> David
My sincere apologies. In future I will make a running sample before
posting.

I did make a sample, and found that the problem was the *variable* that
was in the scope of one class, not the other. So my question is
basically wrong - sorry again for wasting your time.
This topic is locked and can not be replied to.