2012-05-17 6 views

Respuesta

-2

Recomiendo agregar un método to_yaml personalizado en su clase que construye el formato yaml específico que desea.

Sé que to_json acepta parámetros para indicarle qué atributos serializar, pero no puedo encontrar lo mismo para to_yaml.

Aquí está la fuente real de to_yaml:

# File activerecord/lib/active_record/base.rb, line 653 

    def to_yaml(opts = {}) #:nodoc: 
    if YAML.const_defined?(:ENGINE) && !YAML::ENGINE.syck? 
     super 
    else 
     coder = {} 
     encode_with(coder) 
     YAML.quick_emit(self, opts) do |out| 
     out.map(taguri, to_yaml_style) do |map| 
      coder.each { |k, v| map.add(k, v) } 
     end 
     end 
    end 
    end 

lo que parece que puede haber una oportunidad para establecer opts para que incluya pares clave/valor específicos en el yaml.

8

Después de una cantidad excesiva de búsqueda me encontré con esto:

class Point 
    def to_yaml_properties 
    ["@x", "@y"] 
    end 
end 

Este método se utiliza para seleccionar las propiedades que YAML serializa el procesamiento. Existe un enfoque más poderoso que involucra emisores personalizados (en Psych) pero no sé de qué se trata.

Esta solución solo funciona en Ruby 1.8; en Ruby 1.9, to_yaml ha cambiado a usar Psych, para lo cual la respuesta de Matt es encode_with.

22

En Ruby 1.9, to_yaml_properties is deprecated; si está usando Ruby 1.9, un método de prueba más futuro sería utilizar encode_with:

class Point 
    def encode_with coder 
    coder['x'] = @x 
    coder['y'] = @y 
    end 
end 

En este caso, eso es todo lo que necesita, como el valor predeterminado es establecer la variable de instancia correspondiente del nuevo objeto a la valor apropiado cuando se carga de Yaml, pero en casos más comple se podría utilizar init_with:

def init_with coder 
    @x = coder['x'] 
    @y = coder['y'] 
end 
+0

FYI: Si sobrescribe # '' init_with' para una subclase de ActiveRecord :: base', recuerde que debe volver 'self', de lo contrario cualquier momento se instancia un modelo que lo hará devuelve nil. – siannopollo

1

Si desea que todos los campos, pero unos pocos, que podría hacer esto

def encode_with(coder) 
    vars = instance_variables.map{|x| x.to_s} 
    vars = vars - ['@unwanted_field1', '@unwanted_field2'] 

    vars.each do |var| 
    var_val = eval(var) 
    coder[var.gsub('@', '')] = var_val 
    end 
end 

Esto le impide tener que administrar manualmente la lista. Probado en Ruby 1.9

1

Si usted tiene un montón de variables de instancia, se puede usar una versión corta como ésta

def encode_with(coder) 
    %w[ x y a b c d e f g ].each { |v| coder[ v ] = instance_variable_get "@#{v}" } 
end 
0

Debe utilizar #encode_with porque #to_yaml_properties está en desuso:

def encode_with(coder) 
    # remove @unwanted and @other_unwanted variable from the dump 
    (instance_variables - [:@unwanted, :@other_unwanted]).each do |var| 
    var = var.to_s      # convert symbol to string 
    coder[var.gsub('@', '')] = eval(var) # set key and value in coder hash 
    end 
end 

o puede preferir esto si eval es demasiado peligroso y solo necesita filtrar una instancia de var. Todos los otros VARs necesitan tener un descriptor de acceso:

attr_accessor :keep_this, :unwanted 

def encode_with(coder) 
    # reject @unwanted var, all others need to have an accessor 
    instance_variables.reject{|x|x==:@unwanted}.map(&:to_s).each do |var| 
    coder[var[1..-1]] = send(var[1..-1]) 
    end 
end 
+0

Agregue algunos comentarios a su respuesta. – HDJEMAI

Cuestiones relacionadas