Does module Process have a private instance method 'wait'? - ruby

A few days ago, when I looked up my Dash documents, I found a weird ruby code snippet.
include Process
fork { exit 99 } #=> 27429
wait #=> 27429
$?.exitstatus #=> 99
The thing shocked me is why the Object class get the 'wait' instance method when it include the Process mudule. the Process module has only a class method 'wait' as the document indicated.

Many Ruby stdlib modules are written in a way that allows one to use either:
FileUtils.mkdir_p
or
include FileUtils
mkdir_p
This is done by using module_function:
module FileUtils
def mkdir_p(*args)
...
end
module_function :mkdir_p
end
This makes it possible to use the method as a class method with FileUtils.mkdir_p and as an instance method mkdir_p when included. It makes the instance method private when included:
class Foo
include FileUtils
def test
mkdir_p
end
end
Foo.mkdir_p # => NoMethodError (undefined method `mkdir_p`...
Foo.new.mkdir_p # => NoMethodError (private method `mkdir_p`...
Foo.new.test # => no problem there
It's also possible to make module functions private by using module_function together with private_class_method:
module AlarmClock
def is_it_time?
morning_yet?
end
module_function :is_it_time?
def morning_yet?
(7..11).cover?(Time.now.hour)
end
module_function :morning_yet?
private_class_method :morning_yet?
end
Now you have a public module function which uses a private module function and your module is still includable and usable in another class/module:
AlarmClock.morning_yet? # => NoMethodError (private method `morning_yet?' ..
AlarmClock.is_it_time? # => true
class WristWatch
include AlarmClock
def start_beeping
return "beep" if is_it_time?
end
def stop_beeping
return "silence" if !morning_yet?
end
end
WristWatch.new.morning_yet? # => NoMethodError (private ..
WristWatch.new.is_it_time? # => NoMethodError (private ..
WristWatch.new.start_beeping => "beep"
WristWatch.new.stop_beeping "silence"
Some stdlib modules have a helper method for not having to write two extra lines, for example fileutils.rb:
module FileUtils
def self.private_module_function(name) #:nodoc:
module_function name
private_class_method name
end
...
end
Process is built-in and written in C, so it does not come from something like process.rb, but I assume it has been written in a similiar manner.

Wait is an instance method of class Concurrent::Event which in turn is inherting from Module whose superclass is Object, thus you are able to access wait method.
For Reference:
https://www.rubydoc.info/github/ruby-concurrency/concurrent-ruby/Concurrent%2FEvent:wait.

Related

Is there to shorten `def self.method_name` and `def method_name` into one method?

So say I have this class:
class This
def a(that)
puts that
end
def self.b(that)
puts that
end
end
This.b("Hello!") # => passes
This.a("Hello!") # => fails
the_class = This.new()
the_class.b("Hello!") # => fails
the_class.a("Hello!") # => passes
Is there a way to shorten both of those methods into one method that is able to be called on a uninitialized object, AND is able to be called on an already initialized one, or will I always have to write a method like that twice?
You can extract the functionality into a module and both extend and include it.
module A
def a(that)
puts that
end
end
class This
include A # defines instance methods
extend A # defines class methods
end
This.a("foo") # => "foo"
This.new.a("foo") # => "foo"
Although I think it's more common to either include or extend and not both. The reason being that instance methods often depend on instance state, whereas class methods don't. If you have an instance This.new and want to call a class method, you can use .class i.e. This.new.class.a
The following bit of code uses some metaprogramming tricks to auto copy over any class methods to instances of that class.
module AutoAddMethods
def singleton_method_added(symbol)
define_method(symbol, method(symbol).to_proc)
end
end
class Foo
extend AutoAddMethods
#bar = 39
def initialize
#bar = 42
end
def test_one # Only added as an instance method.
puts "One #{#bar.inspect}"
end
def self.test_two # Added as both an instance and class method.
puts "Two #{#bar.inspect}"
end
end
i = Foo.new
i.test_one
i.test_two
Foo.test_two
And here is my test run output:
One 42
Two 39
Two 39
The test_two method is callable from both the class and its instances. It runs as if in the class.

What is the issue with the method acces in ancestors chain in Ruby

