tstmedia/active_zuora

View on GitHub
lib/active_zuora/base.rb

Summary

Maintainability
A
0 mins
Test Coverage
require 'bigdecimal'
require 'bigdecimal/util'

module ActiveZuora
  module Base

    extend ActiveSupport::Concern

    # This is the default connection object to use for all Base classes.
    # Each individual Base class can overwrite it.
    class << self
      attr_accessor :connection
    end

    included do
      include Fields
      include ActiveModel::Validations
      include BelongsToAssociations
      class << self
        attr_accessor :namespace
        attr_writer :zuora_object_name
        attr_writer :connection
      end
      delegate :namespace, :zuora_object_name, :to => 'self.class'
    end

    def xml_field_names
      # Which field names should be rendered during build_xml.
      # Choose only field names that have been changed.
      # Make sure the order in fields is maintained.
      field_names & changed.map(&:to_sym)
    end

    def build_xml(xml, soap, options={})
      namespace = options.delete(:namespace) || self.namespace
      qualifier = soap.namespace_by_uri(namespace)
      custom_element_name = options.delete(:element_name)
      element_name = custom_element_name || zuora_object_name
      attributes = options.delete(:force_type) ? 
        { "xsi:type" => "#{qualifier}:#{zuora_object_name}" } : {}
      xml.tag!(qualifier, element_name.to_sym, attributes) do
        xml_field_names.map { |field_name| get_field!(field_name) }.each do |field|
          field.build_xml(xml, soap, send(field.name), options)
        end
      end
    end

    def add_zuora_errors(zuora_errors)
      return if zuora_errors.blank?
      zuora_errors = [zuora_errors] unless zuora_errors.is_a?(Array)
      zuora_errors.each { |error| errors.add(:base, error[:message].capitalize) }
    end

    module ClassMethods

      def zuora_object_name
        @zuora_object_name ||= self.name.split("::").last
      end

      def connection
        @connection || Base.connection
      end

      def nested_class_name(unnested_class_name)
        # This helper method will take a class name, and nest it inside
        # the same module/class as self.
        (name.split("::")[0..-2] << unnested_class_name).join("::")
      end

    end

  end
end