Method on module level not working

Hi,

I’ve written a little ruby application with roughly 20 methods in two classes which I have kind of wrapped in one module as a common namespace to hold everything together. I introduced optparse on the module level to parse options which worked fine. Then I decided to put the part related to parsing the options into a couple of methods due to readability / code style guide conformance but that’s not working anymore.

Here’s what the simplified working code comes down to:

  module ModuleWorking
    puts "This works"
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end

And here’s an example of what I’m trying to achieve but what’s not working:

  module ModuleNotWorking
    def another_method
      puts "This does not work"
    end
    another_method
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

As I’m still kind of a ruby newbie I’m probably missing a basic concept (OO?) but can’t really get my head around what’s wrong here…any hints would be most welcome!

Cheers,
Michael

Hi Michael,

another_method is an instance method. This means it can be called from
instances of objects that include ModuleNotWorking. The body of the module
is evaluated in the context of the module itself, i.e. self is
ModuleNotWorking. You can define a singleton method on self and then call
it, for instance:

module ModuleNotWorking
  def self.another_method
    puts "This DOES work"
  end

  another_method
end

One minor note: instead of running the setup code the moment the module is
evaluated you may consider adding a setup method and calling it explicitly.
For example:

# lib/your_module.rb
module YourModule
  def self.setup
    parse_args
    do_somethig_else
  end

  def self.parse_args
  end
end

# bin/app.rb
YourModule.setup

Cheers,
Greg Navis

···

On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze <michael@schwarze-web.de> wrote:

Hi,

I’ve written a little ruby application with roughly 20 methods in two
classes which I have kind of wrapped in one module as a common namespace to
hold everything together. I introduced optparse on the module level to
parse options which worked fine. Then I decided to put the part related to
parsing the options into a couple of methods due to readability / code
style guide conformance but that’s not working anymore.

Here’s what the simplified working code comes down to:

  module ModuleWorking
    puts "This works"
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end

And here’s an example of what I’m trying to achieve but what’s not working:

  module ModuleNotWorking
    def another_method
      puts "This does not work"
    end
    another_method
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end
#=> NameError: undefined local variable or method `another_method’ for
ModuleNotWorking:Module

As I’m still kind of a ruby newbie I’m probably missing a basic concept
(OO?) but can’t really get my head around what’s wrong here…any hints would
be most welcome!

Cheers,
Michael

  module ModuleWorking
    puts "This works"
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end

You should not have statements or method calls in the middle of
the module definition, like the 'puts' statement or 'another_method'
in your second example.

And here’s an example of what I’m trying to achieve but what’s not working:

  module ModuleNotWorking
    def another_method
      puts "This does not work"
    end
    another_method
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

Instead, define your modules and classes and then "do stuff"
by using them in the "main program", like this:

···

Am 04.11.2015 um 10:25 schrieb Michael Schwarze:

~~~
module ModuleWorking

  def self.another_method # note the 'self' -> module method
    puts "This works"
  end

  class MyClass

    def my_method
      puts "This works, too"
    end
  end
end

ModuleWorking.another_method

object = ModuleWorking::MyClass.new
object.my_method
~~~

Of course you can also use your methods from within other methods.

Regards,
Marcus

--
GitHub: stomar (Marcus Stollsteimer) · GitHub
PGP: 0x6B3A101A

Hi,

I’ve written a little ruby application with roughly 20 methods in two
classes which I have kind of wrapped in one module as a common namespace to
hold everything together. I introduced optparse on the module level to
parse options which worked fine.

Why do you use Optparse in a module? This is intended to be used for
processes because those only have a list of strings as arguments. For
libraries you can define arbitrary types as arguments or pass on individual
state. There is usually no need for parsing lists of strings.

Then I decided to put the part related to parsing the options into a
couple of methods due to readability / code style guide conformance but
that’s not working anymore.

Here’s what the simplified working code comes down to:

  module ModuleWorking
    puts "This works"
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end

And here’s an example of what I’m trying to achieve but what’s not working:

  module ModuleNotWorking
    def another_method
      puts "This does not work"
    end
    another_method
    class MyClass
      def my_method
        # lot’s of stuff omitted here
      end
    end
  end
#=> NameError: undefined local variable or method `another_method’ for
ModuleNotWorking:Module

Here is another way to make it work:

