2016-12-27 23 views
1

典型的な接頭辞を持つメソッドがたくさんあるとしましょう。メソッド名のプレフィックスを動的に生成

def pref_foo 
    # code 
end 

def pref_bar 
    # code 
end 

私は、自動的に(それがRailsの中で行うのかのように:Model.find_by_smth)私のメソッド名にそれらの接頭辞を付加する方法を学びたいです。私は自分の名前にする方法と前に付加pref_を取るので、私の方法foopref_fooとして利用可能となってきているいくつかのスコープpref_を、作成したい言い換えれば


module Bar 
    # definition of some wrapper `pref_` 
end 

class Foo 
    include Bar 

    <some wrapper from Bar> do 
    def foo 
     puts 'What does a computer scientist wear on Halloween?' 
    end 

    def bar 
     puts 'A bit-mask.' 
    end 
    end 
end 

foo = Foo.new 

foo.pref_foo # => "What does a computer scientist wear on Halloween?" 
foo.pref_bar # => "A bit-mask." 
+0

['method_missing'](https://ruby-doc.org/core-2.3.3/BasicObject.html#method-i-method_missing)を確認してください:) –

答えて

5

この作業を行いどのよう

class Module 
    def with_prefix(prefix, &block) 
    m = Module.new 
    m.instance_eval(&block) 
    m.methods(false).each do |name| 
     define_method "#{prefix}_#{name}", &m.method(name) 
     module_function "#{prefix}_#{name}" unless self.is_a?(Class) 
    end 
    end 
end 

class A 
    with_prefix :pref do 
    with_prefix :and do 
     def foo 
     puts "foo called" 
     end 

     def bar 
     puts "bar called" 
     end 
    end 
    end 
end 

A.new.pref_and_foo 
A.new.pref_and_bar 

、これを試してみてください?

  • 私たちは、この関数は、名前とブロック
  • を取るすべてのクラス
  • のスーパークラスに新しい機能with_prefixを定義するには、匿名のモジュールのコンテキストでブロックを評価します。
  • これは、そのモジュール
  • のすべての機能を超える匿名モジュールのdef文ではなく、クラス
  • 列挙あなたは、コールバックメソッドを使用することができ、これらの機能のそれぞれ
+0

驚くばかり!もう一つ質問: 'with_prefix'を入れ子にするにはどうしたらいいですか? – Viktor

+1

@viktordanilovが更新されました! – akuhn

+0

この回答は完全に恩恵に値します – Viktor

1

のための接頭辞のメソッドを作成し実行しModule#includedクラスメソッドMethod#instance_methods,Method#alias_method,Module#remove_methodおよびObject#sendを以下のように使用します。 alias_methodremove_methodはプライベートクラスのメソッドであるため、

module Bar 
    def self.included(klass) 
    klass.instance_methods(false).each do |m| 
     klass.send :alias_method, "pref_#{m.to_s}".to_sym, m 
     klass.send :remove_method, m 
    end 
    end 
end 

class Foo 
    def foo 
    puts 'hi' 
    end 

    def bar 
    puts 'ho' 
    end 

    include Bar 
end 

Foo.instance_methods.select { |m| [:foo, :bar, :pref_foo, :pref_bar].include?(m) } 
    #=> [:pref_foo, :pref_bar] 

Foo.new.pref_foo 
    #=> "hi" 

Foo.new.foo 
    #=> NoMethodError: undefined method `foo' for #<Foo:0x007fdecb0633d8> 

sendを使用する必要があります。文include Barは、明らかにFooのインスタンスメソッドの定義に従わなければなりません。

質問は "私のインスタンスメソッド名にプレフィックスを自動的に追加したい"という質問があるので、プレフィックスは配線されていなければなりません。

関連する問題