2016-04-14 1 views
0

動的に生成されたクラスメソッドを記述することで自分のコードをDRYしようとしています。Rubyで動的に生成されるクラスに変数を渡す

私が欲しいのは、複数のエラークラスを持つことであるとClass.new {}ブロックに、変数を渡すことができないので、私は、

ルビー

class ChatPolicy::Error < StandardError 
ERROR_CLASSES = [ 
    { class_name: 'UserBlacklisted', message: 'Message 1' }, 
    { class_name: 'UserSuspended', message: 'Message 2' }, 
    { class_name: 'UserNotEligibleToRent', message: 'Message 3' }, 
    { class_name: 'MembershipTierNotAllowed', message: 'Message 4' } 
] 

ERROR_CLASSES.each do |cls| 
    Object.const_set(cls[:class_name], Class.new { 
     attr_reader :object 

     def initialize(object) 
      @object = object 
      @message = cls[:message] 
     end 
    }) 
end 
end 

ただし、次のコードを持っている。私はできませんメッセージ変数を初期化します。私はそれをどのように達成することができるのだろうか?話ではありません

答えて

2

defでメソッドを定義した場合、メソッド定義内の外側スコープのローカル変数、つまりの変数clsを参照することはできません。

はブロック内からそのようなローカル変数を参照し、ブロックを使用してdefine_methodのメソッドを作成できます。

だからあなたの例では、メソッド本体を使用すると、体内の clsを参照することができ、ブロックがあるので、それは今

define_method(:initialize) do |object| 

にライン

def initialize(object) 

を変更することにより、作業得ることができます。

+0

ありがとう@マット。今は動作しますが、コンソールからの警告があります。 '1:warning:トップレベルの定数UserSuspendedはChatPolicy :: Error :: UserSuspendedによって参照されています'どうすれば解決できるのでしょうか? –

+0

** ** **実際には、コンソールで 'ChatPolicy :: Error :: UserSuspended'と入力したときに' UserSuspended'になるので、実際には動作しません。 –

+0

@ mudasobwaの解決策に基づいて解決策を見つけました。 'Object_const_set'は' const_set'だけ使う必要はありません。 –

1

However, since in the Class.new {} block, the variable cannot be passed in.

「変数がで渡すことはできませんが、」これは、についてです「ブロック内で、受信機が異なるとclsローカル変数を解決することはできません。」という目標を達成するための2つの可能なアプローチがあります。 :

- 表示されているものから直接メッセージをルックアップ:

@message = ChatPolicy::Error::ERROR_CLASSES.detect do |hash| 
    hash[:class_name] == self.class.name 
end[:message] 

- 又はclass_evalを使用:

ERROR_CLASSES.each do |cls| 
    Object.const_set(cls[:class_name], class_eval %Q| 
     Class.new { 
     attr_reader :object 

     def initialize(object) 
      @object = object 
      @message = '#{cls[:message]}' # ⇐ HERE !!! 
     end 
    }|) 
end 

UPD @mattによるアプローチが優れています。私は歴史的な目的のためだけにこの答えを残す。

+0

あなたとマットのソリューションの両方が適切なソリューションに貢献しました。おかげで –

関連する問題