"This" meaning the problem, or meaning ManyToMany? It's pretty simple to use. You're mapper should extend ManyToMany, and you should have a "field": object m2m extends MappedManyToMany(.../*the two MetaMappers and foreign keys, see the docs/source*/) Then you can treat m2m as a Buffer, adding and deleting children. Call save on the mapper or m2m to propogate the adding/deleting to the database, and refresh to reset its contents to reflect the database. However, as noted currently the children must be saved before they are added. This is not the case for OneToMany, and for ManyToMany it should not be a problem because usually the children exist independently of the parent--that's why they can have 0 or 1 or more "parents."
------------------------------------- Randinn<[email protected]> wrote: Anyone have code showing this in action as it were? On Aug 6, 8:39 am, Naftoli Gugenheim <[email protected]> wrote: > Oh, I think I know what the problem is. I think I should classify it as a bug. > Since you're adding a Role that isn't saved yet, and ManyToMany tracks the > children via the join table, it can't access the child. As a workaround save > the Role before adding it, although the need to do so is against the idea of > ManyToMany and OneToMany. I will see what I can do, G-d willing. > > ------------------------------------- > > glenn<[email protected]> wrote: > > Naftoli, > > Hate to do this to you, but I'm getting the following error using > ManyToMany for Users to Roles: > > Message: java.lang.RuntimeException: Broken join > scala.Predef$.error(Predef.scala:76) > net.liftweb.mapper.ManyToMany$MappedManyToMany$$anonfun$children$1$ > $anonfun$apply$1.apply(ManyToMany.scala:54) > net.liftweb.mapper.ManyToMany$MappedManyToMany$$anonfun$children$1$ > $anonfun$apply$1.apply(ManyToMany.scala:54) > net.liftweb.util.EmptyBox.openOr(Box.scala:372) > net.liftweb.mapper.ManyToMany$MappedManyToMany$$anonfun$children > $1.apply(ManyToMany.scala:54) > net.liftweb.mapper.ManyToMany$MappedManyToMany$$anonfun$children > $1.apply(ManyToMany.scala:54) > scala.List.map(List.scala:812) > net.liftweb.mapper.ManyToMany$MappedManyToMany.children > (ManyToMany.scala:54) > net.liftweb.mapper.ManyToMany$MappedManyToMany.elements > (ManyToMany.scala:96) > scala.Seq$class.flatMap(Seq.scala:293) > net.liftweb.mapper.ManyToMany$MappedManyToMany.flatMap > (ManyToMany.scala:44) > > def edit(ns: NodeSeq): NodeSeq = { > val theUser = view.entity > val addRole = TheBindParam("insert", view.snippet.link("edit", () > => theUser.roles += new Role, Text(S?("Add Role")))) > > bind("user", ns, > "firstname" -> text(theUser.firstName.is, theUser.firstName > (_), ("size","20")), > "lastname" -> text(theUser.lastName.is,theUser.lastName(_), > ("size", "30")), > "roles" -> theUser.roles.flatMap{role => > bind("role", ns, > "name" -> role.name.toForm, > "remove" -> SHtml.submit(S?("Remove"), ()=> > theUser.roles -= role) > ) > }, > addRole, > "submit" -> SHtml.submit(S?("Save"), ()=>view.save) > ) > } > > The offending code seems to be the line: "roles" -> > theUser.roles.flatMap{.... > in the above bind method when I click on the addRole link. > > Here's my User class: > > class User extends MegaProtoUser[User] with ManyToMany[Long,User]{ > def getSingleton = User // what's the "meta" server > > object roles > extends MappedManyToMany(UserRole, UserRole.user, UserRole.role, > Role) > > } > > What am I doing wrong? You can see how difficult it is to slog through > this code, let alone just > trying to explain the problem so I can get help. > > On Aug 5, 9:57 am, Naftoli Gugenheim <[email protected]> wrote: > > > I'll try. > > By the way, as per my correction, you can implement list the regular way > > without ModelView, and just use ModelSnippet's load function in your edit > > link or button, passing it the User instance. > > > ------------------------------------- > > > glenn<[email protected]> wrote: > > > Naftoli, > > > I fixed my code per your comments and now I can edit and remove users > > from a list, as long as I populate the list with > > ModelView instances, as you said. As for the docs, this step was not > > clear to me at all. I just assumed that the list was > > just populated with User entities and the view in the ModelSnippet was > > instantiated with the selected User on each request. > > > It sounds like your plate is pretty full, so I won't expect much, but > > sometime soon, could you provide an example, or improved > > docs, for using TableEditor and its related ItemsList trait. > > > Thanks for all. > > > Glenn... > > > On Aug 5, 9:18 am, Naftoli Gugenheim <[email protected]> wrote: > > > > Correction: ModelSnippet.load takes the actual Mapper instance, not the > > > ModelView wrapper. > > > > ------------------------------------- > > > > Naftoli Gugenheim<[email protected]> wrote: > > > > To answer your immediate question, the listing should not refer to the > > > snippet's view but new ModelView instances for each entity. Then > > > editAction is shorthand for the snippet's link method with a callback to > > > call load on the ModelView. To set the snippet's view's entity, either > > > call load on the snippet with the other ModelView, or call load on the > > > other ModelView (or just set its entity directly). > > > As far as documentation, please tell me what scaladocs need what > > > clarification. Thanks. > > > > ------------------------------------- > > > > glenn<[email protected]> wrote: > > > > Naftoli, > > > > Functional programming systems are notoriously difficult to document. > > > The only way to really know what's going on is to meticulously trace > > > through the source. But that requires > > > time-consuming trial and error coding. So, without clear examples > > > demonstrating exactly what you have in mind, I and others in the same > > > boat, could spend days and still not > > > get it right. > > > > For example, I tried this: > > > > var theUser:User = null > > > val view = new ModelView(theUser, this) > > > > def list(ns: NodeSeq): NodeSeq = User.currentUser.map({user => > > > User.findAll.flatMap({u => > > > bind("user", chooseTemplate("user", "entry", ns), > > > "firstname" -> Text(u.firstName.is), > > > "lastname" -> Text(u.lastName.is), > > > "email" -> Text(u.email.is), > > > "roles" -> u.roles.map(_.name.toString).mkString(", > > > "), > > > view.editAction, > > > view.removeAction > > > ) > > > }) > > > }) openOr Text("You're not logged in") > > > > and, I get a null value exception when I try to remove a user in the > > > list. Simply using > > > val view = new ModelView(new User, this), doesn't work either, > > > although I don't get an > > > exception. Now, where should I be calling load in all of this? > > > > Glenn... > > > > On Aug 3, 6:22 pm, Naftoli Gugenheim <[email protected]> wrote: > > > > > Your snippet should extend ModelSnippet (which extends StatefulSnippet). > > > > Then write: > > > > val view = new ModelView(new User, this) {} > > > > Calling load on another ModelView that references the snippet will load > > > > its entity into that view val. It has a number of methods of possible > > > > interest, like save which checks validity. > > > > Also see Util. > > > > Are you seeing the scaladocs? > > > > > ------------------------------------- > > > > > glenn<[email protected]> wrote: > > > > > Just to add to what I just wrote, I don't see how your ModelView can > > > > be applied to > > > > User, which already extends a class, MegaProtoUser. Maybe I'm not > > > > comprehending this correctly. > > > > > Glenn... > > > > > On Aug 3, 3:48 pm, glenn <[email protected]> wrote: > > > > > > Naftoli, > > > > > > Liked your OneToMany article, but not sure how the new > > > > > ModelView and ModelSnippet code can be applied to ManyToMany. > > > > > Can you provide a sample? > > > > > > Glenn... > > > > > > On Aug 2, 1:21 pm, Naftoli Gugenheim <[email protected]> wrote: > > > > > > > I put an article on the wiki about OneToMany > > > > > > --http://wiki.github.com/dpp/liftweb/how-to-work-with-one-to-many-relat... > > > > > > . > > > > > > > On Sun, Aug 2, 2009 at 11:20 AM, Naftoli Gugenheim > > > > > > <[email protected]>wrote: > > > > > > > > Glad to hear. Also see mapper.view.ItemsList (anyone have a > > > > > > > better name?), > > > > > > > which is used byTableEditor. It's a similar idea without > > > > > > > relationships. > > > > > > > Should MappedOne/ManyToMany be based on ItemsList? > > > > > > > Also should I take Mapped out of those names? After all, they're > > > > > > > not > > > > > > > MappedFields and they don't correspond to a table column. > > > > > > > > ------------------------------------- > > > > > > > Magnus Alvestad<[email protected]> wrote: > > > > > > > > This work that you've done in Mapper fits in very well with > > > > > > > something > > > > > > > I've been planning to do. In a Java project some time ago we > > > > > > > implemented a 'change engine'. We were loading big pension > > > > > > > agreements, > > > > > > > manipulating them in a web interface and finally saving them back > > > > > > > to > > > > > > > the database. While the user was working on the agreement, we > > > > > > > generated a list of changes, containing enough information to > > > > > > > replay > > > > > > > or unroll the change. We could use this to implement undo and some > > > > > > > semi-intelligent merging when two users were trying to commit > > > > > > > changes > > > > > > > to the same agreement. We also let the user review his changes > > > > > > > before > > > > > > > saving, and we indicated changed fields visually. We were even > > > > > > > thinking of implementing some kind of macro or replay > > > > > > > functionality, > > > > > > > but never got that far. > > > > > > > > I've been trying to implement something similar as a lift > > > > > > > component, > > > > > > > but with the old relationship handling it wasn't practical. With > > > > > > > your > > > > > > > changes it should be. Thanks! > > > > > > > > -Magnus > > > > > > > > On Jul 27, 9:57 pm, Naftoli Gugenheim <[email protected]> > > > > > > > wrote: > > > > > > > > I committed some code last night, which can help building > > > > > > > > mapper-based > > > > > > > view snippets, with G-d's help. It includes the following classes: > > > > > > > > (1-2) net.liftweb.mapper.OneToMany, ManyToMany: Gives a more > > > > > > > object-oriented approach to managing related entites. You can > > > > > > > manage the > > > > > > > many side of a 1-n and n-n as a mutable collection of children, > > > > > > > and the > > > > > > > parent of a child can be set directly, instead of via its id. And > > > > > > > the > > > > > > > children are not saved to the database when you add them until > > > > > > > you call save > > > > > > > on it or its parent, nor deleted when you remove tem until you > > > > > > > call > > > > > > > delete_!, which is very helpful when you > > ... > > read more » --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---
