class WellActually::Mounter

Constants

BLANK_RE

Attributes

attributes[R]
klass[R]
overwrites[R]
strick[R]

Public Class Methods

new(klass:, overwrites: nil, overwrite: nil, attributes:, strict:false) click to toggle source
# File lib/well_actually/mounter.rb, line 7
def initialize(klass:, overwrites: nil, overwrite: nil, attributes:, strict:false)
  overwrites = overwrite || overwrites
  raise ArgumentError.new("overwrite must be a symbol or an array of symbols") unless overwrites.is_a?(Symbol) || (overwrites.is_a?(Array) && overwrites.all?{|a| a.is_a?(Symbol)})
  raise ArgumentError.new("attributes must be an array of symbols") unless attributes.is_a?(Array) && attributes.all?{|a| a.is_a?(Symbol)}
  @klass = klass
  @overwrites = overwrites
  @attributes = attributes.uniq
  @strict = strict
end

Public Instance Methods

mount() click to toggle source
# File lib/well_actually/mounter.rb, line 17
def mount
  klass.class_variable_set(:@@well_actually_attributes, attributes.map{|_attr| _attr.to_s})
  klass.class_variable_set(:@@well_actually_overwrites, [*overwrites])
  klass.class_variable_set(:@@well_actually_strict, strick)

  klass.send(:define_singleton_method, :well_actually_attributes) do
    self.class_variable_get(:@@well_actually_attributes)
  end

  klass.send(:define_method, :well_actually_attributes) do
    self.class.well_actually_attributes
  end

  klass.send(:define_singleton_method, :well_actually_overwrites) do
    self.class_variable_get(:@@well_actually_overwrites)
  end

  klass.send(:define_singleton_method, :well_actually_strict) do
    self.class_variable_get(:@@well_actually_strict)
  end

  klass.send(:define_method, :well_actually_overwrites) do
    self.class.well_actually_overwrites.map do |overwrite|
      self.public_send(overwrite) if (self.respond_to?(overwrite) ||  self.class.well_actually_strict)
    end.compact.reduce({}) do |result, overwrite|
      result.merge(overwrite || {}) do |key, v1, v2|
        v1 = nil unless self.well_actually_overwrite_value_check(key, v1)
        v2 = nil unless self.well_actually_overwrite_value_check(key, v2)
        v1.nil? ? v2 : v1
      end
    end
  end

  klass.send(:define_method, :well_actually?) do
    !!self.instance_variable_get(:@well_actually)
  end

  klass.send(:define_method, :well_actually) do
    self.clone.tap do |actually|
      actually.readonly! if actually.respond_to?(:readonly!)
      actually.instance_variable_set(:@well_actually, true)
      self.send(:well_actually_overwrite_safe).each do |_attr, _value|
        if actually.respond_to?(:"#{_attr}=")
          actually.public_send(:"#{_attr}=", _value)
        else
          actually.instance_variable_set(:"@#{_attr}", _value)
        end
      end
    end
  end

  klass.send(:define_method, :well_actually_overwrite_safe) do
    (self.well_actually_overwrites || {}).select do |key, value|
      self.well_actually_overwrite_value_check(key, value)
    end
  end

  klass.send(:define_method, :well_actually_overwrite_value_check) do |key, value|
    self.well_actually_attributes.include?(key) && !value.nil? && (!value.is_a?(String) || !value.match(BLANK_RE))
  end
end