Naftoli,

At the risk of discussing something obviously beyond my pay grade,
isn't the real issue Scala traits
and the use of parameterized types. The ManyToMany trait is defined
as:

trait ManyToMany[K,T<:KeyedMapper[K, T]]....

But this isn't really correct,is it, the parameter is too broad, and
that leads to a lot of the confusion and results in the need for
unnecessary documentation. When you think about it, why all the
duplication? Why do I need to
write my User entity as:

class User extends MegaProtoUser[User] with ManyToMany[Long,User]

when we all know that this would be much cleaner:

class User extends MegaProtoUser[User] with ManyToMany.

But traits aren't like interfaces. They have implementation and would
need to know something about
the parent class they are attached to - and how would you accomplish
that (reflection, maybe). This is
more a Scala issue than a Lift one, I think.

Glenn...


On Aug 5, 8:24 pm, Naftoli Gugenheim <[email protected]> wrote:
> Building causes a stack overflow?
> So the question is, is it the resident compiler or plain scalac also crashes? 
> Or just the presentation compiler? What do you see in the error log view or 
> file?
> I get compiler crashes very often when doing fancy mapper type related tricks.
>
> -------------------------------------
>
> 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 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 [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
-~----------~----~----~----~------~----~------~--~---

Reply via email to