web-dev-qa-db-ja.com

define_methodを使用してクラスメソッドを作成するにはどうすればよいですか?

これは、メタメソッドでクラスメソッドを作成しようとしている場合に便利です。

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

フォローする私の答え...

102
Chinasaur

Ruby 1.9ではこれを行うことができます:

class A
  define_singleton_method :loudly do |message|
    puts message.upcase
  end
end

A.loudly "my message"

# >> MY MESSAGE
186
fguillen

Sendを使用してdefine_methodを呼び出すことを好み、メタクラスにアクセスするためのメタクラスメソッドを作成することも好きです。

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
25
Vincent Robert

これはRuby 1.8+で最も簡単な方法です:

class A
  class << self
    def method_name
      ...
    end
  end
end
11
Joseph Jaber

派生元: Jay および Why .

self.create_class_method(method_name)
  (class << self; self; end).instance_eval do
    define_method method_name do
      ...
    end
  end
end

Update:以下のVRの貢献による;より簡潔なメソッド(この方法で1つのメソッドのみを定義している限り)は、まだスタンドアロンです。

self.create_class_method(method_name)
  (class << self; self; end).send(:define_method, method_name) do
    ...
  end
end

ただし、send()を使用してdefine_method()などのプライベートメソッドにアクセスすることは必ずしも良い考えではないことに注意してください(Ruby 1.9)でなくなる予定です)。

8
Chinasaur

Railsで使用します。懸念から動的にクラスメソッドを定義する場合:

module Concerns::Testable
  extend ActiveSupport::Concern

  included do 
    singleton_class.instance_eval do
      define_method(:test) do
        puts 'test'
      end
    end
  end
end
5
Artur Beljajev

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
0
Bijan