class SBF::Client::BaseEntity

Constants

ELSE

Attributes

errors[R]

Public Class Methods

allow_instantiation?() click to toggle source

Class method which retrieves the

# File lib/stbaldricks/entities/lib/base.rb, line 218
def self.allow_instantiation?
  !@disallow_instantiation
end
attr_accessor(*vars) click to toggle source
Calls superclass method
# File lib/stbaldricks/entities/lib/base.rb, line 247
def self.attr_accessor(*vars)
  defined_attributes.merge(vars)
  super(*vars)

  vars.each do |attribute|
    define_attribute_methods attribute
    define_changing_attr_methods attribute, false, true
  end

  add_boolean_methods(vars, true)
end
attr_reader(*vars) click to toggle source

Override for the ruby built-in attribute accessors. Creates a list of attributes that can be accessed at will and adds some helper methods.

Calls superclass method
# File lib/stbaldricks/entities/lib/base.rb, line 230
def self.attr_reader(*vars)
  defined_attributes.merge(vars)
  super(*vars)
  add_boolean_methods(vars)
end
attr_writer(*vars) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 236
def self.attr_writer(*vars)
  defined_attributes.merge(vars)

  vars.each do |attribute|
    define_attribute_methods attribute
    define_changing_attr_methods attribute
  end

  add_boolean_methods(vars, true)
end
collection_attributes() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 362
def self.collection_attributes
  @collection_attributes ||= Set.new
end
defined_attributes() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 350
def self.defined_attributes
  @defined_attributes ||= Set.new
