def attributes_hash_is_empty?(hash, klass)
      hash.all? do |key, value|
        # convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
        column_name = key.to_s.split('(', 2)[0]

        # datetimes will always have a value. so we ignore them when checking whether the hash is empty.
        # this could be a bad idea. but the current situation (excess record entry) seems worse.
        next true if mulitpart_ignored?(key, klass)

        # defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
        # booleans always have value, so they are ignored if not changed from default
        next true if default_value?(column_name, klass, value)

        if params_hash? value
          attributes_hash_is_empty?(value, klass)
        elsif value.is_a?(Array)
          value.all?(&:blank?)
        else
          value.respond_to?(:empty?) ? value.empty? : false
        end
      end
    end
def attributes_hash_is_empty?(hash, klass)
      hash.all? do |key, value|
        # convert any possible multi-parameter attributes like 'created_at(5i)' to simply 'created_at'
        column_name = key.to_s.split('(', 2)[0]

        # datetimes will always have a value. so we ignore them when checking whether the hash is empty.
        # this could be a bad idea. but the current situation (excess record entry) seems worse.
        next true if mulitpart_ignored?(key, klass)

        # defaults are pre-filled on the form. we can't use them to determine if the user intends a new row.
        # booleans always have value, so they are ignored if not changed from default
        next true if default_value?(column_name, klass, value)

        if params_hash? value
          attributes_hash_is_empty?(value, klass)
        elsif value.is_a?(Array)
          value.all?(&:blank?)
        else
          value.respond_to?(:empty?) ? value.empty? : false
        end
      end
    end
Determines whether the given attributes hash is "empty".
 This isn't a literal emptiness - it's an attempt to discern whether the user intended it to be empty or not.