Ruby: Is it possible to define a class method in a module?
module Common
def foo
puts 'foo'
end
end
class A
extend Common
end
class B
extend Common
end
class C
extend Common
end
A.foo
Or, you can extend the classes afterwards:
class A
end
class B
end
class C
end
[A, B, C].each do |klass|
klass.extend Common
end
Define a class method in a module
You can extend
the module in your class, your code should be like this:
module Base
def all
puts "All Users"
end
end
class User
extend Base
end
When you do something like this:
module MyModule
def self.module_method
puts "module!"
end
end
You're actually adding the method in the module itself, you could call the previous method like this:
MyModule.module_method
There is a way to just include the module
and get the behaviour that you want, but I don't think this could be considered the "way to go". Look at the example:
module Base
def self.included(klass)
def klass.all
puts "all users"
end
end
end
class User
include Base
end
But like I said, if you can go with the extend
class method, it is a better suit.
Ruby: Use module method inside a class method
By including the module, you make module_method
is an instance method on TestClass
, meaning you need to invoke it on an instance of the class, not the class itself.
If you want to make it a method on the class itself, you need to extend TestModule
, not include
it.
module TestModule
def module_method
"module"
end
end
class TestClass
extend TestModule # extend, not include
def self.testSelfMethod
str = module_method
puts str
end
TestClass.testSelfMethod # "method"
end
What are the practical differences between a module method and a class method in Ruby?
tl;dr: There are no class methods and module methods in Ruby, only instance methods. Considering that they are both just instance methods, and thus the same thing, there cannot possibly be any difference.
There is no such thing as a "class method" or a "module method" in Ruby. Ruby has exactly one kind of method: instance methods.
We sometimes use the word "class method" or "module method" out of convenience when talking about a certain pattern of using instance methods, but there is no such concept in Ruby. "Class methods" and "module methods" are really just singleton methods of an object which just happens to be an instance of the Module
class or the Class
class. There is absolutely no difference whatsoever between a singleton method of an object which happens to be an instance of Class
, Module
, String
, Array
, Hash
, Object
, Foo
, Bar
, Whatever
, or Garbledigookidoo
.
Oh. Did I mention? Singleton methods don't exist, either. Again, it is a word we use for certain kinds of usages of methods, but they are really just regular boring old instance methods of the singleton class of an object.
However, "instance method of the singleton class of foo
" and "instance method of the singleton class of Foo
, where Foo
is an instance of Class
" are really long, and so we shorten them to "singleton method of foo
" and "class method of Foo
" out of convenience, knowing full well that those are fictions that don't actually exist in the language.
Unlike Java, which has three different kinds of methods (instance methods, static methods, and constructors (which are kinda-sorta like methods)), Ruby has exactly one kind of method: instance methods. No class methods, no module methods, no global methods, no top-level methods, no static methods, no constructors. It does, however, have three kinds of classes: regular classes, singleton classes, and include classes (the latter being classes that get synthesized and injected into the inheritance hierarchy when you call include
or prepend
). These classes differ mainly in whether methods like Object#class
, Class#superclass
, and Class#ancestors
display them or suppress them. Singleton classes are suppressed by all of them, include classes by the first two, but shown by ancestors
.
Is there a way to use class method in a module without extend it in rails?
Use Module#module_function
to make a single function to be a module function:
module M
def m1; puts "m1"; end
def m2; puts "m2"; end
module_function :m2
end
or:
module M
def m1; puts "m1"; end
module_function # from now on all functions are defined as module_functions
def m2; puts "m2"; end
end
M.m1 #⇒ NoMethodError: undefined method `m1' for M:Module
M.m2 #⇒ "m2"
self.included – including class methods from a module in Ruby
What's the difference between the two examples?
The first code block adds the class methods in ClassMethods
to the including class and calls the scope
method on it as well. The second one does neither of these things and will result in a NoMethodError
because the module has no scope
class method. self.some_class_method
will not be available on the including class once the module is included.
For the full story on how module inclusion works in Ruby, read my answer here:
Inheriting class methods from modules / mixins in Ruby
What's the point of self.included
if a module's sole purpose is to be included?
Inclusion is not the only purpose of modules. They are also used for other things such as namespacing or simply storing various class methods that are then callable on the module itself.
Why doesn't Ruby include class methods automatically?
Theoretically Ruby could automatically add all class methods defined in a module to the including class, but in practice that would be a bad idea, because you would not get to choose anymore whether you want to include class methods — all class methods would be included every time, whether or not they are intended to be included. Consider this example:
module M
def self.class_method
"foo"
end
def self.configure_module
# add configuration for this module
end
end
class C
include M
end
Here, the configure_module
method is obviously not supposed to be added to C
, as its purpose is to set the configuration for the module object. Yet, if we had auto-inclusion for class methods, you would not be able to prevent it from being included.
But all instance methods are already included! How is that okay then?
Instance methods in a module are only really useful if they are included into a class, since modules cannot have instances, only classes can. So in a module every instance method is expected to be included somewhere to work.
A "class" method on a module is different, because it can be called on the module itself, so it can be used just fine regardless of whether it's also added to the including class. That is why it is better that you have a choice there.
Define a class method in a module with a variable name
When you define Filters::Base::ClassMethods
, it evaluates self in that context so the method you'll end up defining is ClassMethods.classmethods
(since the gsub won't do anything).
Like the included hook you tapped into in Base, you want to use extended in ClassMethods:
module Filters
module Base
module ClassMethods
@@filters = {}
def filter name, &block
@@filters[name] = block
end
def run query = {}
query.each do |name, value|
@@filters[name.to_sym].call(value) unless @@filters[name.to_sym].nil?
end
Object.const_get(self.to_s.gsub('Filter', ''))
end
def self.extended(base)
define_method(base.to_s.downcase.gsub('filter', '').to_sym) do
Object.const_get(self.to_s.gsub('Filter', ''))
end
end
end
def self.included base
base.extend ClassMethods
end
end
end
class ShowFilter
include Filters::Base
filter :title do |title|
self.show.where(:title => title)
end
end
Define class method based on import success
Thanks for all the hints I received
the solution I'm going to use is:
try:
import numpy
except ImportError:
numpy = None
class xxx:
if numpy:
def main2():
ret_array= numpy.array([],dtype=numpy.double)
return ret_array
else:
def main2():
print ("do nothing")
How to access class method from the included hook of a Ruby module
There'a a method_added
callback you could use:
module MyModule
def self.included(includer)
def includer.method_added(name)
puts "Method added #{name.inspect}"
end
end
end
class MyClass
include MyModule
def foo ; end
end
Output:
Method added :foo
If you want to track both, existing and future methods, you might need something like this:
module MyModule
def self.on_method(name)
puts "Method #{name.inspect}"
end
def self.included(includer)
includer.instance_methods(false).each do |name|
on_method(name)
end
def includer.method_added(name)
MyModule.on_method(name)
end
end
end
Example:
class MyClass
def foo ; end
include MyModule
def bar; end
end
# Method :foo
# Method :bar
Related Topics
How to Condense Summable Metrics to a Unique Identifier in a Ruby Table
What Is the Fully Qualified Name of a Model in Ruby on Rails
Why Won't Ternary Operator Work with Redirect
Ruby, Value Bucketing, Beautify Code
Rspec - How to Test Activerecord::Recordnotfound
Watir Won't Download PDF, Only Opens in Viewer
Ruby String Prepend '\' Character
Login Session Data Not Persisting in Rails 6
How to Install Nokogiri on MAC Os Sierra 10.12
How to Add 'Each' Method to Ruby Object (Or Should I Extend Array)
Instagram Ruby Gem - Unable to Reach Callback Url
Bind and Destructure Block Arguments
How to Sign Out in a Rails App, Using Devise Gem, No Route Matches /Users/Sign_Out
Replacing an Element in Nested Array Ruby
Selenium Can't Find Fields with Type Number
I Want to Match All Punctuation in My Regexp Except Apostrophes. How to Do That in Ruby
Why Can't I Create Active Records That Count for Something in Rspec
How to Keep Sending Emails to Users Every Week Depending on User Date Input in Rails