I have define a method that has few class inside of it and few modules. From one of the classes I am trying to call a method that is defined in a module(inside the common one) and I get an access error. Here is the full hierachy:
module Top
class NestedClass
#some code
NestedModule::method_name
end
module NestedModule
def method_name
#some code
end
end
end
And the error that I get: undefined method 'method_name' for Top::NestedModule:Module
Write it as :
module Top
module NestedModule
def self.method_name
#some code
end
end
class NestedClass
#some code
NestedModule::method_name
end
end
In your case you did NestedModule::method_name before defining the module NestedModule.
You cannot call undeclared methods as well as instance module methods directly.
Maybe this will clear things out for you:
module Top
module NestedModule
def self.module_method
1
end
def instance_method
2
end
end
class NestedClass
NestedModule.module_method # => 1
NestedModule.instance_method(:instance_method) # => #<UnboundMethod: Top::NestedModule#instance_method>
extend NestedModule
instance_method # => 2
include NestedModule
new.instance_method # => 2
end
end
And although "NestedModule::module_method" would also work here, the convention is to use dots when calling class/module methods, and double colons when accessing nested modules/classes.

Disable unused method in gem

I am trying to disable the unused method in gem that is present in my rails app. Is it possible?
You can use remove_method http://apidock.com/ruby/Module/remove_method
I'm curious why you want to do this though.
You can override the method and let it behave differently or the below ruby built in approach:
undef_method http://ruby-doc.org/core-2.0.0/Module.html#method-i-undef_method
or
remove_method http://ruby-doc.org/core-2.0.0/Module.html#remove_method-method
If you want to remove method from the particular class (not from the ancestors) you should use remove_method.
If also you want to search superclasses and mixed-in modules for a receiver then use undef_method.
There's also undef keyword which acts similar as remove_method but probably a bit faster. It receives method name (not symbol or string).
Usage:
class Parent
def foo; end
def baz; end
end
class Child < Parent
def bar; end
end
Child.send :remove_method, :bar # I use send for space-economy.
# You should reopen the class
Child.new.bar # => NoMethodError
Child.send :remove_method, :foo # NameError: method `foo' not defined in Child
Child.send :undef_method, :foo
Child.new.foo # => NoMethodError
Parent.class_eval { undef baz }
Parent.new.baz # => NoMethodError

Accessing Private Methods from Module Functions in Ruby

I'm trying to create private helper methods for module functions to no avail. I feel like there's something very simple I'm missing.
Updated example with a more understandable use case:
module FancyScorer
module_function
def score(ary)
scores = []
ary.each_slice(2).with_index do |slice, i|
scores <<
case i % 2
when 0
score_eventh(ary)
else
score_oddth(ary)
end
end
scores.inject(:+)
end
private
def score_eventh(ary)
ary.inject(:+) / (ary.size - 1)
end
def score_oddth(ary)
ary.inject(:*) / (ary.size - 1)
end
end
FancyScorer.score([1,2,3,4])
# => `block in score_curiously': undefined method `score_eventh'
# for FancyScorer:Module (NoMethodError)
Note: The private methods should remain private.
Here's the use case: there are several modules that contain various scoring techniques, e.g. FancyScorer, SimpleScorer, ComplexScorer. These functions are tested independently, and then are employed to create a score method for different classes. For instance:
class A
...
def score
FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics)
end
end
class B
...
def score
0.5*FancyScorer.score(metrics) + 2*SimpleScorer.score(metrics[0,3]) + ComplexScorer.score(metrics)
end
end
Previous example with no provided use case:
module Party
module_function
def pooper
enjoy
end
private
def enjoy
puts "Wahoo!"
end
end
Party.pooper
# => NameError: undefined local variable or method `enjoy' for Party:module
# from (party): in `pooper`
module_function(symbol, ...) → self says:-
Creates module functions for the named methods. These functions may be called with the module as a receiver, and also become available as instance methods to classes that mix in the module. Module functions are copies of the original, and so may be changed independently. The instance-method versions are made private. If used with no arguments, subsequently defined methods become module functions.
You need to make sure you declare the helper method as a #private_class_method: private only affects instance methods.
module Party
def enjoy
puts 'hello'
end
def pooper
enjoy
end
private_class_method :enjoy
module_function :pooper
end
Party.pooper # => 'hello'
Party.enjoy # => private method `enjoy' called for Party:Module (NoMethodError)
Furthermore, you should be careful about the ordering of accessibility keywords like public, private, and module_function. These do not overlap, but rather override.
module Party
module_function # Module function declarations begin
def pooper
bar
end
def bar
enjoy
end
private # Private declarations begin, module function declarations end
module_function # Private declarations end, module function declarations begin
def enjoy # Therefore, this is a module function
"Wahoo!"
end
end
Party.pooper # => "Wahoo!"
Party.bar # => "Wahoo!"
Party.enjoy # => "Wahoo!" <-- No longer private
Note here module_function overrides the previous private declaration.
Here some more examples when module_function will do its job, and when not.
The module_function definitions stop once another accessibility keyword pops up. In this example, module_function is interrupted by public making #pooper a public instance method. Use of private would similarly block module_method.
module Party
module_function
public
def pooper
"i am pooper"
end
end
Party.pooper
# undefined method `pooper' for Party:Module (NoMethodError)
Now if the order is changed:
module Party
public
module_function
def pooper
"i am pooper"
end
end
Party.pooper # => "i am pooper"

