module NoBrainer::Document::Store::ClassMethods

Public Instance Methods

store(store_attribute, options = {}) click to toggle source
# File lib/no_brainer/document/store.rb, line 111
def store(store_attribute, options = {})
  store_accessor(store_attribute, options[:accessors], **options.slice(:prefix, :suffix)) if options.has_key? :accessors
end
store_accessor(store_attribute, *keys, prefix: nil, suffix: nil) click to toggle source
Calls superclass method
# File lib/no_brainer/document/store.rb, line 115
def store_accessor(store_attribute, *keys, prefix: nil, suffix: nil)
  keys = keys.flatten

  accessor_prefix =
    case prefix
    when String, Symbol
      "#{prefix}_"
    when TrueClass
      "#{store_attribute}_"
    else
      ""
    end
  accessor_suffix =
    case suffix
    when String, Symbol
      "_#{suffix}"
    when TrueClass
      "_#{store_attribute}"
    else
      ""
    end

  field store_attribute, type: Hash, default: {} unless has_field?(store_attribute)

  define_method("#{store_attribute}=") do |value|
    super(value) if value.is_a?(Hash) || value.nil?
  end

  _store_accessors_module.module_eval do
    keys.each do |key|
      accessor_key = "#{accessor_prefix}#{key}#{accessor_suffix}"

      define_method("#{accessor_key}=") do |value|
        write_store_attribute(store_attribute, key, value)
      end

      define_method(accessor_key) do
        read_store_attribute(store_attribute, key)
      end

      define_method("#{accessor_key}_changed?") do
        return false unless __send__("#{store_attribute}_changed?")
        prev_store, new_store = changes[store_attribute]
        if NoBrainer.rails4?
          (prev_store && prev_store[key.to_s]) != (new_store && new_store[key.to_s])
        else
          (prev_store && prev_store.dig(key)) != (new_store && new_store.dig(key))
        end
      end

      define_method("#{accessor_key}_change") do
        return unless __send__("#{store_attribute}_changed?")
        prev_store, new_store = changes[store_attribute]
        if NoBrainer.rails4?
          [(prev_store && prev_store[key.to_s]), (new_store && new_store[key.to_s])]
        else
          [(prev_store && prev_store.dig(key)), (new_store && new_store.dig(key))]
        end
      end

      define_method("#{accessor_key}_was") do
        return unless __send__("#{store_attribute}_changed?")
        prev_store, _new_store = changes[store_attribute]
        if NoBrainer.rails4?
          (prev_store && prev_store[key.to_s])
        else
          (prev_store && prev_store.dig(key))
        end
      end

      # NoBrainer doesn't have `attribute_will_change!` so those methods
      # can't be implemented yet.
      # See https://github.com/NoBrainerORM/nobrainer/pull/190
      #
      # define_method("saved_change_to_#{accessor_key}?") do
      #   return false unless __send__("saved_change_to_#{store_attribute}?")
      #   prev_store, new_store = __send__("saved_change_to_#{store_attribute}")
      #   prev_store&.dig(key) != new_store&.dig(key)
      # end

      # define_method("saved_change_to_#{accessor_key}") do
      #   return unless __send__("saved_change_to_#{store_attribute}?")
      #   prev_store, new_store = __send__("saved_change_to_#{store_attribute}")
      #   [prev_store&.dig(key), new_store&.dig(key)]
      # end

      # define_method("#{accessor_key}_before_last_save") do
      #   return unless __send__("saved_change_to_#{store_attribute}?")
      #   prev_store, _new_store = __send__("saved_change_to_#{store_attribute}")
      #   prev_store&.dig(key)
      # end
    end
  end

  # assign new store attribute and create new hash to ensure that each class in the hierarchy
  # has its own hash of stored attributes.
  self.local_stored_attributes ||= {}
  self.local_stored_attributes[store_attribute] ||= []
  self.local_stored_attributes[store_attribute] |= keys
end
stored_attributes() click to toggle source
# File lib/no_brainer/document/store.rb, line 224
def stored_attributes
  parent = superclass.respond_to?(:stored_attributes) ? superclass.stored_attributes : {}
  if local_stored_attributes
    parent.merge!(local_stored_attributes) { |k, a, b| a | b }
  end
  parent
end