如何将函数应用于每个类属性值?

时间:2012-09-11 13:27:34

标签: ruby xml-serialization metaprogramming

我有这个超类

# encoding: utf-8

class EntidadeCte

  include ROXML
  include ActiveModel::Validations

  class << self
    # apelida o xml_accessor do ROXML para cte_attr
    alias :cte_attr :xml_accessor

    # define um accessor ruby comum para os atributos do cte
    def xml_accessor(*attrs)
      attr_accessor *attrs
    end

    # todos os atributos da entidade
    def cte_attrs
      roxml_attrs.map(&:attr_name)
    end

  end

  # todos os atributos da entidade do objeto
  def cte_attrs
    self.class.cte_attrs
  end

  # retorna o xml representando a entidade
  def to_cte
    doc = Nokogiri::XML::Document.new
    doc.root = to_xml
    doc.serialize
  end

  # retorna o xml ou delega a classe herdada
  def to_s
    self.respond_to? :to_cte ? to_cte : super
  end

end

和这个子类

# encoding: utf-8

    class TagCte < EntidadeCte

      def initialize
        self.xmlns = "http://www.portalfiscal.inf.br/cte"  
      end

      xml_name :CTe

      cte_attr :xmlns, :from => "@xmlns"
      cte_attr :infCte, :as => ConhecimentoTransporte

    end

我想做的是,一旦我在我的子类对象上调用to_cte,它就会返回其属性的值,但只有在将函数应用于每个属性之后才能返回。我想首先规范化它们的值(从字符串中移除重音,转义引号,特殊字符等)。在这种情况下我该怎么做?

1 个答案:

答案 0 :(得分:0)

你在这里展示的代码显然有很多缺失。我推测你的实体对象上有某些“属性”,它们只是通过链接到attr_accessor来定义。在EntitadeCte的特定子类(或子类)中,您希望将某些特殊行为应用于这些“属性”。

子类的所有“属性”是否都直接在该子类中定义?或者其中一些是继承的?

如果它们是直接在子类中定义的,您只需在子类中重新定义cte_attr,如:

class Subclass < EntitadeCte
  def self.cte_attr(*attrs)
    attrs.each do |attr|
      attr_writer(attr)
      class_eval("def #{attr}; do something special to @#{attr} here; end")
    end
  end
end

因此,您不是使用attr_accessor,而是定义自己的等效“类宏”,这会为读者添加一些特殊行为。

您的评论中的

更新:,听起来像是所有 EntitadeCte的子类需要对属性进行相同的特殊处理。是对的吗?在这种情况下,您只需将超类中的cte_attr的定义更改为类似上面的示例代码。

或者,您可以定义cte_attr(在超类中)以生成 2 读取器方法,一个用于规范化属性值,另一个用于规范化属性值。然后编写一个使用“规范化”属性读取器的to_cte方法。

有各种选择。如果我在这里给出的选择不符合您的需求,那么您需要更具体地了解您想要做什么。问题是某些子类应该使用“规范化”属性,而其他子类应该使用“非规范化”属性?或者您想要动态打开和关闭“规范化”的问题是什么?