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<gl...@exmbly.com> 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 <naftoli...@gmail.com> 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<gl...@exmbly.com> 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 <naftoli...@gmail.com> wrote: > > > Correction: ModelSnippet.load takes the actual Mapper instance, not the > > ModelView wrapper. > > > ------------------------------------- > > > Naftoli Gugenheim<naftoli...@gmail.com> 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<gl...@exmbly.com> 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 <naftoli...@gmail.com> 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<gl...@exmbly.com> 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 <gl...@exmbly.com> 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 <naftoli...@gmail.com> 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 > > > > > <naftoli...@gmail.com>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<magnus.alves...@gmail.com> 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 <naftoli...@gmail.com> 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 need to keep track of > > > > > > adds/removes > > > > > > through multiple requests. For example, if you are displaying a > > > > > > list and you > > > > > > can click delete, but it shouldn't be permanently deleted until you > > > > > > click > > > > > > save. > > > > > > > There is a new package, ...mapper.view, which contains a number of > > > > > > utilities for mapper-based views: > > > > > > > (3-4) ModelView and ModelSnippet provide a number of building > > > > > > > blocks for > > > > > > views that are too complex to CRUDify. Inherit ModelSnippet (which > > > > > > extends > > > > > > StatefulSnippet) and wrap your entities in ModelView (view is used > > > > > > in the > > > > > > sense of a wrapper). > > > > > > > (5) Util provides some more building blocks that just be imported, > > > > > > without needing a ModelSnippet context. > > > > > > > (6-7) Paginator makes it easy to create paginated, user sortable > > > > > > listings. You can use PaginatedSnippet instead of ModelSnippet to > > > > > > help. > > > > > > > (8-10) ItemsList lets you manage a list of entities with pending > > > > > > additions and deletions. It's used byTableEditor, which is a very > > > > > > easy to > > > > > > use and customizable snippet to edit tables directly. It's useful > > > > > > for > > > > > > editing short lists, e.g., a lookup table like cities. Don't forget > > > > > > to > > > > > > register the table in Boot. > > > > > > > (11) Then there's the experimental FormProcessor, if you need > > > > > > > your form > > > > > > to be processed in one block instead of separate closures, e.g., to > > > > > > surround > > > > > > with try. > > > > > > > (12) Also experimental is sitemap.XmlMenu which lets you write > > > > > > > menus in > > > > > > xml. > > > > > > > (13) I may add CaseEnum, which lets you write case classes that > > > > > > automatically double as an Enumeration. > > > > > > > Questions, comments, suggestions, and constructive criticism are > > > > > > > more > > > > > > than welcome! > > > > > > > Thanks. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Lift" group. To post to this group, send email to liftweb@googlegroups.com To unsubscribe from this group, send email to liftweb+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/liftweb?hl=en -~----------~----~----~----~------~----~------~--~---