$ruby <<EXAMPLE
module ModuleNotWorking
  extend self

  def another_method
    puts "This does not work"
  end

  another_method

  class MyClass
    def my_method
       # lot’s of stuff omitted here
    end
  end
end
EXAMPLE
This does not work

Well, now the message is misleading. :slight_smile:

What this basically does it extends the module instance with itself making
all methods defined in the module available as instance methods of the
module itself. This is a more implicit variant of what Greg suggested.

As I’m still kind of a ruby newbie I’m probably missing a basic concept

(OO?) but can’t really get my head around what’s wrong here…any hints would
be most welcome!

No, you're not missing a basic concept - certainly not OO. This is
basically how modules work: they define instance methods that can be made
usable in two ways:

Classes including modules. Then all instances of these classes can use
methods defined in the module like they were defined as instance methods of
the class.

Use method Object#extend(module). This will make the instance's singleton
class include the module. Then the same mechanism applies as above and
methods defined in the module are available as instance methods of the
instance on which you invoked #extend.

You can try these things nicely in IRB. Helpful methods: Class#ancestors,
Object#singleton_class, Object#class.

Kind regards

robert

···

On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze <michael@schwarze-web.de> wrote:

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/

Hi Greg,

Many thanks! I have to dig a little bit deeper into the singleton method thing but it works. Actually your second example looks exactly like what I was trying to achieve.

Is this the „right“ / Ruby way of handling command-line arguments with a singleton setup method? Couldn’t really convince myself so far to putting it into an „artificial“ class, that’s why I put it at module level…

Cheers,
Michael

···

Am 04.11.2015 um 11:00 schrieb Greg Navis <contact@gregnavis.com>:

Hi Michael,

another_method is an instance method. This means it can be called from instances of objects that include ModuleNotWorking. The body of the module is evaluated in the context of the module itself, i.e. self is ModuleNotWorking. You can define a singleton method on self and then call it, for instance:

module ModuleNotWorking
def self.another_method
   puts "This DOES work"
end

another_method
end

One minor note: instead of running the setup code the moment the module is evaluated you may consider adding a setup method and calling it explicitly. For example:

# lib/your_module.rb
module YourModule
def self.setup
   parse_args
   do_somethig_else
end

def self.parse_args
end
end

# bin/app.rb
YourModule.setup

Cheers,
Greg Navis

On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze <michael@schwarze-web.de> wrote:
Hi,

I’ve written a little ruby application with roughly 20 methods in two classes which I have kind of wrapped in one module as a common namespace to hold everything together. I introduced optparse on the module level to parse options which worked fine. Then I decided to put the part related to parsing the options into a couple of methods due to readability / code style guide conformance but that’s not working anymore.

Here’s what the simplified working code comes down to:

module ModuleWorking
   puts "This works"
   class MyClass
     def my_method
       # lot’s of stuff omitted here
     end
   end
end

And here’s an example of what I’m trying to achieve but what’s not working:

module ModuleNotWorking
   def another_method
     puts "This does not work"
   end
   another_method
   class MyClass
     def my_method
       # lot’s of stuff omitted here
     end
   end
end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

As I’m still kind of a ruby newbie I’m probably missing a basic concept (OO?) but can’t really get my head around what’s wrong here…any hints would be most welcome!

Cheers,
Michael

Mit freundlichem Gruß
Michael Schwarze

Hi Marcus,

Many thanks to you, too; your slightly different perspective / example really helped, esp. your referencing of „main program“, which makes it clear, „where“ I am with my modules!

Best,
Michael

···

Am 04.11.2015 um 11:08 schrieb sto.mar@web.de:

Am 04.11.2015 um 10:25 schrieb Michael Schwarze:

module ModuleWorking
  puts "This works"
  class MyClass
    def my_method
      # lot’s of stuff omitted here
    end
  end
end

You should not have statements or method calls in the middle of
the module definition, like the 'puts' statement or 'another_method'
in your second example.

And here’s an example of what I’m trying to achieve but what’s not working:

module ModuleNotWorking
  def another_method
    puts "This does not work"
  end
  another_method
  class MyClass
    def my_method
      # lot’s of stuff omitted here
    end
  end
end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

Instead, define your modules and classes and then "do stuff"
by using them in the "main program", like this:

