I should probably take Mapped out of the name, because it's not a MappedField.
------------------------------------- glenn<[email protected]> wrote: Naftoli, I set up my mapper to use your new ManyToMany trait, but I'm not sure how exactly to use it in a snippet or view. Here's what I have so far, a User, Role and UserRole for my model classes: class Role extends LongKeyedMapper[Role] with IdPK { def getSingleton = Role object name extends MappedPoliteString(this, 50) { override def setFilter = notNull _ :: trim _ :: super.setFilter } } class UserRole extends LongKeyedMapper[UserRole] with IdPK { def getSingleton = UserRole object role extends MappedLongForeignKey(this, Role){ override def dbIndexed_? = true } object user extends MappedLongForeignKey(this,User) { override def dbIndexed_? = true } } class User extends MegaProtoUser[User] with ManyToMany[UserRole, Role] { def getSingleton = User // what's the "meta" server // define an additional field for a personal essay object textArea extends MappedTextarea(this, 2048) { override def textareaRows = 10 override def textareaCols = 50 override def displayName = "Personal Essay" } object role extends MappedManyToMany(UserRole, this, Role) } and their corresponding singleton objects. In the past, without the ManyToMany trait, I would do this in User object override def editXhtml(user: User) = { (<form method="post" action={S.uri}> <table><tr><td colspan="2">{S.??("edit")}</td></tr> {localForm(user, true)} <tr><td>Roles</td><td><user:roles/></td></tr> <tr><td> </td><td><user:submit/></td></tr> <tr><td><a href={changePasswordPath.mkString("/", "/", "")} >{S.??("change.password")}</a></td></tr> </table> </form>) } and bind this with the following to show the roles for a particular user as a comma delimited string. def innerEdit = User.isa_?("admin") match { case true => bind("user", editXhtml(theUser), "roles" -> text(roles, doRolesAndSubmit), "submit" -> SHtml.submit(S.??("edit"), testEdit _)) case false => bind("user", editXhtml(theUser), "roles" -> theUser.showRoles, "submit" -> SHtml.submit(S.??("edit"), testEdit _)) } here roles is defined as var roles = theUser.roles.map(_.name.is).mkString(", ") Do you have an example of how to achieve something similar with your new ManyToMany and MappedManyToMany code? Appreciate any help you can give me. Thanks, Glenn... On Jul 28, 3:05 pm, Naftoli Gugenheim <[email protected]> wrote: > Did you update your source jar? Try deleting it from your repository just to > be sure, then mvn dependency:sources etc. > Either way you can access the source on github. > > ------------------------------------- > > glenn<[email protected]> wrote: > > Naftoli, > > The ManyToMany class is in the new lift-mapper jar, but the source is > not available in 1.1-SNAPSHOT-sources. Could you provide? > Thanks, > > Glenn... > > On Jul 27, 3:50 pm, Naftoli Gugenheim <[email protected]> wrote: > > > I committed it last night, so I think it should be there. > > To use many-to-many, simply mix ManyToMany to your mapper, then create a > > MappedManyToMany field like any other field. See the scaladocs for > > specifics. > > Then in your view you can use the field like a collection, e.g., remove an > > element with -=, and save the mapper to apply the changes. > > > ------------------------------------- > > > glenn<[email protected]> wrote: > > > Sounds great. I've been using hacks such as adding code like this to > > my mapper classes just to create a Many-to-Many > > relationship between say, tag and content tables (using an > > intermediary ContentTag table). Similarly, I've done User/Roles > > relationships. > > > private object _dbTags extends HasManyThrough(this, Tag, ContentTag, > > ContentTag.content, ContentTag.tag) > > > private[model] var _tags : List[Tag] = _ > > > private val locker = new Object > > > def tags : List[Tag] = locker.synchronized { > > if(_tags eq null){ > > _tags = _dbTags() > > } > > _tags > > } > > > def tags(newTags:String) = locker.synchronized { > > _tags = newTags.roboSplit(",").map(Tag.byName(_)) > > this > > } > > > def tags(newTags:List[Tag]) = locker.synchronized { > > _tags = newTags > > this > > } > > > def tagsToo:List[Tag] = ContentTag.findAll(By(ContentTag.content, > > this.id)).map(_.tag.obj.open_!) > > > def showTags = Text(tags.map(_.name.is).mkString(", ")) > > > But, then I have to add code like this to the meta-mapper objects: > > > def addTags(entry: Content) { > > if(entry._tags ne null){ > > entry._tags.foreach(ContentTag.join(_, entry)) > > } > > } > > > def delTags(entry:Content) = > > ContentTag.findAll(By(ContentTag.content, entry)).foreach > > (_.delete_!) > > > It's not very pretty. Nor easy to duplicate. > > > I hope your new code is considerably less messy. > > > Is it in the repo-snapshot repository yet. > > > On Jul 27, 12: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 by TableEditor, 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 -~----------~----~----~----~------~----~------~--~---
