How do I use define_method to create class methods

2020-01-27 10:33发布

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...

6条回答
乱世女痞
2楼-- · 2020-01-27 10:46

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
查看更多
何必那么认真
3楼-- · 2020-01-27 10:47

This is the simplest way in Ruby 1.8+:

class A
  class << self
    def method_name
      ...
    end
  end
end
查看更多
Lonely孤独者°
4楼-- · 2020-01-27 10:59

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
查看更多
\"骚年 ilove
5楼-- · 2020-01-27 10:59

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).

查看更多
一夜七次
6楼-- · 2020-01-27 11:01

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
查看更多
smile是对你的礼貌
7楼-- · 2020-01-27 11:01

You could also do something like this without relying on define_method:

A.class_eval do
  def self.class_method_name(param)
    puts param
  end
end

A.class_method_name("hello") # outputs "hello" and returns nil
查看更多
登录 后发表回答