~~~
module ModuleWorking

def self.another_method # note the 'self' -> module method
  puts "This works"
end

class MyClass

  def my_method
    puts "This works, too"
  end
end
end

ModuleWorking.another_method

object = ModuleWorking::MyClass.new
object.my_method
~~~

Of course you can also use your methods from within other methods.

Regards,
Marcus

--
GitHub: stomar (Marcus Stollsteimer) · GitHub
PGP: 0x6B3A101A

Mit freundlichem Gruß
Michael Schwarze

Hi Robert,

My reason for using Optparse is its nice / consistent / unix-like way of handling command-line .arguments, esp. optional ones and without thinking about their order by using shortcuts (-h / —help, etc.), like in

bin/app.rb —input file.csv —output file.txt —format XYZ

Is there another / „better“ way of achieving this in Ruby?

Using it in a module / at module level was more or less accidentally…I think I got the point of the singleton / self thing, but I have to admit that Marcus’ and Gregs way does look more „naturally“ (easier?) to me, but that’s probably because I’m still not that familiar with the concept and have to play a little bit around with your example / methods.

Many thanks!

Cheers,
Michael

···

Am 04.11.2015 um 18:10 schrieb Robert Klemme <shortcutter@googlemail.com>:

On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze <michael@schwarze-web.de> wrote:
Hi,

I’ve written a little ruby application with roughly 20 methods in two classes which I have kind of wrapped in one module as a common namespace to hold everything together. I introduced optparse on the module level to parse options which worked fine.

Why do you use Optparse in a module? This is intended to be used for processes because those only have a list of strings as arguments. For libraries you can define arbitrary types as arguments or pass on individual state. There is usually no need for parsing lists of strings.

Then I decided to put the part related to parsing the options into a couple of methods due to readability / code style guide conformance but that’s not working anymore.

Here’s what the simplified working code comes down to:

module ModuleWorking
   puts "This works"
   class MyClass
     def my_method
       # lot’s of stuff omitted here
     end
   end
end

And here’s an example of what I’m trying to achieve but what’s not working:

module ModuleNotWorking
   def another_method
     puts "This does not work"
   end
   another_method
   class MyClass
     def my_method
       # lot’s of stuff omitted here
     end
   end
end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

Here is another way to make it work:

$ruby <<EXAMPLE
module ModuleNotWorking
extend self

def another_method
   puts "This does not work"
end

another_method

class MyClass
   def my_method
      # lot’s of stuff omitted here
   end
end
end
EXAMPLE
This does not work

Well, now the message is misleading. :slight_smile:

What this basically does it extends the module instance with itself making all methods defined in the module available as instance methods of the module itself. This is a more implicit variant of what Greg suggested.

As I’m still kind of a ruby newbie I’m probably missing a basic concept (OO?) but can’t really get my head around what’s wrong here…any hints would be most welcome!

No, you're not missing a basic concept - certainly not OO. This is basically how modules work: they define instance methods that can be made usable in two ways:

Classes including modules. Then all instances of these classes can use methods defined in the module like they were defined as instance methods of the class.

Use method Object#extend(module). This will make the instance's singleton class include the module. Then the same mechanism applies as above and methods defined in the module are available as instance methods of the instance on which you invoked #extend.

You can try these things nicely in IRB. Helpful methods: Class#ancestors, Object#singleton_class, Object#class.

Kind regards

robert

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can - without end}
http://blog.rubybestpractices.com/

Mit freundlichem Gruß
Michael Schwarze

…just one more thing :wink:

What’s your opinion on wrapping the contents of bin/app.rb into my module, too?

# bin/app.rb
module YourModule
   setup
   # probably more to follow here
end

Best,
Michael

···

Am 04.11.2015 um 21:23 schrieb Schwarze Consulting - Michael Schwarze <michael.schwarze@schwarze-consulting.de>:

Hi Greg,

Many thanks! I have to dig a little bit deeper into the singleton method thing but it works. Actually your second example looks exactly like what I was trying to achieve.

Is this the „right“ / Ruby way of handling command-line arguments with a singleton setup method? Couldn’t really convince myself so far to putting it into an „artificial“ class, that’s why I put it at module level…

Cheers,
Michael

Am 04.11.2015 um 11:00 schrieb Greg Navis <contact@gregnavis.com>:

