2016-04-14 27 views
0

我想通过编写一个动态生成的类方法来干我的代码。将变量传递到Ruby中的动态生成的类

我想是有多个错误类和我有以下代码

红宝石

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 

然而,由于在Class.new {}块,变量不能被通过。我不能初始化消息变量。我想知道如何才能做到这一点?

回答

2

当您使用def定义方法时,不能在方法定义中引用外部范围的局部变量,即initialize方法中的cls变量。

可以指的是块内部的这种局部变量,您可以使用块创建一个方法define_method

所以在你的榜样,你可以得到它的工作通过改变线路

def initialize(object) 

define_method(:initialize) do |object| 

现在,因为该方法的身体是你可以参考cls身体内部的块。

+0

谢谢@matt。它现在有效,但控制台发出警告。 '1:警告:顶级常量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局部变量不能得到解决。”有实现目标两种可能的方法:

- 直接从什么是可见查找消息:

@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

您和马特的解决方案都为您提供正确的解决方案。谢谢 –

相关问题