Can I invoke an instance method on a Ruby module without including it?

Background:
I have a module which declares a number of instance methods
module UsefulThings
def get_file; ...
def delete_file; ...
def format_text(x); ...
end
And I want to call some of these methods from within a class. How you normally do this in ruby is like this:
class UsefulWorker
include UsefulThings
def do_work
format_text("abc")
...
end
end
Problem
include UsefulThings brings in all of the methods from UsefulThings. In this case I only want format_text and explicitly do not want get_file and delete_file.
I can see several possible solutions to this:
Somehow invoke the method directly on the module without including it anywhere
I don't know how/if this can be done. (Hence this question)
Somehow include Usefulthings and only bring in some of it's methods
I also don't know how/if this can be done
Create a proxy class, include UsefulThings in that, then delegate format_text to that proxy instance
This would work, but anonymous proxy classes are a hack. Yuck.
Split up the module into 2 or more smaller modules
This would also work, and is probably the best solution I can think of, but I'd prefer to avoid it as I'd end up with a proliferation of dozens and dozens of modules - managing this would be burdensome
Why are there lots of unrelated functions in a single module? It's ApplicationHelper from a rails app, which our team has de-facto decided on as the dumping ground for anything not specific enough to belong anywhere else. Mostly standalone utility methods that get used everywhere. I could break it up into seperate helpers, but there'd be 30 of them, all with 1 method each... this seems unproductive
I think the shortest way to do just throw-away single call (without altering existing modules or creating new ones) would be as follows:
Class.new.extend(UsefulThings).get_file
If a method on a module is turned into a module function you can simply call it off of Mods as if it had been declared as
module Mods
def self.foo
puts "Mods.foo(self)"
end
end
The module_function approach below will avoid breaking any classes which include all of Mods.
module Mods
def foo
puts "Mods.foo"
end
end
class Includer
include Mods
end
Includer.new.foo
Mods.module_eval do
module_function(:foo)
public :foo
end
Includer.new.foo # this would break without public :foo above
class Thing
def bar
Mods.foo
end
end
Thing.new.bar
However, I'm curious why a set of unrelated functions are all contained within the same module in the first place?
Edited to show that includes still work if public :foo is called after module_function :foo
Another way to do it if you "own" the module is to use module_function.
module UsefulThings
def a
puts "aaay"
end
module_function :a
def b
puts "beee"
end
end
def test
UsefulThings.a
UsefulThings.b # Fails! Not a module method
end
test
If you want to call these methods without including module in another class then you need to define them as module methods:
module UsefulThings
def self.get_file; ...
def self.delete_file; ...
def self.format_text(x); ...
end
and then you can call them with
UsefulThings.format_text("xxx")
or
UsefulThings::format_text("xxx")
But anyway I would recommend that you put just related methods in one module or in one class. If you have problem that you want to include just one method from module then it sounds like a bad code smell and it is not good Ruby style to put unrelated methods together.
To invoke a module instance method without including the module (and without creating intermediary objects):
class UsefulWorker
def do_work
UsefulThings.instance_method(:format_text).bind(self).call("abc")
...
end
end
Not sure if someone still needs it after 10 years but I solved it using eigenclass.
module UsefulThings
def useful_thing_1
"thing_1"
end
class << self
include UsefulThings
end
end
class A
include UsefulThings
end
class B
extend UsefulThings
end
UsefulThings.useful_thing_1 # => "thing_1"
A.new.useful_thing_1 # => "thing_1"
B.useful_thing_1 # => "thing_1"
Firstly, I'd recommend breaking the module up into the useful things you need. But you can always create a class extending that for your invocation:
module UsefulThings
def a
puts "aaay"
end
def b
puts "beee"
end
end
def test
ob = Class.new.send(:include, UsefulThings).new
ob.a
end
test
A. In case you, always want to call them in a "qualified", standalone way (UsefulThings.get_file), then just make them static as others pointed out,
module UsefulThings
def self.get_file; ...
def self.delete_file; ...
def self.format_text(x); ...
# Or.. make all of the "static"
class << self
def write_file; ...
def commit_file; ...
end
end
B. If you still want to keep the mixin approach in same cases, as well the one-off standalone invocation, you can have a one-liner module that extends itself with the mixin:
module UsefulThingsMixin
def get_file; ...
def delete_file; ...
def format_text(x); ...
end
module UsefulThings
extend UsefulThingsMixin
end
So both works then:
UsefulThings.get_file() # one off
class MyUser
include UsefulThingsMixin
def f
format_text # all useful things available directly
end
end
IMHO it's cleaner than module_function for every single method - in case want all of them.
As I understand the question, you want to mix some of a module's instance methods into a class.
Let's begin by considering how Module#include works. Suppose we have a module UsefulThings that contains two instance methods:
module UsefulThings
def add1
self + 1
end
def add3
self + 3
end
end
UsefulThings.instance_methods
#=> [:add1, :add3]
and Fixnum includes that module:
class Fixnum
def add2
puts "cat"
end
def add3
puts "dog"
end
include UsefulThings
end
We see that:
Fixnum.instance_methods.select { |m| m.to_s.start_with? "add" }
#=> [:add2, :add3, :add1]
1.add1
2
1.add2
cat
1.add3
dog
Were you expecting UsefulThings#add3 to override Fixnum#add3, so that 1.add3 would return 4? Consider this:
Fixnum.ancestors
#=> [Fixnum, UsefulThings, Integer, Numeric, Comparable,
# Object, Kernel, BasicObject]
When the class includes the module, the module becomes the class' superclass. So, because of how inheritance works, sending add3 to an instance of Fixnum will cause Fixnum#add3 to be invoked, returning dog.
Now let's add a method :add2 to UsefulThings:
module UsefulThings
def add1
self + 1
end
def add2
self + 2
end
def add3
self + 3
end
end
We now wish Fixnum to include only the methods add1 and add3. Is so doing, we expect to get the same results as above.
Suppose, as above, we execute:
class Fixnum
def add2
puts "cat"
end
def add3
puts "dog"
end
include UsefulThings
end
What is the result? The unwanted method :add2 is added to Fixnum, :add1 is added and, for reasons I explained above, :add3 is not added. So all we have to do is undef :add2. We can do that with a simple helper method:
module Helpers
def self.include_some(mod, klass, *args)
klass.send(:include, mod)
(mod.instance_methods - args - klass.instance_methods).each do |m|
klass.send(:undef_method, m)
end
end
end
which we invoke like this:
class Fixnum
def add2
puts "cat"
end
def add3
puts "dog"
end
Helpers.include_some(UsefulThings, self, :add1, :add3)
end
Then:
Fixnum.instance_methods.select { |m| m.to_s.start_with? "add" }
#=> [:add2, :add3, :add1]
1.add1
2
1.add2
cat
1.add3
dog
which is the result we want.
After almost 9 years here's a generic solution:
module CreateModuleFunctions
def self.included(base)
base.instance_methods.each do |method|
base.module_eval do
module_function(method)
public(method)
end
end
end
end
RSpec.describe CreateModuleFunctions do
context "when included into a Module" do
it "makes the Module's methods invokable via the Module" do
module ModuleIncluded
def instance_method_1;end
def instance_method_2;end
include CreateModuleFunctions
end
expect { ModuleIncluded.instance_method_1 }.to_not raise_error
end
end
end
The unfortunate trick you need to apply is to include the module after the methods have been defined. Alternatively you may also include it after the context is defined as ModuleIncluded.send(:include, CreateModuleFunctions).
Or you can use it via the reflection_utils gem.
spec.add_dependency "reflection_utils", ">= 0.3.0"
require 'reflection_utils'
include ReflectionUtils::CreateModuleFunctions
This old question comes to me today when I am studing Ruby and found interesting so I want to answer with my new knowlege.
Assume that you have the module
module MyModule
def say
'I say'
end
def cheer
'I cheer'
end
end
then with the class so call Animal I can take cheer method from MyModule as following
class Animal
define_method(:happy, MyModule.method(:cheer))
end
This is so called unbound method, so you can take a callable object and bind it to another place(s).
From this point, you can use the method as usual, such as
my_dog = Animal.new
my_dog.happy # => "I cheer"
Hope this help as I also learned something new today.
To learn further, you can use irb and take a look at Method object.

Resources