Class: Isomorphic::Factory::AbstractFactory Abstract

Inherits:
Object
  • Object
show all
Defined in:
lib/isomorphic/factory.rb

Overview

This class is abstract.

Subclass and override #const_get and #xmlattrs to implement a custom class.

Generic base class for Isomorphic factories.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(base) ⇒ AbstractFactory

Default constructor

Parameters:

  • base (Module)

    the base module



43
44
45
46
47
# File 'lib/isomorphic/factory.rb', line 43

def initialize(base)
  super()

  @base = base
end

Instance Attribute Details

#baseObject (readonly)

Returns the value of attribute base.



38
39
40
# File 'lib/isomorphic/factory.rb', line 38

def base
  @base
end

Instance Method Details

#for(klass, **options) {|instance| ... } ⇒ Object

Build a new instance of the given class.

Parameters:

  • klass (Class)

    the class

  • options (Hash<#to_sym, Object>)

    the options

Options Hash (**options):

  • :attributes (Hash<#to_sym, Object>) — default: {}

    the attributes for the new instance

  • :xmlattrs (Hash<#to_sym, #to_s>) — default: {}

    the XML attributes for the new instance

Yield Parameters:

  • instance (Object)

    the new instance

Yield Returns:

  • (void)

Returns:

  • (Object)

    the new instance

Raises:



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/isomorphic/factory.rb', line 59

def for(klass, **options, &block)
  unless klass.is_a?(::Class) && (klass.parents[-2] == base)
    raise Isomorphic::InvalidFactoryClass.new(nil, base, klass, nil)
  end

  instance = klass.new

  if options.key?(:attributes)
    update_attributes(instance, options[:attributes])
  end

  send(:xmlattrs).select { |xmlattr_name|
    instance.respond_to?(:"xmlattr_#{xmlattr_name}=")
  }.each do |xmlattr_name|
    instance.send(:"xmlattr_#{xmlattr_name}=", send(:"xmlattr_#{xmlattr_name}_for", instance))
  end

  unless block.nil?
    case block.arity
      when 1 then block.call(instance)
      else instance.instance_eval(&block)
    end
  end

  instance
end

#path(instance, *method_names, **options) ⇒ Object?

Build a chain of new instances by reflecting on the instance methods for the given instance and then return the end of the chain.

Parameters:

  • instance (Object)

    the instance

  • method_names (Array<#to_sym>)

    the method names

  • options (Hash<#to_sym, Object>)

    the options

Options Hash (**options):

  • :try (Boolean) — default: false

    return nil if any receiver in the chain is blank

  • :attributes (Hash<#to_sym, Object>) — default: {}

    the attributes for the new instance

  • :xmlattrs (Hash<#to_sym, #to_s>) — default: {}

    the XML attributes for the new instance

Returns:

  • (Object, nil)

    the new instance or nil

Raises:



97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/isomorphic/factory.rb', line 97

def path(instance, *method_names, **options)
  method_names.inject([instance.class, instance]) { |pair, method_name|
    orig_class, orig_instance = *pair

    if orig_instance.nil? && options[:try]
      [::NilClass, orig_instance]
    else
      s = method_name.to_s
      const_name = s[0].upcase.concat(s[1..-1])

      new_class = const_get(base, orig_class, const_name)

      unless new_class.is_a?(::Class)
        raise Isomorphic::InvalidFactoryClass.new(nil, base, orig_class, const_name)
      end

      new_instance = orig_instance.send(method_name) || (options[:try] ? nil : orig_instance.send(:"#{method_name}=", send(:for, new_class)))

      [new_class, new_instance]
    end
  }[1]
end

#path?(instance, *method_names) ⇒ Boolean

Is the chain of instances present?

Parameters:

  • instance (Object)

    the instance

  • method_names (Array<#to_sym>)

    the method names

Returns:

  • (Boolean)

    true if the chain of instances is present; otherwise, false

Raises:



126
127
128
# File 'lib/isomorphic/factory.rb', line 126

def path?(instance, *method_names)
  !path(instance, *method_names, try: true).nil?
end

#update_attributes(instance, attributes = {}) ⇒ void

Note:

Before assignment, attributes from the passed-in hash are duplicated.

This method returns an undefined value.

Updates the attributes of the instance from the passed-in hash.

Parameters:

  • instance (Object)

    the instance

  • attributes (Hash<#to_sym, Object>) (defaults to: {})

    the attributes



137
138
139
140
141
142
143
# File 'lib/isomorphic/factory.rb', line 137

def update_attributes(instance, attributes = {})
  attributes.each do |method_name, value|
    instance.send(:"#{method_name}=", ::Marshal.load(::Marshal.dump(value)))
  end

  return
end

#xmlattrsArray<#to_sym>

Note:

For each XML attribute name, e.g., name, a corresponding instance method #xmlattr_{name}_for(instance) must be defined.

Returns the array of XML attribute names that are accepted by this factory.

Returns:

  • (Array<#to_sym>)

    the XML attribute names



150
151
152
# File 'lib/isomorphic/factory.rb', line 150

def xmlattrs
  []
end