使用超类不是gem的克隆方法制作ruby对象的深层副本

时间:2015-08-03 21:34:06

标签: ruby-on-rails ruby ruby-on-rails-4 ruby-on-rails-3.2

我有ruby类,我正在尝试实现克隆方法。我希望能够使用所有类都可以继承的通用克隆方法。类的属性可以是数组类型,散列或其他对象。

我可以使它更通用,以便深入克隆吗?可能在超类QueryModel中定义一个克隆方法?怎么会有用?

class Bool < QueryModel

  attr_accessor :name, :should, :must, :must_not

  def clone
    Bool.new(self.name, self.should.clone, self.must.clone, self.must_not.clone) 
  end


  def serialize
      result_hash = {}
      query_hash = {}

      if( instance_variable_defined?(:@should) )
      query_hash[:should] = @should.serialize
      end

      if( instance_variable_defined?(:@must) )
        query_hash[:must] = @must.serialize
      end

      if( instance_variable_defined?(:@must_not) )
        query_hash[:must_not] = @must_not.serialize
      end

      if( instance_variable_defined?(:@should) || instance_variable_defined?(:@must) || instance_variable_defined?(:@must_not) )
        return result_hash = query_hash
    end
  end
end

以下是可能使用克隆的地方:

class Query < QueryModel

  attr_accessor :query_string, :query, :bool

  def serialize 
    result_hash = {}
    query_hash = {}

    if( instance_variable_defined?(:@query_string) )
      query_hash[:query_string] = @query_string.serialize
      #result_hash[:query] = query_hash
    end

    if( instance_variable_defined?(:@query) )
      query_hash[:query] = @query
    end

    if( !instance_variable_defined?(@bool) )
      if( instance_variable_defined?(:@query) || instance_variable_defined?(:@query_string) )
        result_hash[:query] = query_hash
        return result_hash
      end
    else
      bool =  @bool.clone
      result_hash[:query] = bool
    end

  end

end

2 个答案:

答案 0 :(得分:0)

如果您不害怕新宝石,amoeba宝石拥有克隆AR对象所需的一切。如果你真的只想复制对象的属性而不是关系,那么dup方法就是你想要的。

更新:抱歉,昨天晚了,我以为你是以某种方式使用ActiveRecord。对于纯ruby解决方案,只需使用Object#clone方法而不覆盖,并指定Object#clone的行为,如下所示:

class Bool
  def initialize_copy(original)
    super # this already clones instance vars that are not objects

    # your custom strategy for 
    # referenced objects can be here

  end
end

以下是docs对此的评论。

答案 1 :(得分:0)

如果您使用创建/原型设计模式解决问题,您可以执行以下示例 -

class ConcretePrototype
  def copy
  prototype = clone

    instance_variables.each do |ivar_name|
      prototype.instance_variable_set( ivar_name,
      instance_variable_get(ivar_name).clone)
    end

    prototype
  end
end

class Application
  def run
    concreate_prototype = ConcretePrototype.new
    concreate_prototype_2 = concreate_prototype.copy
    puts concreate_prototype.inspect
    puts concreate_prototype_2.inspect
  end
end

这样你可以在没有任何宝石的情况下深度克隆对象。 参考 - https://github.com/vatrai/design_patterns/blob/master/creational/prototype.rb