Permalink
Browse files

Merge branch 'wip_1068_1072_1076'

* wip_1068_1072_1076:
  Fix #1076
  Fix #1068
  Fix #1072
  • Loading branch information...
2 parents d840afd + 764ed5a commit 9d850e7525d368bd0a446362bf190cb21c624b3c @nafg nafg committed Aug 5, 2011
@@ -39,7 +39,7 @@ trait ManyToMany extends BaseKeyedMapper {
* If they are all successful returns true.
*/
abstract override def save = {
- manyToManyFields.forall(_.save) && super.save
+ super.save && manyToManyFields.forall(_.save)
}
/**
@@ -199,19 +199,18 @@ trait ManyToMany extends BaseKeyedMapper {
/**
* Save the state of this MappedManyToMany to the database.
* This will do the following:
- * 1) Prune references the following join table instances:
- * a. Those whose "parent" foreign key does not equal the parent's primary key
- * b. Those whose "child" foreign key's value is its defaultValue, i.e., -1
- * 2) Delete all join table instances whose child instance was removed
- * 3) Save all child instances
- * 4) If step 3 succeeds save all join instances
- * 5) Return true if steps 2-4 all returned true; otherwise false
+ * 1) Prune join table instances whose "child" foreign key's value is its defaultValue, i.e., -1
+ * 2) Set all join table instances' "parent" foreign key
+ * 3) Delete all join table instances whose child instance was removed
+ * 4) Save all child instances
+ * 5) If step 3 succeeds save all join instances
+ * 6) Return true if steps 2-4 all returned true; otherwise false
*/
def save = {
_joins = joins.filter { join =>
- thisFK(join)(_.is == ManyToMany.this.primaryKeyField.is) &&
- otherFK(join)(f => f.is != f.defaultValue)
+ otherFK(join)(f => f.is != f.defaultValue)
}
+ _joins foreach { thisFK(_)(_ set ManyToMany.this.primaryKeyField.is) }
removedJoins.forall {_.delete_!} & ( // continue saving even if deleting fails
children.forall(_.save) &&
@@ -51,12 +51,16 @@ trait OneToMany[K,T<:KeyedMapper[K, T]] extends KeyedMapper[K,T] { this: T =>
* Returns false as soon as the parent or a one-to-many field returns false.
* If they are all successful returns true.
*/
- override def delete_! = {
- super.delete_! &&
- oneToManyFields.forall( _ match {
- case f: Cascade[_] => f.delete_!
- case _ => true
- } )
+ override def delete_! = DB.use(connectionIdentifier){_ =>
+ if(oneToManyFields.forall{
+ case f: Cascade[_] => f.delete_!
+ case _ => true
+ })
+ super.delete_!
+ else {
+ DB.rollback(connectionIdentifier)
+ false
+ }
}
@@ -24,9 +24,11 @@ import common.{Box, Full, Empty}
import util.BindPlus._
import util.{Helpers, BindHelpers}
import Helpers._
-import http.{SHtml, S, DispatchSnippet}
+import http.{SHtml, S, DispatchSnippet, js}
import S.?
+import js.JsCmds.{Script, Run}
+
import mapper.{Mapper, MetaMapper, LongKeyedMetaMapper, MappedField}
import Util._
@@ -245,7 +247,7 @@ trait ItemsListEditor[T<:Mapper[T]] {
def customBind(item: T): NodeSeq=>NodeSeq = (ns: NodeSeq) => ns
def edit(xhtml: NodeSeq): NodeSeq = {
- def unsavedScript = (<head><script type="text/javascript">
+ def unsavedScript = (<head>{Script(Run("""
var safeToContinue = false
window.onbeforeunload = function(evt) {{ // thanks Tim!
if(!safeToContinue) {{
@@ -255,7 +257,7 @@ trait ItemsListEditor[T<:Mapper[T]] {
return reply;
}}
}}
- </script></head>)
+ """))}</head>)
val noPrompt = "onclick" -> "safeToContinue=true"
val optScript = if(
(items.added.length + items.removed.length == 0) &&
@@ -43,6 +43,19 @@ object OneToManySpecs extends Specification {
fields.length must_== 1
fields(0).asInstanceOf[Any] must_== contact.phones
}
+ "cascade delete" in {
+ val contact = Contact.create
+ contact.phones += Phone.create
+ contact.save
+
+ Contact.count must_== 1
+ Phone.count must_== 1
+
+ contact.delete_!
+
+ Contact.count must_== 0
+ Phone.count must_== 0
+ }
}
}
@@ -51,13 +64,13 @@ object OneToManySpecs extends Specification {
class Contact extends LongKeyedMapper[Contact] with IdPK with OneToMany[Long, Contact] {
def getSingleton = Contact
- object phones extends MappedOneToMany(Phone, Phone.contact)
+ object phones extends MappedOneToMany(Phone, Phone.contact) with Cascade[Phone]
}
object Contact extends Contact with LongKeyedMetaMapper[Contact]
class Phone extends LongKeyedMapper[Phone] with IdPK {
def getSingleton = Phone
- object contact extends LongMappedMapper(this, Contact)
+ object contact extends MappedLongForeignKey(this, Contact)
object number extends MappedString(this, 10)
}
object Phone extends Phone with LongKeyedMetaMapper[Phone]

0 comments on commit 9d850e7

Please sign in to comment.