How do I use define_method to create class methods?
51,272
Solution 1
I think in Ruby 1.9 you can do this:
class A
define_singleton_method :loudly do |message|
puts message.upcase
end
end
A.loudly "my message"
# >> MY MESSAGE
Solution 2
I prefer using send to call define_method, and I also like to create a metaclass method to access the metaclass:
class Object
def metaclass
class << self
self
end
end
end
class MyClass
# Defines MyClass.my_method
self.metaclass.send(:define_method, :my_method) do
...
end
end
Solution 3
This is the simplest way in Ruby 1.8+:
class A
class << self
def method_name
...
end
end
end
Solution 4
To be used in Rails if you want to define class methods dynamically from concern:
module Concerns::Testable
extend ActiveSupport::Concern
included do
singleton_class.instance_eval do
define_method(:test) do
puts 'test'
end
end
end
end
Solution 5
Derived from: Jay and Why, who also provide ways to make this prettier.
self.create_class_method(method_name)
(class << self; self; end).instance_eval do
define_method method_name do
...
end
end
end
Update: from VR's contribution below; a more concise method (as long as you're only defining one method this way) that is still standalone:
self.create_class_method(method_name)
(class << self; self; end).send(:define_method, method_name) do
...
end
end
but note that using send() to access private methods like define_method() is not necessarily a good idea (my understanding is that it is going away in Ruby 1.9).
Related videos on Youtube
Author by
Chinasaur
Updated on July 08, 2022Comments
-
Chinasaur almost 2 years
This is useful if you are trying to create class methods metaprogramatically:
def self.create_methods(method_name) # To create instance methods: define_method method_name do ... end # To create class methods that refer to the args on create_methods: ??? end
My answer to follow...
-
Chinasaur about 15 yearsI decided to go with my original answer. My understanding is that using send() to access private methods if going away in Ruby 1.9, so that didn't seem like a good thing to use. Plus if you are defining more than one method, instance_evaling a block is cleaner.
-
Chinasaur almost 15 yearsBetter (?) alternative may be to put things in a module and then have your create_class_method extend the module onto the class??? See: blog.jayfields.com/2008/07/ruby-underuse-of-modules.html
-
Amol Pujari almost 12 years@Vincent Robert any link which would explain the magic of metaclass method?
-
Vincent Robert almost 12 yearsclass << self; self; end; simply reopens the class of self (class << self) and then returns that class (self) so actually returning the metaclass of self.
-
Pyro over 11 yearsalso
singleton_class.define_method
-
A Fader Darkly about 11 yearsI really like this one. Small, neat, reads well and it's portable. Of course, you could ask what I'm doing using ruby 1.8 in 2013...
-
Joshua Pinter over 4 years@Pyro Just to clarify, would you just go
singleton_class.define_method :loudly do |message|
etc.?