org.positronicnet.orm

SoftDelete

trait SoftDelete [T <: ManagedRecord] extends BaseRecordManager[T] with SoftDeleteScope[T]

Mixin for record managers, to implement "soft deletion". (Written as a first-draft ORM extension, largely to make sure I wasn't painting myself into a corner where such things are impossible, so API here is subject to change.) See the "todo list" sample app for a usage example.

With this scheme, items that the user deletes aren't really deleted immediately. Instead, they get marked with an is_deleted flag, which puts them in limbo from which they can be recalled with an undelete.

Whenever we're doing a soft deletion, similar items that already were in limbo do in fact go away.

To activate the basic machinery for a record type, make sure the table corresponding to the records has an is_deleted column (you don't have to map it), and mix SoftDelete[T] into the record manager.

This gets you something pretty aggressive about expunging prior is_deleted records --- anything in the table that already was is_deleted gets the axe. To control that, you can mix SoftDeleteScope into derived scopes (e.g. a HasMany).

Also, if you have a many-to-one relation, and the parent records are subject to soft deletion, the child records might want to know about it. You can use the ParentSoftDeleteListener trait to look for that...

Linear Supertypes
Ordering
  1. Alphabetic
  2. By inheritance
Inherited
  1. Hide All
  2. Show all
  1. SoftDelete
  2. SoftDeleteScope
  3. SoftDeleteQueries
  4. BaseRecordManager
  5. Scope
  6. NotifierDelegator
  7. Notifier
  8. BaseNotificationManager
  9. NotificationManager
  10. BaseNotifier
  11. AnyRef
  12. Any
Visibility
  1. Public
  2. All

Value Members

  1. def ! (action: Action[IndexedSeq[T]]): Unit

    Perform the action, usually on a worker thread associated with this notifier.

    Perform the action, usually on a worker thread associated with this notifier. Results may be posted back to the calling thread, viz. the conventions documented in org.positronicnet.notifications.Actions.

    Definition Classes
    ScopeNotifierDelegatorNotifier
  2. def != (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  3. def != (arg0: Any): Boolean

    Attributes
    final
    Definition Classes
    Any
  4. def ## (): Int

    Attributes
    final
    Definition Classes
    AnyRef → Any
  5. def == (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  6. def == (arg0: Any): Boolean

    Attributes
    final
    Definition Classes
    Any
  7. def asInstanceOf [T0] : T0

    Attributes
    final
    Definition Classes
    Any
  8. val baseQuery : org.positronicnet.content.ContentQuery[_, _]

    ContentQuery whose conditions match those declared for the Scope.

    ContentQuery whose conditions match those declared for the Scope.

    Definition Classes
    BaseRecordManagerScope
  9. def clone (): AnyRef

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  10. lazy val count : CachingNotifier[Long]

    Notifier which can be used to fetch, or to receive updates on, the number of records matching the scope's conditions.

    Notifier which can be used to fetch, or to receive updates on, the number of records matching the scope's conditions. One usage pattern:

        Bugs.count ! AddWatcher( this ) { bugCount =>
          if (bugCount == 0) {
            startActivity( new Intent( this, classOf[ CelebrationActivity ])
            Bugs ! StopWatcher( this )
            finish
          }
        }
    

    The onChangeTo method in PositronicActivityHelpers can simplify this a bit... but I digress.

    Note that count is supported only if it is supported by the underlying ContentRepository; e.g., by databases, but not by ContentProviders.

    Definition Classes
    Scope
  11. def countQuery [Q] (initial: Q)(fn: (Q) ⇒ Scope[T]): ValueQuery[Q, Long]

    As for recordsQuery, but returns a notifier of the count of records matching the extra conditions.

    As for recordsQuery, but returns a notifier of the count of records matching the extra conditions.

    Definition Classes
    Scope
  12. def cursorNotifier [T] (thunk: ⇒ T): Notifier[T]

  13. def cursorQuery [Q, R] (initialVal: Q)(queryFunc: (Q) ⇒ R): NonSharedValueQuery[Q, R]

  14. def dataPairs (rec: T): Seq[(String, ContentValue)]

    Attributes
    protected
    Definition Classes
    BaseRecordManager
  15. def delete (rec: T, scope: Scope[T]): Unit

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  16. def deleteAll (qry: org.positronicnet.content.ContentQuery[_, _], scope: Scope[T]): Unit

    Attributes
    protected[orm]
    Definition Classes
    SoftDeleteBaseRecordManager
  17. def deleteAll (scope: Scope[T]): Unit

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  18. lazy val dependencyGetterOption : Option[(T) ⇒ Map[String, org.positronicnet.orm.HasManyAssociation[_]]]

    Attributes
    protected
    Definition Classes
    BaseRecordManager
  19. def doChange (thunk: ⇒ Unit): Unit

  20. def dumpFieldsMapping (sfunc: (String) ⇒ Unit): Unit

    Definition Classes
    BaseRecordManager
  21. def eq (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  22. def equals (arg0: Any): Boolean

    Definition Classes
    AnyRef → Any
  23. val facility : AppFacility

    AppFacility associated with the content source.

    AppFacility associated with the content source.

    Definition Classes
    BaseRecordManagerScope
  24. def fetchOnThisThread : IndexedSeq[T]

    Synchronously fetch the value being monitored by this Notifier.

    Synchronously fetch the value being monitored by this Notifier.

    Definition Classes
    NotifierDelegatorNotifier
  25. def fetchRecords (qry: org.positronicnet.content.ContentQuery[_, _]): IndexedSeq[T]

    Fetch and construct the records from a ContentQuery on this record manager's ContentRepository.

    Fetch and construct the records from a ContentQuery on this record manager's ContentRepository.

    This is largely an internal method. It's made available mostly for the sake of ORM extensions, to be implemented as traits mixed into RecordManager subclasses, on the model of SoftDelete.

    Definition Classes
    BaseRecordManager
  26. val fieldsBuffer : ArrayBuffer[MappedField]

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  27. def fieldsSeq : Seq[MappedField]

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  28. def finalize (): Unit

    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws()
  29. def find (id: RecordId[T], qry: org.positronicnet.content.ContentQuery[_, _]): T

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  30. def findOnThisThread (id: RecordId[T]): T

    Find the record with the given id, if it exists, running the query on the current thread, and returning it as the value.

    Find the record with the given id, if it exists, running the query on the current thread, and returning it as the value.

    XXX should only find it if it matches conditions of the scope, as per Rails.

    Definition Classes
    Scope
  31. lazy val fullQuery : org.positronicnet.content.ContentQuery[_, _]

    ContentQuery whose conditions match those for the records in scope.

    ContentQuery whose conditions match those for the records in scope. Ordinarily the same as baseQuery, but some RecordManagers may add extra conditions to, e.g., make soft-deleted records invisible from an ordinary fetch.

    Definition Classes
    Scope
  32. def getClass (): java.lang.Class[_]

    Attributes
    final
    Definition Classes
    AnyRef
  33. def handleVanishingParent (qry: org.positronicnet.content.ContentQuery[_, _]): Unit

    Support for "cascading deletes", when the parent record in a many-to-one association is gone.

    Support for "cascading deletes", when the parent record in a many-to-one association is gone.

    This is largely an internal method. It's made available mostly for the sake of ORM extensions, to be implemented as traits mixed into RecordManager subclasses, on the model of SoftDelete.

    Definition Classes
    BaseRecordManager
  34. def hasDeleted : CachingNotifier[Boolean]

    org.positronicnet.notications.Notifier for whether this Scope has any deleted records within it:

    org.positronicnet.notications.Notifier for whether this Scope has any deleted records within it:

        myList.items.hasDeleted ! Fetch{ hasDeleted => {
          if ( hasDeleted )
            myList.items ! Undelete
          else
            toast( R.string.undeletes_exhausted )
        }}
    
    Definition Classes
    SoftDeleteQueries
  35. def hashCode (): Int

    Definition Classes
    AnyRef → Any
  36. def idFromLong (rawId: Long): RecordId[T]

    Upcasting a raw Long to an ID; sometimes useful in cases where serializing "baked" record Ids is really awkward, as in the extras to a pending intent.

    Upcasting a raw Long to an ID; sometimes useful in cases where serializing "baked" record Ids is really awkward, as in the extras to a pending intent...

    Definition Classes
    BaseRecordManager
  37. def isInstanceOf [T0] : Boolean

    Attributes
    final
    Definition Classes
    Any
  38. def killDependentRecords (qry: org.positronicnet.content.ContentQuery[_, _]): Option[Unit]

    Attributes
    protected
    Definition Classes
    BaseRecordManager
  39. def limit (lim: Int): Scope[T]

    Produce a modified subscope which supplies at most a given number of records.

    Produce a modified subscope which supplies at most a given number of records. The string supplied is used directly in a SQL limit clause. May not be supported by all repositories; in particular, it is not supported by ContentProviders.

    Definition Classes
    Scope
  40. def limit (str: String): Scope[T]

    Produce a modified subscope which supplies at most a given number of records.

    Produce a modified subscope which supplies at most a given number of records. The string supplied is used directly in a SQL limit clause. May not be supported by all repositories; in particular, it is not supported by ContentProviders.

    Definition Classes
    Scope
  41. def mapField (fieldName: String, columnName: String, how: How = MapAs.ReadWrite): Unit

    Declare that the field named fieldName in our org.positronic.orm.ManagedRecord subclass T is to be mapped to the persistent storage columnName.

    Declare that the field named fieldName in our org.positronic.orm.ManagedRecord subclass T is to be mapped to the persistent storage columnName. If the primaryKey argument is set true, this field and column will be treated as the record's primary key; this currently must be a Long.

    For Database mapping, when using a RecordManager, it is rarely necessary to call this explicitly; so long as you're following the usual naming conventions, the ORM will figure out what's going on without being told. Those conventions are:

    • A column named _id will be mapped to a field named id, and will be treated as the primary key.
    • A column with a name like_this will be mapped to a camel-cased field likeThis.

    However, a BaseRecordManager will not map any columns by default, and requires you to map everything explicitly.

    Definition Classes
    BaseRecordManager
  42. def ne (arg0: AnyRef): Boolean

    Attributes
    final
    Definition Classes
    AnyRef
  43. def newRecord : T

    Produce a new object (to be populated with mapped data from a query).

    Produce a new object (to be populated with mapped data from a query).

    Default is to use a niladic constructor if one exists. Failing that, if there is one constructor, and defaults for all its arguments, we'll use that.

    Note that if you override this, you might want to provide a niladic constructor anyway on the class itself, or strange and unuseuful things will happen when attempting to serialize and deserialize our RecordIds, e.g., when putting them into the extras of an android Intent.

    Definition Classes
    BaseRecordManager
  44. def noteChange : Unit

  45. def notifierDelegate : CachingNotifier[IndexedSeq[T]]

    The Notifier to which the delegator forwards, well.

    The Notifier to which the delegator forwards, well... everything here.

    Definition Classes
    ScopeNotifierDelegator
  46. def notify (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
  47. def notifyAll (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
  48. def numDeleted : CachingNotifier[Long]

    As hasDeleted, but notifies for the number of deleted records.

    As hasDeleted, but notifies for the number of deleted records.

    Definition Classes
    SoftDeleteQueries
  49. def onThisThread (action: Action[IndexedSeq[T]]): Unit

    Perform the action, synchronously on the calling thread.

    Perform the action, synchronously on the calling thread.

    Definition Classes
    ScopeNotifierDelegatorNotifier
  50. def onThread (thunk: ⇒ Unit): Unit

    Definition Classes
    BaseNotifier
  51. def order (str: String): Scope[T]

    Produce a modified subscope which supplies records in a particular order.

    Produce a modified subscope which supplies records in a particular order. The string supplied is used directly in a SQL order clause (or passed to the underlying ContentProvider, if appropriate).

    Definition Classes
    Scope
  52. def primaryKey (fieldName: String, columnName: String): Unit

    Declare a mapping, as with mapField, for a field to be designated as the primary key.

    Declare a mapping, as with mapField, for a field to be designated as the primary key.

    Definition Classes
    BaseRecordManager
  53. def queryForAll (qry: org.positronicnet.content.ContentQuery[_, _]): org.positronicnet.content.ContentQuery[_, _]

    Attributes
    protected[orm]
    Definition Classes
    SoftDeleteBaseRecordManager
  54. def queryForRecord (rec: T): org.positronicnet.content.ContentQuery[_, _]

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  55. lazy val records : CachingNotifier[IndexedSeq[T]]

    Definition Classes
    Scope
  56. def recordsQuery [Q] (initial: Q)(fn: (Q) ⇒ Scope[T]): ValueQuery[Q, IndexedSeq[T]]

    Returns a notifier for a subset of the records covered by this scope, matching extra conditions, which can be changed later by sending a Requery message.

    Returns a notifier for a subset of the records covered by this scope, matching extra conditions, which can be changed later by sending a Requery message.

    This can be used, for example, as the source for an IndexedSeqSourceAdapter, which displays the rows matching the user's "current search condition", whatever it may be, and changes when the condition changes, but without having to rewire the IndexedSeqSourceAdapter, perhaps something like so:

        val matchingBugs =
          Bugs.recordsQuery( "" ){ pattern =>
            Bugs.where( "tag_line like ?", pattern )
          }
    
         // ... later ...
    
        matchingBugs ! Requery( "newpattern" )
    

    The Requery will cause any declared watchers of matchingBugs to be notified of the new query result.

    Definition Classes
    Scope
  57. def save (rec: T, scope: Scope[T]): RecordId[T]

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  58. def subScopeFor (query: org.positronicnet.content.ContentQuery[_, _]): Scope[T]

    Attributes
    protected[orm]
    Definition Classes
    Scope
  59. def synchronized [T0] (arg0: ⇒ T0): T0

    Attributes
    final
    Definition Classes
    AnyRef
  60. def toString (): String

    Definition Classes
    AnyRef → Any
  61. def unsavedId : RecordId[T]

    Definition Classes
    BaseRecordManager
  62. def updateAll (scope: Scope[T], vals: Seq[(String, ContentValue)]): Unit

    Attributes
    protected[orm]
    Definition Classes
    BaseRecordManager
  63. def valueNotifier [T] (thunk: ⇒ T): CachingNotifier[T]

  64. def valueQuery [Q, R] (initialVal: Q)(queryFunc: (Q) ⇒ R): ValueQuery[Q, R]

  65. def wait (): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()
  66. def wait (arg0: Long, arg1: Int): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()
  67. def wait (arg0: Long): Unit

    Attributes
    final
    Definition Classes
    AnyRef
    Annotations
    @throws()
  68. def where (str: String, vals: ContentValue*): Scope[T]

    Produce a restricted subscope containing only records matching an extra SQL condition, possibly including ? placeholders which can get filled in by the supplied ContentValue arguments, if any.

    Produce a restricted subscope containing only records matching an extra SQL condition, possibly including ? placeholders which can get filled in by the supplied ContentValue arguments, if any. Example:

        val recentBugs =
          Bugs.where( "state != ? and create_date > ?",
                      "closed",
                      System.currentTimeMillis - 3*86400*1000 )
    

    Note that the columns are named using internal SQL column names, not the Java mapped versions.

    (Note for the future: we could consider changing this by allowing syntax like "{createDate}>?", where the string in curly-braces would be a Java field name to be mapped to the SQL equivalent. But that's not there yet.)

    Definition Classes
    Scope
  69. def whereEq (pairs: (String, ContentValue)*): Scope[T]

    Produce a restricted subscope containing only records where particular fields have particular values.

    Produce a restricted subscope containing only records where particular fields have particular values. The argument is a set of (String,[[org.positronicnet.content.ContentValue]]) pairs, often entered using -> notation, like so:

        Bugs.whereEq( "status"->"done", "ownerId"->joe.id )
    

    Note that columns can be designated by either the names of the columns in the underlying tables, or the names of the Scala vals in the classes that they get mapped to.

    Definition Classes
    Scope

Inherited from SoftDeleteScope[T]

Inherited from SoftDeleteQueries[T]

Inherited from BaseRecordManager[T]

Inherited from Scope[T]

Inherited from NotifierDelegator[IndexedSeq[T]]

Inherited from Notifier[IndexedSeq[T]]

Inherited from BaseNotificationManager

Inherited from NotificationManager

Inherited from BaseNotifier

Inherited from AnyRef

Inherited from Any