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"
Extending a class method in a module
1) Cleaner/shorter
module ClassMethods
def wrap(method)
old = "_#{method}".to_sym
alias_method old, method
define_method method do |*args|
send(old, *args)
end
end
end
class Foo
extend ClassMethods
def bar(arg = 'foo')
puts arg
end
wrap :bar
end
As far as I know there is no way to achieve this without renaming. You could try to call super
inside the define_method
block. But first of all, a call to super
from within a define_method
will only succeed if you specify arguments explicitly, otherwise you receive an error. But even if you call e.g. super(*args)
, self
in that context would be an instance of Foo. So a call to bar
would go to the super classes of Foo
, not be found and ultimately result in an error.
2) Yes, like so
define_method method do |def_val='foo', *rest|
send(old, def_val, *rest)
end
However, in Ruby 1.8 it is not possible to use a block in define_method
, but this has been fixed for 1.9. If you are using 1.9, you could also use this
define_method method do |def_val='foo', *rest, &block|
send(old, def_val, *rest, &block)
end
3) No, unfortunately. alias_method
requires the existence of the methods that it takes as input. As Ruby methods come into existence as they are parsed, the wrap
call must be placed after the definition of bar
otherwise alias_method
would raise an exception.
Ruby: Do something when extending an instance with a module
You can define self.extended in the module:
module Mod
def self.extended(base)
raise "Cannot extend #{base}" unless base.is_a?(GoodKlass)
end
def hello
"Hello from Mod.\n"
end
end
extending class with modules containing class methods of the same name
module ModA
extend ActiveSupport::Concern
module ClassMethods
def bar
puts "this is method bar of ModA"
end
# grab UnboundMethod of ModA::ClassMethods::bar
a_bar = instance_method(:bar)
# using define_method to capture a_bar
define_method :extend_with_mod_a do
puts "extending #{self} with ModA"
# invoke ModA::ClassMethods::bar properly bound to the class being extended/included with ModA
a_bar.bind(self).call
end
end
end
Related Topics
Documentation for Psych To_Yaml Options
Multiple Level Nesting in Yaml
Suppresing Output to Console with Ruby
Rails - Aciverecord Use :Dependent => :Destroy on Condition
Rails Initializes Extremely Slow on Ruby 1.9.1
Expected #Count to Have Changed by 1, But Was Not Given a Block
Run a Command Line with Custom Environment
Convert Array-Of-Hashes to a Hash-Of-Hashes, Indexed by an Attribute of the Hashes
How to Convert Utf8 Combined Characters into Single Utf8 Characters in Ruby
What Are the Steps Needed to Create and Publish a Rubygem of Your Own
Lion Osx: How to Install Libfreetype.6.Dylib
Why Is Bigdecimal Returning a Weird Value
Require': Cannot Load Such File -- Spec_Helper (Loaderror)
Uninitialized Constant > Actioncable::Server::Configuration::Applicationcable
Find Case-Insensitive Word Matches in a Line
How to Add a Single Backslash Character to a String in Ruby
How to Call a Parent App's Helper Method from a Rails 3.1 Engine