class AssociateJsonb::WithStoreAttribute::InstanceMethodsOnActivation

Public Class Methods

new(mixin, store, attribute, key, is_array) click to toggle source
# File lib/associate_jsonb/with_store_attribute.rb, line 118
      def initialize(mixin, store, attribute, key, is_array)
        is_array = !!(is_array && attribute.to_s =~ /_ids$/)

        array_or_attr = ->(value) {
          is_array \
           ? %Q(Array(#{value})) \
           : %Q(#{value})
         }

        on_store_change = "_write_attribute(:#{attribute}, #{array_or_attr.call %Q(#{store}["#{key}"])})"
        on_attr_change = "super(#{array_or_attr.call %Q(given)})"

        if is_array
          mixin.class_eval <<~CODE, __FILE__, __LINE__ + 1
            def #{attribute}
              _read_attribute(:#{attribute}) || []
            end
          CODE
        end

        mixin.class_eval <<~CODE, __FILE__, __LINE__ + 1
          def #{store}=(given)
            if given.is_a?(::String)
              given = ActiveSupport::JSON.decode(given) rescue nil
            end

            if AssociateJsonb.merge_hash?(self.class.attribute_types["#{store}"])
              if !given
                given = {}
                #{store}.keys.each do |k|
                  given[k] = nil
                end
              end
              super(#{store}.deep_merge(given.deep_stringify_keys))

              self.#{attribute}= #{store}["#{key}"] if #{store}.key?("#{key}")
            else
              super given || {}
              self.#{attribute}= #{store}["#{key}"]
            end

            #{store}
          end

          def #{attribute}=(given)
            #{on_attr_change}
            value = #{store}["#{key}"] = #{attribute}.presence
            #{store}.delete("#{key}") unless !value.nil? || AssociateJsonb.merge_hash?(self.class.attribute_types["#{store}"])
            value
          end
        CODE
      end