2013-05-28 47 views
0

我有一个对象PersistentObject,你可以认为它是从ORM中弹出的,它是一个可以在你的编程语言中原生使用的对象(与后端无关),它有方法loadsave,数据库。在Ruby中,如何在实现为类方法的构造函数中初始化实例变量?

我希望我的PersistentObject是可伪造的,即我希望能够将它初始化为一个轻量级指针,该指针仅用于引用数据库中的对象。当(如果)时刻到了,我可以通过实际访问数据库并将其提取出来将它错误地写入内存。这里的要点是能够将该对象添加到集合中作为参考,而不需要获取对象。我也希望能够用传统的构造函数初始化旧的对象,然后将其提交给数据库(当你需要从头开始创建一个新对象,而不是操纵现有对象时,这很方便)。

所以我有一个对象具有多个构造函数:一个经典的,一个基于数据库中的对象GUID创建错误。当对象初始化为错误时,我希望实例方法能够作为实例变量访问该状态,因为错误操作与完全加载的对象上的操作不同。但由于显而易见的原因,我不希望客户弄乱我的内心状态,所以我不想为伊娃创建一个访问者。所以我的问题是,我如何从对象实例中的类方法初始化/设置ivar,以便我的类的外部客户端不能混淆它(即将其值设置为其他值)?

对不起,所有的代码应该使它更清晰。我试过一些显然不起作用的东西,但很好地说明了这一点。道歉,如果这是一个基本的问题,我对Ruby很新。

class PersistentObject 
    def initialize(opts={}) 
     @id = opts[:id] || new_id 
     @data = opts[:data] || nil 
    end 

    def self.new_fault(id) 
     new_object = PersistentObject.new 
     [email protected] = true   #<----- How do you achieve this? 
     new_object 
    end 

    def new_id 
     #returns a new globally unique id 
    end 

    def fault? 
     @fault 
    end 

    def load 
     if fault? 
      #fault in the object from the database by fetching the record corresponding to the id 
      @fault = false 
     end 
    end 

    def save 
     #save the object to the database 
    end 
end 

#I create a new object as a fault, I can add it to collections, refer to it all I want, etc., but I can't access it's data, I just have a lightweight pointer which can be created without ever hitting the database 
o = PersistentObject.new_fault("123") 

#Now let's suppose I need the object's data, so I'll load it 
o.load 

#Now I can use the object, change it's data, etc. 
p o.data 
o.data = "foo" 

#And when I'm ready I can save it back to the database 
o.save 

编辑: 我应该说,我的心脏没有被设置在从类方法访问该实例的伊娃,我很高兴地听到一个惯用的Ruby模式的解决此问题的详细。

回答

-1

这是不可能的。我不是在谈论“在Ruby中不可能”,我正在谈论数学,在逻辑上是不可能的。你有两个要求:

  1. 另一个物体不应该被允许设置@fault
  2. 另一个对象应该被允许设置@fault。 (记住,PersistentObject只是另一个对象。)

应该立即明显,这两个要求互相矛盾,因此,你想要什么根本无法来完成。期。

您可以为@fault创建一个attr_writer,然后PersistentObject可以写入...但其他人也可以。您可以让作者private,然后PersistentObject需要使用元编程(即编程)。send)来规避访问保护...但其他人也可以。您可以使用instance_variable_set直接让PersistentObject设置为@fault ...但其他人也可以。

0

如果你的目标是设置实例变量,那么我同意斯蒂芬的答案。为了回答您的编辑,另一种方法是另一种选择添加到构造:

class PersistentObject 
    def initialize(opts={}) 
     @id = opts[:id] || new_id 
     @data = opts[:data] || nil 
     @fault = opts[:fault] || false 
    end 

    def self.new_fault(id) 
     self.new(fault: true) 
    end 

    ... 

不幸的是,Ruby的非常规实施的私有/保护使它们不能存活了这个问题。

相关问题