Hi Michael,

another_method is an instance method. This means it can be called from instances of objects that include ModuleNotWorking. The body of the module is evaluated in the context of the module itself, i.e. self is ModuleNotWorking. You can define a singleton method on self and then call it, for instance:

module ModuleNotWorking
def self.another_method
  puts "This DOES work"
end

another_method
end

One minor note: instead of running the setup code the moment the module is evaluated you may consider adding a setup method and calling it explicitly. For example:

# lib/your_module.rb
module YourModule
def self.setup
  parse_args
  do_somethig_else
end

def self.parse_args
end
end

# bin/app.rb
YourModule.setup

Cheers,
Greg Navis

On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze <michael@schwarze-web.de> wrote:
Hi,

I’ve written a little ruby application with roughly 20 methods in two classes which I have kind of wrapped in one module as a common namespace to hold everything together. I introduced optparse on the module level to parse options which worked fine. Then I decided to put the part related to parsing the options into a couple of methods due to readability / code style guide conformance but that’s not working anymore.

Here’s what the simplified working code comes down to:

module ModuleWorking
  puts "This works"
  class MyClass
    def my_method
      # lot’s of stuff omitted here
    end
  end
end

And here’s an example of what I’m trying to achieve but what’s not working:

module ModuleNotWorking
  def another_method
    puts "This does not work"
  end
  another_method
  class MyClass
    def my_method
      # lot’s of stuff omitted here
    end
  end
end
#=> NameError: undefined local variable or method `another_method’ for ModuleNotWorking:Module

As I’m still kind of a ruby newbie I’m probably missing a basic concept (OO?) but can’t really get my head around what’s wrong here…any hints would be most welcome!

Cheers,
Michael

Mit freundlichem Gruß
Michael Schwarze

Hi Robert,

My reason for using Optparse is its nice / consistent / unix-like way of
handling command-line .arguments, esp. optional ones and without thinking
about their order by using shortcuts (-h / —help, etc.), like in

bin/app.rb —input file.csv —output file.txt —format XYZ

Is there another / „better“ way of achieving this in Ruby?

Yes, definitively! The usual pattern is to use a Hash in 1.9 and prior

irb(main):009:0> def foo(options = {}) a=options[:a]; b=options[:b]||2;
printf "a=%p b=%p\n", a, b end
=> :foo
irb(main):010:0> foo
a=nil b=2
=> nil
irb(main):011:0> foo(:a => 1)
a=1 b=2
=> nil
irb(main):012:0> foo(a: 3)
a=3 b=2
=> nil
irb(main):013:0> foo(b: 4)
a=nil b=4
=> nil
irb(main):014:0> foo(b: 5, a: 6)
a=6 b=5
=> nil

In 2.* you can use keyword arguments:

irb(main):029:0> def foo(a: nil, b: 2) printf "a=%p b=%p\n", a, b end
=> :foo
irb(main):030:0> foo
a=nil b=2
=> nil
irb(main):031:0> foo(a: 1)
a=1 b=2
=> nil
irb(main):032:0> foo(b: 3)
a=nil b=3
=> nil
irb(main):033:0> foo(b: 4, a: 5)
a=5 b=4
=> nil

There is no need to parse String values etc. For example, if you want to
provide numeric values you have to put them into a String otherwise
OptionParser will choke:

irb(main):039:0> op=OptionParser.new {|o| o.on("-x NUM", Integer) {|v| p v}}
...
irb(main):040:0> op.parse %w{-x 123} # Strings
123
=>
irb(main):041:0> op.parse ["-x", 123]
TypeError: no implicit conversion of Fixnum into String
        from /usr/share/ruby/2.2.0/optparse.rb:378:in `match'
        from /usr/share/ruby/2.2.0/optparse.rb:378:in `parse_arg'
        from /usr/share/ruby/2.2.0/optparse.rb:531:in `parse'
        from /usr/share/ruby/2.2.0/optparse.rb:1424:in `block in
