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
-~----------~----~----~----~------~----~------~--~---