end
entity_attr_accessor(attribute, full_class, partial_class = nil, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 299
def self.entity_attr_accessor(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_attr_accessor(attribute, mapping_for_single_class, optional)
end
entity_attr_reader(attribute, full_class, partial_class = nil, optional = false) click to toggle source

Entity attr accessors are simpler to define/easier to read but they really just create a type mapping for the given inputs and then function the same as the multitype attribute accessors do.

# File lib/stbaldricks/entities/lib/base.rb, line 289
def self.entity_attr_reader(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_attr_reader(attribute, mapping_for_single_class, optional)
end
entity_attr_writer(attribute, full_class, partial_class = nil, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 294
def self.entity_attr_writer(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_attr_writer(attribute, mapping_for_single_class, optional)
end
entity_attributes() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 358
def self.entity_attributes
  @entity_attributes ||= Set.new
end
entity_collection_attr_accessor(attribute, full_class, partial_class = nil, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 344
def self.entity_collection_attr_accessor(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_collection_attr_accessor(attribute, mapping_for_single_class, optional)
end
entity_collection_attr_reader(attribute, full_class, partial_class = nil, optional = false) click to toggle source

Entity attr accessors are simpler to define/easier to read but they really just create a type mapping for the given inputs and then function the same as the multitype attribute accessors do.

# File lib/stbaldricks/entities/lib/base.rb, line 334
def self.entity_collection_attr_reader(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_collection_attr_reader(attribute, mapping_for_single_class, optional)
end
entity_collection_attr_writer(attribute, full_class, partial_class = nil, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 339
def self.entity_collection_attr_writer(attribute, full_class, partial_class = nil, optional = false)
  mapping_for_single_class = [[ELSE, full_class, partial_class]]
  multitype_collection_attr_writer(attribute, mapping_for_single_class, optional)
end
inherited(base) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 585
def self.inherited(base)
  # Add all of our attributes to the class that is inheriting us.
  base.defined_attributes.merge(defined_attributes) unless defined_attributes.empty?
  base.optional_attributes.merge(optional_attributes) unless optional_attributes.empty?
  base.entity_attributes.merge(entity_attributes) unless entity_attributes.empty?
end
multitype_attr_accessor(attribute, class_mappings, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 278
def self.multitype_attr_accessor(attribute, class_mappings, optional = false)
  entity_attributes << attribute
  optional_attributes << attribute if optional
  attr_accessor(attribute)
  add_multitype_setter_method(attribute, class_mappings)
end
multitype_attr_reader(attribute, class_mappings, optional = false) click to toggle source

Multitype Attribute accessors. These methods take an array of type to class mappings. Expected form is:

[<lamda method which evals to true if this type should be used>, <full class>, <partial class>], […]
# File lib/stbaldricks/entities/lib/base.rb, line 264
def self.multitype_attr_reader(attribute, class_mappings, optional = false)
  entity_attributes << attribute
  optional_attributes << attribute if optional
  attr_reader(attribute)
  add_multitype_setter_method(attribute, class_mappings, true)
end
multitype_attr_writer(attribute, class_mappings, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 271
def self.multitype_attr_writer(attribute, class_mappings, optional = false)
  entity_attributes << attribute
  optional_attributes << attribute if optional
  attr_writer(attribute)
  add_multitype_setter_method(attribute, class_mappings)
end
multitype_collection_attr_accessor(attribute, class_mappings, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 323
def self.multitype_collection_attr_accessor(attribute, class_mappings, optional = false)
  collection_attributes << attribute
  optional_attributes << attribute if optional
  attr_accessor(attribute)
  add_multitype_collection_setter_method(attribute, class_mappings)
end
multitype_collection_attr_reader(attribute, class_mappings, optional = false) click to toggle source

Multitype Collection accessors. These methods take an array of type to class mappings. Expected form is:

[<lamda method which evals to true if this type should be used>, <full class>, <partial class>], […]
# File lib/stbaldricks/entities/lib/base.rb, line 309
def self.multitype_collection_attr_reader(attribute, class_mappings, optional = false)
  collection_attributes << attribute
  optional_attributes << attribute if optional
  attr_reader(attribute)
  add_multitype_collection_setter_method(attribute, class_mappings, true)
end
multitype_collection_attr_writer(attribute, class_mappings, optional = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 316
def self.multitype_collection_attr_writer(attribute, class_mappings, optional = false)
  collection_attributes << attribute
  optional_attributes << attribute if optional
  attr_writer(attribute)
  add_multitype_collection_setter_method(attribute, class_mappings)
end
new(data = {}, clear_changes = false) click to toggle source
Calls superclass method
# File lib/stbaldricks/entities/lib/base.rb, line 28
def initialize(data = {}, clear_changes = false)
  # If disallow instantiation has been set, raise an error if someone is trying to call initilaize
  raise SBF::Client::Error, 'Initialize is not valid on a base object. Use the full or partial version' unless self.class.allow_instantiation?

  super()

  @errors = SBF::Client::Entity::Errors.new(self)
  initialize_attributes(data)
  reload_recursive if clear_changes
end
optional_attributes() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 354
def self.optional_attributes
  @optional_attributes ||= Set.new
end

Private Class Methods

add_boolean_methods(vars, setter = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 366
def self.add_boolean_methods(vars, setter = false)
  vars.each do |attribute|
    split_attribute = attribute.to_s.split('is_')
    next if split_attribute.length <= 1

    define_method(:"#{split_attribute.last}?") { send(attribute) }
    define_changing_attr_methods(attribute, true) if setter
  end
end
add_class_selector_method(attribute, class_mappings) click to toggle source

Creates a private method which resolves the class type based on the class mappings and the value rubocop:disable Metrics/MethodLength rubocop:todo Metrics/PerceivedComplexity

# File lib/stbaldricks/entities/lib/base.rb, line 394
def self.add_class_selector_method(attribute, class_mappings) # rubocop:todo Metrics/CyclomaticComplexity
  method_name = :"select_#{attribute}_class"

  define_singleton_method(method_name) do |value|
    parsed_class_mappings = get_mappings(attribute, class_mappings)

    # No class conversion if the value is nil
    return nil if value.nil?

    if value.is_a?(Hash)
      # Allow setting of the value using a hash
      return NilClass if value.empty?

      # Find the first class mapping whose check returns true
      check, full_class, partial_class = parsed_class_mappings.find { |check, _, _| check.call(value) }
      raise SBF::Client::Error, "unknown #{attribute} type" if check.nil?

      # If a user specifies exactly the partial fields, then this should be a partial.
      return partial_class if partial_class && (value.keys - partial_class.defined_attributes.to_a).empty?

      # Otherwise
      return full_class if full_class

    else
      # No class conversion if the value is already an entity
      return nil if parsed_class_mappings.any? do |_, c1, c2|
        [c1, c2].compact.any? do |allowed_class|
          if allowed_class.instance_of?(Class)
            # Otherwise, return true if the value is an instance of the allowed class
            value.is_a?(allowed_class)

          elsif allowed_class.instance_of?(Module)
            # If we specified a module, assume this is an enum and return true if the value
            # is one of the valid constant values for the module
            allowed_class.constants.any? { |const_name| allowed_class.const_get(const_name) == value }

          end
        end
      end

      # Convert to child class if given class is a parent of the same name
      parsed_class_mappings.each do |_, c1, c2|
        [c1, c2].compact.each do |allowed_class|
          return allowed_class if allowed_class.ancestors.find { |a| a == value.class && a.demodulize == value.class.demodulize }
        end
      end

      # Don't know how to handle whatever the user entered. Raise an error.
      # (Nil and Hash are always valid values)
      valid_classes = ['NilClass', Hash]
      parsed_class_mappings.each do |_, class1, class2|
        valid_classes << class1
        valid_classes << class2 unless class2.nil?
      end

      raise SBF::Client::Error, "Unsupported value for #{name}.#{attribute}: #{value}. Should be one of #{valid_classes.join(', ')}"
    end
  end

  private_class_method method_name
end
add_multitype_collection_setter_method(attribute, class_mappings, private_method = false) click to toggle source

Base collection setter. Allows for the collection to be an array types of types.

# File lib/stbaldricks/entities/lib/base.rb, line 526
def self.add_multitype_collection_setter_method(attribute, class_mappings, private_method = false)
  add_class_selector_method(attribute, class_mappings)

  define_method(:"#{attribute}=") do |values|
    values ||= []
    raise SBF::Client::Error, "#{attribute} must be an array" unless values.is_a?(Array)

    converted_collection = values.map { |value| convert_value(attribute, value) }
    instance_variable_set(:"@#{attribute}", converted_collection)
    send(:"#{attribute}_will_change!") if respond_to?(:"#{attribute}_will_change!")
  end

  # Make the setter private if requested (so you can set through the constructor but not anywhere else)
  private :"#{attribute}=" if private_method
end
add_multitype_setter_method(attribute, class_mappings, private_method = false) click to toggle source

Base entity setter. Allows for the property to be an array of types.

# File lib/stbaldricks/entities/lib/base.rb, line 511
def self.add_multitype_setter_method(attribute, class_mappings, private_method = false)
  add_class_selector_method(attribute, class_mappings)

  method_name = :"#{attribute}="
  define_method(method_name) do |value|
    instance_variable_set(:"@#{attribute}", convert_value(attribute, value))
    send(:"#{attribute}_will_change!") if respond_to?(:"#{attribute}_will_change!")
  end

  # Make the setter private if requested (so you can set through the constructor but not anywhere else)
  private method_name if private_method
end
define_changing_attr_methods(attribute, is_boolean = false, define_reader = false) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 377
def self.define_changing_attr_methods(attribute, is_boolean = false, define_reader = false)
  if define_reader
    define_method(:"#{attribute}") do
      instance_variable_get("@#{attribute}".to_sym)
    end
  end

  define_method(:"#{attribute}=") do |val|
    send(:"#{attribute}_will_change!") unless val == instance_variable_get("@#{attribute}".to_sym) && !val.nil?
    instance_variable_set("@#{attribute}".to_sym, is_boolean ? val.to_s.to_b : val)
  end
end
disallow_instantiation() click to toggle source

So this method is meant to ensure that you don't do SBF::Client::Participant.new and are forced, instead, to be explicit about calling either SBF::Client::FullParticipant.new or SBF::Client::PartialParticipant.new

# File lib/stbaldricks/entities/lib/base.rb, line 212
def self.disallow_instantiation
  @disallow_instantiation = true
end
get_mappings(attribute, class_mappings) click to toggle source

rubocop:enable Metrics/PerceivedComplexity rubocop:enable Metrics/MethodLength

# File lib/stbaldricks/entities/lib/base.rb, line 459
def self.get_mappings(attribute, class_mappings)
  # Parse the mappings information and save it off
  mapping_var = :"@#{attribute}_class_mappings"
  instance_variable_set(mapping_var, parse_class_mappings(class_mappings)) unless instance_variable_defined?(mapping_var)

  instance_variable_get(mapping_var)
end
parse_class_mappings(mappings) click to toggle source

Validates the input structure of the class mappings array and returns a new array with the class strings converted to actual classes

# File lib/stbaldricks/entities/lib/base.rb, line 470
def self.parse_class_mappings(mappings)
  raise SBF::Client::Error, "Invalid class mapping structure: #{mappings.class}" unless mappings.is_a?(Array)

  mappings.map do |check, full_class, partial_class|
    raise SBF::Client::Error, "Invalid class mapping check: #{check.class}" unless check.is_a?(Proc)

    full_class = full_class.to_class
    unless full_class.nil? || full_class.is_a?(NilClass) || full_class.ancestors.include?(BaseEntity) || full_class.instance_of?(Module)
      raise SBF::Client::Error, "Invalid class mapping full class: #{full_class}"
    end

    partial_class = partial_class.to_class
    unless partial_class.nil? || partial_class.is_a?(NilClass) || partial_class.ancestors.include?(BaseEntity)
      raise SBF::Client::Error, "Invalid class mapping partial class: #{partial_class}"
    end

    [check, full_class, partial_class]
  end
end

Public Instance Methods

destroyed?() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 66
def destroyed?
  @destroyed
end
dirty_data(with_keys = false) click to toggle source
Returns a hash of changed data for the entity and its sub-entities

@param with_keys [Boolean] when true, include the keys of the current entity. (sub-entity keys will always be included if they are present) @return [Hash] the changed data

# File lib/stbaldricks/entities/lib/base.rb, line 79
def dirty_data(with_keys = false)
  data = {}
  changes.each { |k, arr| data[k.to_sym] = arr[1] }

  instance_variables.each do |var|
    attribute_symbol = var.to_s.delete('@').to_sym
    attribute = instance_variable_get(var)
    if attribute.is_a?(BaseEntity)
      if attribute.dirty_data(true).empty?
        next unless changed.map(&:to_sym).include?(attribute_symbol)

        data.merge!(attribute_symbol => attribute.keys_hash)
      else
        data.merge!(attribute_symbol => attribute.dirty_data(true))
      end
    elsif attribute.is_a?(Array)
      next unless attribute.all? { |e| e.is_a?(BaseEntity) } && attribute.any? { |e| !e.dirty_data(true).empty? }

      data.merge!(attribute_symbol => attribute)
    end
  end

  return data if data.empty?

  with_keys ? keys_hash.merge(data) : data
end
error() click to toggle source

Attempt to return an ErrorEntity similar to or exactly like the original

# File lib/stbaldricks/entities/lib/base.rb, line 595
def error
  log_deprecated('error', caller)
  return nil if single_active_model_error.nil?

  details = single_active_model_error.find { |x| x.is_a?(String) } if single_active_model_error.is_a?(Array)
  details ||= single_active_model_error.is_a?(String) ? single_active_model_error : nil
  field = single_active_model_error.is_a?(Array) ? single_active_model_error.find { |x| x.is_a?(Symbol) && x != :base } : nil

  fields = errors.keys.reject { |k| k == :base }.empty? ? nil : errors.keys.reject { |k| k == :base }.map(&:to_s)
  details = details["#{errors.type}: ".length..(details.length - 1)] if details.start_with?("#{errors.type}: ")
  details = details["#{field}: ".length..(details.length - 1)] if details.start_with?("#{field}: ")

  SBF::Client::ErrorEntity.new(code: errors.code, type: errors.type, details: details, errors: fields)
end
keys_hash() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 106
def keys_hash
  respond_to?(:id) && id ? {id: id} : {}
end
model_name() click to toggle source

Overridden from ActiveModel::Naming to remove namespace and Full/Partial

# File lib/stbaldricks/entities/lib/base.rb, line 40
def model_name
  @model_name ||= ActiveModel::Name.new(self, SBF::Client, self.class.name.gsub(/::(Full|Partial)/, '::'))
end
not_provided_attributes() click to toggle source

Class method to retrieve the not_provided_attributes attribute

# File lib/stbaldricks/entities/lib/base.rb, line 223
def not_provided_attributes
  @not_provided_attributes ||= Set.new
end
persisted?() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 44
def persisted?
  true
end
reload!() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 48
def reload!
  # get the values from the persistence layer
  clear_changes_information
end
reload_recursive() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 53
def reload_recursive
  instance_variables.each do |var|
    attribute = instance_variable_get(var)
    attribute.reload_recursive if attribute.is_a?(BaseEntity)
    attribute.each { |a| a.reload_recursive if a.is_a?(BaseEntity) } if attribute.is_a?(Array)
  end
  reload!
end
rollback!() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 62
def rollback!
  restore_attributes
end
to_hash() click to toggle source

Recursively converts an entity into a Hash

# File lib/stbaldricks/entities/lib/base.rb, line 544
def to_hash
  entity_hash = {}
  self.class.defined_attributes.each do |key|
    # If the method was not retrieved, do not include it in the hash
    next if not_provided_attributes.include?(key)

    # Get the value
    value = send(key)

    # If the value is an Entity, call to_hash on it (recursively)
    entity_hash[key] = if value.is_a?(BaseEntity)
                         value.to_hash

                       # If the value is an Array, need to try to call to_hash on each item
                       elsif value.is_a?(Array)
                         value.map do |element|
                           next element.to_hash if element.is_a?(BaseEntity)

                           next element
                         end

                       # Collections should return empty array rather than nil
                       elsif value.nil? && self.class.collection_attributes.include?(key)
                         []

                       # Just set the value
                       else
                         value

                       end
  end

  # Return the hash
  entity_hash
end
to_json(*a) click to toggle source

Recursively convert an entity into json

# File lib/stbaldricks/entities/lib/base.rb, line 581
def to_json(*a)
  to_hash.to_json(*a)
end
to_partial() click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 70
def to_partial
  base_class = self.class.name.gsub(/(.*::)(Full|Partial)(.*)/, '\1')
  base_name = self.class.name.gsub(/(.*::)(Full|Partial)(.*)/, '\3')
  "#{base_class}Partial#{base_name}".to_class.new(to_hash)
end

Private Instance Methods

convert_value(attribute, value) click to toggle source

Convert the value to an instance of the appropriate class.

# File lib/stbaldricks/entities/lib/base.rb, line 492
def convert_value(attribute, value)
  entity_class_selector_method = :"select_#{attribute}_class"
  entity_class = self.class.send(entity_class_selector_method, value)

  # If the entity_class is nil, then that means don't convert anything
  return value if entity_class.nil?

  # If the entity_class is the NilClass, return nil
  return nil if entity_class == NilClass

  # If we are converting to a subclass, we need to first grab the hash of data from the parent object
  value = value.to_hash if !value.is_a?(Hash) && value.respond_to?(:to_hash)

  # Convert to an instance of the appropriate entity class.
  entity_class.new(value)
end
getter_backup_method_name(name) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 205
def getter_backup_method_name(name)
  "_#{name}".to_sym
end
getter_method_name(name) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 195
def getter_method_name(name)
  name.to_sym
end
initialize_attributes(data) click to toggle source

rubocop:disable Naming/MemoizedInstanceVariableName

# File lib/stbaldricks/entities/lib/base.rb, line 113
def initialize_attributes(data)
  data ||= {}
  data.each do |key, value|
    # Use the setter if one is available, otherwise set the variable directly
    setter = "#{key}=".to_sym
    if respond_to?(setter, true)
      send(setter, value)

    elsif respond_to?(key.to_sym)
      instance_variable_set("@#{key}".to_sym, value)
      attribute_will_change!(key.to_sym)
    end
  end

  # For each attribute that may be optional, call mark_attribute_not_provided
  # if the data set does not contain a key with the optional attribute's name
  self.class.optional_attributes.each { |name| mark_attribute_not_provided(name) unless data.key?(name) }
  @defined_attributes ||= Set.new
  @optional_attributes ||= Set.new
  @not_provided_attributes ||= Set.new
  @entity_attributes ||= Set.new
  @collection_attributes ||= Set.new
end
mark_attribute_not_provided(name) click to toggle source

rubocop:enable Naming/MemoizedInstanceVariableName

Calls superclass method
# File lib/stbaldricks/entities/lib/base.rb, line 139
def mark_attribute_not_provided(name)
  return if not_provided_attributes.include?(name)

  # Put the method in the list of not_provided methods
  not_provided_attributes << name

  # Back up the original version of the setter method if it doesn't already exist
  setter = setter_method_name(name)
  setter_backup = setter_backup_method_name(name)
  singleton_class.send(:alias_method, setter_backup, setter) unless respond_to?(setter_backup, true)

  # Back up the original version of the getter method if it doesn't already exist
  getter = getter_method_name(name)
  getter_backup = getter_backup_method_name(name)
  singleton_class.send(:alias_method, getter_backup, getter) unless respond_to?(getter_backup, true)

  # If we set the value in a not_provided method, that means we now have requested the data and we
  # should replace the original getter/setter and set the value using the original method
  define_singleton_method(setter) do |v|
    unmark_attribute_not_provided(name)
    super(v)
  end

  # If we try to get the value in a not_provided method, we should raise an error
  define_singleton_method(getter) do
    raise(
      SBF::Client::DataNotProvidedError,
      "Data not provided for the #{name} attribute. This is usually due to the attribute not being requested in the 'with' declaration"
    )
  end
end
setter_backup_method_name(name) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 200
def setter_backup_method_name(name)
  "_#{name}=".to_sym
end
setter_method_name(name) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 190
def setter_method_name(name)
  "#{name}=".to_sym
end
unmark_attribute_not_provided(name) click to toggle source
# File lib/stbaldricks/entities/lib/base.rb, line 172
def unmark_attribute_not_provided(name)
  return unless not_provided_attributes.include?(name)

  # Remove the method from the list of not_provided methods
  not_provided_attributes.delete(name)

  # Replace the original version of the setter method using the backup
  setter = setter_method_name(name)
  setter_backup = setter_backup_method_name(name)
  singleton_class.send(:alias_method, setter, setter_backup)

  # Replace the original version of the getter method using the backup
  getter = getter_method_name(name)
  getter_backup = getter_backup_method_name(name)
  singleton_class.send(:alias_method, getter, getter_backup)
end