def set_inversible_noncollection_attribute(newval, accessors, inverse_writer)
      rdr, wtr = accessors
      # the previous value
      oldval = send(rdr)
      # bail if no change
      return newval if newval.equal?(oldval)

      # clear the previous inverse
      logger.debug { "Moving #{qp} from #{oldval.qp} to #{newval.qp}..." } if oldval and newval
      if oldval then
        clr_wtr = self.class === oldval && oldval.send(rdr).equal?(self) ? wtr : inverse_writer
        oldval.send(clr_wtr, nil)
      end
      
      # call the writer
      send(wtr, newval)
      
      # call the inverse writer on self
      if newval then
        newval.send(inverse_writer, self)
        logger.debug { "Moved #{qp} from #{oldval.qp} to #{newval.qp}." } if oldval
      end
      
      newval
    end
def set_inversible_noncollection_attribute(newval, accessors, inverse_writer)
      rdr, wtr = accessors
      # the previous value
      oldval = send(rdr)
      # bail if no change
      return newval if newval.equal?(oldval)

      # clear the previous inverse
      logger.debug { "Moving #{qp} from #{oldval.qp} to #{newval.qp}..." } if oldval and newval
      if oldval then
        clr_wtr = self.class === oldval && oldval.send(rdr).equal?(self) ? wtr : inverse_writer
        oldval.send(clr_wtr, nil)
      end
      
      # call the writer
      send(wtr, newval)
      
      # call the inverse writer on self
      if newval then
        newval.send(inverse_writer, self)
        logger.debug { "Moved #{qp} from #{oldval.qp} to #{newval.qp}." } if oldval
      end
      
      newval
    end
Sets a non-collection attribute value in a way which enforces inverse integrity.

 @param [Object] newval the value to set
 @param [(Symbol, Symbol)] accessors the reader and writer methods to use in setting the
   attribute
 @param [Symbol] inverse_writer the inverse attribute writer method
 @private