parse_in_order'
        from /usr/share/ruby/2.2.0/optparse.rb:1383:in `catch'
        from /usr/share/ruby/2.2.0/optparse.rb:1383:in `parse_in_order'
        from /usr/share/ruby/2.2.0/optparse.rb:1377:in `order!'
        from /usr/share/ruby/2.2.0/optparse.rb:1469:in `permute!'
        from /usr/share/ruby/2.2.0/optparse.rb:1491:in `parse!'
        from /usr/share/ruby/2.2.0/optparse.rb:1480:in `parse'
        from (irb):41
        from /usr/bin/irb:11:in `<main>'

See here for example: https://robots.thoughtbot.com/ruby-2-keyword-arguments

Using it in a module / at module level was more or less accidentally…I

think I got the point of the singleton / self thing, but I have to admit
that Marcus’ and Gregs way does look more „naturally“ (easier?) to me, but
that’s probably because I’m still not that familiar with the concept and
have to play a little bit around with your example / methods.

I would consider the solution with extend(self) not very clean because I
think one should use a module either as a namespace OR as a container for
instance methods - but not both at the same time. I suggest you play a bit
around with the methods I mentioned to get the hang of it.

Many thanks!

You're welcome!

Kind regards

robert

···

On Tue, Nov 10, 2015 at 7:27 AM, Michael Schwarze <michael@schwarze-web.de> wrote:

--
[guy, jim, charlie].each {|him| remember.him do |as, often| as.you_can -
without end}
http://blog.rubybestpractices.com/

Hi Michael,

I'm glad you found my comment helpful.

Regarding the singleton setup method - you can create a class MyTool that
implements the logic of your tool (delegating to other objects if it has
subcommands or is more complicated). The script would look like:

MyTool.new(ARGV).run

The advantage of this approach is that it's _very_ testable.

You may also look into https://github.com/erikhuda/thor - I used it when I
needed a CLI tool. There are also other libraries of this type.

Best regards

···

--
Greg Navis

On Tue, Nov 10, 2015 at 7:27 AM, Michael Schwarze <michael@schwarze-web.de> wrote:

Hi Greg,

Many thanks! I have to dig a little bit deeper into the singleton method
thing but it works. Actually your second example looks exactly like what I
was trying to achieve.

Is this the „right“ / Ruby way of handling command-line arguments with a
singleton setup method? Couldn’t really convince myself so far to putting
it into an „artificial“ class, that’s why I put it at module level…

Cheers,
Michael

> Am 04.11.2015 um 11:00 schrieb Greg Navis <contact@gregnavis.com>:
>
> Hi Michael,
>
> another_method is an instance method. This means it can be called from
instances of objects that include ModuleNotWorking. The body of the module
is evaluated in the context of the module itself, i.e. self is
ModuleNotWorking. You can define a singleton method on self and then call
it, for instance:
>
> module ModuleNotWorking
> def self.another_method
> puts "This DOES work"
> end
>
> another_method
> end
>
> One minor note: instead of running the setup code the moment the module
is evaluated you may consider adding a setup method and calling it
explicitly. For example:
>
> # lib/your_module.rb
> module YourModule
> def self.setup
> parse_args
> do_somethig_else
> end
>
> def self.parse_args
> end
> end
>
> # bin/app.rb
> YourModule.setup
>
> Cheers,
> Greg Navis
>
> On Wed, Nov 4, 2015 at 10:25 AM, Michael Schwarze < > michael@schwarze-web.de> wrote:
> Hi,
>
> I’ve written a little ruby application with roughly 20 methods in two
classes which I have kind of wrapped in one module as a common namespace to
hold everything together. I introduced optparse on the module level to
parse options which worked fine. Then I decided to put the part related to
parsing the options into a couple of methods due to readability / code
style guide conformance but that’s not working anymore.
>
> Here’s what the simplified working code comes down to:
>
> module ModuleWorking
> puts "This works"
> class MyClass
> def my_method
> # lot’s of stuff omitted here
> end
> end
> end
>
> And here’s an example of what I’m trying to achieve but what’s not
working:
>
> module ModuleNotWorking
> def another_method
> puts "This does not work"
> end
> another_method
> class MyClass
> def my_method
> # lot’s of stuff omitted here
> end
> end
> end
> #=> NameError: undefined local variable or method `another_method’ for
ModuleNotWorking:Module
>
> As I’m still kind of a ruby newbie I’m probably missing a basic concept
(OO?) but can’t really get my head around what’s wrong here…any hints would
be most welcome!
>
> Cheers,
> Michael
>
>
>

Mit freundlichem Gruß
Michael Schwarze